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