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