• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2016 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // validationEGL.cpp: Validation functions for generic EGL entry point parameters
8 
9 #include "libANGLE/validationEGL_autogen.h"
10 
11 #include "common/utilities.h"
12 #include "libANGLE/Config.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Device.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/EGLSync.h"
17 #include "libANGLE/Image.h"
18 #include "libANGLE/Stream.h"
19 #include "libANGLE/Surface.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/Thread.h"
22 #include "libANGLE/formatutils.h"
23 #include "libANGLE/renderer/DisplayImpl.h"
24 
25 #include <EGL/eglext.h>
26 
27 namespace egl
28 {
29 namespace
30 {
GetMaximumMipLevel(const gl::Context * context,gl::TextureType type)31 size_t GetMaximumMipLevel(const gl::Context *context, gl::TextureType type)
32 {
33     const gl::Caps &caps = context->getCaps();
34 
35     int maxDimension = 0;
36     switch (type)
37     {
38         case gl::TextureType::_2D:
39         case gl::TextureType::_2DArray:
40         case gl::TextureType::_2DMultisample:
41             maxDimension = caps.max2DTextureSize;
42             break;
43         case gl::TextureType::Rectangle:
44             maxDimension = caps.maxRectangleTextureSize;
45             break;
46         case gl::TextureType::CubeMap:
47             maxDimension = caps.maxCubeMapTextureSize;
48             break;
49         case gl::TextureType::_3D:
50             maxDimension = caps.max3DTextureSize;
51             break;
52 
53         default:
54             UNREACHABLE();
55     }
56 
57     return gl::log2(maxDimension);
58 }
59 
TextureHasNonZeroMipLevelsSpecified(const gl::Context * context,const gl::Texture * texture)60 bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
61 {
62     size_t maxMip = GetMaximumMipLevel(context, texture->getType());
63     for (size_t level = 1; level < maxMip; level++)
64     {
65         if (texture->getType() == gl::TextureType::CubeMap)
66         {
67             for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
68             {
69                 if (texture->getFormat(face, level).valid())
70                 {
71                     return true;
72                 }
73             }
74         }
75         else
76         {
77             if (texture->getFormat(gl::NonCubeTextureTypeToTarget(texture->getType()), level)
78                     .valid())
79             {
80                 return true;
81             }
82         }
83     }
84 
85     return false;
86 }
87 
CubeTextureHasUnspecifiedLevel0Face(const gl::Texture * texture)88 bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
89 {
90     ASSERT(texture->getType() == gl::TextureType::CubeMap);
91     for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
92     {
93         if (!texture->getFormat(face, 0).valid())
94         {
95             return true;
96         }
97     }
98 
99     return false;
100 }
101 
ValidateStreamAttribute(const ValidationContext * val,const EGLAttrib attribute,const EGLAttrib value,const DisplayExtensions & extensions)102 bool ValidateStreamAttribute(const ValidationContext *val,
103                              const EGLAttrib attribute,
104                              const EGLAttrib value,
105                              const DisplayExtensions &extensions)
106 {
107     switch (attribute)
108     {
109         case EGL_STREAM_STATE_KHR:
110         case EGL_PRODUCER_FRAME_KHR:
111         case EGL_CONSUMER_FRAME_KHR:
112             val->setError(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
113             return false;
114         case EGL_CONSUMER_LATENCY_USEC_KHR:
115             // Technically not in spec but a latency < 0 makes no sense so we check it
116             if (value < 0)
117             {
118                 val->setError(EGL_BAD_PARAMETER, "Latency must be positive");
119                 return false;
120             }
121             break;
122         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
123             if (!extensions.streamConsumerGLTexture)
124             {
125                 val->setError(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
126                 return false;
127             }
128             // Again not in spec but it should be positive anyways
129             if (value < 0)
130             {
131                 val->setError(EGL_BAD_PARAMETER, "Timeout must be positive");
132                 return false;
133             }
134             break;
135         default:
136             val->setError(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
137             return false;
138     }
139     return true;
140 }
141 
ValidateCreateImageMipLevelCommon(const ValidationContext * val,const gl::Context * context,const gl::Texture * texture,EGLAttrib level)142 bool ValidateCreateImageMipLevelCommon(const ValidationContext *val,
143                                        const gl::Context *context,
144                                        const gl::Texture *texture,
145                                        EGLAttrib level)
146 {
147     // Note that the spec EGL_create_image spec does not explicitly specify an error
148     // when the level is outside the base/max level range, but it does mention that the
149     // level "must be a part of the complete texture object <buffer>". It can be argued
150     // that out-of-range levels are not a part of the complete texture.
151     const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
152     if (level > 0 &&
153         (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
154          static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
155     {
156         val->setError(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
157         return false;
158     }
159 
160     if (level == 0 && !texture->isMipmapComplete() &&
161         TextureHasNonZeroMipLevelsSpecified(context, texture))
162     {
163         val->setError(EGL_BAD_PARAMETER,
164                       "if level is zero and the texture is incomplete, it must "
165                       "have no mip levels specified except zero.");
166         return false;
167     }
168 
169     return true;
170 }
171 
ValidateConfigAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)172 bool ValidateConfigAttribute(const ValidationContext *val,
173                              const Display *display,
174                              EGLAttrib attribute)
175 {
176     switch (attribute)
177     {
178         case EGL_BUFFER_SIZE:
179         case EGL_ALPHA_SIZE:
180         case EGL_BLUE_SIZE:
181         case EGL_GREEN_SIZE:
182         case EGL_RED_SIZE:
183         case EGL_DEPTH_SIZE:
184         case EGL_STENCIL_SIZE:
185         case EGL_CONFIG_CAVEAT:
186         case EGL_CONFIG_ID:
187         case EGL_LEVEL:
188         case EGL_NATIVE_RENDERABLE:
189         case EGL_NATIVE_VISUAL_ID:
190         case EGL_NATIVE_VISUAL_TYPE:
191         case EGL_SAMPLES:
192         case EGL_SAMPLE_BUFFERS:
193         case EGL_SURFACE_TYPE:
194         case EGL_TRANSPARENT_TYPE:
195         case EGL_TRANSPARENT_BLUE_VALUE:
196         case EGL_TRANSPARENT_GREEN_VALUE:
197         case EGL_TRANSPARENT_RED_VALUE:
198         case EGL_BIND_TO_TEXTURE_RGB:
199         case EGL_BIND_TO_TEXTURE_RGBA:
200         case EGL_MIN_SWAP_INTERVAL:
201         case EGL_MAX_SWAP_INTERVAL:
202         case EGL_LUMINANCE_SIZE:
203         case EGL_ALPHA_MASK_SIZE:
204         case EGL_COLOR_BUFFER_TYPE:
205         case EGL_RENDERABLE_TYPE:
206         case EGL_MATCH_NATIVE_PIXMAP:
207         case EGL_CONFORMANT:
208         case EGL_MAX_PBUFFER_WIDTH:
209         case EGL_MAX_PBUFFER_HEIGHT:
210         case EGL_MAX_PBUFFER_PIXELS:
211             break;
212 
213         case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
214             if (!display->getExtensions().surfaceOrientation)
215             {
216                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
217                 return false;
218             }
219             break;
220 
221         case EGL_COLOR_COMPONENT_TYPE_EXT:
222             if (!display->getExtensions().pixelFormatFloat)
223             {
224                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_pixel_format_float is not enabled.");
225                 return false;
226             }
227             break;
228 
229         case EGL_RECORDABLE_ANDROID:
230             if (!display->getExtensions().recordable)
231             {
232                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_recordable is not enabled.");
233                 return false;
234             }
235             break;
236 
237         case EGL_FRAMEBUFFER_TARGET_ANDROID:
238             if (!display->getExtensions().framebufferTargetANDROID)
239             {
240                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_framebuffer_target is not enabled.");
241                 return false;
242             }
243             break;
244 
245         case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
246             if (!display->getExtensions().iosurfaceClientBuffer)
247             {
248                 val->setError(EGL_BAD_ATTRIBUTE,
249                               "EGL_ANGLE_iosurface_client_buffer is not enabled.");
250                 return false;
251             }
252             break;
253 
254         case EGL_Y_INVERTED_NOK:
255             if (!display->getExtensions().textureFromPixmapNOK)
256             {
257                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
258                 return false;
259             }
260             break;
261 
262         case EGL_MATCH_FORMAT_KHR:
263             if (!display->getExtensions().lockSurface3KHR)
264             {
265                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not enabled.");
266                 return false;
267             }
268             break;
269 
270         default:
271             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
272             return false;
273     }
274 
275     return true;
276 }
277 
ValidateConfigAttributeValue(const ValidationContext * val,const Display * display,EGLAttrib attribute,EGLAttrib value)278 bool ValidateConfigAttributeValue(const ValidationContext *val,
279                                   const Display *display,
280                                   EGLAttrib attribute,
281                                   EGLAttrib value)
282 {
283     switch (attribute)
284     {
285 
286         case EGL_BIND_TO_TEXTURE_RGB:
287         case EGL_BIND_TO_TEXTURE_RGBA:
288             switch (value)
289             {
290                 case EGL_DONT_CARE:
291                 case EGL_TRUE:
292                 case EGL_FALSE:
293                     break;
294                 default:
295                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_bind_to_texture invalid attribute: 0x%X",
296                                   static_cast<uint32_t>(value));
297                     return false;
298             }
299             break;
300 
301         case EGL_COLOR_BUFFER_TYPE:
302             switch (value)
303             {
304                 case EGL_RGB_BUFFER:
305                 case EGL_LUMINANCE_BUFFER:
306                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
307                 case EGL_DONT_CARE:
308                     break;
309                 default:
310                     val->setError(EGL_BAD_ATTRIBUTE,
311                                   "EGL_color_buffer_type invalid attribute: 0x%X",
312                                   static_cast<uint32_t>(value));
313                     return false;
314             }
315             break;
316 
317         case EGL_NATIVE_RENDERABLE:
318             switch (value)
319             {
320                 case EGL_DONT_CARE:
321                 case EGL_TRUE:
322                 case EGL_FALSE:
323                     break;
324                 default:
325                     val->setError(EGL_BAD_ATTRIBUTE,
326                                   "EGL_native_renderable invalid attribute: 0x%X",
327                                   static_cast<uint32_t>(value));
328                     return false;
329             }
330             break;
331 
332         case EGL_TRANSPARENT_TYPE:
333             switch (value)
334             {
335                 case EGL_NONE:
336                 case EGL_TRANSPARENT_RGB:
337                 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
338                 case EGL_DONT_CARE:
339                     break;
340                 default:
341                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_transparent_type invalid attribute: 0x%X",
342                                   static_cast<uint32_t>(value));
343                     return false;
344             }
345             break;
346 
347         case EGL_RECORDABLE_ANDROID:
348             switch (value)
349             {
350                 case EGL_TRUE:
351                 case EGL_FALSE:
352                 case EGL_DONT_CARE:
353                     break;
354                 default:
355                     val->setError(EGL_BAD_ATTRIBUTE,
356                                   "EGL_RECORDABLE_ANDROID invalid attribute: 0x%X",
357                                   static_cast<uint32_t>(value));
358                     return false;
359             }
360             break;
361 
362         case EGL_COLOR_COMPONENT_TYPE_EXT:
363             switch (value)
364             {
365                 case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
366                 case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
367                 case EGL_DONT_CARE:
368                     break;
369                 default:
370                     val->setError(EGL_BAD_ATTRIBUTE,
371                                   "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: 0x%X",
372                                   static_cast<uint32_t>(value));
373                     return false;
374             }
375             break;
376 
377         case EGL_MATCH_FORMAT_KHR:
378             switch (value)
379             {
380                 case EGL_FORMAT_RGB_565_KHR:
381                 case EGL_FORMAT_RGBA_8888_KHR:
382                 case EGL_FORMAT_RGB_565_EXACT_KHR:
383                 case EGL_FORMAT_RGBA_8888_EXACT_KHR:
384                     break;
385                 default:
386                     val->setError(EGL_BAD_ATTRIBUTE,
387                                   "EGL_KHR_lock_surface3 invalid attribute: 0x%X",
388                                   static_cast<uint32_t>(value));
389                     return false;
390             }
391             break;
392 
393         default:
394             break;
395     }
396 
397     return true;
398 }
399 
ValidateConfigAttributes(const ValidationContext * val,const Display * display,const AttributeMap & attributes)400 bool ValidateConfigAttributes(const ValidationContext *val,
401                               const Display *display,
402                               const AttributeMap &attributes)
403 {
404     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateConfigAttribute));
405 
406     for (const auto &attrib : attributes)
407     {
408         EGLAttrib pname = attrib.first;
409         EGLAttrib value = attrib.second;
410         ANGLE_VALIDATION_TRY(ValidateConfigAttributeValue(val, display, pname, value));
411     }
412 
413     return true;
414 }
415 
ValidateColorspaceAttribute(const ValidationContext * val,const DisplayExtensions & displayExtensions,EGLAttrib colorSpace)416 bool ValidateColorspaceAttribute(const ValidationContext *val,
417                                  const DisplayExtensions &displayExtensions,
418                                  EGLAttrib colorSpace)
419 {
420     switch (colorSpace)
421     {
422         case EGL_GL_COLORSPACE_SRGB:
423             break;
424         case EGL_GL_COLORSPACE_LINEAR:
425             break;
426         case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
427             if (!displayExtensions.glColorspaceDisplayP3Linear)
428             {
429                 val->setError(EGL_BAD_ATTRIBUTE,
430                               "EXT_gl_colorspace_display_p3_linear is not available.");
431                 return false;
432             }
433             break;
434         case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
435             if (!displayExtensions.glColorspaceDisplayP3)
436             {
437                 val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_display_p3 is not available.");
438                 return false;
439             }
440             break;
441         case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
442             if (!displayExtensions.glColorspaceDisplayP3Passthrough)
443             {
444                 val->setError(EGL_BAD_ATTRIBUTE,
445                               "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.");
446                 return false;
447             }
448             break;
449         case EGL_GL_COLORSPACE_SCRGB_EXT:
450             if (!displayExtensions.glColorspaceScrgb)
451             {
452                 val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_scrgb is not available.");
453                 return false;
454             }
455             break;
456         case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
457             if (!displayExtensions.glColorspaceScrgbLinear)
458             {
459                 val->setError(EGL_BAD_ATTRIBUTE,
460                               "EXT_gl_colorspace_scrgb_linear is not available.");
461                 return false;
462             }
463             break;
464         default:
465             val->setError(EGL_BAD_ATTRIBUTE);
466             return false;
467     }
468     return true;
469 }
ValidatePlatformType(const ValidationContext * val,const ClientExtensions & clientExtensions,EGLAttrib platformType)470 bool ValidatePlatformType(const ValidationContext *val,
471                           const ClientExtensions &clientExtensions,
472                           EGLAttrib platformType)
473 {
474     switch (platformType)
475     {
476         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
477             break;
478 
479         case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
480         case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
481             if (!clientExtensions.platformANGLED3D)
482             {
483                 val->setError(EGL_BAD_ATTRIBUTE, "Direct3D platform is unsupported.");
484                 return false;
485             }
486             break;
487 
488         case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
489         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
490             if (!clientExtensions.platformANGLEOpenGL)
491             {
492                 val->setError(EGL_BAD_ATTRIBUTE, "OpenGL platform is unsupported.");
493                 return false;
494             }
495             break;
496 
497         case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
498             if (!clientExtensions.platformANGLENULL)
499             {
500                 val->setError(EGL_BAD_ATTRIBUTE,
501                               "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
502                               "requires EGL_ANGLE_platform_angle_null.");
503                 return false;
504             }
505             break;
506 
507         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
508             if (!clientExtensions.platformANGLEVulkan)
509             {
510                 val->setError(EGL_BAD_ATTRIBUTE, "Vulkan platform is unsupported.");
511                 return false;
512             }
513             break;
514 
515         case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
516             if (!clientExtensions.platformANGLEMetal)
517             {
518                 val->setError(EGL_BAD_ATTRIBUTE, "Metal platform is unsupported.");
519                 return false;
520             }
521             break;
522 
523         default:
524             val->setError(EGL_BAD_ATTRIBUTE, "Unknown platform type.");
525             return false;
526     }
527 
528     return true;
529 }
530 
ValidateGetPlatformDisplayCommon(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)531 bool ValidateGetPlatformDisplayCommon(const ValidationContext *val,
532                                       EGLenum platform,
533                                       const void *native_display,
534                                       const AttributeMap &attribMap)
535 {
536     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
537 
538     switch (platform)
539     {
540         case EGL_PLATFORM_ANGLE_ANGLE:
541             if (!clientExtensions.platformANGLE)
542             {
543                 val->setError(EGL_BAD_PARAMETER, "Platform ANGLE extension is not active");
544                 return false;
545             }
546             break;
547         case EGL_PLATFORM_DEVICE_EXT:
548             if (!clientExtensions.platformDevice)
549             {
550                 val->setError(EGL_BAD_PARAMETER, "Platform Device extension is not active");
551                 return false;
552             }
553             break;
554         default:
555             val->setError(EGL_BAD_CONFIG, "Bad platform type.");
556             return false;
557     }
558 
559     attribMap.initializeWithoutValidation();
560 
561     if (platform == EGL_PLATFORM_ANGLE_ANGLE)
562     {
563         EGLAttrib platformType       = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
564         bool enableAutoTrimSpecified = false;
565         bool enableD3D11on12         = false;
566         bool presentPathSpecified    = false;
567         bool luidSpecified           = false;
568         bool deviceIdSpecified       = false;
569 
570         Optional<EGLAttrib> majorVersion;
571         Optional<EGLAttrib> minorVersion;
572         Optional<EGLAttrib> deviceType;
573         Optional<EGLAttrib> eglHandle;
574 
575         for (const auto &curAttrib : attribMap)
576         {
577             const EGLAttrib value = curAttrib.second;
578 
579             switch (curAttrib.first)
580             {
581                 case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
582                 {
583                     ANGLE_VALIDATION_TRY(ValidatePlatformType(val, clientExtensions, value));
584                     platformType = value;
585                     break;
586                 }
587 
588                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
589                     if (value != EGL_DONT_CARE)
590                     {
591                         majorVersion = value;
592                     }
593                     break;
594 
595                 case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
596                     if (value != EGL_DONT_CARE)
597                     {
598                         minorVersion = value;
599                     }
600                     break;
601 
602                 case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
603                     switch (value)
604                     {
605                         case EGL_TRUE:
606                         case EGL_FALSE:
607                             break;
608                         default:
609                             val->setError(EGL_BAD_ATTRIBUTE, "Invalid automatic trim attribute");
610                             return false;
611                     }
612                     enableAutoTrimSpecified = true;
613                     break;
614 
615                 case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
616                     if (!clientExtensions.platformANGLED3D ||
617                         !clientExtensions.platformANGLED3D11ON12)
618                     {
619                         val->setError(EGL_BAD_ATTRIBUTE,
620                                       "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.");
621                         return false;
622                     }
623 
624                     switch (value)
625                     {
626                         case EGL_TRUE:
627                         case EGL_FALSE:
628                             break;
629                         default:
630                             val->setError(EGL_BAD_ATTRIBUTE, "Invalid D3D11on12 attribute");
631                             return false;
632                     }
633                     enableD3D11on12 = true;
634                     break;
635 
636                 case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
637                     if (!clientExtensions.experimentalPresentPath)
638                     {
639                         val->setError(EGL_BAD_ATTRIBUTE,
640                                       "EGL_ANGLE_experimental_present_path extension not active");
641                         return false;
642                     }
643 
644                     switch (value)
645                     {
646                         case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
647                         case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
648                             break;
649                         default:
650                             val->setError(EGL_BAD_ATTRIBUTE,
651                                           "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE");
652                             return false;
653                     }
654                     presentPathSpecified = true;
655                     break;
656 
657                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
658                     switch (value)
659                     {
660                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
661                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
662                             break;
663 
664                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
665                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
666                             if (!clientExtensions.platformANGLED3D)
667                             {
668                                 val->setError(EGL_BAD_ATTRIBUTE,
669                                               "EGL_ANGLE_platform_angle_d3d is not supported");
670                                 return false;
671                             }
672                             break;
673 
674                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
675                             if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
676                             {
677                                 val->setError(EGL_BAD_ATTRIBUTE,
678                                               "EGL_ANGLE_platform_angle_device_type_"
679                                               "egl_angle is not supported");
680                                 return false;
681                             }
682                             break;
683 
684                         case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
685                             if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
686                             {
687                                 val->setError(EGL_BAD_ATTRIBUTE,
688                                               "EGL_ANGLE_platform_angle_device_type_"
689                                               "swiftshader is not supported");
690                                 return false;
691                             }
692                             break;
693 
694                         default:
695                             val->setError(EGL_BAD_ATTRIBUTE,
696                                           "Invalid value for "
697                                           "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
698                                           "attrib");
699                             return false;
700                     }
701                     deviceType = value;
702                     break;
703 
704                 case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
705                     if (!clientExtensions.platformANGLE)
706                     {
707                         val->setError(EGL_BAD_ATTRIBUTE,
708                                       "EGL_ANGLE_platform_angle extension not active");
709                         return false;
710                     }
711                     if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
712                     {
713                         val->setError(EGL_BAD_ATTRIBUTE,
714                                       "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
715                                       "must be EGL_TRUE, EGL_FALSE, or "
716                                       "EGL_DONT_CARE.");
717                         return false;
718                     }
719                     break;
720 
721                 case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
722                     if (value != EGL_DONT_CARE)
723                     {
724                         eglHandle = value;
725                     }
726                     break;
727 
728                 case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
729                 case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
730                     luidSpecified = true;
731                     break;
732                 case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE:
733                     // The property does not have an effect if it's not active, so do not check
734                     // for non-support.
735                     switch (value)
736                     {
737                         case EGL_FALSE:
738                         case EGL_TRUE:
739                             break;
740                         default:
741                             val->setError(EGL_BAD_ATTRIBUTE,
742                                           "Invalid value for "
743                                           "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
744                                           "EAGL_ANGLE attrib");
745                             return false;
746                     }
747                     break;
748                 case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE:
749                     // The property does not have an effect if it's not active, so do not check
750                     // for non-support.
751                     switch (value)
752                     {
753                         case EGL_FALSE:
754                         case EGL_TRUE:
755                             break;
756                         default:
757                             val->setError(EGL_BAD_ATTRIBUTE,
758                                           "Invalid value for "
759                                           "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
760                                           "CGL_ANGLE attrib");
761                             return false;
762                     }
763                     break;
764                 case EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE:
765                 case EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE:
766                     if (!clientExtensions.platformANGLEDeviceId)
767                     {
768                         val->setError(EGL_BAD_ATTRIBUTE,
769                                       "EGL_ANGLE_platform_angle_device_id is not supported");
770                         return false;
771                     }
772                     deviceIdSpecified = true;
773                     break;
774                 default:
775                     break;
776             }
777         }
778 
779         if (!majorVersion.valid() && minorVersion.valid())
780         {
781             val->setError(EGL_BAD_ATTRIBUTE,
782                           "Must specify major version if you specify a minor version.");
783             return false;
784         }
785 
786         if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
787             platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
788         {
789             val->setError(EGL_BAD_ATTRIBUTE,
790                           "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
791                           "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
792             return false;
793         }
794 
795         if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
796         {
797             val->setError(EGL_BAD_ATTRIBUTE,
798                           "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
799                           "requires a device type of "
800                           "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
801             return false;
802         }
803 
804         if (enableD3D11on12)
805         {
806             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
807             {
808                 val->setError(EGL_BAD_ATTRIBUTE,
809                               "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
810                               "requires a platform type of "
811                               "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
812                 return false;
813             }
814 
815             if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
816                 deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
817             {
818                 val->setError(EGL_BAD_ATTRIBUTE,
819                               "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
820                               "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
821                               "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE");
822                 return false;
823             }
824         }
825 
826         if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
827         {
828             val->setError(EGL_BAD_ATTRIBUTE,
829                           "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
830                           "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
831             return false;
832         }
833 
834         if (luidSpecified)
835         {
836             if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
837             {
838                 val->setError(EGL_BAD_ATTRIBUTE,
839                               "EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE and "
840                               "EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE "
841                               "require a platform type of "
842                               "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
843                 return false;
844             }
845 
846             if (attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) == 0 &&
847                 attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) == 0)
848             {
849                 val->setError(EGL_BAD_ATTRIBUTE,
850                               "If either EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE "
851                               "and/or EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE are "
852                               "specified, at least one must non-zero.");
853                 return false;
854             }
855         }
856 
857         if (deviceIdSpecified)
858         {
859             if (attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0) == 0 &&
860                 attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0) == 0)
861             {
862                 val->setError(EGL_BAD_ATTRIBUTE,
863                               "If either EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE "
864                               "and/or EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE are "
865                               "specified, at least one must non-zero.");
866                 return false;
867             }
868         }
869 
870         if (deviceType.valid())
871         {
872             switch (deviceType.value())
873             {
874                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
875                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
876                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
877                         platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
878                     {
879                         val->setError(EGL_BAD_ATTRIBUTE,
880                                       "This device type requires a "
881                                       "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
882                                       "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.");
883                         return false;
884                     }
885                     break;
886 
887                 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
888                     if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
889                     {
890                         val->setError(EGL_BAD_ATTRIBUTE,
891                                       "This device type requires a "
892                                       "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.");
893                         return false;
894                     }
895                     break;
896 
897                 default:
898                     break;
899             }
900         }
901 
902         if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
903         {
904             if ((majorVersion.valid() && majorVersion.value() != 1) ||
905                 (minorVersion.valid() && minorVersion.value() != 0))
906             {
907                 val->setError(EGL_BAD_ATTRIBUTE,
908                               "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
909                               "only supports Vulkan 1.0.");
910                 return false;
911             }
912         }
913 
914         if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
915             platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
916         {
917             val->setError(EGL_BAD_ATTRIBUTE,
918                           "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
919                           "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.");
920             return false;
921         }
922     }
923     else if (platform == EGL_PLATFORM_DEVICE_EXT)
924     {
925         const Device *eglDevice = static_cast<const Device *>(native_display);
926         if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
927         {
928             val->setError(EGL_BAD_ATTRIBUTE,
929                           "native_display should be a valid EGL device if "
930                           "platform equals EGL_PLATFORM_DEVICE_EXT");
931             return false;
932         }
933     }
934     else
935     {
936         UNREACHABLE();
937     }
938 
939     if (attribMap.contains(EGL_POWER_PREFERENCE_ANGLE))
940     {
941         if (!clientExtensions.displayPowerPreferenceANGLE)
942         {
943             val->setError(EGL_BAD_ATTRIBUTE,
944                           "Attribute EGL_POWER_PREFERENCE_ANGLE "
945                           "requires EGL_ANGLE_display_power_preference.");
946             return false;
947         }
948         EGLAttrib value = attribMap.get(EGL_POWER_PREFERENCE_ANGLE, 0);
949         if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
950         {
951             val->setError(EGL_BAD_ATTRIBUTE,
952                           "EGL_POWER_PREFERENCE_ANGLE must be "
953                           "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
954             return false;
955         }
956     }
957 
958     if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
959     {
960         if (!clientExtensions.featureControlANGLE)
961         {
962             val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
963             return false;
964         }
965         else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
966         {
967             val->setError(EGL_BAD_ATTRIBUTE,
968                           "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer");
969             return false;
970         }
971     }
972     if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
973     {
974         if (!clientExtensions.featureControlANGLE)
975         {
976             val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
977             return false;
978         }
979         else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
980         {
981             val->setError(EGL_BAD_ATTRIBUTE,
982                           "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer");
983             return false;
984         }
985     }
986 
987     return true;
988 }
989 
ValidateStream(const ValidationContext * val,const Display * display,const Stream * stream)990 bool ValidateStream(const ValidationContext *val, const Display *display, const Stream *stream)
991 {
992     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
993 
994     const DisplayExtensions &displayExtensions = display->getExtensions();
995     if (!displayExtensions.stream)
996     {
997         val->setError(EGL_BAD_ACCESS, "Stream extension not active");
998         return false;
999     }
1000 
1001     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
1002     {
1003         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
1004         return false;
1005     }
1006 
1007     return true;
1008 }
1009 
ValidateLabeledObject(const ValidationContext * val,const Display * display,ObjectType objectType,EGLObjectKHR object,LabeledObject ** outLabeledObject)1010 bool ValidateLabeledObject(const ValidationContext *val,
1011                            const Display *display,
1012                            ObjectType objectType,
1013                            EGLObjectKHR object,
1014                            LabeledObject **outLabeledObject)
1015 {
1016     switch (objectType)
1017     {
1018         case ObjectType::Context:
1019         {
1020             gl::Context *context = static_cast<gl::Context *>(object);
1021             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
1022             *outLabeledObject = context;
1023             break;
1024         }
1025 
1026         case ObjectType::Display:
1027         {
1028             ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1029             if (display != object)
1030             {
1031                 if (val)
1032                 {
1033                     val->setError(EGL_BAD_PARAMETER,
1034                                   "when object type is EGL_OBJECT_DISPLAY_KHR, the "
1035                                   "object must be the same as the display.");
1036                 }
1037                 return false;
1038             }
1039 
1040             *outLabeledObject = static_cast<Display *>(object);
1041             break;
1042         }
1043 
1044         case ObjectType::Image:
1045         {
1046             Image *image = static_cast<Image *>(object);
1047             ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
1048             *outLabeledObject = image;
1049             break;
1050         }
1051 
1052         case ObjectType::Stream:
1053         {
1054             Stream *stream = static_cast<Stream *>(object);
1055             ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
1056             *outLabeledObject = stream;
1057             break;
1058         }
1059 
1060         case ObjectType::Surface:
1061         {
1062             Surface *surface = static_cast<Surface *>(object);
1063             ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
1064             *outLabeledObject = surface;
1065             break;
1066         }
1067 
1068         case ObjectType::Sync:
1069         {
1070             Sync *sync = static_cast<Sync *>(object);
1071             ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
1072             *outLabeledObject = sync;
1073             break;
1074         }
1075 
1076         case ObjectType::Thread:
1077         {
1078             ASSERT(val);
1079             *outLabeledObject = val->eglThread;
1080             break;
1081         }
1082 
1083         default:
1084             if (val)
1085             {
1086                 val->setError(EGL_BAD_PARAMETER, "unknown object type.");
1087             }
1088             return false;
1089     }
1090 
1091     return true;
1092 }
1093 
1094 // This is a common sub-check of Display status that's shared by multiple functions
ValidateDisplayPointer(const ValidationContext * val,const Display * display)1095 bool ValidateDisplayPointer(const ValidationContext *val, const Display *display)
1096 {
1097     if (display == EGL_NO_DISPLAY)
1098     {
1099         if (val)
1100         {
1101             val->setError(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
1102         }
1103         return false;
1104     }
1105 
1106     if (!Display::isValidDisplay(display))
1107     {
1108         if (val)
1109         {
1110             val->setError(EGL_BAD_DISPLAY, "display is not a valid display: 0x%p", display);
1111         }
1112         return false;
1113     }
1114 
1115     return true;
1116 }
1117 
ValidCompositorTimingName(CompositorTiming name)1118 bool ValidCompositorTimingName(CompositorTiming name)
1119 {
1120     switch (name)
1121     {
1122         case CompositorTiming::CompositeDeadline:
1123         case CompositorTiming::CompositInterval:
1124         case CompositorTiming::CompositToPresentLatency:
1125             return true;
1126 
1127         default:
1128             return false;
1129     }
1130 }
1131 
ValidTimestampType(Timestamp timestamp)1132 bool ValidTimestampType(Timestamp timestamp)
1133 {
1134     switch (timestamp)
1135     {
1136         case Timestamp::RequestedPresentTime:
1137         case Timestamp::RenderingCompleteTime:
1138         case Timestamp::CompositionLatchTime:
1139         case Timestamp::FirstCompositionStartTime:
1140         case Timestamp::LastCompositionStartTime:
1141         case Timestamp::FirstCompositionGPUFinishedTime:
1142         case Timestamp::DisplayPresentTime:
1143         case Timestamp::DequeueReadyTime:
1144         case Timestamp::ReadsDoneTime:
1145             return true;
1146 
1147         default:
1148             return false;
1149     }
1150 }
1151 
ValidateCompatibleSurface(const ValidationContext * val,const Display * display,const gl::Context * context,const Surface * surface)1152 bool ValidateCompatibleSurface(const ValidationContext *val,
1153                                const Display *display,
1154                                const gl::Context *context,
1155                                const Surface *surface)
1156 {
1157     const Config *contextConfig = context->getConfig();
1158     const Config *surfaceConfig = surface->getConfig();
1159 
1160     // Surface compatible with client API - only OPENGL_ES supported
1161     switch (context->getClientMajorVersion())
1162     {
1163         case 1:
1164             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
1165             {
1166                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 1.x.");
1167                 return false;
1168             }
1169             break;
1170         case 2:
1171             if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
1172             {
1173                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 2.x.");
1174                 return false;
1175             }
1176             break;
1177         case 3:
1178             if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
1179             {
1180                 val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 3.x.");
1181                 return false;
1182             }
1183             break;
1184         default:
1185             val->setError(EGL_BAD_MATCH, "Surface not compatible with Context API.");
1186             return false;
1187     }
1188 
1189     // EGL KHR no config context
1190     if (context->getConfig() == EGL_NO_CONFIG_KHR)
1191     {
1192         const DisplayExtensions &displayExtensions = display->getExtensions();
1193         if (displayExtensions.noConfigContext)
1194         {
1195             return true;
1196         }
1197         val->setError(EGL_BAD_MATCH, "Context with no config is not supported.");
1198         return false;
1199     }
1200 
1201     // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
1202 
1203     bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
1204     if (!colorBufferCompat)
1205     {
1206         val->setError(EGL_BAD_MATCH, "Color buffer types are not compatible.");
1207         return false;
1208     }
1209 
1210     bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
1211                        surfaceConfig->greenSize == contextConfig->greenSize &&
1212                        surfaceConfig->blueSize == contextConfig->blueSize &&
1213                        surfaceConfig->alphaSize == contextConfig->alphaSize &&
1214                        surfaceConfig->luminanceSize == contextConfig->luminanceSize;
1215     if (!colorCompat)
1216     {
1217         val->setError(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
1218         return false;
1219     }
1220 
1221     bool componentTypeCompat =
1222         surfaceConfig->colorComponentType == contextConfig->colorComponentType;
1223     if (!componentTypeCompat)
1224     {
1225         val->setError(EGL_BAD_MATCH, "Color buffer component types are not compatible.");
1226         return false;
1227     }
1228 
1229     bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
1230                     surfaceConfig->stencilSize == contextConfig->stencilSize;
1231     if (!dsCompat)
1232     {
1233         val->setError(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
1234         return false;
1235     }
1236 
1237     bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
1238     if (!surfaceTypeCompat)
1239     {
1240         val->setError(EGL_BAD_MATCH, "Surface type is not compatible.");
1241         return false;
1242     }
1243 
1244     return true;
1245 }
1246 
ValidateCreateSyncBase(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs,bool isExt)1247 bool ValidateCreateSyncBase(const ValidationContext *val,
1248                             const Display *display,
1249                             EGLenum type,
1250                             const AttributeMap &attribs,
1251                             bool isExt)
1252 {
1253     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1254 
1255     attribs.initializeWithoutValidation();
1256 
1257     gl::Context *currentContext  = val->eglThread->getContext();
1258     egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
1259 
1260     switch (type)
1261     {
1262         case EGL_SYNC_FENCE_KHR:
1263             if (!attribs.isEmpty())
1264             {
1265                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1266                 return false;
1267             }
1268 
1269             if (!display->getExtensions().fenceSync)
1270             {
1271                 val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
1272                 return false;
1273             }
1274 
1275             if (display != currentDisplay)
1276             {
1277                 val->setError(EGL_BAD_MATCH,
1278                               "CreateSync can only be called on the current display");
1279                 return false;
1280             }
1281 
1282             ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
1283 
1284             if (!currentContext->getExtensions().EGLSyncOES)
1285             {
1286                 val->setError(EGL_BAD_MATCH,
1287                               "EGL_SYNC_FENCE_KHR cannot be used without "
1288                               "GL_OES_EGL_sync support.");
1289                 return false;
1290             }
1291             break;
1292 
1293         case EGL_SYNC_NATIVE_FENCE_ANDROID:
1294             if (!display->getExtensions().fenceSync)
1295             {
1296                 val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
1297                 return false;
1298             }
1299 
1300             if (!display->getExtensions().nativeFenceSyncANDROID)
1301             {
1302                 val->setError(EGL_BAD_DISPLAY,
1303                               "EGL_ANDROID_native_fence_sync extension is not available.");
1304                 return false;
1305             }
1306 
1307             if (display != currentDisplay)
1308             {
1309                 val->setError(EGL_BAD_MATCH,
1310                               "CreateSync can only be called on the current display");
1311                 return false;
1312             }
1313 
1314             ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
1315 
1316             if (!currentContext->getExtensions().EGLSyncOES)
1317             {
1318                 val->setError(EGL_BAD_MATCH,
1319                               "EGL_SYNC_FENCE_KHR cannot be used without "
1320                               "GL_OES_EGL_sync support.");
1321                 return false;
1322             }
1323 
1324             for (const auto &attributeIter : attribs)
1325             {
1326                 EGLAttrib attribute = attributeIter.first;
1327 
1328                 switch (attribute)
1329                 {
1330                     case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
1331                         break;
1332 
1333                     default:
1334                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1335                         return false;
1336                 }
1337             }
1338             break;
1339 
1340         case EGL_SYNC_REUSABLE_KHR:
1341             if (!attribs.isEmpty())
1342             {
1343                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1344                 return false;
1345             }
1346 
1347             if (!display->getExtensions().reusableSyncKHR)
1348             {
1349                 val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
1350                 return false;
1351             }
1352             break;
1353 
1354         default:
1355             if (isExt)
1356             {
1357                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid type parameter");
1358                 return false;
1359             }
1360             else
1361             {
1362                 val->setError(EGL_BAD_PARAMETER, "Invalid type parameter");
1363                 return false;
1364             }
1365     }
1366 
1367     return true;
1368 }
1369 
ValidateGetSyncAttribBase(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute)1370 bool ValidateGetSyncAttribBase(const ValidationContext *val,
1371                                const Display *display,
1372                                const Sync *sync,
1373                                EGLint attribute)
1374 {
1375     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
1376 
1377     switch (attribute)
1378     {
1379         case EGL_SYNC_CONDITION_KHR:
1380             switch (sync->getType())
1381             {
1382                 case EGL_SYNC_FENCE_KHR:
1383                 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1384                     break;
1385 
1386                 default:
1387                     val->setError(EGL_BAD_ATTRIBUTE,
1388                                   "EGL_SYNC_CONDITION_KHR is not valid for this sync type.");
1389                     return false;
1390             }
1391             break;
1392 
1393         // The following attributes are accepted by all types
1394         case EGL_SYNC_TYPE_KHR:
1395         case EGL_SYNC_STATUS_KHR:
1396             break;
1397 
1398         default:
1399             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
1400             return false;
1401     }
1402 
1403     return true;
1404 }
1405 
ValidateQueryDisplayAttribBase(const ValidationContext * val,const Display * display,const EGLint attribute)1406 bool ValidateQueryDisplayAttribBase(const ValidationContext *val,
1407                                     const Display *display,
1408                                     const EGLint attribute)
1409 {
1410     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
1411 
1412     switch (attribute)
1413     {
1414         case EGL_DEVICE_EXT:
1415             if (!Display::GetClientExtensions().deviceQueryEXT)
1416             {
1417                 val->setError(EGL_BAD_DISPLAY, "EGL_EXT_device_query extension is not available.");
1418                 return false;
1419             }
1420             break;
1421 
1422         case EGL_FEATURE_COUNT_ANGLE:
1423             if (!Display::GetClientExtensions().featureControlANGLE)
1424             {
1425                 val->setError(EGL_BAD_DISPLAY,
1426                               "EGL_ANGLE_feature_control extension is not available.");
1427                 return false;
1428             }
1429             break;
1430 
1431         default:
1432             val->setError(EGL_BAD_ATTRIBUTE, "attribute is not valid.");
1433             return false;
1434     }
1435 
1436     return true;
1437 }
1438 
ValidateCreateContextAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)1439 bool ValidateCreateContextAttribute(const ValidationContext *val,
1440                                     const Display *display,
1441                                     EGLAttrib attribute)
1442 {
1443     switch (attribute)
1444     {
1445         case EGL_CONTEXT_CLIENT_VERSION:
1446         case EGL_CONTEXT_MINOR_VERSION:
1447         case EGL_CONTEXT_FLAGS_KHR:
1448         case EGL_CONTEXT_OPENGL_DEBUG:
1449             break;
1450 
1451         case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1452             // Only valid for OpenGL (non-ES) contexts
1453             val->setError(EGL_BAD_ATTRIBUTE);
1454             return false;
1455 
1456         case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1457             if (!display->getExtensions().createContextRobustness)
1458             {
1459                 val->setError(EGL_BAD_ATTRIBUTE);
1460                 return false;
1461             }
1462             break;
1463 
1464         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1465             if (!display->getExtensions().createContextRobustness)
1466             {
1467                 val->setError(EGL_BAD_ATTRIBUTE);
1468                 return false;
1469             }
1470             break;
1471 
1472         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
1473         {
1474             // We either need to have -
1475             // 1. EGL 1.5 which added support for this as part of core spec
1476             // 2. EGL_KHR_create_context extension which requires EGL 1.4
1477             constexpr EGLint kRequiredMajorVersion = 1;
1478             constexpr EGLint kRequiredMinorVersion = 5;
1479             if ((kEglMajorVersion < kRequiredMajorVersion ||
1480                  kEglMinorVersion < kRequiredMinorVersion) &&
1481                 !display->getExtensions().createContext)
1482             {
1483                 val->setError(EGL_BAD_ATTRIBUTE);
1484                 return false;
1485             }
1486             break;
1487         }
1488 
1489         case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1490             if (!display->getExtensions().createContextNoError)
1491             {
1492                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
1493                 return false;
1494             }
1495             break;
1496 
1497         case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1498             if (!display->getExtensions().createContextWebGLCompatibility)
1499             {
1500                 val->setError(EGL_BAD_ATTRIBUTE,
1501                               "Attribute "
1502                               "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
1503                               "EGL_ANGLE_create_context_webgl_compatibility.");
1504                 return false;
1505             }
1506             break;
1507 
1508         case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1509             if (!display->getExtensions().createContextBindGeneratesResource)
1510             {
1511                 val->setError(EGL_BAD_ATTRIBUTE,
1512                               "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
1513                               "EGL_CHROMIUM_create_context_bind_generates_resource.");
1514                 return false;
1515             }
1516             break;
1517 
1518         case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1519             if (!display->getExtensions().displayTextureShareGroup)
1520             {
1521                 val->setError(EGL_BAD_ATTRIBUTE,
1522                               "Attribute "
1523                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
1524                               "EGL_ANGLE_display_texture_share_group.");
1525                 return false;
1526             }
1527             break;
1528 
1529         case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
1530             if (!display->getExtensions().displayTextureShareGroup)
1531             {
1532                 val->setError(EGL_BAD_ATTRIBUTE,
1533                               "Attribute "
1534                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE requires "
1535                               "EGL_ANGLE_display_semaphore_share_group.");
1536                 return false;
1537             }
1538             break;
1539 
1540         case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1541             if (!display->getExtensions().createContextClientArrays)
1542             {
1543                 val->setError(EGL_BAD_ATTRIBUTE,
1544                               "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
1545                               "EGL_ANGLE_create_context_client_arrays.");
1546                 return false;
1547             }
1548             break;
1549 
1550         case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1551             if (!display->getExtensions().programCacheControlANGLE)
1552             {
1553                 val->setError(EGL_BAD_ATTRIBUTE,
1554                               "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
1555                               "requires EGL_ANGLE_program_cache_control.");
1556                 return false;
1557             }
1558             break;
1559 
1560         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1561             if (!display->getExtensions().robustResourceInitializationANGLE)
1562             {
1563                 val->setError(EGL_BAD_ATTRIBUTE,
1564                               "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1565                               "requires EGL_ANGLE_robust_resource_initialization.");
1566                 return false;
1567             }
1568             break;
1569 
1570         case EGL_EXTENSIONS_ENABLED_ANGLE:
1571             if (!display->getExtensions().createContextExtensionsEnabled)
1572             {
1573                 val->setError(EGL_BAD_ATTRIBUTE,
1574                               "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
1575                               "requires EGL_ANGLE_create_context_extensions_enabled.");
1576                 return false;
1577             }
1578             break;
1579 
1580         case EGL_POWER_PREFERENCE_ANGLE:
1581             if (!display->getExtensions().powerPreference)
1582             {
1583                 val->setError(EGL_BAD_ATTRIBUTE,
1584                               "Attribute EGL_POWER_PREFERENCE_ANGLE "
1585                               "requires EGL_ANGLE_power_preference.");
1586                 return false;
1587             }
1588             break;
1589 
1590         case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1591             if (!display->getExtensions().createContextBackwardsCompatible)
1592             {
1593                 val->setError(EGL_BAD_ATTRIBUTE,
1594                               "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
1595                               "requires EGL_ANGLE_create_context_backwards_compatible.");
1596                 return false;
1597             }
1598             break;
1599 
1600         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1601             if (!display->getExtensions().contextPriority)
1602             {
1603                 val->setError(EGL_BAD_ATTRIBUTE,
1604                               "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
1605                               "extension EGL_IMG_context_priority.");
1606                 return false;
1607             }
1608             break;
1609 
1610         case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
1611             if (!display->getExtensions().robustnessVideoMemoryPurgeNV)
1612             {
1613                 val->setError(EGL_BAD_ATTRIBUTE,
1614                               "Attribute EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV requires "
1615                               "extension EGL_NV_robustness_video_memory_purge.");
1616                 return false;
1617             }
1618             break;
1619 
1620         case EGL_EXTERNAL_CONTEXT_ANGLE:
1621             if (!display->getExtensions().externalContextAndSurface)
1622             {
1623                 val->setError(EGL_BAD_ATTRIBUTE,
1624                               "Attribute "
1625                               "EGL_EXTERNAL_CONTEXT_ANGLE requires "
1626                               "EGL_ANGLE_external_context_and_surface.");
1627                 return false;
1628             }
1629             break;
1630         case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
1631             if (!display->getExtensions().externalContextAndSurface)
1632             {
1633                 val->setError(EGL_BAD_ATTRIBUTE,
1634                               "Attribute "
1635                               "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE requires "
1636                               "EGL_ANGLE_external_context_and_surface.");
1637                 return false;
1638             }
1639             break;
1640 
1641         case EGL_PROTECTED_CONTENT_EXT:
1642             if (!display->getExtensions().protectedContentEXT)
1643             {
1644                 val->setError(EGL_BAD_ATTRIBUTE,
1645                               "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
1646                               "extension EGL_EXT_protected_content.");
1647                 return false;
1648             }
1649             break;
1650 
1651         case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
1652             if (!display->getExtensions().contextVirtualizationANGLE)
1653             {
1654                 val->setError(EGL_BAD_ATTRIBUTE,
1655                               "Attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE requires "
1656                               "extension EGL_ANGLE_context_virtualization.");
1657                 return false;
1658             }
1659             break;
1660 
1661         case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
1662             if (!display->getExtensions().metalCreateContextOwnershipIdentityANGLE)
1663             {
1664                 val->setError(EGL_BAD_ATTRIBUTE,
1665                               "Attribute EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE requires "
1666                               "EGL_ANGLE_metal_create_context_ownership_identity.");
1667             }
1668             break;
1669 
1670         default:
1671             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
1672             return false;
1673     }
1674 
1675     return true;
1676 }
1677 
ValidateCreateContextAttributeValue(const ValidationContext * val,const Display * display,const gl::Context * shareContext,EGLAttrib attribute,EGLAttrib value)1678 bool ValidateCreateContextAttributeValue(const ValidationContext *val,
1679                                          const Display *display,
1680                                          const gl::Context *shareContext,
1681                                          EGLAttrib attribute,
1682                                          EGLAttrib value)
1683 {
1684     switch (attribute)
1685     {
1686         case EGL_CONTEXT_CLIENT_VERSION:
1687         case EGL_CONTEXT_MINOR_VERSION:
1688         case EGL_CONTEXT_OPENGL_DEBUG:
1689         case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
1690             break;
1691 
1692         case EGL_CONTEXT_FLAGS_KHR:
1693         {
1694             // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
1695             constexpr EGLint kValidContextFlags =
1696                 (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
1697             if ((value & ~kValidContextFlags) != 0)
1698             {
1699                 val->setError(EGL_BAD_ATTRIBUTE);
1700                 return false;
1701             }
1702             break;
1703         }
1704 
1705         case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1706             if (value != EGL_TRUE && value != EGL_FALSE)
1707             {
1708                 val->setError(EGL_BAD_ATTRIBUTE);
1709                 return false;
1710             }
1711             break;
1712 
1713         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1714         case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
1715             if (value != EGL_LOSE_CONTEXT_ON_RESET_EXT && value != EGL_NO_RESET_NOTIFICATION_EXT)
1716             {
1717                 val->setError(EGL_BAD_ATTRIBUTE);
1718                 return false;
1719             }
1720 
1721             if (shareContext && shareContext->isResetNotificationEnabled() !=
1722                                     (value == EGL_LOSE_CONTEXT_ON_RESET_EXT))
1723             {
1724                 val->setError(EGL_BAD_MATCH);
1725                 return false;
1726             }
1727             break;
1728 
1729         case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1730             if (value != EGL_TRUE && value != EGL_FALSE)
1731             {
1732                 val->setError(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
1733                 return false;
1734             }
1735             break;
1736 
1737         case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1738             if (value != EGL_TRUE && value != EGL_FALSE)
1739             {
1740                 val->setError(EGL_BAD_ATTRIBUTE,
1741                               "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
1742                               "EGL_TRUE or EGL_FALSE.");
1743                 return false;
1744             }
1745             break;
1746 
1747         case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1748             if (value != EGL_TRUE && value != EGL_FALSE)
1749             {
1750                 val->setError(EGL_BAD_ATTRIBUTE,
1751                               "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
1752                               "must be EGL_TRUE or EGL_FALSE.");
1753                 return false;
1754             }
1755             break;
1756 
1757         case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1758             if (value != EGL_TRUE && value != EGL_FALSE)
1759             {
1760                 val->setError(EGL_BAD_ATTRIBUTE,
1761                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
1762                               "EGL_TRUE or EGL_FALSE.");
1763                 return false;
1764             }
1765             if (shareContext &&
1766                 shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE))
1767             {
1768                 val->setError(EGL_BAD_ATTRIBUTE,
1769                               "All contexts within a share group must be "
1770                               "created with the same value of "
1771                               "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
1772                 return false;
1773             }
1774             break;
1775 
1776         case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
1777             if (value != EGL_TRUE && value != EGL_FALSE)
1778             {
1779                 val->setError(EGL_BAD_ATTRIBUTE,
1780                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE must be "
1781                               "EGL_TRUE or EGL_FALSE.");
1782                 return false;
1783             }
1784             if (shareContext &&
1785                 shareContext->usingDisplaySemaphoreShareGroup() != (value == EGL_TRUE))
1786             {
1787                 val->setError(EGL_BAD_ATTRIBUTE,
1788                               "All contexts within a share group must be "
1789                               "created with the same value of "
1790                               "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE.");
1791                 return false;
1792             }
1793             break;
1794 
1795         case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1796             if (value != EGL_TRUE && value != EGL_FALSE)
1797             {
1798                 val->setError(EGL_BAD_ATTRIBUTE,
1799                               "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
1800                               "be EGL_TRUE or EGL_FALSE.");
1801                 return false;
1802             }
1803             break;
1804 
1805         case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1806             if (value != EGL_TRUE && value != EGL_FALSE)
1807             {
1808                 val->setError(EGL_BAD_ATTRIBUTE,
1809                               "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
1810                               "be EGL_TRUE or EGL_FALSE.");
1811                 return false;
1812             }
1813             break;
1814 
1815         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1816             if (value != EGL_TRUE && value != EGL_FALSE)
1817             {
1818                 val->setError(EGL_BAD_ATTRIBUTE,
1819                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1820                               "either EGL_TRUE or EGL_FALSE.");
1821                 return false;
1822             }
1823             break;
1824 
1825         case EGL_EXTENSIONS_ENABLED_ANGLE:
1826             if (value != EGL_TRUE && value != EGL_FALSE)
1827             {
1828                 val->setError(EGL_BAD_ATTRIBUTE,
1829                               "EGL_EXTENSIONS_ENABLED_ANGLE must be "
1830                               "either EGL_TRUE or EGL_FALSE.");
1831                 return false;
1832             }
1833             break;
1834 
1835         case EGL_POWER_PREFERENCE_ANGLE:
1836             if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
1837             {
1838                 val->setError(EGL_BAD_ATTRIBUTE,
1839                               "EGL_POWER_PREFERENCE_ANGLE must be "
1840                               "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
1841                 return false;
1842             }
1843             break;
1844 
1845         case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1846             if (value != EGL_TRUE && value != EGL_FALSE)
1847             {
1848                 val->setError(EGL_BAD_ATTRIBUTE,
1849                               "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
1850                               "either EGL_TRUE or EGL_FALSE.");
1851                 return false;
1852             }
1853             break;
1854 
1855         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1856             switch (value)
1857             {
1858                 case EGL_CONTEXT_PRIORITY_LOW_IMG:
1859                 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1860                 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1861                     break;
1862                 default:
1863                     val->setError(EGL_BAD_ATTRIBUTE,
1864                                   "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
1865                                   "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
1866                                   "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
1867                                   "EGL_CONTEXT_PRIORITY_HIGH_IMG.");
1868                     return false;
1869             }
1870             break;
1871 
1872         case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
1873             if (value != EGL_TRUE && value != EGL_FALSE)
1874             {
1875                 val->setError(EGL_BAD_ATTRIBUTE,
1876                               "EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV must "
1877                               "be either EGL_TRUE or EGL_FALSE.");
1878                 return false;
1879             }
1880             break;
1881 
1882         case EGL_EXTERNAL_CONTEXT_ANGLE:
1883             if (value != EGL_TRUE && value != EGL_FALSE)
1884             {
1885                 val->setError(EGL_BAD_ATTRIBUTE,
1886                               "EGL_EXTERNAL_CONTEXT_ANGLE must "
1887                               "be either EGL_TRUE or EGL_FALSE.");
1888                 return false;
1889             }
1890             if (shareContext && (value == EGL_TRUE))
1891             {
1892                 val->setError(
1893                     EGL_BAD_ATTRIBUTE,
1894                     "EGL_EXTERNAL_CONTEXT_ANGLE doesn't allow creating with sharedContext.");
1895                 return false;
1896             }
1897             break;
1898         case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
1899             if (value != EGL_TRUE && value != EGL_FALSE)
1900             {
1901                 val->setError(EGL_BAD_ATTRIBUTE,
1902                               "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE must "
1903                               "be either EGL_TRUE or EGL_FALSE.");
1904                 return false;
1905             }
1906             break;
1907 
1908         case EGL_PROTECTED_CONTENT_EXT:
1909             if (value != EGL_TRUE && value != EGL_FALSE)
1910             {
1911                 val->setError(EGL_BAD_ATTRIBUTE,
1912                               "EGL_PROTECTED_CONTENT_EXT must "
1913                               "be either EGL_TRUE or EGL_FALSE.");
1914                 return false;
1915             }
1916             break;
1917 
1918         case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
1919             if (value == 0)
1920             {
1921                 val->setError(EGL_BAD_ATTRIBUTE,
1922                               "EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE must"
1923                               "be non-zero.");
1924                 return false;
1925             }
1926             break;
1927 
1928         default:
1929             UNREACHABLE();
1930             return false;
1931     }
1932 
1933     return true;
1934 }
1935 
ValidateCreatePbufferSurfaceAttribute(const ValidationContext * val,const Display * display,EGLAttrib attribute)1936 bool ValidateCreatePbufferSurfaceAttribute(const ValidationContext *val,
1937                                            const Display *display,
1938                                            EGLAttrib attribute)
1939 {
1940     const DisplayExtensions &displayExtensions = display->getExtensions();
1941 
1942     switch (attribute)
1943     {
1944         case EGL_WIDTH:
1945         case EGL_HEIGHT:
1946         case EGL_LARGEST_PBUFFER:
1947         case EGL_TEXTURE_FORMAT:
1948         case EGL_TEXTURE_TARGET:
1949         case EGL_MIPMAP_TEXTURE:
1950         case EGL_VG_COLORSPACE:
1951         case EGL_GL_COLORSPACE:
1952         case EGL_VG_ALPHA_FORMAT:
1953             break;
1954 
1955         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1956             if (!displayExtensions.robustResourceInitializationANGLE)
1957             {
1958                 val->setError(EGL_BAD_ATTRIBUTE,
1959                               "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1960                               "requires EGL_ANGLE_robust_resource_initialization.");
1961                 return false;
1962             }
1963             break;
1964 
1965         case EGL_PROTECTED_CONTENT_EXT:
1966             if (!displayExtensions.protectedContentEXT)
1967             {
1968                 val->setError(EGL_BAD_ATTRIBUTE,
1969                               "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
1970                               "extension EGL_EXT_protected_content.");
1971                 return false;
1972             }
1973             break;
1974 
1975         default:
1976             val->setError(EGL_BAD_ATTRIBUTE);
1977             return false;
1978     }
1979 
1980     return true;
1981 }
1982 
ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext * val,const Display * display,EGLAttrib attribute,EGLAttrib value)1983 bool ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext *val,
1984                                                 const Display *display,
1985                                                 EGLAttrib attribute,
1986                                                 EGLAttrib value)
1987 {
1988     const DisplayExtensions &displayExtensions = display->getExtensions();
1989 
1990     switch (attribute)
1991     {
1992         case EGL_WIDTH:
1993         case EGL_HEIGHT:
1994             if (value < 0)
1995             {
1996                 val->setError(EGL_BAD_PARAMETER);
1997                 return false;
1998             }
1999             break;
2000 
2001         case EGL_LARGEST_PBUFFER:
2002             break;
2003 
2004         case EGL_TEXTURE_FORMAT:
2005             switch (value)
2006             {
2007                 case EGL_NO_TEXTURE:
2008                 case EGL_TEXTURE_RGB:
2009                 case EGL_TEXTURE_RGBA:
2010                     break;
2011                 default:
2012                     val->setError(EGL_BAD_ATTRIBUTE);
2013                     return false;
2014             }
2015             break;
2016 
2017         case EGL_TEXTURE_TARGET:
2018             switch (value)
2019             {
2020                 case EGL_NO_TEXTURE:
2021                 case EGL_TEXTURE_2D:
2022                     break;
2023                 default:
2024                     val->setError(EGL_BAD_ATTRIBUTE);
2025                     return false;
2026             }
2027             break;
2028 
2029         case EGL_MIPMAP_TEXTURE:
2030             break;
2031 
2032         case EGL_VG_COLORSPACE:
2033             break;
2034 
2035         case EGL_GL_COLORSPACE:
2036             ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2037             break;
2038 
2039         case EGL_VG_ALPHA_FORMAT:
2040             break;
2041 
2042         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
2043             ASSERT(displayExtensions.robustResourceInitializationANGLE);
2044             if (value != EGL_TRUE && value != EGL_FALSE)
2045             {
2046                 val->setError(EGL_BAD_ATTRIBUTE,
2047                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
2048                               "either EGL_TRUE or EGL_FALSE.");
2049                 return false;
2050             }
2051             break;
2052 
2053         case EGL_PROTECTED_CONTENT_EXT:
2054             ASSERT(displayExtensions.protectedContentEXT);
2055             if (value != EGL_TRUE && value != EGL_FALSE)
2056             {
2057                 val->setError(EGL_BAD_ATTRIBUTE,
2058                               "EGL_PROTECTED_CONTENT_EXT must "
2059                               "be either EGL_TRUE or EGL_FALSE.");
2060                 return false;
2061             }
2062             break;
2063 
2064         default:
2065             UNREACHABLE();
2066             return false;
2067     }
2068 
2069     return true;
2070 }
2071 }  // anonymous namespace
2072 
setError(EGLint error) const2073 void ValidationContext::setError(EGLint error) const
2074 {
2075     eglThread->setError(error, entryPoint, labeledObject, nullptr);
2076 }
2077 
setError(EGLint error,const char * message...) const2078 void ValidationContext::setError(EGLint error, const char *message...) const
2079 {
2080     ASSERT(message);
2081 
2082     constexpr uint32_t kBufferSize = 1000;
2083     char buffer[kBufferSize];
2084 
2085     va_list args;
2086     va_start(args, message);
2087     vsnprintf(buffer, kBufferSize, message, args);
2088 
2089     eglThread->setError(error, entryPoint, labeledObject, buffer);
2090 }
2091 
ValidateDisplay(const ValidationContext * val,const Display * display)2092 bool ValidateDisplay(const ValidationContext *val, const Display *display)
2093 {
2094     ANGLE_VALIDATION_TRY(ValidateDisplayPointer(val, display));
2095 
2096     if (!display->isInitialized())
2097     {
2098         if (val)
2099         {
2100             val->setError(EGL_NOT_INITIALIZED, "display is not initialized.");
2101         }
2102         return false;
2103     }
2104 
2105     if (display->isDeviceLost())
2106     {
2107         if (val)
2108         {
2109             val->setError(EGL_CONTEXT_LOST, "display had a context loss");
2110         }
2111         return false;
2112     }
2113 
2114     return true;
2115 }
2116 
ValidateSurface(const ValidationContext * val,const Display * display,const Surface * surface)2117 bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface)
2118 {
2119     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2120 
2121     if (!display->isValidSurface(surface))
2122     {
2123         if (val)
2124         {
2125             val->setError(EGL_BAD_SURFACE);
2126         }
2127         return false;
2128     }
2129 
2130     return true;
2131 }
2132 
ValidateConfig(const ValidationContext * val,const Display * display,const Config * config)2133 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config)
2134 {
2135     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2136 
2137     if (!display->isValidConfig(config))
2138     {
2139         if (val)
2140         {
2141             val->setError(EGL_BAD_CONFIG);
2142         }
2143         return false;
2144     }
2145 
2146     return true;
2147 }
2148 
ValidateContext(const ValidationContext * val,const Display * display,const gl::Context * context)2149 bool ValidateContext(const ValidationContext *val,
2150                      const Display *display,
2151                      const gl::Context *context)
2152 {
2153     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2154 
2155     if (!display->isValidContext(context))
2156     {
2157         if (val)
2158         {
2159             val->setError(EGL_BAD_CONTEXT);
2160         }
2161         return false;
2162     }
2163 
2164     return true;
2165 }
2166 
ValidateImage(const ValidationContext * val,const Display * display,const Image * image)2167 bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image)
2168 {
2169     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2170 
2171     if (!display->isValidImage(image))
2172     {
2173         if (val)
2174         {
2175             val->setError(EGL_BAD_PARAMETER, "image is not valid.");
2176         }
2177         return false;
2178     }
2179 
2180     return true;
2181 }
2182 
ValidateDevice(const ValidationContext * val,const Device * device)2183 bool ValidateDevice(const ValidationContext *val, const Device *device)
2184 {
2185     if (device == EGL_NO_DEVICE_EXT)
2186     {
2187         if (val)
2188         {
2189             val->setError(EGL_BAD_ACCESS, "device is EGL_NO_DEVICE.");
2190         }
2191         return false;
2192     }
2193 
2194     if (!Device::IsValidDevice(device))
2195     {
2196         if (val)
2197         {
2198             val->setError(EGL_BAD_ACCESS, "device is not valid.");
2199         }
2200         return false;
2201     }
2202 
2203     return true;
2204 }
2205 
ValidateSync(const ValidationContext * val,const Display * display,const Sync * sync)2206 bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync)
2207 {
2208     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2209 
2210     if (!display->isValidSync(sync))
2211     {
2212         if (val)
2213         {
2214             val->setError(EGL_BAD_PARAMETER, "sync object is not valid.");
2215         }
2216         return false;
2217     }
2218 
2219     return true;
2220 }
2221 
GetThreadIfValid(const Thread * thread)2222 const Thread *GetThreadIfValid(const Thread *thread)
2223 {
2224     // Threads should always be valid
2225     return thread;
2226 }
2227 
GetDisplayIfValid(const Display * display)2228 const Display *GetDisplayIfValid(const Display *display)
2229 {
2230     return ValidateDisplay(nullptr, display) ? display : nullptr;
2231 }
2232 
GetSurfaceIfValid(const Display * display,const Surface * surface)2233 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
2234 {
2235     return ValidateSurface(nullptr, display, surface) ? surface : nullptr;
2236 }
2237 
GetImageIfValid(const Display * display,const Image * image)2238 const Image *GetImageIfValid(const Display *display, const Image *image)
2239 {
2240     return ValidateImage(nullptr, display, image) ? image : nullptr;
2241 }
2242 
GetStreamIfValid(const Display * display,const Stream * stream)2243 const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
2244 {
2245     return ValidateStream(nullptr, display, stream) ? stream : nullptr;
2246 }
2247 
GetContextIfValid(const Display * display,const gl::Context * context)2248 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
2249 {
2250     return ValidateContext(nullptr, display, context) ? context : nullptr;
2251 }
2252 
GetDeviceIfValid(const Device * device)2253 const Device *GetDeviceIfValid(const Device *device)
2254 {
2255     return ValidateDevice(nullptr, device) ? device : nullptr;
2256 }
2257 
GetSyncIfValid(const Display * display,const Sync * sync)2258 const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
2259 {
2260     return ValidateSync(nullptr, display, sync) ? sync : nullptr;
2261 }
2262 
GetLabeledObjectIfValid(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object)2263 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
2264                                        const Display *display,
2265                                        ObjectType objectType,
2266                                        EGLObjectKHR object)
2267 {
2268     if (objectType == ObjectType::Thread)
2269     {
2270         return thread;
2271     }
2272 
2273     LabeledObject *labeledObject = nullptr;
2274     if (ValidateLabeledObject(nullptr, display, objectType, object, &labeledObject))
2275     {
2276         return labeledObject;
2277     }
2278 
2279     return nullptr;
2280 }
2281 
ValidateInitialize(const ValidationContext * val,const Display * display,const EGLint * major,const EGLint * minor)2282 bool ValidateInitialize(const ValidationContext *val,
2283                         const Display *display,
2284                         const EGLint *major,
2285                         const EGLint *minor)
2286 {
2287     return ValidateDisplayPointer(val, display);
2288 }
2289 
ValidateTerminate(const ValidationContext * val,const Display * display)2290 bool ValidateTerminate(const ValidationContext *val, const Display *display)
2291 {
2292     return ValidateDisplayPointer(val, display);
2293 }
2294 
ValidateCreateContext(const ValidationContext * val,const Display * display,const Config * configuration,const gl::Context * shareContext,const AttributeMap & attributes)2295 bool ValidateCreateContext(const ValidationContext *val,
2296                            const Display *display,
2297                            const Config *configuration,
2298                            const gl::Context *shareContext,
2299                            const AttributeMap &attributes)
2300 {
2301     if (configuration)
2302     {
2303         ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
2304     }
2305     else
2306     {
2307         ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2308         const DisplayExtensions &displayExtensions = display->getExtensions();
2309         if (!displayExtensions.noConfigContext)
2310         {
2311             val->setError(EGL_BAD_CONFIG);
2312             return false;
2313         }
2314     }
2315 
2316     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreateContextAttribute));
2317 
2318     for (const auto &attributePair : attributes)
2319     {
2320         EGLAttrib attribute = attributePair.first;
2321         EGLAttrib value     = attributePair.second;
2322         ANGLE_VALIDATION_TRY(
2323             ValidateCreateContextAttributeValue(val, display, shareContext, attribute, value));
2324     }
2325 
2326     // Get the requested client version (default is 1) and check it is 2 or 3.
2327     EGLAttrib clientMajorVersion = attributes.get(EGL_CONTEXT_CLIENT_VERSION, 1);
2328     EGLAttrib clientMinorVersion = attributes.get(EGL_CONTEXT_MINOR_VERSION, 0);
2329 
2330     switch (clientMajorVersion)
2331     {
2332         case 1:
2333             if (clientMinorVersion != 0 && clientMinorVersion != 1)
2334             {
2335                 val->setError(EGL_BAD_ATTRIBUTE);
2336                 return false;
2337             }
2338             if (configuration == EGL_NO_CONFIG_KHR)
2339             {
2340                 val->setError(EGL_BAD_MATCH);
2341                 return false;
2342             }
2343             if ((configuration != EGL_NO_CONFIG_KHR) &&
2344                 !(configuration->renderableType & EGL_OPENGL_ES_BIT))
2345             {
2346                 val->setError(EGL_BAD_MATCH);
2347                 return false;
2348             }
2349             break;
2350 
2351         case 2:
2352             if (clientMinorVersion != 0)
2353             {
2354                 val->setError(EGL_BAD_ATTRIBUTE);
2355                 return false;
2356             }
2357             if ((configuration != EGL_NO_CONFIG_KHR) &&
2358                 !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
2359             {
2360                 val->setError(EGL_BAD_MATCH);
2361                 return false;
2362             }
2363             break;
2364         case 3:
2365             if (clientMinorVersion < 0 || clientMinorVersion > 2)
2366             {
2367                 val->setError(EGL_BAD_ATTRIBUTE);
2368                 return false;
2369             }
2370             if ((configuration != EGL_NO_CONFIG_KHR) &&
2371                 !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
2372             {
2373                 val->setError(EGL_BAD_MATCH);
2374                 return false;
2375             }
2376             if (display->getMaxSupportedESVersion() <
2377                 gl::Version(static_cast<GLuint>(clientMajorVersion),
2378                             static_cast<GLuint>(clientMinorVersion)))
2379             {
2380                 gl::Version max = display->getMaxSupportedESVersion();
2381                 val->setError(EGL_BAD_ATTRIBUTE,
2382                               "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
2383                               ") is greater than "
2384                               "max supported (%d, %d).",
2385                               clientMajorVersion, clientMinorVersion, max.major, max.minor);
2386                 return false;
2387             }
2388             if ((attributes.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) == EGL_TRUE) &&
2389                 (clientMinorVersion > 1))
2390             {
2391                 val->setError(EGL_BAD_ATTRIBUTE,
2392                               "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
2393                               ") is greater than "
2394                               "max supported 3.1 for WebGL.",
2395                               clientMajorVersion, clientMinorVersion);
2396                 return false;
2397             }
2398             break;
2399         default:
2400             val->setError(EGL_BAD_ATTRIBUTE);
2401             return false;
2402     }
2403 
2404     if (shareContext)
2405     {
2406         // Shared context is invalid or is owned by another display
2407         if (!display->isValidContext(shareContext))
2408         {
2409             val->setError(EGL_BAD_MATCH);
2410             return false;
2411         }
2412     }
2413 
2414     return true;
2415 }
2416 
ValidateCreateWindowSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativeWindowType window,const AttributeMap & attributes)2417 bool ValidateCreateWindowSurface(const ValidationContext *val,
2418                                  const Display *display,
2419                                  const Config *config,
2420                                  EGLNativeWindowType window,
2421                                  const AttributeMap &attributes)
2422 {
2423     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2424 
2425     if (!display->isValidNativeWindow(window))
2426     {
2427         val->setError(EGL_BAD_NATIVE_WINDOW);
2428         return false;
2429     }
2430 
2431     const DisplayExtensions &displayExtensions = display->getExtensions();
2432 
2433     attributes.initializeWithoutValidation();
2434 
2435     for (const auto &attributeIter : attributes)
2436     {
2437         EGLAttrib attribute = attributeIter.first;
2438         EGLAttrib value     = attributeIter.second;
2439 
2440         switch (attribute)
2441         {
2442             case EGL_RENDER_BUFFER:
2443                 switch (value)
2444                 {
2445                     case EGL_BACK_BUFFER:
2446                         break;
2447                     case EGL_SINGLE_BUFFER:
2448                         val->setError(EGL_BAD_MATCH);
2449                         return false;  // Rendering directly to front buffer not supported
2450                     default:
2451                         val->setError(EGL_BAD_ATTRIBUTE);
2452                         return false;
2453                 }
2454                 break;
2455 
2456             case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
2457                 if (!displayExtensions.postSubBuffer)
2458                 {
2459                     val->setError(EGL_BAD_ATTRIBUTE);
2460                     return false;
2461                 }
2462                 break;
2463 
2464             case EGL_WIDTH:
2465             case EGL_HEIGHT:
2466                 if (!displayExtensions.windowFixedSize)
2467                 {
2468                     val->setError(EGL_BAD_ATTRIBUTE);
2469                     return false;
2470                 }
2471                 if (value < 0)
2472                 {
2473                     val->setError(EGL_BAD_PARAMETER);
2474                     return false;
2475                 }
2476                 break;
2477 
2478             case EGL_FIXED_SIZE_ANGLE:
2479                 if (!displayExtensions.windowFixedSize)
2480                 {
2481                     val->setError(EGL_BAD_ATTRIBUTE);
2482                     return false;
2483                 }
2484                 break;
2485 
2486             case EGL_SURFACE_ORIENTATION_ANGLE:
2487                 if (!displayExtensions.surfaceOrientation)
2488                 {
2489                     val->setError(EGL_BAD_ATTRIBUTE,
2490                                   "EGL_ANGLE_surface_orientation is not enabled.");
2491                     return false;
2492                 }
2493                 break;
2494 
2495             case EGL_VG_COLORSPACE:
2496                 val->setError(EGL_BAD_MATCH);
2497                 return false;
2498 
2499             case EGL_GL_COLORSPACE:
2500                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2501                 break;
2502 
2503             case EGL_VG_ALPHA_FORMAT:
2504                 val->setError(EGL_BAD_MATCH);
2505                 return false;
2506 
2507             case EGL_DIRECT_COMPOSITION_ANGLE:
2508                 if (!displayExtensions.directComposition)
2509                 {
2510                     val->setError(EGL_BAD_ATTRIBUTE);
2511                     return false;
2512                 }
2513                 break;
2514 
2515             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
2516                 if (!display->getExtensions().robustResourceInitializationANGLE)
2517                 {
2518                     val->setError(EGL_BAD_ATTRIBUTE,
2519                                   "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
2520                                   "requires EGL_ANGLE_robust_resource_initialization.");
2521                     return false;
2522                 }
2523                 if (value != EGL_TRUE && value != EGL_FALSE)
2524                 {
2525                     val->setError(EGL_BAD_ATTRIBUTE,
2526                                   "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
2527                                   "either EGL_TRUE or EGL_FALSE.");
2528                     return false;
2529                 }
2530                 break;
2531 
2532             case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
2533                 if (!display->getExtensions().ggpStreamDescriptor)
2534                 {
2535                     val->setError(EGL_BAD_ATTRIBUTE,
2536                                   "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
2537                                   "EGL_ANGLE_ggp_stream_descriptor.");
2538                     return false;
2539                 }
2540                 break;
2541 
2542             case EGL_PROTECTED_CONTENT_EXT:
2543                 if (!displayExtensions.protectedContentEXT)
2544                 {
2545                     val->setError(EGL_BAD_ATTRIBUTE,
2546                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
2547                                   "extension EGL_EXT_protected_content.");
2548                     return false;
2549                 }
2550                 if (value != EGL_TRUE && value != EGL_FALSE)
2551                 {
2552                     val->setError(EGL_BAD_ATTRIBUTE,
2553                                   "EGL_PROTECTED_CONTENT_EXT must "
2554                                   "be either EGL_TRUE or EGL_FALSE.");
2555                     return false;
2556                 }
2557                 break;
2558 
2559             case EGL_SWAP_INTERVAL_ANGLE:
2560                 if (!displayExtensions.createSurfaceSwapIntervalANGLE)
2561                 {
2562                     val->setError(EGL_BAD_ATTRIBUTE,
2563                                   "Attribute EGL_SWAP_INTERVAL_ANGLE requires "
2564                                   "extension EGL_ANGLE_create_surface_swap_interval.");
2565                     return false;
2566                 }
2567                 if (value < config->minSwapInterval || value > config->maxSwapInterval)
2568                 {
2569                     val->setError(EGL_BAD_ATTRIBUTE,
2570                                   "EGL_SWAP_INTERVAL_ANGLE must "
2571                                   "be within the EGLConfig min and max swap intervals.");
2572                     return false;
2573                 }
2574                 break;
2575 
2576             default:
2577                 val->setError(EGL_BAD_ATTRIBUTE);
2578                 return false;
2579         }
2580     }
2581 
2582     if ((config->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) != 0 &&
2583         !displayExtensions.mutableRenderBufferKHR)
2584     {
2585         val->setError(EGL_BAD_ATTRIBUTE,
2586                       "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR requires EGL_KHR_mutable_render_buffer.");
2587         return false;
2588     }
2589 
2590     if (Display::hasExistingWindowSurface(window))
2591     {
2592         val->setError(EGL_BAD_ALLOC);
2593         return false;
2594     }
2595 
2596     return true;
2597 }
2598 
ValidateCreatePbufferSurface(const ValidationContext * val,const Display * display,const Config * config,const AttributeMap & attributes)2599 bool ValidateCreatePbufferSurface(const ValidationContext *val,
2600                                   const Display *display,
2601                                   const Config *config,
2602                                   const AttributeMap &attributes)
2603 {
2604     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2605     ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreatePbufferSurfaceAttribute));
2606 
2607     for (const auto &attributeIter : attributes)
2608     {
2609         EGLAttrib attribute = attributeIter.first;
2610         EGLAttrib value     = attributeIter.second;
2611 
2612         ANGLE_VALIDATION_TRY(
2613             ValidateCreatePbufferSurfaceAttributeValue(val, display, attribute, value));
2614     }
2615 
2616     if ((config->surfaceType & EGL_PBUFFER_BIT) == 0)
2617     {
2618         val->setError(EGL_BAD_MATCH);
2619         return false;
2620     }
2621 
2622     const Caps &caps = display->getCaps();
2623 
2624     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2625     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2626 
2627     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2628         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2629     {
2630         val->setError(EGL_BAD_MATCH);
2631         return false;
2632     }
2633 
2634     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2635         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2636     {
2637         val->setError(EGL_BAD_ATTRIBUTE);
2638         return false;
2639     }
2640 
2641     EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2642     EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2643     if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2644         (!gl::isPow2(width) || !gl::isPow2(height)))
2645     {
2646         val->setError(EGL_BAD_MATCH);
2647         return false;
2648     }
2649 
2650     return true;
2651 }
2652 
ValidateCreatePbufferFromClientBuffer(const ValidationContext * val,const Display * display,EGLenum buftype,EGLClientBuffer buffer,const Config * config,const AttributeMap & attributes)2653 bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
2654                                            const Display *display,
2655                                            EGLenum buftype,
2656                                            EGLClientBuffer buffer,
2657                                            const Config *config,
2658                                            const AttributeMap &attributes)
2659 {
2660     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2661 
2662     const DisplayExtensions &displayExtensions = display->getExtensions();
2663 
2664     attributes.initializeWithoutValidation();
2665 
2666     switch (buftype)
2667     {
2668         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
2669             if (!displayExtensions.d3dShareHandleClientBuffer)
2670             {
2671                 val->setError(EGL_BAD_PARAMETER);
2672                 return false;
2673             }
2674             if (buffer == nullptr)
2675             {
2676                 val->setError(EGL_BAD_PARAMETER);
2677                 return false;
2678             }
2679             break;
2680 
2681         case EGL_D3D_TEXTURE_ANGLE:
2682             if (!displayExtensions.d3dTextureClientBuffer)
2683             {
2684                 val->setError(EGL_BAD_PARAMETER);
2685                 return false;
2686             }
2687             if (buffer == nullptr)
2688             {
2689                 val->setError(EGL_BAD_PARAMETER);
2690                 return false;
2691             }
2692             break;
2693 
2694         case EGL_IOSURFACE_ANGLE:
2695             if (!displayExtensions.iosurfaceClientBuffer)
2696             {
2697                 val->setError(EGL_BAD_PARAMETER,
2698                               "<buftype> EGL_IOSURFACE_ANGLE requires the "
2699                               "EGL_ANGLE_iosurface_client_buffer extension.");
2700                 return false;
2701             }
2702             if (buffer == nullptr)
2703             {
2704                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be non null");
2705                 return false;
2706             }
2707             break;
2708         case EGL_EXTERNAL_SURFACE_ANGLE:
2709             if (!display->getExtensions().externalContextAndSurface)
2710             {
2711                 val->setError(EGL_BAD_ATTRIBUTE,
2712                               "Attribute "
2713                               "EGL_EXTERNAL_SURFACE_ANGLE requires "
2714                               "EGL_ANGLE_external_context_and_surface.");
2715                 return false;
2716             }
2717             if (buffer != nullptr)
2718             {
2719                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
2720                 return false;
2721             }
2722             break;
2723 
2724         default:
2725             val->setError(EGL_BAD_PARAMETER);
2726             return false;
2727     }
2728 
2729     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2730          attributeIter != attributes.end(); attributeIter++)
2731     {
2732         EGLAttrib attribute = attributeIter->first;
2733         EGLAttrib value     = attributeIter->second;
2734 
2735         switch (attribute)
2736         {
2737             case EGL_WIDTH:
2738             case EGL_HEIGHT:
2739                 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
2740                     buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
2741                     buftype != EGL_EXTERNAL_SURFACE_ANGLE)
2742                 {
2743                     val->setError(EGL_BAD_PARAMETER,
2744                                   "Width and Height are not supported for this <buftype>");
2745                     return false;
2746                 }
2747                 if (value < 0)
2748                 {
2749                     val->setError(EGL_BAD_PARAMETER, "Width and Height must be positive");
2750                     return false;
2751                 }
2752                 break;
2753 
2754             case EGL_TEXTURE_FORMAT:
2755                 switch (value)
2756                 {
2757                     case EGL_NO_TEXTURE:
2758                     case EGL_TEXTURE_RGB:
2759                     case EGL_TEXTURE_RGBA:
2760                         break;
2761                     default:
2762                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_FORMAT");
2763                         return false;
2764                 }
2765                 break;
2766 
2767             case EGL_TEXTURE_TARGET:
2768                 switch (value)
2769                 {
2770                     case EGL_NO_TEXTURE:
2771                     case EGL_TEXTURE_2D:
2772                         break;
2773                     case EGL_TEXTURE_RECTANGLE_ANGLE:
2774                         if (buftype != EGL_IOSURFACE_ANGLE)
2775                         {
2776                             val->setError(EGL_BAD_PARAMETER,
2777                                           "<buftype> doesn't support rectangle texture targets");
2778                             return false;
2779                         }
2780                         break;
2781 
2782                     default:
2783                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_TARGET");
2784                         return false;
2785                 }
2786                 break;
2787 
2788             case EGL_MIPMAP_TEXTURE:
2789                 break;
2790 
2791             case EGL_IOSURFACE_PLANE_ANGLE:
2792                 if (buftype != EGL_IOSURFACE_ANGLE)
2793                 {
2794                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support iosurface plane");
2795                     return false;
2796                 }
2797                 break;
2798 
2799             case EGL_TEXTURE_TYPE_ANGLE:
2800                 if (buftype != EGL_IOSURFACE_ANGLE)
2801                 {
2802                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support texture type");
2803                     return false;
2804                 }
2805                 break;
2806 
2807             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2808                 if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
2809                 {
2810                     val->setError(EGL_BAD_ATTRIBUTE,
2811                                   "<buftype> doesn't support texture internal format");
2812                     return false;
2813                 }
2814                 break;
2815 
2816             case EGL_GL_COLORSPACE:
2817                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2818                 {
2819                     val->setError(EGL_BAD_ATTRIBUTE,
2820                                   "<buftype> doesn't support setting GL colorspace");
2821                     return false;
2822                 }
2823                 break;
2824 
2825             case EGL_IOSURFACE_USAGE_HINT_ANGLE:
2826                 if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
2827                 {
2828                     val->setError(EGL_BAD_ATTRIBUTE,
2829                                   "IOSurface usage hint must only contain READ or WRITE");
2830                     return false;
2831                 }
2832                 break;
2833 
2834             case EGL_TEXTURE_OFFSET_X_ANGLE:
2835             case EGL_TEXTURE_OFFSET_Y_ANGLE:
2836                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2837                 {
2838                     val->setError(EGL_BAD_ATTRIBUTE,
2839                                   "<buftype> doesn't support setting texture offset");
2840                     return false;
2841                 }
2842                 if (value < 0)
2843                 {
2844                     val->setError(EGL_BAD_ATTRIBUTE, "Texture offset cannot be negative");
2845                     return false;
2846                 }
2847                 break;
2848 
2849             case EGL_PROTECTED_CONTENT_EXT:
2850                 if (!displayExtensions.protectedContentEXT)
2851                 {
2852                     val->setError(EGL_BAD_ATTRIBUTE,
2853                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
2854                                   "extension EGL_EXT_protected_content.");
2855                     return false;
2856                 }
2857                 if (value != EGL_TRUE && value != EGL_FALSE)
2858                 {
2859                     val->setError(EGL_BAD_ATTRIBUTE,
2860                                   "EGL_PROTECTED_CONTENT_EXT must "
2861                                   "be either EGL_TRUE or EGL_FALSE.");
2862                     return false;
2863                 }
2864                 break;
2865 
2866             default:
2867                 val->setError(EGL_BAD_ATTRIBUTE);
2868                 return false;
2869         }
2870     }
2871 
2872     EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
2873     if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
2874     {
2875         val->setError(EGL_BAD_ATTRIBUTE, "invalid GL colorspace");
2876         return false;
2877     }
2878 
2879     if (!(config->surfaceType & EGL_PBUFFER_BIT))
2880     {
2881         val->setError(EGL_BAD_MATCH);
2882         return false;
2883     }
2884 
2885     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2886     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2887     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2888         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2889     {
2890         val->setError(EGL_BAD_MATCH);
2891         return false;
2892     }
2893     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2894         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2895     {
2896         // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
2897         // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
2898         // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
2899         // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
2900         // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
2901         // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
2902         // OSX?
2903         if (buftype != EGL_IOSURFACE_ANGLE)
2904         {
2905             val->setError(EGL_BAD_ATTRIBUTE);
2906             return false;
2907         }
2908     }
2909 
2910     if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
2911     {
2912         EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2913         EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2914 
2915         if (width == 0 || height == 0)
2916         {
2917             val->setError(EGL_BAD_ATTRIBUTE);
2918             return false;
2919         }
2920 
2921         const Caps &caps = display->getCaps();
2922         if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2923             (!gl::isPow2(width) || !gl::isPow2(height)))
2924         {
2925             val->setError(EGL_BAD_MATCH);
2926             return false;
2927         }
2928     }
2929 
2930     if (buftype == EGL_IOSURFACE_ANGLE)
2931     {
2932         if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
2933         {
2934             val->setError(EGL_BAD_ATTRIBUTE,
2935                           "EGL_IOSURFACE requires the texture target to match the config");
2936             return false;
2937         }
2938         if (textureFormat != EGL_TEXTURE_RGBA)
2939         {
2940             val->setError(EGL_BAD_ATTRIBUTE, "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format");
2941             return false;
2942         }
2943 
2944         if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
2945             !attributes.contains(EGL_TEXTURE_FORMAT) ||
2946             !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
2947             !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
2948             !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
2949         {
2950             val->setError(EGL_BAD_PARAMETER, "Missing required attribute for EGL_IOSURFACE");
2951             return false;
2952         }
2953     }
2954 
2955     ANGLE_EGL_TRY_RETURN(val->eglThread,
2956                          display->validateClientBuffer(config, buftype, buffer, attributes),
2957                          val->entryPoint, val->labeledObject, false);
2958 
2959     return true;
2960 }
2961 
ValidateCreatePixmapSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes)2962 bool ValidateCreatePixmapSurface(const ValidationContext *val,
2963                                  const Display *display,
2964                                  const Config *config,
2965                                  EGLNativePixmapType pixmap,
2966                                  const AttributeMap &attributes)
2967 {
2968     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2969 
2970     const DisplayExtensions &displayExtensions = display->getExtensions();
2971 
2972     attributes.initializeWithoutValidation();
2973 
2974     for (const auto &attributePair : attributes)
2975     {
2976         EGLAttrib attribute = attributePair.first;
2977         EGLAttrib value     = attributePair.second;
2978 
2979         switch (attribute)
2980         {
2981             case EGL_GL_COLORSPACE:
2982                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2983                 break;
2984 
2985             case EGL_VG_COLORSPACE:
2986                 break;
2987             case EGL_VG_ALPHA_FORMAT:
2988                 break;
2989 
2990             case EGL_TEXTURE_FORMAT:
2991                 if (!displayExtensions.textureFromPixmapNOK)
2992                 {
2993                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2994                     return false;
2995                 }
2996                 switch (value)
2997                 {
2998                     case EGL_NO_TEXTURE:
2999                     case EGL_TEXTURE_RGB:
3000                     case EGL_TEXTURE_RGBA:
3001                         break;
3002                     default:
3003                         val->setError(EGL_BAD_ATTRIBUTE);
3004                         return false;
3005                 }
3006                 break;
3007 
3008             case EGL_TEXTURE_TARGET:
3009                 if (!displayExtensions.textureFromPixmapNOK)
3010                 {
3011                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
3012                     return false;
3013                 }
3014                 switch (value)
3015                 {
3016                     case EGL_NO_TEXTURE:
3017                     case EGL_TEXTURE_2D:
3018                         break;
3019                     default:
3020                         val->setError(EGL_BAD_ATTRIBUTE);
3021                         return false;
3022                 }
3023                 break;
3024 
3025             case EGL_MIPMAP_TEXTURE:
3026                 if (!displayExtensions.textureFromPixmapNOK)
3027                 {
3028                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
3029                     return false;
3030                 }
3031                 break;
3032 
3033             case EGL_PROTECTED_CONTENT_EXT:
3034                 if (!displayExtensions.protectedContentEXT)
3035                 {
3036                     val->setError(EGL_BAD_ATTRIBUTE,
3037                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
3038                                   "extension EGL_EXT_protected_content.");
3039                     return false;
3040                 }
3041                 if (value != EGL_TRUE && value != EGL_FALSE)
3042                 {
3043                     val->setError(EGL_BAD_ATTRIBUTE,
3044                                   "EGL_PROTECTED_CONTENT_EXT must "
3045                                   "be either EGL_TRUE or EGL_FALSE.");
3046                     return false;
3047                 }
3048                 break;
3049 
3050             default:
3051                 val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR, attribute);
3052                 return false;
3053         }
3054     }
3055 
3056     if (!(config->surfaceType & EGL_PIXMAP_BIT))
3057     {
3058         val->setError(EGL_BAD_MATCH, "Congfig does not suport pixmaps.");
3059         return false;
3060     }
3061 
3062     ANGLE_EGL_TRY_RETURN(val->eglThread, display->valdiatePixmap(config, pixmap, attributes),
3063                          val->entryPoint, val->labeledObject, false);
3064 
3065     return true;
3066 }
3067 
ValidateMakeCurrent(const ValidationContext * val,const Display * display,const Surface * draw,const Surface * read,const gl::Context * context)3068 bool ValidateMakeCurrent(const ValidationContext *val,
3069                          const Display *display,
3070                          const Surface *draw,
3071                          const Surface *read,
3072                          const gl::Context *context)
3073 {
3074     if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
3075     {
3076         val->setError(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
3077         return false;
3078     }
3079 
3080     // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
3081     // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
3082     if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
3083     {
3084         if (display->getExtensions().surfacelessContext)
3085         {
3086             if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
3087             {
3088                 val->setError(EGL_BAD_MATCH,
3089                               "If ctx is not EGL_NOT_CONTEXT, draw or read must "
3090                               "both be EGL_NO_SURFACE, or both not");
3091                 return false;
3092             }
3093         }
3094         else
3095         {
3096             val->setError(EGL_BAD_MATCH,
3097                           "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
3098             return false;
3099         }
3100     }
3101 
3102     // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
3103     // EGL_BAD_MATCH error is generated.
3104     if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
3105     {
3106         val->setError(EGL_BAD_MATCH,
3107                       "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
3108         return false;
3109     }
3110 
3111     if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
3112     {
3113         val->setError(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
3114         return false;
3115     }
3116 
3117     // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
3118     if (!display->isInitialized() &&
3119         (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
3120     {
3121         val->setError(EGL_NOT_INITIALIZED, "'dpy' not initialized");
3122         return false;
3123     }
3124 
3125     if (context != EGL_NO_CONTEXT)
3126     {
3127         ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3128     }
3129 
3130     if (display->isInitialized() && display->isDeviceLost())
3131     {
3132         val->setError(EGL_CONTEXT_LOST);
3133         return false;
3134     }
3135 
3136     if (draw != EGL_NO_SURFACE)
3137     {
3138         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, draw));
3139     }
3140 
3141     if (read != EGL_NO_SURFACE)
3142     {
3143         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, read));
3144         ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
3145     }
3146 
3147     if (draw != read)
3148     {
3149         if (draw)
3150         {
3151             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, draw));
3152         }
3153         if (read)
3154         {
3155             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
3156         }
3157     }
3158     return true;
3159 }
3160 
ValidateCreateImage(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)3161 bool ValidateCreateImage(const ValidationContext *val,
3162                          const Display *display,
3163                          const gl::Context *context,
3164                          EGLenum target,
3165                          EGLClientBuffer buffer,
3166                          const AttributeMap &attributes)
3167 {
3168 
3169     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3170 
3171     attributes.initializeWithoutValidation();
3172 
3173     const DisplayExtensions &displayExtensions = display->getExtensions();
3174 
3175     // TODO(geofflang): Complete validation from EGL_KHR_image_base:
3176     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
3177     // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
3178 
3179     for (AttributeMap::const_iterator attributeIter = attributes.begin();
3180          attributeIter != attributes.end(); attributeIter++)
3181     {
3182         EGLAttrib attribute = attributeIter->first;
3183         EGLAttrib value     = attributeIter->second;
3184 
3185         switch (attribute)
3186         {
3187             case EGL_IMAGE_PRESERVED:
3188                 switch (value)
3189                 {
3190                     case EGL_TRUE:
3191                     case EGL_FALSE:
3192                         break;
3193 
3194                     default:
3195                         val->setError(EGL_BAD_PARAMETER,
3196                                       "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.");
3197                         return false;
3198                 }
3199                 break;
3200 
3201             case EGL_GL_TEXTURE_LEVEL:
3202                 if (!displayExtensions.glTexture2DImage &&
3203                     !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
3204                 {
3205                     val->setError(EGL_BAD_PARAMETER,
3206                                   "EGL_GL_TEXTURE_LEVEL cannot be used "
3207                                   "without KHR_gl_texture_*_image support.");
3208                     return false;
3209                 }
3210 
3211                 if (value < 0)
3212                 {
3213                     val->setError(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL cannot be negative.");
3214                     return false;
3215                 }
3216                 break;
3217 
3218             case EGL_GL_TEXTURE_ZOFFSET:
3219                 if (!displayExtensions.glTexture3DImage)
3220                 {
3221                     val->setError(EGL_BAD_PARAMETER,
3222                                   "EGL_GL_TEXTURE_ZOFFSET cannot be used "
3223                                   "without KHR_gl_texture_3D_image support.");
3224                     return false;
3225                 }
3226                 break;
3227 
3228             case EGL_GL_COLORSPACE:
3229                 if (!displayExtensions.glColorspace)
3230                 {
3231                     val->setError(EGL_BAD_PARAMETER,
3232                                   "EGL_GL_COLORSPACE cannot be used "
3233                                   "without EGL_KHR_gl_colorspace support.");
3234                     return false;
3235                 }
3236                 switch (value)
3237                 {
3238                     case EGL_GL_COLORSPACE_DEFAULT_EXT:
3239                         break;
3240                     default:
3241                         ANGLE_VALIDATION_TRY(
3242                             ValidateColorspaceAttribute(val, displayExtensions, value));
3243                         break;
3244                 }
3245                 break;
3246 
3247             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
3248                 if (!displayExtensions.imageD3D11Texture && !displayExtensions.vulkanImageANGLE)
3249                 {
3250                     val->setError(
3251                         EGL_BAD_PARAMETER,
3252                         "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE cannot be used without "
3253                         "EGL_ANGLE_image_d3d11_texture or EGL_ANGLE_vulkan_image support.");
3254                     return false;
3255                 }
3256                 break;
3257 
3258             case EGL_D3D11_TEXTURE_PLANE_ANGLE:
3259                 if (!displayExtensions.imageD3D11Texture)
3260                 {
3261                     val->setError(EGL_BAD_ATTRIBUTE,
3262                                   "EGL_D3D11_TEXTURE_PLANE_ANGLE cannot be used without "
3263                                   "EGL_ANGLE_image_d3d11_texture support.");
3264                     return false;
3265                 }
3266                 break;
3267 
3268             case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
3269                 if (!displayExtensions.imageD3D11Texture)
3270                 {
3271                     val->setError(EGL_BAD_ATTRIBUTE,
3272                                   "EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
3273                                   "EGL_ANGLE_image_d3d11_texture support.");
3274                     return false;
3275                 }
3276                 break;
3277 
3278             case EGL_WIDTH:
3279             case EGL_HEIGHT:
3280                 if (target != EGL_LINUX_DMA_BUF_EXT)
3281                 {
3282                     val->setError(
3283                         EGL_BAD_PARAMETER,
3284                         "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT");
3285                     return false;
3286                 }
3287                 break;
3288 
3289             case EGL_LINUX_DRM_FOURCC_EXT:
3290             case EGL_DMA_BUF_PLANE0_FD_EXT:
3291             case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
3292             case EGL_DMA_BUF_PLANE0_PITCH_EXT:
3293             case EGL_DMA_BUF_PLANE1_FD_EXT:
3294             case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
3295             case EGL_DMA_BUF_PLANE1_PITCH_EXT:
3296             case EGL_DMA_BUF_PLANE2_FD_EXT:
3297             case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
3298             case EGL_DMA_BUF_PLANE2_PITCH_EXT:
3299                 if (!displayExtensions.imageDmaBufImportEXT)
3300                 {
3301                     val->setError(EGL_BAD_PARAMETER,
3302                                   "Parameter cannot be used without "
3303                                   "EGL_EXT_image_dma_buf_import support.");
3304                     return false;
3305                 }
3306                 break;
3307 
3308             case EGL_YUV_COLOR_SPACE_HINT_EXT:
3309                 if (!displayExtensions.imageDmaBufImportEXT)
3310                 {
3311                     val->setError(EGL_BAD_PARAMETER,
3312                                   "Parameter cannot be used without "
3313                                   "EGL_EXT_image_dma_buf_import support.");
3314                     return false;
3315                 }
3316 
3317                 switch (value)
3318                 {
3319                     case EGL_ITU_REC601_EXT:
3320                     case EGL_ITU_REC709_EXT:
3321                     case EGL_ITU_REC2020_EXT:
3322                         break;
3323 
3324                     default:
3325                         val->setError(EGL_BAD_PARAMETER,
3326                                       "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.");
3327                         return false;
3328                 }
3329                 break;
3330 
3331             case EGL_SAMPLE_RANGE_HINT_EXT:
3332                 if (!displayExtensions.imageDmaBufImportEXT)
3333                 {
3334                     val->setError(EGL_BAD_PARAMETER,
3335                                   "Parameter cannot be used without "
3336                                   "EGL_EXT_image_dma_buf_import support.");
3337                     return false;
3338                 }
3339 
3340                 switch (value)
3341                 {
3342                     case EGL_YUV_FULL_RANGE_EXT:
3343                     case EGL_YUV_NARROW_RANGE_EXT:
3344                         break;
3345 
3346                     default:
3347                         val->setError(EGL_BAD_PARAMETER,
3348                                       "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.");
3349                         return false;
3350                 }
3351                 break;
3352 
3353             case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
3354             case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
3355                 if (!displayExtensions.imageDmaBufImportEXT)
3356                 {
3357                     val->setError(EGL_BAD_PARAMETER,
3358                                   "Parameter cannot be used without "
3359                                   "EGL_EXT_image_dma_buf_import support.");
3360                     return false;
3361                 }
3362 
3363                 switch (value)
3364                 {
3365                     case EGL_YUV_CHROMA_SITING_0_EXT:
3366                     case EGL_YUV_CHROMA_SITING_0_5_EXT:
3367                         break;
3368 
3369                     default:
3370                         val->setError(
3371                             EGL_BAD_PARAMETER,
3372                             "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
3373                             "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.");
3374                         return false;
3375                 }
3376                 break;
3377 
3378             case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
3379             case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
3380             case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
3381             case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
3382             case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
3383             case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
3384             case EGL_DMA_BUF_PLANE3_FD_EXT:
3385             case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
3386             case EGL_DMA_BUF_PLANE3_PITCH_EXT:
3387             case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
3388             case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
3389                 if (!displayExtensions.imageDmaBufImportModifiersEXT)
3390                 {
3391                     val->setError(EGL_BAD_PARAMETER,
3392                                   "Parameter cannot be used without "
3393                                   "EGL_EXT_image_dma_buf_import_modifiers support.");
3394                     return false;
3395                 }
3396                 break;
3397 
3398             case EGL_PROTECTED_CONTENT_EXT:
3399                 if (!displayExtensions.protectedContentEXT)
3400                 {
3401                     val->setError(EGL_BAD_ATTRIBUTE,
3402                                   "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
3403                                   "extension EGL_EXT_protected_content.");
3404                     return false;
3405                 }
3406                 if (value != EGL_TRUE && value != EGL_FALSE)
3407                 {
3408                     val->setError(EGL_BAD_ATTRIBUTE,
3409                                   "EGL_PROTECTED_CONTENT_EXT must "
3410                                   "be either EGL_TRUE or EGL_FALSE.");
3411                     return false;
3412                 }
3413                 break;
3414 
3415             case EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE:
3416             case EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE:
3417                 if (!displayExtensions.vulkanImageANGLE)
3418                 {
3419                     val->setError(EGL_BAD_ATTRIBUTE,
3420                                   "Attribute EGL_VULKAN_IMAGE_CREATE_INFO_{HI,LO}_ANGLE require "
3421                                   "extension EGL_ANGLE_vulkan_image.");
3422                     return false;
3423                 }
3424                 break;
3425 
3426             default:
3427                 val->setError(EGL_BAD_PARAMETER, "invalid attribute: 0x%04" PRIxPTR "X", attribute);
3428                 return false;
3429         }
3430     }
3431 
3432     switch (target)
3433     {
3434         case EGL_GL_TEXTURE_2D:
3435         {
3436             if (!displayExtensions.glTexture2DImage)
3437             {
3438                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
3439                 return false;
3440             }
3441 
3442             if (buffer == 0)
3443             {
3444                 val->setError(EGL_BAD_PARAMETER,
3445                               "buffer cannot reference a 2D texture with the name 0.");
3446                 return false;
3447             }
3448 
3449             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3450             const gl::Texture *texture =
3451                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3452             if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
3453             {
3454                 val->setError(EGL_BAD_PARAMETER, "target is not a 2D texture.");
3455                 return false;
3456             }
3457 
3458             if (texture->getBoundSurface() != nullptr)
3459             {
3460                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3461                 return false;
3462             }
3463 
3464             EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3465             if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
3466                 texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
3467             {
3468                 val->setError(EGL_BAD_PARAMETER,
3469                               "target 2D texture does not have a valid size at specified level.");
3470                 return false;
3471             }
3472 
3473             bool protectedContentAttrib =
3474                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3475             if (protectedContentAttrib != texture->hasProtectedContent())
3476             {
3477                 val->setError(EGL_BAD_PARAMETER,
3478                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3479                               "of target.");
3480                 return false;
3481             }
3482 
3483             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3484         }
3485         break;
3486 
3487         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3488         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3489         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3490         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3491         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3492         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3493         {
3494             if (!displayExtensions.glTextureCubemapImage)
3495             {
3496                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
3497                 return false;
3498             }
3499 
3500             if (buffer == 0)
3501             {
3502                 val->setError(EGL_BAD_PARAMETER,
3503                               "buffer cannot reference a cubemap texture with the name 0.");
3504                 return false;
3505             }
3506 
3507             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3508             const gl::Texture *texture =
3509                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3510             if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
3511             {
3512                 val->setError(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
3513                 return false;
3514             }
3515 
3516             if (texture->getBoundSurface() != nullptr)
3517             {
3518                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3519                 return false;
3520             }
3521 
3522             EGLAttrib level               = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3523             gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
3524             if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
3525                 texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
3526             {
3527                 val->setError(EGL_BAD_PARAMETER,
3528                               "target cubemap texture does not have a valid "
3529                               "size at specified level and face.");
3530                 return false;
3531             }
3532 
3533             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3534 
3535             if (level == 0 && !texture->isMipmapComplete() &&
3536                 CubeTextureHasUnspecifiedLevel0Face(texture))
3537             {
3538                 val->setError(EGL_BAD_PARAMETER,
3539                               "if level is zero and the texture is incomplete, "
3540                               "it must have all of its faces specified at level "
3541                               "zero.");
3542                 return false;
3543             }
3544 
3545             bool protectedContentAttrib =
3546                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3547             if (protectedContentAttrib != texture->hasProtectedContent())
3548             {
3549                 val->setError(EGL_BAD_PARAMETER,
3550                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3551                               "of target.");
3552                 return false;
3553             }
3554         }
3555         break;
3556 
3557         case EGL_GL_TEXTURE_3D:
3558         {
3559             if (!displayExtensions.glTexture3DImage)
3560             {
3561                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
3562                 return false;
3563             }
3564 
3565             if (buffer == 0)
3566             {
3567                 val->setError(EGL_BAD_PARAMETER,
3568                               "buffer cannot reference a 3D texture with the name 0.");
3569                 return false;
3570             }
3571 
3572             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3573             const gl::Texture *texture =
3574                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3575             if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
3576             {
3577                 val->setError(EGL_BAD_PARAMETER, "target is not a 3D texture.");
3578                 return false;
3579             }
3580 
3581             if (texture->getBoundSurface() != nullptr)
3582             {
3583                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3584                 return false;
3585             }
3586 
3587             EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3588             EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
3589             if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3590                 texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3591                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
3592             {
3593                 val->setError(EGL_BAD_PARAMETER,
3594                               "target 3D texture does not have a valid size at specified level.");
3595                 return false;
3596             }
3597 
3598             if (static_cast<size_t>(zOffset) >=
3599                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
3600             {
3601                 val->setError(EGL_BAD_PARAMETER,
3602                               "target 3D texture does not have enough layers "
3603                               "for the specified Z offset at the specified "
3604                               "level.");
3605                 return false;
3606             }
3607 
3608             bool protectedContentAttrib =
3609                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3610             if (protectedContentAttrib != texture->hasProtectedContent())
3611             {
3612                 val->setError(EGL_BAD_PARAMETER,
3613                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3614                               "of target.");
3615                 return false;
3616             }
3617 
3618             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3619         }
3620         break;
3621 
3622         case EGL_GL_RENDERBUFFER:
3623         {
3624             if (!displayExtensions.glRenderbufferImage)
3625             {
3626                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
3627                 return false;
3628             }
3629 
3630             if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
3631             {
3632                 val->setError(EGL_BAD_PARAMETER,
3633                               "EGL_GL_TEXTURE_LEVEL cannot be used in "
3634                               "conjunction with a renderbuffer target.");
3635                 return false;
3636             }
3637 
3638             if (buffer == 0)
3639             {
3640                 val->setError(EGL_BAD_PARAMETER,
3641                               "buffer cannot reference a renderbuffer with the name 0.");
3642                 return false;
3643             }
3644 
3645             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3646             const gl::Renderbuffer *renderbuffer =
3647                 context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3648             if (renderbuffer == nullptr)
3649             {
3650                 val->setError(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
3651                 return false;
3652             }
3653 
3654             if (renderbuffer->getSamples() > 0)
3655             {
3656                 val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
3657                 return false;
3658             }
3659 
3660             bool protectedContentAttrib =
3661                 (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
3662             if (protectedContentAttrib != renderbuffer->hasProtectedContent())
3663             {
3664                 val->setError(EGL_BAD_ACCESS,
3665                               "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
3666                               "of target.");
3667                 return false;
3668             }
3669         }
3670         break;
3671 
3672         case EGL_NATIVE_BUFFER_ANDROID:
3673         {
3674             if (!displayExtensions.imageNativeBuffer)
3675             {
3676                 val->setError(EGL_BAD_PARAMETER, "EGL_ANDROID_image_native_buffer not supported.");
3677                 return false;
3678             }
3679 
3680             if (context != nullptr)
3681             {
3682                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3683                 return false;
3684             }
3685 
3686             ANGLE_EGL_TRY_RETURN(
3687                 val->eglThread,
3688                 display->validateImageClientBuffer(context, target, buffer, attributes),
3689                 val->entryPoint, val->labeledObject, false);
3690         }
3691         break;
3692 
3693         case EGL_D3D11_TEXTURE_ANGLE:
3694             if (!displayExtensions.imageD3D11Texture)
3695             {
3696                 val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_image_d3d11_texture not supported.");
3697                 return false;
3698             }
3699 
3700             if (context != nullptr)
3701             {
3702                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3703                 return false;
3704             }
3705 
3706             ANGLE_EGL_TRY_RETURN(
3707                 val->eglThread,
3708                 display->validateImageClientBuffer(context, target, buffer, attributes),
3709                 val->entryPoint, val->labeledObject, false);
3710             break;
3711 
3712         case EGL_LINUX_DMA_BUF_EXT:
3713             if (!displayExtensions.imageDmaBufImportEXT)
3714             {
3715                 val->setError(EGL_BAD_PARAMETER, "EGL_EXT_image_dma_buf_import not supported.");
3716                 return false;
3717             }
3718 
3719             if (context != nullptr)
3720             {
3721                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3722                 return false;
3723             }
3724 
3725             if (buffer != nullptr)
3726             {
3727                 val->setError(EGL_BAD_PARAMETER, "buffer must be NULL.");
3728                 return false;
3729             }
3730 
3731             {
3732                 EGLenum kRequiredParameters[] = {EGL_WIDTH,
3733                                                  EGL_HEIGHT,
3734                                                  EGL_LINUX_DRM_FOURCC_EXT,
3735                                                  EGL_DMA_BUF_PLANE0_FD_EXT,
3736                                                  EGL_DMA_BUF_PLANE0_OFFSET_EXT,
3737                                                  EGL_DMA_BUF_PLANE0_PITCH_EXT};
3738                 for (EGLenum requiredParameter : kRequiredParameters)
3739                 {
3740                     if (!attributes.contains(requiredParameter))
3741                     {
3742                         val->setError(EGL_BAD_PARAMETER,
3743                                       "Missing required parameter 0x%X for image target "
3744                                       "EGL_LINUX_DMA_BUF_EXT.",
3745                                       requiredParameter);
3746                         return false;
3747                     }
3748                 }
3749 
3750                 bool containPlane0ModifierLo =
3751                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
3752                 bool containPlane0ModifierHi =
3753                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
3754                 bool containPlane1ModifierLo =
3755                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
3756                 bool containPlane1ModifierHi =
3757                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
3758                 bool containPlane2ModifierLo =
3759                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
3760                 bool containPlane2ModifierHi =
3761                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
3762                 bool containPlane3ModifierLo =
3763                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
3764                 bool containPlane3ModifierHi =
3765                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
3766                 if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
3767                     (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
3768                     (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
3769                     (containPlane3ModifierLo ^ containPlane3ModifierHi))
3770                 {
3771                     val->setError(
3772                         EGL_BAD_PARAMETER,
3773                         "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
3774                         "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.");
3775                     return false;
3776                 }
3777             }
3778             break;
3779 
3780         case EGL_METAL_TEXTURE_ANGLE:
3781             if (!displayExtensions.mtlTextureClientBuffer)
3782             {
3783                 val->setError(EGL_BAD_PARAMETER,
3784                               "EGL_ANGLE_metal_texture_client_buffer not supported.");
3785                 return false;
3786             }
3787 
3788             if (context != nullptr)
3789             {
3790                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3791                 return false;
3792             }
3793 
3794             ANGLE_EGL_TRY_RETURN(
3795                 val->eglThread,
3796                 display->validateImageClientBuffer(context, target, buffer, attributes),
3797                 val->entryPoint, val->labeledObject, false);
3798             break;
3799         case EGL_VULKAN_IMAGE_ANGLE:
3800             if (!displayExtensions.vulkanImageANGLE)
3801             {
3802                 val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_vulkan_image not supported.");
3803                 return false;
3804             }
3805 
3806             if (context != nullptr)
3807             {
3808                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3809                 return false;
3810             }
3811 
3812             {
3813                 const EGLenum kRequiredParameters[] = {
3814                     EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE,
3815                     EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE,
3816                 };
3817                 for (EGLenum requiredParameter : kRequiredParameters)
3818                 {
3819                     if (!attributes.contains(requiredParameter))
3820                     {
3821                         val->setError(EGL_BAD_PARAMETER,
3822                                       "Missing required parameter 0x%X for image target "
3823                                       "EGL_VULKAN_IMAGE_ANGLE.",
3824                                       requiredParameter);
3825                         return false;
3826                     }
3827                 }
3828             }
3829 
3830             ANGLE_EGL_TRY_RETURN(
3831                 val->eglThread,
3832                 display->validateImageClientBuffer(context, target, buffer, attributes),
3833                 val->entryPoint, val->labeledObject, false);
3834             break;
3835         default:
3836             val->setError(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
3837             return false;
3838     }
3839 
3840     if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
3841     {
3842         val->setError(EGL_BAD_PARAMETER,
3843                       "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.");
3844         return false;
3845     }
3846 
3847     return true;
3848 }
3849 
ValidateDestroyImage(const ValidationContext * val,const Display * display,const Image * image)3850 bool ValidateDestroyImage(const ValidationContext *val, const Display *display, const Image *image)
3851 {
3852     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3853 
3854     return true;
3855 }
3856 
ValidateCreateImageKHR(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)3857 bool ValidateCreateImageKHR(const ValidationContext *val,
3858                             const Display *display,
3859                             const gl::Context *context,
3860                             EGLenum target,
3861                             EGLClientBuffer buffer,
3862                             const AttributeMap &attributes)
3863 {
3864     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3865 
3866     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3867     {
3868         // It is out of spec what happens when calling an extension function when the extension is
3869         // not available.
3870         // EGL_BAD_DISPLAY seems like a reasonable error.
3871         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
3872         return false;
3873     }
3874 
3875     return ValidateCreateImage(val, display, context, target, buffer, attributes);
3876 }
3877 
ValidateDestroyImageKHR(const ValidationContext * val,const Display * display,const Image * image)3878 bool ValidateDestroyImageKHR(const ValidationContext *val,
3879                              const Display *display,
3880                              const Image *image)
3881 {
3882     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3883 
3884     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3885     {
3886         // It is out of spec what happens when calling an extension function when the extension is
3887         // not available.
3888         // EGL_BAD_DISPLAY seems like a reasonable error.
3889         val->setError(EGL_BAD_DISPLAY);
3890         return false;
3891     }
3892 
3893     return true;
3894 }
3895 
ValidateCreateDeviceANGLE(const ValidationContext * val,EGLint device_type,const void * native_device,const EGLAttrib * attrib_list)3896 bool ValidateCreateDeviceANGLE(const ValidationContext *val,
3897                                EGLint device_type,
3898                                const void *native_device,
3899                                const EGLAttrib *attrib_list)
3900 {
3901     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3902     if (!clientExtensions.deviceCreation)
3903     {
3904         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3905         return false;
3906     }
3907 
3908     if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
3909     {
3910         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
3911         return false;
3912     }
3913 
3914     switch (device_type)
3915     {
3916         case EGL_D3D11_DEVICE_ANGLE:
3917             if (!clientExtensions.deviceCreationD3D11)
3918             {
3919                 val->setError(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
3920                 return false;
3921             }
3922             break;
3923         default:
3924             val->setError(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
3925             return false;
3926     }
3927 
3928     return true;
3929 }
3930 
ValidateReleaseDeviceANGLE(const ValidationContext * val,const Device * device)3931 bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *device)
3932 {
3933     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3934     if (!clientExtensions.deviceCreation)
3935     {
3936         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3937         return false;
3938     }
3939 
3940     if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
3941     {
3942         val->setError(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
3943         return false;
3944     }
3945 
3946     Display *owningDisplay = device->getOwningDisplay();
3947     if (owningDisplay != nullptr)
3948     {
3949         val->setError(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
3950         return false;
3951     }
3952 
3953     return true;
3954 }
3955 
ValidateCreateSync(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3956 bool ValidateCreateSync(const ValidationContext *val,
3957                         const Display *display,
3958                         EGLenum type,
3959                         const AttributeMap &attribs)
3960 {
3961     return ValidateCreateSyncBase(val, display, type, attribs, false);
3962 }
3963 
ValidateCreateSyncKHR(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3964 bool ValidateCreateSyncKHR(const ValidationContext *val,
3965                            const Display *display,
3966                            EGLenum type,
3967                            const AttributeMap &attribs)
3968 {
3969     return ValidateCreateSyncBase(val, display, type, attribs, true);
3970 }
3971 
ValidateDestroySync(const ValidationContext * val,const Display * display,const Sync * sync)3972 bool ValidateDestroySync(const ValidationContext *val, const Display *display, const Sync *sync)
3973 {
3974     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3975     return true;
3976 }
3977 
ValidateDestroySyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked)3978 bool ValidateDestroySyncKHR(const ValidationContext *val,
3979                             const Display *dpyPacked,
3980                             const Sync *syncPacked)
3981 {
3982     return ValidateDestroySync(val, dpyPacked, syncPacked);
3983 }
3984 
ValidateClientWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags,EGLTime timeout)3985 bool ValidateClientWaitSync(const ValidationContext *val,
3986                             const Display *display,
3987                             const Sync *sync,
3988                             EGLint flags,
3989                             EGLTime timeout)
3990 {
3991     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3992     return true;
3993 }
3994 
ValidateClientWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags,EGLTimeKHR timeout)3995 bool ValidateClientWaitSyncKHR(const ValidationContext *val,
3996                                const Display *dpyPacked,
3997                                const Sync *syncPacked,
3998                                EGLint flags,
3999                                EGLTimeKHR timeout)
4000 {
4001     return ValidateClientWaitSync(val, dpyPacked, syncPacked, flags, timeout);
4002 }
4003 
ValidateWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags)4004 bool ValidateWaitSync(const ValidationContext *val,
4005                       const Display *display,
4006                       const Sync *sync,
4007                       EGLint flags)
4008 {
4009     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4010 
4011     const DisplayExtensions &extensions = display->getExtensions();
4012     if (!extensions.waitSync)
4013     {
4014         val->setError(EGL_BAD_ACCESS, "EGL_KHR_wait_sync extension is not available");
4015         return false;
4016     }
4017 
4018     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
4019 
4020     gl::Context *context = val->eglThread->getContext();
4021     if (context == nullptr)
4022     {
4023         val->setError(EGL_BAD_MATCH, "No context is current.");
4024         return false;
4025     }
4026 
4027     if (!context->getExtensions().EGLSyncOES)
4028     {
4029         val->setError(EGL_BAD_MATCH,
4030                       "Server-side waits cannot be performed without "
4031                       "GL_OES_EGL_sync support.");
4032         return false;
4033     }
4034 
4035     if (flags != 0)
4036     {
4037         val->setError(EGL_BAD_PARAMETER, "flags must be zero");
4038         return false;
4039     }
4040 
4041     return true;
4042 }
4043 
ValidateWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags)4044 bool ValidateWaitSyncKHR(const ValidationContext *val,
4045                          const Display *dpyPacked,
4046                          const Sync *syncPacked,
4047                          EGLint flags)
4048 {
4049     return ValidateWaitSync(val, dpyPacked, syncPacked, flags);
4050 }
4051 
ValidateGetSyncAttrib(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLAttrib * value)4052 bool ValidateGetSyncAttrib(const ValidationContext *val,
4053                            const Display *display,
4054                            const Sync *sync,
4055                            EGLint attribute,
4056                            const EGLAttrib *value)
4057 {
4058     if (value == nullptr)
4059     {
4060         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
4061         return false;
4062     }
4063     return ValidateGetSyncAttribBase(val, display, sync, attribute);
4064 }
4065 
ValidateGetSyncAttribKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLint * value)4066 bool ValidateGetSyncAttribKHR(const ValidationContext *val,
4067                               const Display *display,
4068                               const Sync *sync,
4069                               EGLint attribute,
4070                               const EGLint *value)
4071 {
4072     if (value == nullptr)
4073     {
4074         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
4075         return false;
4076     }
4077     return ValidateGetSyncAttribBase(val, display, sync, attribute);
4078 }
4079 
ValidateCreateStreamKHR(const ValidationContext * val,const Display * display,const AttributeMap & attributes)4080 bool ValidateCreateStreamKHR(const ValidationContext *val,
4081                              const Display *display,
4082                              const AttributeMap &attributes)
4083 {
4084     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4085 
4086     const DisplayExtensions &displayExtensions = display->getExtensions();
4087     if (!displayExtensions.stream)
4088     {
4089         val->setError(EGL_BAD_ALLOC, "Stream extension not active");
4090         return false;
4091     }
4092 
4093     attributes.initializeWithoutValidation();
4094 
4095     for (const auto &attributeIter : attributes)
4096     {
4097         EGLAttrib attribute = attributeIter.first;
4098         EGLAttrib value     = attributeIter.second;
4099 
4100         ANGLE_VALIDATION_TRY(ValidateStreamAttribute(val, attribute, value, displayExtensions));
4101     }
4102 
4103     return true;
4104 }
4105 
ValidateDestroyStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream)4106 bool ValidateDestroyStreamKHR(const ValidationContext *val,
4107                               const Display *display,
4108                               const Stream *stream)
4109 {
4110     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4111     return true;
4112 }
4113 
ValidateStreamAttribKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,EGLint value)4114 bool ValidateStreamAttribKHR(const ValidationContext *val,
4115                              const Display *display,
4116                              const Stream *stream,
4117                              EGLenum attribute,
4118                              EGLint value)
4119 {
4120     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4121 
4122     if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
4123     {
4124         val->setError(EGL_BAD_STATE_KHR, "Bad stream state");
4125         return false;
4126     }
4127 
4128     return ValidateStreamAttribute(val, attribute, value, display->getExtensions());
4129 }
4130 
ValidateQueryStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLint * value)4131 bool ValidateQueryStreamKHR(const ValidationContext *val,
4132                             const Display *display,
4133                             const Stream *stream,
4134                             EGLenum attribute,
4135                             const EGLint *value)
4136 {
4137     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4138 
4139     switch (attribute)
4140     {
4141         case EGL_STREAM_STATE_KHR:
4142         case EGL_CONSUMER_LATENCY_USEC_KHR:
4143             break;
4144         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
4145             if (!display->getExtensions().streamConsumerGLTexture)
4146             {
4147                 val->setError(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
4148                 return false;
4149             }
4150             break;
4151         default:
4152             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4153             return false;
4154     }
4155 
4156     return true;
4157 }
4158 
ValidateQueryStreamu64KHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLuint64KHR * value)4159 bool ValidateQueryStreamu64KHR(const ValidationContext *val,
4160                                const Display *display,
4161                                const Stream *stream,
4162                                EGLenum attribute,
4163                                const EGLuint64KHR *value)
4164 {
4165     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4166 
4167     switch (attribute)
4168     {
4169         case EGL_CONSUMER_FRAME_KHR:
4170         case EGL_PRODUCER_FRAME_KHR:
4171             break;
4172         default:
4173             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4174             return false;
4175     }
4176 
4177     return true;
4178 }
4179 
ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext * val,const Display * display,const Stream * stream)4180 bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
4181                                                 const Display *display,
4182                                                 const Stream *stream)
4183 {
4184     gl::Context *context = val->eglThread->getContext();
4185     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4186 
4187     const DisplayExtensions &displayExtensions = display->getExtensions();
4188     if (!displayExtensions.streamConsumerGLTexture)
4189     {
4190         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4191         return false;
4192     }
4193 
4194     if (!context->getExtensions().EGLStreamConsumerExternalNV)
4195     {
4196         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
4197         return false;
4198     }
4199 
4200     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4201     {
4202         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4203         return false;
4204     }
4205 
4206     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
4207     {
4208         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4209         return false;
4210     }
4211 
4212     // Lookup the texture and ensure it is correct
4213     gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
4214     if (texture == nullptr || texture->id().value == 0)
4215     {
4216         val->setError(EGL_BAD_ACCESS, "No external texture bound");
4217         return false;
4218     }
4219 
4220     return true;
4221 }
4222 
ValidateStreamConsumerAcquireKHR(const ValidationContext * val,const Display * display,const Stream * stream)4223 bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
4224                                       const Display *display,
4225                                       const Stream *stream)
4226 {
4227     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4228 
4229     const DisplayExtensions &displayExtensions = display->getExtensions();
4230     if (!displayExtensions.streamConsumerGLTexture)
4231     {
4232         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4233         return false;
4234     }
4235 
4236     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4237     {
4238         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4239         return false;
4240     }
4241 
4242     gl::Context *context = val->eglThread->getContext();
4243     if (!context)
4244     {
4245         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
4246         return false;
4247     }
4248 
4249     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4250 
4251     if (!stream->isConsumerBoundToContext(context))
4252     {
4253         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
4254         return false;
4255     }
4256 
4257     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
4258         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
4259     {
4260         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
4261         return false;
4262     }
4263 
4264     // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
4265     // However, the timeout is effectively ignored since it has no useful functionality with the
4266     // current producers that are implemented, so we don't allow that state
4267     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4268         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4269     {
4270         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4271         return false;
4272     }
4273 
4274     return true;
4275 }
4276 
ValidateStreamConsumerReleaseKHR(const ValidationContext * val,const Display * display,const Stream * stream)4277 bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
4278                                       const Display *display,
4279                                       const Stream *stream)
4280 {
4281     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4282 
4283     const DisplayExtensions &displayExtensions = display->getExtensions();
4284     if (!displayExtensions.streamConsumerGLTexture)
4285     {
4286         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4287         return false;
4288     }
4289 
4290     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4291     {
4292         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4293         return false;
4294     }
4295 
4296     gl::Context *context = val->eglThread->getContext();
4297     if (!context)
4298     {
4299         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
4300         return false;
4301     }
4302 
4303     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4304 
4305     if (!stream->isConsumerBoundToContext(context))
4306     {
4307         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
4308         return false;
4309     }
4310 
4311     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
4312         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
4313     {
4314         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
4315         return false;
4316     }
4317 
4318     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4319         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4320     {
4321         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4322         return false;
4323     }
4324 
4325     return true;
4326 }
4327 
ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)4328 bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
4329                                                       const Display *display,
4330                                                       const Stream *stream,
4331                                                       const AttributeMap &attribs)
4332 {
4333     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4334 
4335     const DisplayExtensions &displayExtensions = display->getExtensions();
4336     if (!displayExtensions.streamConsumerGLTexture)
4337     {
4338         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
4339         return false;
4340     }
4341 
4342     gl::Context *context = val->eglThread->getContext();
4343     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4344 
4345     // Although technically not a requirement in spec, the context needs to be checked for support
4346     // for external textures or future logic will cause assertations. This extension is also
4347     // effectively useless without external textures.
4348     if (!context->getExtensions().EGLStreamConsumerExternalNV)
4349     {
4350         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
4351         return false;
4352     }
4353 
4354     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
4355     {
4356         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
4357         return false;
4358     }
4359 
4360     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
4361     {
4362         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
4363         return false;
4364     }
4365 
4366     const gl::Caps &glCaps = context->getCaps();
4367 
4368     EGLAttrib colorBufferType = EGL_RGB_BUFFER;
4369     EGLAttrib planeCount      = -1;
4370     EGLAttrib plane[3];
4371     for (int i = 0; i < 3; i++)
4372     {
4373         plane[i] = -1;
4374     }
4375 
4376     attribs.initializeWithoutValidation();
4377 
4378     for (const auto &attributeIter : attribs)
4379     {
4380         EGLAttrib attribute = attributeIter.first;
4381         EGLAttrib value     = attributeIter.second;
4382 
4383         switch (attribute)
4384         {
4385             case EGL_COLOR_BUFFER_TYPE:
4386                 if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
4387                 {
4388                     val->setError(EGL_BAD_PARAMETER, "Invalid color buffer type");
4389                     return false;
4390                 }
4391                 colorBufferType = value;
4392                 break;
4393             case EGL_YUV_NUMBER_OF_PLANES_EXT:
4394                 // planeCount = -1 is a tag for the default plane count so the value must be checked
4395                 // to be positive here to ensure future logic doesn't break on invalid negative
4396                 // inputs
4397                 if (value < 0)
4398                 {
4399                     val->setError(EGL_BAD_MATCH, "Invalid plane count");
4400                     return false;
4401                 }
4402                 planeCount = value;
4403                 break;
4404             default:
4405                 if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
4406                     attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
4407                 {
4408                     if ((value < 0 ||
4409                          value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
4410                         value != EGL_NONE)
4411                     {
4412                         val->setError(EGL_BAD_ACCESS, "Invalid texture unit");
4413                         return false;
4414                     }
4415                     plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
4416                 }
4417                 else
4418                 {
4419                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4420                     return false;
4421                 }
4422         }
4423     }
4424 
4425     if (colorBufferType == EGL_RGB_BUFFER)
4426     {
4427         if (planeCount > 0)
4428         {
4429             val->setError(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
4430             return false;
4431         }
4432         for (int i = 0; i < 3; i++)
4433         {
4434             if (plane[i] != -1)
4435             {
4436                 val->setError(EGL_BAD_MATCH, "Planes cannot be specified");
4437                 return false;
4438             }
4439         }
4440 
4441         // Lookup the texture and ensure it is correct
4442         gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
4443         if (texture == nullptr || texture->id().value == 0)
4444         {
4445             val->setError(EGL_BAD_ACCESS, "No external texture bound");
4446             return false;
4447         }
4448     }
4449     else
4450     {
4451         if (planeCount == -1)
4452         {
4453             planeCount = 2;
4454         }
4455         if (planeCount < 1 || planeCount > 3)
4456         {
4457             val->setError(EGL_BAD_MATCH, "Invalid YUV plane count");
4458             return false;
4459         }
4460         for (EGLAttrib i = planeCount; i < 3; i++)
4461         {
4462             if (plane[i] != -1)
4463             {
4464                 val->setError(EGL_BAD_MATCH, "Invalid plane specified");
4465                 return false;
4466             }
4467         }
4468 
4469         // Set to ensure no texture is referenced more than once
4470         std::set<gl::Texture *> textureSet;
4471         for (EGLAttrib i = 0; i < planeCount; i++)
4472         {
4473             if (plane[i] == -1)
4474             {
4475                 val->setError(EGL_BAD_MATCH, "Not all planes specified");
4476                 return false;
4477             }
4478             if (plane[i] != EGL_NONE)
4479             {
4480                 gl::Texture *texture = context->getState().getSamplerTexture(
4481                     static_cast<unsigned int>(plane[i]), gl::TextureType::External);
4482                 if (texture == nullptr || texture->id().value == 0)
4483                 {
4484                     val->setError(
4485                         EGL_BAD_ACCESS,
4486                         "No external texture bound at one or more specified texture units");
4487                     return false;
4488                 }
4489                 if (textureSet.find(texture) != textureSet.end())
4490                 {
4491                     val->setError(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
4492                     return false;
4493                 }
4494                 textureSet.insert(texture);
4495             }
4496         }
4497     }
4498 
4499     return true;
4500 }
4501 
ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)4502 bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
4503                                                  const Display *display,
4504                                                  const Stream *stream,
4505                                                  const AttributeMap &attribs)
4506 {
4507     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4508 
4509     const DisplayExtensions &displayExtensions = display->getExtensions();
4510     if (!displayExtensions.streamProducerD3DTexture)
4511     {
4512         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4513         return false;
4514     }
4515 
4516     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4517 
4518     attribs.initializeWithoutValidation();
4519 
4520     if (!attribs.isEmpty())
4521     {
4522         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4523         return false;
4524     }
4525 
4526     if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
4527     {
4528         val->setError(EGL_BAD_STATE_KHR, "Stream not in connecting state");
4529         return false;
4530     }
4531 
4532     switch (stream->getConsumerType())
4533     {
4534         case Stream::ConsumerType::GLTextureYUV:
4535             if (stream->getPlaneCount() != 2)
4536             {
4537                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4538                 return false;
4539             }
4540             break;
4541 
4542         case Stream::ConsumerType::GLTextureRGB:
4543             if (stream->getPlaneCount() != 1)
4544             {
4545                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4546                 return false;
4547             }
4548             break;
4549 
4550         default:
4551             val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4552             return false;
4553     }
4554 
4555     return true;
4556 }
4557 
ValidateStreamPostD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const void * texture,const AttributeMap & attribs)4558 bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
4559                                        const Display *display,
4560                                        const Stream *stream,
4561                                        const void *texture,
4562                                        const AttributeMap &attribs)
4563 {
4564     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4565 
4566     const DisplayExtensions &displayExtensions = display->getExtensions();
4567     if (!displayExtensions.streamProducerD3DTexture)
4568     {
4569         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4570         return false;
4571     }
4572 
4573     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4574 
4575     attribs.initializeWithoutValidation();
4576 
4577     for (auto &attributeIter : attribs)
4578     {
4579         EGLAttrib attribute = attributeIter.first;
4580         EGLAttrib value     = attributeIter.second;
4581 
4582         switch (attribute)
4583         {
4584             case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
4585                 if (value < 0)
4586                 {
4587                     val->setError(EGL_BAD_PARAMETER, "Invalid subresource index");
4588                     return false;
4589                 }
4590                 break;
4591             case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
4592                 if (value < 0)
4593                 {
4594                     val->setError(EGL_BAD_PARAMETER, "Invalid plane offset");
4595                     return false;
4596                 }
4597                 break;
4598             default:
4599                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4600                 return false;
4601         }
4602     }
4603 
4604     if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
4605         stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4606         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4607     {
4608         val->setError(EGL_BAD_STATE_KHR, "Stream not fully configured");
4609         return false;
4610     }
4611 
4612     if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
4613     {
4614         val->setError(EGL_BAD_MATCH, "Incompatible stream producer");
4615         return false;
4616     }
4617 
4618     if (texture == nullptr)
4619     {
4620         val->setError(EGL_BAD_PARAMETER, "Texture is null");
4621         return false;
4622     }
4623 
4624     ANGLE_EGL_TRY_RETURN(val->eglThread, stream->validateD3D11Texture(texture, attribs),
4625                          val->entryPoint, val->labeledObject, false);
4626 
4627     return true;
4628 }
4629 
ValidateSyncControlCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface)4630 bool ValidateSyncControlCHROMIUM(const ValidationContext *val,
4631                                  const Display *display,
4632                                  const Surface *eglSurface)
4633 {
4634     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4635     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4636 
4637     const DisplayExtensions &displayExtensions = display->getExtensions();
4638     if (!displayExtensions.syncControlCHROMIUM)
4639     {
4640         val->setError(EGL_BAD_ACCESS, "syncControlCHROMIUM extension not active");
4641         return false;
4642     }
4643 
4644     return true;
4645 }
4646 
ValidateSyncControlRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface)4647 bool ValidateSyncControlRateANGLE(const ValidationContext *val,
4648                                   const Display *display,
4649                                   const Surface *eglSurface)
4650 {
4651     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4652     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4653 
4654     const DisplayExtensions &displayExtensions = display->getExtensions();
4655     if (!displayExtensions.syncControlRateANGLE)
4656     {
4657         val->setError(EGL_BAD_ACCESS, "syncControlRateANGLE extension not active");
4658         return false;
4659     }
4660 
4661     return true;
4662 }
4663 
ValidateGetMscRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLint * numerator,const EGLint * denominator)4664 bool ValidateGetMscRateANGLE(const ValidationContext *val,
4665                              const Display *display,
4666                              const Surface *eglSurface,
4667                              const EGLint *numerator,
4668                              const EGLint *denominator)
4669 {
4670     ANGLE_VALIDATION_TRY(ValidateSyncControlRateANGLE(val, display, eglSurface));
4671 
4672     if (numerator == nullptr)
4673     {
4674         val->setError(EGL_BAD_PARAMETER, "numerator is null");
4675         return false;
4676     }
4677     if (denominator == nullptr)
4678     {
4679         val->setError(EGL_BAD_PARAMETER, "denominator is null");
4680         return false;
4681     }
4682 
4683     return true;
4684 }
4685 
ValidateGetSyncValuesCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLuint64KHR * ust,const EGLuint64KHR * msc,const EGLuint64KHR * sbc)4686 bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
4687                                    const Display *display,
4688                                    const Surface *eglSurface,
4689                                    const EGLuint64KHR *ust,
4690                                    const EGLuint64KHR *msc,
4691                                    const EGLuint64KHR *sbc)
4692 {
4693     ANGLE_VALIDATION_TRY(ValidateSyncControlCHROMIUM(val, display, eglSurface));
4694 
4695     if (ust == nullptr)
4696     {
4697         val->setError(EGL_BAD_PARAMETER, "ust is null");
4698         return false;
4699     }
4700     if (msc == nullptr)
4701     {
4702         val->setError(EGL_BAD_PARAMETER, "msc is null");
4703         return false;
4704     }
4705     if (sbc == nullptr)
4706     {
4707         val->setError(EGL_BAD_PARAMETER, "sbc is null");
4708         return false;
4709     }
4710 
4711     return true;
4712 }
4713 
ValidateDestroySurface(const ValidationContext * val,const Display * display,const Surface * surface)4714 bool ValidateDestroySurface(const ValidationContext *val,
4715                             const Display *display,
4716                             const Surface *surface)
4717 {
4718     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4719     return true;
4720 }
4721 
ValidateDestroyContext(const ValidationContext * val,const Display * display,const gl::Context * glCtx)4722 bool ValidateDestroyContext(const ValidationContext *val,
4723                             const Display *display,
4724                             const gl::Context *glCtx)
4725 {
4726     ANGLE_VALIDATION_TRY(ValidateContext(val, display, glCtx));
4727     return true;
4728 }
4729 
ValidateSwapBuffers(const ValidationContext * val,const Display * display,const Surface * eglSurface)4730 bool ValidateSwapBuffers(const ValidationContext *val,
4731                          const Display *display,
4732                          const Surface *eglSurface)
4733 {
4734     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4735 
4736     if (display->isDeviceLost())
4737     {
4738         val->setError(EGL_CONTEXT_LOST);
4739         return false;
4740     }
4741 
4742     if (eglSurface->isLocked())
4743     {
4744         val->setError(EGL_BAD_ACCESS);
4745         return false;
4746     }
4747 
4748     if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
4749         val->eglThread->getCurrentDrawSurface() != eglSurface)
4750     {
4751         val->setError(EGL_BAD_SURFACE);
4752         return false;
4753     }
4754 
4755     return true;
4756 }
4757 
ValidateSwapBuffersWithDamageKHR(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint * rects,EGLint n_rects)4758 bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
4759                                       const Display *display,
4760                                       const Surface *surface,
4761                                       const EGLint *rects,
4762                                       EGLint n_rects)
4763 {
4764     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4765 
4766     if (!display->getExtensions().swapBuffersWithDamage)
4767     {
4768         // It is out of spec what happens when calling an extension function when the extension is
4769         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4770         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_swap_buffers_with_damage is not available.");
4771         return false;
4772     }
4773 
4774     if (surface == EGL_NO_SURFACE)
4775     {
4776         val->setError(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
4777         return false;
4778     }
4779 
4780     if (n_rects < 0)
4781     {
4782         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
4783         return false;
4784     }
4785 
4786     if (n_rects > 0 && rects == nullptr)
4787     {
4788         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
4789         return false;
4790     }
4791 
4792     if (surface->isLocked())
4793     {
4794         val->setError(EGL_BAD_ACCESS);
4795         return false;
4796     }
4797 
4798     // TODO(jmadill): Validate Surface is bound to the thread.
4799 
4800     return true;
4801 }
4802 
ValidateWaitNative(const ValidationContext * val,const EGLint engine)4803 bool ValidateWaitNative(const ValidationContext *val, const EGLint engine)
4804 {
4805     if (val->eglThread->getDisplay() == nullptr)
4806     {
4807         // EGL spec says this about eglWaitNative -
4808         //    eglWaitNative is ignored if there is no current EGL rendering context.
4809         return true;
4810     }
4811 
4812     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
4813 
4814     if (engine != EGL_CORE_NATIVE_ENGINE)
4815     {
4816         val->setError(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value");
4817         return false;
4818     }
4819 
4820     return true;
4821 }
4822 
ValidateCopyBuffers(const ValidationContext * val,const Display * display,const Surface * surface,EGLNativePixmapType target)4823 bool ValidateCopyBuffers(const ValidationContext *val,
4824                          const Display *display,
4825                          const Surface *surface,
4826                          EGLNativePixmapType target)
4827 {
4828     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4829 
4830     if (display->isDeviceLost())
4831     {
4832         val->setError(EGL_CONTEXT_LOST);
4833         return false;
4834     }
4835 
4836     return true;
4837 }
4838 
ValidateBindTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4839 bool ValidateBindTexImage(const ValidationContext *val,
4840                           const Display *display,
4841                           const Surface *surface,
4842                           const EGLint buffer)
4843 {
4844     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4845 
4846     if (buffer != EGL_BACK_BUFFER)
4847     {
4848         val->setError(EGL_BAD_PARAMETER);
4849         return false;
4850     }
4851 
4852     if (surface->getType() == EGL_WINDOW_BIT)
4853     {
4854         val->setError(EGL_BAD_SURFACE);
4855         return false;
4856     }
4857 
4858     if (surface->getBoundTexture())
4859     {
4860         val->setError(EGL_BAD_ACCESS);
4861         return false;
4862     }
4863 
4864     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4865     {
4866         val->setError(EGL_BAD_MATCH);
4867         return false;
4868     }
4869 
4870     if (surface->isLocked())
4871     {
4872         val->setError(EGL_BAD_ACCESS);
4873         return false;
4874     }
4875 
4876     gl::Context *context = val->eglThread->getContext();
4877     if (context)
4878     {
4879         gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
4880         gl::Texture *textureObject = context->getTextureByType(type);
4881         ASSERT(textureObject != nullptr);
4882 
4883         if (textureObject->getImmutableFormat())
4884         {
4885             val->setError(EGL_BAD_MATCH);
4886             return false;
4887         }
4888     }
4889 
4890     return true;
4891 }
4892 
ValidateReleaseTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4893 bool ValidateReleaseTexImage(const ValidationContext *val,
4894                              const Display *display,
4895                              const Surface *surface,
4896                              const EGLint buffer)
4897 {
4898     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4899 
4900     if (buffer != EGL_BACK_BUFFER)
4901     {
4902         val->setError(EGL_BAD_PARAMETER);
4903         return false;
4904     }
4905 
4906     if (surface->getType() == EGL_WINDOW_BIT)
4907     {
4908         val->setError(EGL_BAD_SURFACE);
4909         return false;
4910     }
4911 
4912     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4913     {
4914         val->setError(EGL_BAD_MATCH);
4915         return false;
4916     }
4917 
4918     return true;
4919 }
4920 
ValidateSwapInterval(const ValidationContext * val,const Display * display,EGLint interval)4921 bool ValidateSwapInterval(const ValidationContext *val, const Display *display, EGLint interval)
4922 {
4923     const gl::Context *context = val->eglThread->getContext();
4924     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4925 
4926     Surface *drawSurface = val->eglThread->getCurrentDrawSurface();
4927     if (drawSurface == nullptr)
4928     {
4929         val->setError(EGL_BAD_SURFACE);
4930         return false;
4931     }
4932 
4933     return true;
4934 }
4935 
ValidateBindAPI(const ValidationContext * val,const EGLenum api)4936 bool ValidateBindAPI(const ValidationContext *val, const EGLenum api)
4937 {
4938     switch (api)
4939     {
4940         case EGL_OPENGL_API:
4941         case EGL_OPENVG_API:
4942             val->setError(EGL_BAD_PARAMETER);
4943             return false;  // Not supported by this implementation
4944         case EGL_OPENGL_ES_API:
4945             break;
4946         default:
4947             val->setError(EGL_BAD_PARAMETER);
4948             return false;
4949     }
4950 
4951     return true;
4952 }
4953 
ValidatePresentationTimeANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLnsecsANDROID time)4954 bool ValidatePresentationTimeANDROID(const ValidationContext *val,
4955                                      const Display *display,
4956                                      const Surface *surface,
4957                                      EGLnsecsANDROID time)
4958 {
4959     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4960 
4961     if (!display->getExtensions().presentationTime)
4962     {
4963         // It is out of spec what happens when calling an extension function when the extension is
4964         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4965         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_presentation_time is not available.");
4966         return false;
4967     }
4968 
4969     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4970 
4971     return true;
4972 }
4973 
ValidateSetBlobCacheFuncsANDROID(const ValidationContext * val,const Display * display,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)4974 bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
4975                                       const Display *display,
4976                                       EGLSetBlobFuncANDROID set,
4977                                       EGLGetBlobFuncANDROID get)
4978 {
4979     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4980 
4981     if (display->areBlobCacheFuncsSet())
4982     {
4983         val->setError(EGL_BAD_PARAMETER,
4984                       "Blob cache functions can only be set once in the lifetime of a Display");
4985         return false;
4986     }
4987 
4988     if (set == nullptr || get == nullptr)
4989     {
4990         val->setError(EGL_BAD_PARAMETER, "Blob cache callbacks cannot be null.");
4991         return false;
4992     }
4993 
4994     return true;
4995 }
4996 
ValidateGetConfigAttrib(const ValidationContext * val,const Display * display,const Config * config,EGLint attribute,const EGLint * value)4997 bool ValidateGetConfigAttrib(const ValidationContext *val,
4998                              const Display *display,
4999                              const Config *config,
5000                              EGLint attribute,
5001                              const EGLint *value)
5002 {
5003     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
5004     ANGLE_TRY(ValidateConfigAttribute(val, display, static_cast<EGLAttrib>(attribute)));
5005     return true;
5006 }
5007 
ValidateChooseConfig(const ValidationContext * val,const Display * display,const AttributeMap & attribs,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)5008 bool ValidateChooseConfig(const ValidationContext *val,
5009                           const Display *display,
5010                           const AttributeMap &attribs,
5011                           const EGLConfig *configs,
5012                           EGLint configSize,
5013                           const EGLint *numConfig)
5014 {
5015     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5016     ANGLE_VALIDATION_TRY(ValidateConfigAttributes(val, display, attribs));
5017 
5018     if (numConfig == nullptr)
5019     {
5020         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
5021         return false;
5022     }
5023 
5024     return true;
5025 }
5026 
ValidateGetConfigs(const ValidationContext * val,const Display * display,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)5027 bool ValidateGetConfigs(const ValidationContext *val,
5028                         const Display *display,
5029                         const EGLConfig *configs,
5030                         EGLint configSize,
5031                         const EGLint *numConfig)
5032 {
5033     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5034 
5035     if (numConfig == nullptr)
5036     {
5037         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
5038         return false;
5039     }
5040 
5041     return true;
5042 }
5043 
ValidateGetPlatformDisplay(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)5044 bool ValidateGetPlatformDisplay(const ValidationContext *val,
5045                                 EGLenum platform,
5046                                 const void *native_display,
5047                                 const AttributeMap &attribMap)
5048 {
5049     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
5050 }
5051 
ValidateGetPlatformDisplayEXT(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)5052 bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
5053                                    EGLenum platform,
5054                                    const void *native_display,
5055                                    const AttributeMap &attribMap)
5056 {
5057     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
5058 }
5059 
ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativeWindow,const AttributeMap & attributes)5060 bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
5061                                             const Display *display,
5062                                             const Config *configuration,
5063                                             const void *nativeWindow,
5064                                             const AttributeMap &attributes)
5065 {
5066     if (!Display::GetClientExtensions().platformBase)
5067     {
5068         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
5069         return false;
5070     }
5071 
5072     const void *actualNativeWindow = display->getImplementation()->isX11()
5073                                          ? *reinterpret_cast<const void *const *>(nativeWindow)
5074                                          : nativeWindow;
5075 
5076     return ValidateCreatePlatformWindowSurface(val, display, configuration, actualNativeWindow,
5077                                                attributes);
5078 }
5079 
ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativePixmap,const AttributeMap & attributes)5080 bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
5081                                             const Display *display,
5082                                             const Config *configuration,
5083                                             const void *nativePixmap,
5084                                             const AttributeMap &attributes)
5085 {
5086     if (!Display::GetClientExtensions().platformBase)
5087     {
5088         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
5089         return false;
5090     }
5091 
5092     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
5093 
5094     val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.");
5095     return false;
5096 }
5097 
ValidateProgramCacheGetAttribANGLE(const ValidationContext * val,const Display * display,EGLenum attrib)5098 bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
5099                                         const Display *display,
5100                                         EGLenum attrib)
5101 {
5102     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5103 
5104     if (!display->getExtensions().programCacheControlANGLE)
5105     {
5106         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5107         return false;
5108     }
5109 
5110     switch (attrib)
5111     {
5112         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
5113         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
5114             break;
5115 
5116         default:
5117             val->setError(EGL_BAD_PARAMETER, "Invalid program cache attribute.");
5118             return false;
5119     }
5120 
5121     return true;
5122 }
5123 
ValidateProgramCacheQueryANGLE(const ValidationContext * val,const Display * display,EGLint index,const void * key,const EGLint * keysize,const void * binary,const EGLint * binarysize)5124 bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
5125                                     const Display *display,
5126                                     EGLint index,
5127                                     const void *key,
5128                                     const EGLint *keysize,
5129                                     const void *binary,
5130                                     const EGLint *binarysize)
5131 {
5132     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5133 
5134     if (!display->getExtensions().programCacheControlANGLE)
5135     {
5136         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5137         return false;
5138     }
5139 
5140     if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
5141     {
5142         val->setError(EGL_BAD_PARAMETER, "Program index out of range.");
5143         return false;
5144     }
5145 
5146     if (keysize == nullptr || binarysize == nullptr)
5147     {
5148         val->setError(EGL_BAD_PARAMETER, "keysize and binarysize must always be valid pointers.");
5149         return false;
5150     }
5151 
5152     if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
5153     {
5154         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
5155         return false;
5156     }
5157 
5158     if ((key == nullptr) != (binary == nullptr))
5159     {
5160         val->setError(EGL_BAD_PARAMETER, "key and binary must both be null or both non-null.");
5161         return false;
5162     }
5163 
5164     return true;
5165 }
5166 
ValidateProgramCachePopulateANGLE(const ValidationContext * val,const Display * display,const void * key,EGLint keysize,const void * binary,EGLint binarysize)5167 bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
5168                                        const Display *display,
5169                                        const void *key,
5170                                        EGLint keysize,
5171                                        const void *binary,
5172                                        EGLint binarysize)
5173 {
5174     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5175 
5176     if (!display->getExtensions().programCacheControlANGLE)
5177     {
5178         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5179         return false;
5180     }
5181 
5182     if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
5183     {
5184         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
5185         return false;
5186     }
5187 
5188     if (key == nullptr || binary == nullptr)
5189     {
5190         val->setError(EGL_BAD_PARAMETER, "null pointer in arguments.");
5191         return false;
5192     }
5193 
5194     // Upper bound for binarysize is arbitrary.
5195     if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
5196     {
5197         val->setError(EGL_BAD_PARAMETER, "binarysize out of valid range.");
5198         return false;
5199     }
5200 
5201     return true;
5202 }
5203 
ValidateProgramCacheResizeANGLE(const ValidationContext * val,const Display * display,EGLint limit,EGLint mode)5204 bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
5205                                      const Display *display,
5206                                      EGLint limit,
5207                                      EGLint mode)
5208 {
5209     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5210 
5211     if (!display->getExtensions().programCacheControlANGLE)
5212     {
5213         val->setError(EGL_BAD_ACCESS, "Extension not supported");
5214         return false;
5215     }
5216 
5217     if (limit < 0)
5218     {
5219         val->setError(EGL_BAD_PARAMETER, "limit must be non-negative.");
5220         return false;
5221     }
5222 
5223     switch (mode)
5224     {
5225         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
5226         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
5227             break;
5228 
5229         default:
5230             val->setError(EGL_BAD_PARAMETER, "Invalid cache resize mode.");
5231             return false;
5232     }
5233 
5234     return true;
5235 }
5236 
ValidateSurfaceAttrib(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,EGLint value)5237 bool ValidateSurfaceAttrib(const ValidationContext *val,
5238                            const Display *display,
5239                            const Surface *surface,
5240                            EGLint attribute,
5241                            EGLint value)
5242 {
5243     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5244     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5245 
5246     if (surface == EGL_NO_SURFACE)
5247     {
5248         val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
5249         return false;
5250     }
5251 
5252     switch (attribute)
5253     {
5254         case EGL_MIPMAP_LEVEL:
5255             break;
5256 
5257         case EGL_MULTISAMPLE_RESOLVE:
5258             switch (value)
5259             {
5260                 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
5261                     break;
5262 
5263                 case EGL_MULTISAMPLE_RESOLVE_BOX:
5264                     if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
5265                     {
5266                         val->setError(EGL_BAD_MATCH,
5267                                       "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.");
5268                         return false;
5269                     }
5270                     break;
5271 
5272                 default:
5273                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid multisample resolve type.");
5274                     return false;
5275             }
5276             break;
5277 
5278         case EGL_SWAP_BEHAVIOR:
5279             switch (value)
5280             {
5281                 case EGL_BUFFER_PRESERVED:
5282                     if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
5283                     {
5284                         val->setError(EGL_BAD_MATCH,
5285                                       "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.");
5286                         return false;
5287                     }
5288                     break;
5289 
5290                 case EGL_BUFFER_DESTROYED:
5291                     break;
5292 
5293                 default:
5294                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid swap behaviour.");
5295                     return false;
5296             }
5297             break;
5298 
5299         case EGL_WIDTH:
5300         case EGL_HEIGHT:
5301             if (!display->getExtensions().windowFixedSize)
5302             {
5303                 val->setError(EGL_BAD_ATTRIBUTE,
5304                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
5305                               "EGL_ANGLE_window_fixed_size support.");
5306                 return false;
5307             }
5308             if (!surface->isFixedSize())
5309             {
5310                 val->setError(EGL_BAD_MATCH,
5311                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
5312                               "EGL_FIXED_SIZE_ANGLE being enabled on the surface.");
5313                 return false;
5314             }
5315             break;
5316 
5317         case EGL_TIMESTAMPS_ANDROID:
5318             if (!display->getExtensions().getFrameTimestamps)
5319             {
5320                 val->setError(EGL_BAD_ATTRIBUTE,
5321                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
5322                               "EGL_ANDROID_get_frame_timestamps support.");
5323                 return false;
5324             }
5325             switch (value)
5326             {
5327                 case EGL_TRUE:
5328                 case EGL_FALSE:
5329                     break;
5330 
5331                 default:
5332                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid value.");
5333                     return false;
5334             }
5335             break;
5336 
5337         case EGL_RENDER_BUFFER:
5338             if (!display->getExtensions().mutableRenderBufferKHR)
5339             {
5340                 val->setError(
5341                     EGL_BAD_ATTRIBUTE,
5342                     "Attribute EGL_RENDER_BUFFER requires EGL_KHR_mutable_render_buffer.");
5343                 return false;
5344             }
5345 
5346             if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER)
5347             {
5348                 val->setError(EGL_BAD_ATTRIBUTE,
5349                               "EGL_RENDER_BUFFER must be EGL_BACK_BUFFER or EGL_SINGLE_BUFFER.");
5350                 return false;
5351             }
5352 
5353             if ((surface->getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) == 0)
5354             {
5355                 val->setError(EGL_BAD_MATCH,
5356                               "EGL_RENDER_BUFFER requires the surface type bit "
5357                               "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.");
5358                 return false;
5359             }
5360             break;
5361 
5362         default:
5363             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
5364             return false;
5365     }
5366 
5367     return true;
5368 }
5369 
ValidateQuerySurface(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,const EGLint * value)5370 bool ValidateQuerySurface(const ValidationContext *val,
5371                           const Display *display,
5372                           const Surface *surface,
5373                           EGLint attribute,
5374                           const EGLint *value)
5375 {
5376     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5377     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5378 
5379     if (surface == EGL_NO_SURFACE)
5380     {
5381         val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
5382         return false;
5383     }
5384 
5385     switch (attribute)
5386     {
5387         case EGL_GL_COLORSPACE:
5388         case EGL_VG_ALPHA_FORMAT:
5389         case EGL_VG_COLORSPACE:
5390         case EGL_CONFIG_ID:
5391         case EGL_HEIGHT:
5392         case EGL_HORIZONTAL_RESOLUTION:
5393         case EGL_LARGEST_PBUFFER:
5394         case EGL_MIPMAP_TEXTURE:
5395         case EGL_MIPMAP_LEVEL:
5396         case EGL_MULTISAMPLE_RESOLVE:
5397         case EGL_PIXEL_ASPECT_RATIO:
5398         case EGL_RENDER_BUFFER:
5399         case EGL_SWAP_BEHAVIOR:
5400         case EGL_TEXTURE_FORMAT:
5401         case EGL_TEXTURE_TARGET:
5402         case EGL_VERTICAL_RESOLUTION:
5403         case EGL_WIDTH:
5404             break;
5405 
5406         case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
5407             if (!display->getExtensions().postSubBuffer)
5408             {
5409                 val->setError(EGL_BAD_ATTRIBUTE,
5410                               "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
5411                               "without EGL_ANGLE_surface_orientation support.");
5412                 return false;
5413             }
5414             break;
5415 
5416         case EGL_FIXED_SIZE_ANGLE:
5417             if (!display->getExtensions().windowFixedSize)
5418             {
5419                 val->setError(EGL_BAD_ATTRIBUTE,
5420                               "EGL_FIXED_SIZE_ANGLE cannot be used without "
5421                               "EGL_ANGLE_window_fixed_size support.");
5422                 return false;
5423             }
5424             break;
5425 
5426         case EGL_SURFACE_ORIENTATION_ANGLE:
5427             if (!display->getExtensions().surfaceOrientation)
5428             {
5429                 val->setError(EGL_BAD_ATTRIBUTE,
5430                               "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
5431                               "queried without "
5432                               "EGL_ANGLE_surface_orientation support.");
5433                 return false;
5434             }
5435             break;
5436 
5437         case EGL_DIRECT_COMPOSITION_ANGLE:
5438             if (!display->getExtensions().directComposition)
5439             {
5440                 val->setError(EGL_BAD_ATTRIBUTE,
5441                               "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
5442                               "used without "
5443                               "EGL_ANGLE_direct_composition support.");
5444                 return false;
5445             }
5446             break;
5447 
5448         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
5449             if (!display->getExtensions().robustResourceInitializationANGLE)
5450             {
5451                 val->setError(EGL_BAD_ATTRIBUTE,
5452                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
5453                               "used without EGL_ANGLE_robust_resource_initialization "
5454                               "support.");
5455                 return false;
5456             }
5457             break;
5458 
5459         case EGL_TIMESTAMPS_ANDROID:
5460             if (!display->getExtensions().getFrameTimestamps)
5461             {
5462                 val->setError(EGL_BAD_ATTRIBUTE,
5463                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
5464                               "EGL_ANDROID_get_frame_timestamps support.");
5465                 return false;
5466             }
5467             break;
5468 
5469         case EGL_BUFFER_AGE_EXT:
5470         {
5471             if (!display->getExtensions().bufferAgeEXT)
5472             {
5473                 val->setError(EGL_BAD_ATTRIBUTE,
5474                               "EGL_BUFFER_AGE_EXT cannot be used without "
5475                               "EGL_EXT_buffer_age support.");
5476                 return false;
5477             }
5478             gl::Context *context = val->eglThread->getContext();
5479             if ((context == nullptr) || (context->getCurrentDrawSurface() != surface))
5480             {
5481                 val->setError(EGL_BAD_SURFACE,
5482                               "The surface must be current to the current context "
5483                               "in order to query buffer age per extension "
5484                               "EGL_EXT_buffer_age.");
5485                 return false;
5486             }
5487         }
5488         break;
5489 
5490         case EGL_BITMAP_PITCH_KHR:
5491         case EGL_BITMAP_ORIGIN_KHR:
5492         case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
5493         case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
5494         case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
5495         case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
5496         case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
5497         case EGL_BITMAP_PIXEL_SIZE_KHR:
5498             if (!display->getExtensions().lockSurface3KHR)
5499             {
5500                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not supported.");
5501                 return false;
5502             }
5503             break;
5504 
5505         case EGL_PROTECTED_CONTENT_EXT:
5506             if (!display->getExtensions().protectedContentEXT)
5507             {
5508                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
5509                 return false;
5510             }
5511             break;
5512 
5513         default:
5514             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
5515             return false;
5516     }
5517 
5518     return true;
5519 }
5520 
ValidateQueryContext(const ValidationContext * val,const Display * display,const gl::Context * context,EGLint attribute,const EGLint * value)5521 bool ValidateQueryContext(const ValidationContext *val,
5522                           const Display *display,
5523                           const gl::Context *context,
5524                           EGLint attribute,
5525                           const EGLint *value)
5526 {
5527     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
5528 
5529     switch (attribute)
5530     {
5531         case EGL_CONFIG_ID:
5532         case EGL_CONTEXT_CLIENT_TYPE:
5533         case EGL_CONTEXT_CLIENT_VERSION:
5534         case EGL_RENDER_BUFFER:
5535             break;
5536 
5537         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
5538             if (!display->getExtensions().robustResourceInitializationANGLE)
5539             {
5540                 val->setError(EGL_BAD_ATTRIBUTE,
5541                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
5542                               "used without EGL_ANGLE_robust_resource_initialization "
5543                               "support.");
5544                 return false;
5545             }
5546             break;
5547 
5548         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
5549             if (!display->getExtensions().contextPriority)
5550             {
5551                 val->setError(EGL_BAD_ATTRIBUTE,
5552                               "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
5553                               "extension EGL_IMG_context_priority.");
5554                 return false;
5555             }
5556             break;
5557 
5558         case EGL_PROTECTED_CONTENT_EXT:
5559             if (!display->getExtensions().protectedContentEXT)
5560             {
5561                 val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
5562                 return false;
5563             }
5564             break;
5565 
5566         default:
5567             val->setError(EGL_BAD_ATTRIBUTE, "Invalid context attribute: 0x%04X", attribute);
5568             return false;
5569     }
5570 
5571     return true;
5572 }
5573 
ValidateDebugMessageControlKHR(const ValidationContext * val,EGLDEBUGPROCKHR callback,const AttributeMap & attribs)5574 bool ValidateDebugMessageControlKHR(const ValidationContext *val,
5575                                     EGLDEBUGPROCKHR callback,
5576                                     const AttributeMap &attribs)
5577 {
5578     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5579     if (!clientExtensions.debug)
5580     {
5581         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5582         return false;
5583     }
5584 
5585     attribs.initializeWithoutValidation();
5586 
5587     for (const auto &attrib : attribs)
5588     {
5589         switch (attrib.first)
5590         {
5591             case EGL_DEBUG_MSG_CRITICAL_KHR:
5592             case EGL_DEBUG_MSG_ERROR_KHR:
5593             case EGL_DEBUG_MSG_WARN_KHR:
5594             case EGL_DEBUG_MSG_INFO_KHR:
5595                 if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
5596                 {
5597                     val->setError(EGL_BAD_ATTRIBUTE,
5598                                   "message controls must be EGL_TRUE or EGL_FALSE.");
5599                     return false;
5600                 }
5601                 break;
5602         }
5603     }
5604 
5605     return true;
5606 }
5607 
ValidateQueryDebugKHR(const ValidationContext * val,EGLint attribute,const EGLAttrib * value)5608 bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value)
5609 {
5610     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5611     if (!clientExtensions.debug)
5612     {
5613         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5614         return false;
5615     }
5616 
5617     switch (attribute)
5618     {
5619         case EGL_DEBUG_MSG_CRITICAL_KHR:
5620         case EGL_DEBUG_MSG_ERROR_KHR:
5621         case EGL_DEBUG_MSG_WARN_KHR:
5622         case EGL_DEBUG_MSG_INFO_KHR:
5623         case EGL_DEBUG_CALLBACK_KHR:
5624             break;
5625 
5626         default:
5627             val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04X", attribute);
5628             return false;
5629     }
5630 
5631     return true;
5632 }
5633 
ValidateLabelObjectKHR(const ValidationContext * val,const Display * display,ObjectType objectType,EGLObjectKHR object,EGLLabelKHR label)5634 bool ValidateLabelObjectKHR(const ValidationContext *val,
5635                             const Display *display,
5636                             ObjectType objectType,
5637                             EGLObjectKHR object,
5638                             EGLLabelKHR label)
5639 {
5640     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5641     if (!clientExtensions.debug)
5642     {
5643         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5644         return false;
5645     }
5646 
5647     LabeledObject *labeledObject = nullptr;
5648     ANGLE_VALIDATION_TRY(ValidateLabeledObject(val, display, objectType, object, &labeledObject));
5649 
5650     return true;
5651 }
5652 
ValidateGetCompositorTimingSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,CompositorTiming name)5653 bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
5654                                                  const Display *display,
5655                                                  const Surface *surface,
5656                                                  CompositorTiming name)
5657 {
5658     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5659 
5660     if (!display->getExtensions().getFrameTimestamps)
5661     {
5662         val->setError(EGL_BAD_DISPLAY,
5663                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5664         return false;
5665     }
5666 
5667     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5668 
5669     if (!ValidCompositorTimingName(name))
5670     {
5671         val->setError(EGL_BAD_PARAMETER, "invalid timing name.");
5672         return false;
5673     }
5674 
5675     return true;
5676 }
5677 
ValidateGetCompositorTimingANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLint numTimestamps,const EGLint * names,const EGLnsecsANDROID * values)5678 bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
5679                                         const Display *display,
5680                                         const Surface *surface,
5681                                         EGLint numTimestamps,
5682                                         const EGLint *names,
5683                                         const EGLnsecsANDROID *values)
5684 {
5685     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5686 
5687     if (!display->getExtensions().getFrameTimestamps)
5688     {
5689         val->setError(EGL_BAD_DISPLAY,
5690                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5691         return false;
5692     }
5693 
5694     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5695 
5696     if (names == nullptr && numTimestamps > 0)
5697     {
5698         val->setError(EGL_BAD_PARAMETER, "names is NULL.");
5699         return false;
5700     }
5701 
5702     if (values == nullptr && numTimestamps > 0)
5703     {
5704         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5705         return false;
5706     }
5707 
5708     if (numTimestamps < 0)
5709     {
5710         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5711         return false;
5712     }
5713 
5714     for (EGLint i = 0; i < numTimestamps; i++)
5715     {
5716         CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
5717 
5718         if (!ValidCompositorTimingName(name))
5719         {
5720             val->setError(EGL_BAD_PARAMETER, "invalid compositor timing.");
5721             return false;
5722         }
5723 
5724         if (!surface->getSupportedCompositorTimings().test(name))
5725         {
5726             val->setError(EGL_BAD_PARAMETER, "compositor timing not supported by surface.");
5727             return false;
5728         }
5729     }
5730 
5731     return true;
5732 }
5733 
ValidateGetNextFrameIdANDROID(const ValidationContext * val,const Display * display,const Surface * surface,const EGLuint64KHR * frameId)5734 bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
5735                                    const Display *display,
5736                                    const Surface *surface,
5737                                    const EGLuint64KHR *frameId)
5738 {
5739     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5740 
5741     if (!display->getExtensions().getFrameTimestamps)
5742     {
5743         val->setError(EGL_BAD_DISPLAY,
5744                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5745         return false;
5746     }
5747 
5748     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5749 
5750     if (frameId == nullptr)
5751     {
5752         val->setError(EGL_BAD_PARAMETER, "frameId is NULL.");
5753         return false;
5754     }
5755 
5756     return true;
5757 }
5758 
ValidateGetFrameTimestampSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,Timestamp timestamp)5759 bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
5760                                                const Display *display,
5761                                                const Surface *surface,
5762                                                Timestamp timestamp)
5763 {
5764     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5765 
5766     if (!display->getExtensions().getFrameTimestamps)
5767     {
5768         val->setError(EGL_BAD_DISPLAY,
5769                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5770         return false;
5771     }
5772 
5773     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5774 
5775     if (!ValidTimestampType(timestamp))
5776     {
5777         val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5778         return false;
5779     }
5780 
5781     return true;
5782 }
5783 
ValidateGetFrameTimestampsANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,const EGLnsecsANDROID * values)5784 bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
5785                                        const Display *display,
5786                                        const Surface *surface,
5787                                        EGLuint64KHR frameId,
5788                                        EGLint numTimestamps,
5789                                        const EGLint *timestamps,
5790                                        const EGLnsecsANDROID *values)
5791 {
5792     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5793 
5794     if (!display->getExtensions().getFrameTimestamps)
5795     {
5796         val->setError(EGL_BAD_DISPLAY,
5797                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5798         return false;
5799     }
5800 
5801     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5802 
5803     if (!surface->isTimestampsEnabled())
5804     {
5805         val->setError(EGL_BAD_SURFACE, "timestamp collection is not enabled for this surface.");
5806         return false;
5807     }
5808 
5809     if (timestamps == nullptr && numTimestamps > 0)
5810     {
5811         val->setError(EGL_BAD_PARAMETER, "timestamps is NULL.");
5812         return false;
5813     }
5814 
5815     if (values == nullptr && numTimestamps > 0)
5816     {
5817         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5818         return false;
5819     }
5820 
5821     if (numTimestamps < 0)
5822     {
5823         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5824         return false;
5825     }
5826 
5827     for (EGLint i = 0; i < numTimestamps; i++)
5828     {
5829         Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
5830 
5831         if (!ValidTimestampType(timestamp))
5832         {
5833             val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5834             return false;
5835         }
5836 
5837         if (!surface->getSupportedTimestamps().test(timestamp))
5838         {
5839             val->setError(EGL_BAD_PARAMETER, "timestamp not supported by surface.");
5840             return false;
5841         }
5842     }
5843 
5844     return true;
5845 }
5846 
ValidateQueryStringiANGLE(const ValidationContext * val,const Display * display,EGLint name,EGLint index)5847 bool ValidateQueryStringiANGLE(const ValidationContext *val,
5848                                const Display *display,
5849                                EGLint name,
5850                                EGLint index)
5851 {
5852     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5853 
5854     if (!Display::GetClientExtensions().featureControlANGLE)
5855     {
5856         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_feature_control extension is not available.");
5857         return false;
5858     }
5859 
5860     if (index < 0)
5861     {
5862         val->setError(EGL_BAD_PARAMETER, "index is negative.");
5863         return false;
5864     }
5865 
5866     switch (name)
5867     {
5868         case EGL_FEATURE_NAME_ANGLE:
5869         case EGL_FEATURE_CATEGORY_ANGLE:
5870         case EGL_FEATURE_DESCRIPTION_ANGLE:
5871         case EGL_FEATURE_BUG_ANGLE:
5872         case EGL_FEATURE_STATUS_ANGLE:
5873         case EGL_FEATURE_CONDITION_ANGLE:
5874             break;
5875         default:
5876             val->setError(EGL_BAD_PARAMETER, "name is not valid.");
5877             return false;
5878     }
5879 
5880     if (static_cast<size_t>(index) >= display->getFeatures().size())
5881     {
5882         val->setError(EGL_BAD_PARAMETER, "index is too big.");
5883         return false;
5884     }
5885 
5886     return true;
5887 }
5888 
ValidateQueryDisplayAttribEXT(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5889 bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
5890                                    const Display *display,
5891                                    const EGLint attribute,
5892                                    const EGLAttrib *value)
5893 {
5894     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5895     return true;
5896 }
5897 
ValidateQueryDisplayAttribANGLE(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5898 bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
5899                                      const Display *display,
5900                                      const EGLint attribute,
5901                                      const EGLAttrib *value)
5902 {
5903     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5904     return true;
5905 }
5906 
ValidateGetNativeClientBufferANDROID(const ValidationContext * val,const AHardwareBuffer * buffer)5907 bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
5908                                           const AHardwareBuffer *buffer)
5909 {
5910     // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
5911     // despite it being a display extension.  No display is needed for the implementation though.
5912     if (buffer == nullptr)
5913     {
5914         val->setError(EGL_BAD_PARAMETER, "NULL buffer.");
5915         return false;
5916     }
5917 
5918     return true;
5919 }
5920 
ValidateCreateNativeClientBufferANDROID(const ValidationContext * val,const egl::AttributeMap & attribMap)5921 bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
5922                                              const egl::AttributeMap &attribMap)
5923 {
5924     attribMap.initializeWithoutValidation();
5925 
5926     if (attribMap.isEmpty() || attribMap.begin()->second == EGL_NONE)
5927     {
5928         val->setError(EGL_BAD_PARAMETER, "invalid attribute list.");
5929         return false;
5930     }
5931 
5932     int width     = attribMap.getAsInt(EGL_WIDTH, 0);
5933     int height    = attribMap.getAsInt(EGL_HEIGHT, 0);
5934     int redSize   = attribMap.getAsInt(EGL_RED_SIZE, 0);
5935     int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
5936     int blueSize  = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
5937     int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
5938     int usage     = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
5939 
5940     for (AttributeMap::const_iterator attributeIter = attribMap.begin();
5941          attributeIter != attribMap.end(); attributeIter++)
5942     {
5943         EGLAttrib attribute = attributeIter->first;
5944         switch (attribute)
5945         {
5946             case EGL_WIDTH:
5947             case EGL_HEIGHT:
5948                 // Validation done after the switch statement
5949                 break;
5950             case EGL_RED_SIZE:
5951             case EGL_GREEN_SIZE:
5952             case EGL_BLUE_SIZE:
5953             case EGL_ALPHA_SIZE:
5954                 if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
5955                 {
5956                     val->setError(EGL_BAD_PARAMETER, "incorrect channel size requested");
5957                     return false;
5958                 }
5959                 break;
5960             case EGL_NATIVE_BUFFER_USAGE_ANDROID:
5961                 // The buffer must be used for either a texture or a renderbuffer.
5962                 if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
5963                                EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
5964                                EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
5965                 {
5966                     val->setError(EGL_BAD_PARAMETER, "invalid usage flag");
5967                     return false;
5968                 }
5969                 break;
5970             case EGL_NONE:
5971                 break;
5972             default:
5973                 val->setError(EGL_BAD_ATTRIBUTE, "invalid attribute");
5974                 return false;
5975         }
5976     }
5977 
5978     // Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
5979     // for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
5980     if (width <= 0 || height <= 0)
5981     {
5982         val->setError(EGL_BAD_PARAMETER, "incorrect buffer dimensions requested");
5983         return false;
5984     }
5985 
5986     if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
5987     {
5988         val->setError(EGL_BAD_PARAMETER, "unsupported format");
5989         return false;
5990     }
5991     return true;
5992 }
5993 
ValidateDupNativeFenceFDANDROID(const ValidationContext * val,const Display * display,const Sync * sync)5994 bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
5995                                      const Display *display,
5996                                      const Sync *sync)
5997 {
5998     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5999 
6000     if (!display->getExtensions().nativeFenceSyncANDROID)
6001     {
6002         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_native_fence_sync extension is not available.");
6003         return false;
6004     }
6005 
6006     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
6007 
6008     return true;
6009 }
6010 
ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext * val,const Display * display,const Surface * surface,EGLFrameTokenANGLE frametoken)6011 bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
6012                                             const Display *display,
6013                                             const Surface *surface,
6014                                             EGLFrameTokenANGLE frametoken)
6015 {
6016     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6017 
6018     if (!display->getExtensions().swapWithFrameToken)
6019     {
6020         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available.");
6021         return false;
6022     }
6023 
6024     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
6025 
6026     return true;
6027 }
6028 
ValidatePrepareSwapBuffersANGLE(const ValidationContext * val,const Display * display,const Surface * surface)6029 bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val,
6030                                      const Display *display,
6031                                      const Surface *surface)
6032 {
6033     return ValidateSwapBuffers(val, display, surface);
6034 }
6035 
ValidateSignalSyncKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLenum mode)6036 bool ValidateSignalSyncKHR(const ValidationContext *val,
6037                            const Display *display,
6038                            const Sync *sync,
6039                            EGLenum mode)
6040 {
6041     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6042 
6043     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
6044 
6045     if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
6046     {
6047         if (!display->getExtensions().reusableSyncKHR)
6048         {
6049             val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
6050             return false;
6051         }
6052 
6053         if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
6054         {
6055             val->setError(EGL_BAD_PARAMETER, "eglSignalSyncKHR invalid mode.");
6056             return false;
6057         }
6058 
6059         return true;
6060     }
6061 
6062     val->setError(EGL_BAD_MATCH);
6063     return false;
6064 }
6065 
ValidateQuerySurfacePointerANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint attribute,void * const * value)6066 bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
6067                                       const Display *display,
6068                                       const Surface *eglSurface,
6069                                       EGLint attribute,
6070                                       void *const *value)
6071 {
6072     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6073 
6074     if (!display->getExtensions().querySurfacePointer)
6075     {
6076         val->setError(EGL_BAD_ACCESS);
6077         return false;
6078     }
6079 
6080     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
6081 
6082     // validate the attribute parameter
6083     switch (attribute)
6084     {
6085         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
6086             if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
6087             {
6088                 val->setError(EGL_BAD_ATTRIBUTE);
6089                 return false;
6090             }
6091             break;
6092         case EGL_DXGI_KEYED_MUTEX_ANGLE:
6093             if (!display->getExtensions().keyedMutex)
6094             {
6095                 val->setError(EGL_BAD_ATTRIBUTE);
6096                 return false;
6097             }
6098             break;
6099         default:
6100             val->setError(EGL_BAD_ATTRIBUTE);
6101             return false;
6102     }
6103 
6104     return true;
6105 }
6106 
ValidatePostSubBufferNV(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint x,EGLint y,EGLint width,EGLint height)6107 bool ValidatePostSubBufferNV(const ValidationContext *val,
6108                              const Display *display,
6109                              const Surface *eglSurface,
6110                              EGLint x,
6111                              EGLint y,
6112                              EGLint width,
6113                              EGLint height)
6114 {
6115     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6116 
6117     if (!display->getExtensions().postSubBuffer)
6118     {
6119         val->setError(EGL_BAD_ACCESS);
6120         return false;
6121     }
6122 
6123     if (x < 0 || y < 0 || width < 0 || height < 0)
6124     {
6125         val->setError(EGL_BAD_PARAMETER);
6126         return false;
6127     }
6128 
6129     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
6130 
6131     if (display->isDeviceLost())
6132     {
6133         val->setError(EGL_CONTEXT_LOST);
6134         return false;
6135     }
6136 
6137     return true;
6138 }
6139 
ValidateQueryDeviceAttribEXT(const ValidationContext * val,const Device * device,EGLint attribute,const EGLAttrib * value)6140 bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
6141                                   const Device *device,
6142                                   EGLint attribute,
6143                                   const EGLAttrib *value)
6144 {
6145     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
6146 
6147     if (!Display::GetClientExtensions().deviceQueryEXT)
6148     {
6149         val->setError(EGL_BAD_ACCESS, "EGL_EXT_device_query not supported.");
6150         return false;
6151     }
6152 
6153     // validate the attribute parameter
6154     switch (attribute)
6155     {
6156         case EGL_D3D11_DEVICE_ANGLE:
6157         case EGL_D3D9_DEVICE_ANGLE:
6158             if (!device->getExtensions().deviceD3D || device->getType() != attribute)
6159             {
6160                 val->setError(EGL_BAD_ATTRIBUTE);
6161                 return false;
6162             }
6163             break;
6164         case EGL_EAGL_CONTEXT_ANGLE:
6165             if (!device->getExtensions().deviceEAGL)
6166             {
6167                 val->setError(EGL_BAD_ATTRIBUTE);
6168                 return false;
6169             }
6170             break;
6171         case EGL_METAL_DEVICE_ANGLE:
6172             if (!device->getExtensions().deviceMetal)
6173             {
6174                 val->setError(EGL_BAD_ATTRIBUTE);
6175                 return false;
6176             }
6177             break;
6178         case EGL_VULKAN_VERSION_ANGLE:
6179         case EGL_VULKAN_INSTANCE_ANGLE:
6180         case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
6181         case EGL_VULKAN_PHYSICAL_DEVICE_ANGLE:
6182         case EGL_VULKAN_DEVICE_ANGLE:
6183         case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
6184         case EGL_VULKAN_FEATURES_ANGLE:
6185         case EGL_VULKAN_QUEUE_ANGLE:
6186         case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
6187         case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
6188             if (!device->getExtensions().deviceVulkan)
6189             {
6190                 val->setError(EGL_BAD_ATTRIBUTE);
6191                 return false;
6192             }
6193             break;
6194         case EGL_CGL_CONTEXT_ANGLE:
6195         case EGL_CGL_PIXEL_FORMAT_ANGLE:
6196             if (!device->getExtensions().deviceCGL)
6197             {
6198                 val->setError(EGL_BAD_ATTRIBUTE);
6199                 return false;
6200             }
6201             break;
6202         default:
6203             val->setError(EGL_BAD_ATTRIBUTE);
6204             return false;
6205     }
6206     return true;
6207 }
6208 
ValidateQueryDeviceStringEXT(const ValidationContext * val,const Device * device,EGLint name)6209 bool ValidateQueryDeviceStringEXT(const ValidationContext *val, const Device *device, EGLint name)
6210 {
6211     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
6212     return true;
6213 }
6214 
ValidateReleaseHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)6215 bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
6216                                       const Display *display,
6217                                       const gl::Context *context)
6218 {
6219     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
6220     return true;
6221 }
6222 
ValidateReacquireHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)6223 bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
6224                                         const Display *display,
6225                                         const gl::Context *context)
6226 {
6227     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
6228     return true;
6229 }
6230 
ValidateHandleGPUSwitchANGLE(const ValidationContext * val,const Display * display)6231 bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *display)
6232 {
6233     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6234     return true;
6235 }
6236 
ValidateForceGPUSwitchANGLE(const ValidationContext * val,const Display * display,EGLint gpuIDHigh,EGLint gpuIDLow)6237 bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
6238                                  const Display *display,
6239                                  EGLint gpuIDHigh,
6240                                  EGLint gpuIDLow)
6241 {
6242     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6243     return true;
6244 }
6245 
ValidateGetCurrentDisplay(const ValidationContext * val)6246 bool ValidateGetCurrentDisplay(const ValidationContext *val)
6247 {
6248     return true;
6249 }
6250 
ValidateGetCurrentSurface(const ValidationContext * val,EGLint readdraw)6251 bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw)
6252 {
6253     return true;
6254 }
6255 
ValidateGetDisplay(const ValidationContext * val,EGLNativeDisplayType display_id)6256 bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id)
6257 {
6258     return true;
6259 }
6260 
ValidateGetError(const ValidationContext * val)6261 bool ValidateGetError(const ValidationContext *val)
6262 {
6263     return true;
6264 }
6265 
ValidateGetProcAddress(const ValidationContext * val,const char * procname)6266 bool ValidateGetProcAddress(const ValidationContext *val, const char *procname)
6267 {
6268     return true;
6269 }
6270 
ValidateQueryString(const ValidationContext * val,const Display * dpyPacked,EGLint name)6271 bool ValidateQueryString(const ValidationContext *val, const Display *dpyPacked, EGLint name)
6272 {
6273     if (name != EGL_EXTENSIONS || dpyPacked != nullptr)
6274     {
6275         ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpyPacked));
6276     }
6277 
6278     switch (name)
6279     {
6280         case EGL_CLIENT_APIS:
6281         case EGL_EXTENSIONS:
6282         case EGL_VENDOR:
6283         case EGL_VERSION:
6284             break;
6285         default:
6286             val->setError(EGL_BAD_PARAMETER);
6287             return false;
6288     }
6289     return true;
6290 }
6291 
ValidateWaitGL(const ValidationContext * val)6292 bool ValidateWaitGL(const ValidationContext *val)
6293 {
6294     if (val->eglThread->getDisplay() == nullptr)
6295     {
6296         // EGL spec says this about eglWaitGL -
6297         //    eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
6298         return true;
6299     }
6300 
6301     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
6302     return true;
6303 }
6304 
ValidateQueryAPI(const ValidationContext * val)6305 bool ValidateQueryAPI(const ValidationContext *val)
6306 {
6307     return true;
6308 }
6309 
ValidateReleaseThread(const ValidationContext * val)6310 bool ValidateReleaseThread(const ValidationContext *val)
6311 {
6312     return true;
6313 }
6314 
ValidateWaitClient(const ValidationContext * val)6315 bool ValidateWaitClient(const ValidationContext *val)
6316 {
6317     if (val->eglThread->getDisplay() == nullptr)
6318     {
6319         // EGL spec says this about eglWaitClient -
6320         //    If there is no current context for the current rendering API,
6321         //    the function has no effect but still returns EGL_TRUE.
6322         return true;
6323     }
6324 
6325     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
6326     return true;
6327 }
6328 
ValidateGetCurrentContext(const ValidationContext * val)6329 bool ValidateGetCurrentContext(const ValidationContext *val)
6330 {
6331     return true;
6332 }
6333 
ValidateCreatePlatformPixmapSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_pixmap,const AttributeMap & attrib_listPacked)6334 bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
6335                                          const Display *dpyPacked,
6336                                          const Config *configPacked,
6337                                          const void *native_pixmap,
6338                                          const AttributeMap &attrib_listPacked)
6339 {
6340     EGLNativePixmapType nativePixmap =
6341         reinterpret_cast<EGLNativePixmapType>(const_cast<void *>(native_pixmap));
6342     return ValidateCreatePixmapSurface(val, dpyPacked, configPacked, nativePixmap,
6343                                        attrib_listPacked);
6344 }
6345 
ValidateCreatePlatformWindowSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_window,const AttributeMap & attrib_listPacked)6346 bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
6347                                          const Display *dpyPacked,
6348                                          const Config *configPacked,
6349                                          const void *native_window,
6350                                          const AttributeMap &attrib_listPacked)
6351 {
6352     EGLNativeWindowType nativeWindow =
6353         reinterpret_cast<EGLNativeWindowType>(const_cast<void *>(native_window));
6354     return ValidateCreateWindowSurface(val, dpyPacked, configPacked, nativeWindow,
6355                                        attrib_listPacked);
6356 }
6357 
ValidateLockSurfaceKHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface,const AttributeMap & attributes)6358 bool ValidateLockSurfaceKHR(const ValidationContext *val,
6359                             const egl::Display *dpy,
6360                             const Surface *surface,
6361                             const AttributeMap &attributes)
6362 {
6363     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6364     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6365 
6366     if (!dpy->getExtensions().lockSurface3KHR)
6367     {
6368         val->setError(EGL_BAD_ACCESS);
6369         return false;
6370     }
6371 
6372     if (surface->isLocked())
6373     {
6374         val->setError(EGL_BAD_ACCESS);
6375         return false;
6376     }
6377 
6378     if ((surface->getConfig()->surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == false)
6379     {
6380         val->setError(EGL_BAD_ACCESS, "Config does not support EGL_LOCK_SURFACE_BIT");
6381         return false;
6382     }
6383 
6384     if (surface->isCurrentOnAnyContext())
6385     {
6386         val->setError(EGL_BAD_ACCESS,
6387                       "Surface cannot be current to a context for eglLockSurface()");
6388         return false;
6389     }
6390 
6391     if (surface->hasProtectedContent())
6392     {
6393         val->setError(EGL_BAD_ACCESS, "Surface cannot be protected content for eglLockSurface()");
6394         return false;
6395     }
6396 
6397     attributes.initializeWithoutValidation();
6398 
6399     for (const auto &attributeIter : attributes)
6400     {
6401         EGLAttrib attribute = attributeIter.first;
6402         EGLAttrib value     = attributeIter.second;
6403 
6404         switch (attribute)
6405         {
6406             case EGL_MAP_PRESERVE_PIXELS_KHR:
6407                 if (!((value == EGL_FALSE) || (value == EGL_TRUE)))
6408                 {
6409                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_MAP_PRESERVE_PIXELS_KHR value");
6410                     return false;
6411                 }
6412                 break;
6413             case EGL_LOCK_USAGE_HINT_KHR:
6414                 if ((value & (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR)) != value)
6415                 {
6416                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_LOCK_USAGE_HINT_KHR value");
6417                     return false;
6418                 }
6419                 break;
6420             default:
6421                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid query surface64 attribute");
6422                 return false;
6423         }
6424     }
6425 
6426     return true;
6427 }
6428 
ValidateQuerySurface64KHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface,EGLint attribute,const EGLAttribKHR * value)6429 bool ValidateQuerySurface64KHR(const ValidationContext *val,
6430                                const egl::Display *dpy,
6431                                const Surface *surface,
6432                                EGLint attribute,
6433                                const EGLAttribKHR *value)
6434 {
6435     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6436     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6437 
6438     if (!dpy->getExtensions().lockSurface3KHR)
6439     {
6440         val->setError(EGL_BAD_ACCESS);
6441         return false;
6442     }
6443 
6444     switch (attribute)
6445     {
6446         case EGL_BITMAP_PITCH_KHR:
6447         case EGL_BITMAP_ORIGIN_KHR:
6448         case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
6449         case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
6450         case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
6451         case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
6452         case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
6453         case EGL_BITMAP_PIXEL_SIZE_KHR:
6454         case EGL_BITMAP_POINTER_KHR:
6455             break;
6456         default:
6457             val->setError(EGL_BAD_ATTRIBUTE, "Invalid eglQuerySurface64 attribute");
6458             return false;
6459     }
6460 
6461     if (value == nullptr)
6462     {
6463         val->setError(EGL_BAD_PARAMETER, "value is NULL.");
6464         return false;
6465     }
6466 
6467     if (!surface->isLocked())
6468     {
6469         val->setError(EGL_BAD_ACCESS, "Surface is not locked");
6470         return false;
6471     }
6472 
6473     return true;
6474 }
6475 
ValidateUnlockSurfaceKHR(const ValidationContext * val,const egl::Display * dpy,const Surface * surface)6476 bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
6477                               const egl::Display *dpy,
6478                               const Surface *surface)
6479 {
6480     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6481     ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
6482 
6483     if (!dpy->getExtensions().lockSurface3KHR)
6484     {
6485         val->setError(EGL_BAD_ACCESS);
6486         return false;
6487     }
6488 
6489     if (!surface->isLocked())
6490     {
6491         val->setError(EGL_BAD_PARAMETER, "Surface is not locked.");
6492         return false;
6493     }
6494 
6495     return true;
6496 }
6497 
ValidateExportVkImageANGLE(const ValidationContext * val,const Display * dpy,const Image * image,const void * vkImage,const void * vkImageCreateInfo)6498 bool ValidateExportVkImageANGLE(const ValidationContext *val,
6499                                 const Display *dpy,
6500                                 const Image *image,
6501                                 const void *vkImage,
6502                                 const void *vkImageCreateInfo)
6503 {
6504     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6505     ANGLE_VALIDATION_TRY(ValidateImage(val, dpy, image));
6506 
6507     if (!dpy->getExtensions().vulkanImageANGLE)
6508     {
6509         val->setError(EGL_BAD_ACCESS);
6510         return false;
6511     }
6512 
6513     if (!vkImage)
6514     {
6515         val->setError(EGL_BAD_PARAMETER, "Output VkImage pointer is null.");
6516         return false;
6517     }
6518 
6519     if (!vkImageCreateInfo)
6520     {
6521         val->setError(EGL_BAD_PARAMETER, "Output VkImageCreateInfo pointer is null.");
6522         return false;
6523     }
6524 
6525     return true;
6526 }
6527 
ValidateSetDamageRegionKHR(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint * rects,EGLint n_rects)6528 bool ValidateSetDamageRegionKHR(const ValidationContext *val,
6529                                 const Display *display,
6530                                 const Surface *surface,
6531                                 const EGLint *rects,
6532                                 EGLint n_rects)
6533 {
6534     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
6535     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
6536 
6537     if (!(surface->getType() & EGL_WINDOW_BIT))
6538     {
6539         val->setError(EGL_BAD_MATCH, "surface is not a postable surface");
6540         return false;
6541     }
6542 
6543     if (surface != val->eglThread->getCurrentDrawSurface())
6544     {
6545         val->setError(EGL_BAD_MATCH,
6546                       "surface is not the current draw surface for the calling thread");
6547         return false;
6548     }
6549 
6550     if (surface->getSwapBehavior() != EGL_BUFFER_DESTROYED)
6551     {
6552         val->setError(EGL_BAD_MATCH, "surface's swap behavior is not EGL_BUFFER_DESTROYED");
6553         return false;
6554     }
6555 
6556     if (surface->isDamageRegionSet())
6557     {
6558         val->setError(
6559             EGL_BAD_ACCESS,
6560             "damage region has already been set on surface since the most recent frame boundary");
6561         return false;
6562     }
6563 
6564     if (!surface->bufferAgeQueriedSinceLastSwap())
6565     {
6566         val->setError(EGL_BAD_ACCESS,
6567                       "EGL_BUFFER_AGE_KHR attribute of surface has not been queried since the most "
6568                       "recent frame boundary");
6569         return false;
6570     }
6571 
6572     return true;
6573 }
6574 
ValidateQueryDmaBufFormatsEXT(ValidationContext const * val,Display const * dpy,EGLint max_formats,const EGLint * formats,const EGLint * num_formats)6575 bool ValidateQueryDmaBufFormatsEXT(ValidationContext const *val,
6576                                    Display const *dpy,
6577                                    EGLint max_formats,
6578                                    const EGLint *formats,
6579                                    const EGLint *num_formats)
6580 {
6581     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6582 
6583     if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
6584     {
6585         val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
6586         return false;
6587     }
6588 
6589     if (max_formats < 0)
6590     {
6591         val->setError(EGL_BAD_PARAMETER, "max_formats should not be negative");
6592         return false;
6593     }
6594 
6595     if (max_formats > 0 && formats == nullptr)
6596     {
6597         val->setError(EGL_BAD_PARAMETER, "if max_formats is positive, formats should not be NULL");
6598         return false;
6599     }
6600 
6601     return true;
6602 }
6603 
ValidateQueryDmaBufModifiersEXT(ValidationContext const * val,Display const * dpy,EGLint format,EGLint max_modifiers,const EGLuint64KHR * modifiers,const EGLBoolean * external_only,const EGLint * num_modifiers)6604 bool ValidateQueryDmaBufModifiersEXT(ValidationContext const *val,
6605                                      Display const *dpy,
6606                                      EGLint format,
6607                                      EGLint max_modifiers,
6608                                      const EGLuint64KHR *modifiers,
6609                                      const EGLBoolean *external_only,
6610                                      const EGLint *num_modifiers)
6611 {
6612     ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
6613 
6614     if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
6615     {
6616         val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
6617         return false;
6618     }
6619 
6620     if (max_modifiers < 0)
6621     {
6622         val->setError(EGL_BAD_PARAMETER, "max_modifiers should not be negative");
6623         return false;
6624     }
6625 
6626     if (max_modifiers > 0 && modifiers == nullptr)
6627     {
6628         val->setError(EGL_BAD_PARAMETER,
6629                       "if max_modifiers is positive, modifiers should not be NULL");
6630         return false;
6631     }
6632 
6633     if (!dpy->supportsDmaBufFormat(format))
6634     {
6635         val->setError(EGL_BAD_PARAMETER,
6636                       "format should be one of the formats advertised by QueryDmaBufFormatsEXT");
6637         return false;
6638     }
6639     return true;
6640 }
6641 
6642 }  // namespace egl
6643