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