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