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