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             default:
1993                 val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute.");
1994                 return false;
1995         }
1996     }
1997 
1998     switch (clientMajorVersion)
1999     {
2000         case 1:
2001             if (clientMinorVersion != 0 && clientMinorVersion != 1)
2002             {
2003                 val->setError(EGL_BAD_ATTRIBUTE);
2004                 return false;
2005             }
2006             if (configuration == EGL_NO_CONFIG_KHR)
2007             {
2008                 val->setError(EGL_BAD_MATCH);
2009                 return false;
2010             }
2011             if ((configuration != EGL_NO_CONFIG_KHR) &&
2012                 !(configuration->renderableType & EGL_OPENGL_ES_BIT))
2013             {
2014                 val->setError(EGL_BAD_MATCH);
2015                 return false;
2016             }
2017             break;
2018 
2019         case 2:
2020             if (clientMinorVersion != 0)
2021             {
2022                 val->setError(EGL_BAD_ATTRIBUTE);
2023                 return false;
2024             }
2025             if ((configuration != EGL_NO_CONFIG_KHR) &&
2026                 !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
2027             {
2028                 val->setError(EGL_BAD_MATCH);
2029                 return false;
2030             }
2031             break;
2032         case 3:
2033             if (clientMinorVersion < 0 || clientMinorVersion > 2)
2034             {
2035                 val->setError(EGL_BAD_ATTRIBUTE);
2036                 return false;
2037             }
2038             if ((configuration != EGL_NO_CONFIG_KHR) &&
2039                 !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
2040             {
2041                 val->setError(EGL_BAD_MATCH);
2042                 return false;
2043             }
2044             if (display->getMaxSupportedESVersion() <
2045                 gl::Version(static_cast<GLuint>(clientMajorVersion),
2046                             static_cast<GLuint>(clientMinorVersion)))
2047             {
2048                 val->setError(EGL_BAD_ATTRIBUTE, "Requested GLES version is not supported.");
2049                 return false;
2050             }
2051             break;
2052         default:
2053             val->setError(EGL_BAD_ATTRIBUTE);
2054             return false;
2055             break;
2056     }
2057 
2058     // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
2059     const EGLint validContextFlags =
2060         (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
2061     if ((contextFlags & ~validContextFlags) != 0)
2062     {
2063         val->setError(EGL_BAD_ATTRIBUTE);
2064         return false;
2065     }
2066 
2067     if (shareContext)
2068     {
2069         // Shared context is invalid or is owned by another display
2070         if (!display->isValidContext(shareContext))
2071         {
2072             val->setError(EGL_BAD_MATCH);
2073             return false;
2074         }
2075 
2076         if (shareContext->isResetNotificationEnabled() != resetNotification)
2077         {
2078             val->setError(EGL_BAD_MATCH);
2079             return false;
2080         }
2081     }
2082 
2083     return true;
2084 }
2085 
ValidateCreateWindowSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativeWindowType window,const AttributeMap & attributes)2086 bool ValidateCreateWindowSurface(const ValidationContext *val,
2087                                  const Display *display,
2088                                  const Config *config,
2089                                  EGLNativeWindowType window,
2090                                  const AttributeMap &attributes)
2091 {
2092     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2093 
2094     if (!display->isValidNativeWindow(window))
2095     {
2096         val->setError(EGL_BAD_NATIVE_WINDOW);
2097         return false;
2098     }
2099 
2100     const DisplayExtensions &displayExtensions = display->getExtensions();
2101 
2102     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2103          attributeIter != attributes.end(); attributeIter++)
2104     {
2105         EGLAttrib attribute = attributeIter->first;
2106         EGLAttrib value     = attributeIter->second;
2107 
2108         switch (attribute)
2109         {
2110             case EGL_RENDER_BUFFER:
2111                 switch (value)
2112                 {
2113                     case EGL_BACK_BUFFER:
2114                         break;
2115                     case EGL_SINGLE_BUFFER:
2116                         val->setError(EGL_BAD_MATCH);
2117                         return false;  // Rendering directly to front buffer not supported
2118                     default:
2119                         val->setError(EGL_BAD_ATTRIBUTE);
2120                         return false;
2121                 }
2122                 break;
2123 
2124             case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
2125                 if (!displayExtensions.postSubBuffer)
2126                 {
2127                     val->setError(EGL_BAD_ATTRIBUTE);
2128                     return false;
2129                 }
2130                 break;
2131 
2132             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
2133                 if (!displayExtensions.flexibleSurfaceCompatibility)
2134                 {
2135                     val->setError(EGL_BAD_ATTRIBUTE);
2136                     return false;
2137                 }
2138                 break;
2139 
2140             case EGL_WIDTH:
2141             case EGL_HEIGHT:
2142                 if (!displayExtensions.windowFixedSize)
2143                 {
2144                     val->setError(EGL_BAD_ATTRIBUTE);
2145                     return false;
2146                 }
2147                 if (value < 0)
2148                 {
2149                     val->setError(EGL_BAD_PARAMETER);
2150                     return false;
2151                 }
2152                 break;
2153 
2154             case EGL_FIXED_SIZE_ANGLE:
2155                 if (!displayExtensions.windowFixedSize)
2156                 {
2157                     val->setError(EGL_BAD_ATTRIBUTE);
2158                     return false;
2159                 }
2160                 break;
2161 
2162             case EGL_SURFACE_ORIENTATION_ANGLE:
2163                 if (!displayExtensions.surfaceOrientation)
2164                 {
2165                     val->setError(EGL_BAD_ATTRIBUTE,
2166                                   "EGL_ANGLE_surface_orientation is not enabled.");
2167                     return false;
2168                 }
2169                 break;
2170 
2171             case EGL_VG_COLORSPACE:
2172                 val->setError(EGL_BAD_MATCH);
2173                 return false;
2174 
2175             case EGL_GL_COLORSPACE:
2176                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2177                 break;
2178 
2179             case EGL_VG_ALPHA_FORMAT:
2180                 val->setError(EGL_BAD_MATCH);
2181                 return false;
2182 
2183             case EGL_DIRECT_COMPOSITION_ANGLE:
2184                 if (!displayExtensions.directComposition)
2185                 {
2186                     val->setError(EGL_BAD_ATTRIBUTE);
2187                     return false;
2188                 }
2189                 break;
2190 
2191             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
2192                 if (!display->getExtensions().robustResourceInitialization)
2193                 {
2194                     val->setError(EGL_BAD_ATTRIBUTE,
2195                                   "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
2196                                   "requires EGL_ANGLE_robust_resource_initialization.");
2197                     return false;
2198                 }
2199                 if (value != EGL_TRUE && value != EGL_FALSE)
2200                 {
2201                     val->setError(EGL_BAD_ATTRIBUTE,
2202                                   "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
2203                                   "either EGL_TRUE or EGL_FALSE.");
2204                     return false;
2205                 }
2206                 break;
2207 
2208             case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
2209                 if (!display->getExtensions().ggpStreamDescriptor)
2210                 {
2211                     val->setError(EGL_BAD_ATTRIBUTE,
2212                                   "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
2213                                   "EGL_ANGLE_ggp_stream_descriptor.");
2214                     return false;
2215                 }
2216                 break;
2217 
2218             default:
2219                 val->setError(EGL_BAD_ATTRIBUTE);
2220                 return false;
2221         }
2222     }
2223 
2224     if (Display::hasExistingWindowSurface(window))
2225     {
2226         val->setError(EGL_BAD_ALLOC);
2227         return false;
2228     }
2229 
2230     return true;
2231 }
2232 
ValidateCreatePbufferSurface(const ValidationContext * val,const Display * display,const Config * config,const AttributeMap & attributes)2233 bool ValidateCreatePbufferSurface(const ValidationContext *val,
2234                                   const Display *display,
2235                                   const Config *config,
2236                                   const AttributeMap &attributes)
2237 {
2238     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2239 
2240     const DisplayExtensions &displayExtensions = display->getExtensions();
2241 
2242     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2243          attributeIter != attributes.end(); attributeIter++)
2244     {
2245         EGLAttrib attribute = attributeIter->first;
2246         EGLAttrib value     = attributeIter->second;
2247 
2248         switch (attribute)
2249         {
2250             case EGL_WIDTH:
2251             case EGL_HEIGHT:
2252                 if (value < 0)
2253                 {
2254                     val->setError(EGL_BAD_PARAMETER);
2255                     return false;
2256                 }
2257                 break;
2258 
2259             case EGL_LARGEST_PBUFFER:
2260                 break;
2261 
2262             case EGL_TEXTURE_FORMAT:
2263                 switch (value)
2264                 {
2265                     case EGL_NO_TEXTURE:
2266                     case EGL_TEXTURE_RGB:
2267                     case EGL_TEXTURE_RGBA:
2268                         break;
2269                     default:
2270                         val->setError(EGL_BAD_ATTRIBUTE);
2271                         return false;
2272                 }
2273                 break;
2274 
2275             case EGL_TEXTURE_TARGET:
2276                 switch (value)
2277                 {
2278                     case EGL_NO_TEXTURE:
2279                     case EGL_TEXTURE_2D:
2280                         break;
2281                     default:
2282                         val->setError(EGL_BAD_ATTRIBUTE);
2283                         return false;
2284                 }
2285                 break;
2286 
2287             case EGL_MIPMAP_TEXTURE:
2288                 break;
2289 
2290             case EGL_VG_COLORSPACE:
2291                 break;
2292 
2293             case EGL_GL_COLORSPACE:
2294                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2295                 break;
2296 
2297             case EGL_VG_ALPHA_FORMAT:
2298                 break;
2299 
2300             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
2301                 if (!displayExtensions.flexibleSurfaceCompatibility)
2302                 {
2303                     val->setError(
2304                         EGL_BAD_ATTRIBUTE,
2305                         "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
2306                         "without EGL_ANGLE_flexible_surface_compatibility support.");
2307                     return false;
2308                 }
2309                 break;
2310 
2311             case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
2312                 if (!display->getExtensions().robustResourceInitialization)
2313                 {
2314                     val->setError(EGL_BAD_ATTRIBUTE,
2315                                   "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
2316                                   "requires EGL_ANGLE_robust_resource_initialization.");
2317                     return false;
2318                 }
2319                 if (value != EGL_TRUE && value != EGL_FALSE)
2320                 {
2321                     val->setError(EGL_BAD_ATTRIBUTE,
2322                                   "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
2323                                   "either EGL_TRUE or EGL_FALSE.");
2324                     return false;
2325                 }
2326                 break;
2327 
2328             default:
2329                 val->setError(EGL_BAD_ATTRIBUTE);
2330                 return false;
2331         }
2332     }
2333 
2334     if (!(config->surfaceType & EGL_PBUFFER_BIT))
2335     {
2336         val->setError(EGL_BAD_MATCH);
2337         return false;
2338     }
2339 
2340     const Caps &caps = display->getCaps();
2341 
2342     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2343     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2344 
2345     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2346         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2347     {
2348         val->setError(EGL_BAD_MATCH);
2349         return false;
2350     }
2351 
2352     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2353         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2354     {
2355         val->setError(EGL_BAD_ATTRIBUTE);
2356         return false;
2357     }
2358 
2359     EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2360     EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2361     if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2362         (!gl::isPow2(width) || !gl::isPow2(height)))
2363     {
2364         val->setError(EGL_BAD_MATCH);
2365         return false;
2366     }
2367 
2368     return true;
2369 }
2370 
ValidateCreatePbufferFromClientBuffer(const ValidationContext * val,const Display * display,EGLenum buftype,EGLClientBuffer buffer,const Config * config,const AttributeMap & attributes)2371 bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
2372                                            const Display *display,
2373                                            EGLenum buftype,
2374                                            EGLClientBuffer buffer,
2375                                            const Config *config,
2376                                            const AttributeMap &attributes)
2377 {
2378     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2379 
2380     const DisplayExtensions &displayExtensions = display->getExtensions();
2381 
2382     switch (buftype)
2383     {
2384         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
2385             if (!displayExtensions.d3dShareHandleClientBuffer)
2386             {
2387                 val->setError(EGL_BAD_PARAMETER);
2388                 return false;
2389             }
2390             if (buffer == nullptr)
2391             {
2392                 val->setError(EGL_BAD_PARAMETER);
2393                 return false;
2394             }
2395             break;
2396 
2397         case EGL_D3D_TEXTURE_ANGLE:
2398             if (!displayExtensions.d3dTextureClientBuffer)
2399             {
2400                 val->setError(EGL_BAD_PARAMETER);
2401                 return false;
2402             }
2403             if (buffer == nullptr)
2404             {
2405                 val->setError(EGL_BAD_PARAMETER);
2406                 return false;
2407             }
2408             break;
2409 
2410         case EGL_IOSURFACE_ANGLE:
2411             if (!displayExtensions.iosurfaceClientBuffer)
2412             {
2413                 val->setError(EGL_BAD_PARAMETER,
2414                               "<buftype> EGL_IOSURFACE_ANGLE requires the "
2415                               "EGL_ANGLE_iosurface_client_buffer extension.");
2416                 return false;
2417             }
2418             if (buffer == nullptr)
2419             {
2420                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be non null");
2421                 return false;
2422             }
2423             break;
2424         case EGL_EXTERNAL_SURFACE_ANGLE:
2425             if (!display->getExtensions().externalContextAndSurface)
2426             {
2427                 val->setError(EGL_BAD_ATTRIBUTE,
2428                               "Attribute "
2429                               "EGL_EXTERNAL_SURFACE_ANGLE requires "
2430                               "EGL_ANGLE_external_context_and_surface.");
2431                 return false;
2432             }
2433             if (buffer != nullptr)
2434             {
2435                 val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
2436                 return false;
2437             }
2438             break;
2439 
2440         default:
2441             val->setError(EGL_BAD_PARAMETER);
2442             return false;
2443     }
2444 
2445     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2446          attributeIter != attributes.end(); attributeIter++)
2447     {
2448         EGLAttrib attribute = attributeIter->first;
2449         EGLAttrib value     = attributeIter->second;
2450 
2451         switch (attribute)
2452         {
2453             case EGL_WIDTH:
2454             case EGL_HEIGHT:
2455                 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
2456                     buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
2457                     buftype != EGL_EXTERNAL_SURFACE_ANGLE)
2458                 {
2459                     val->setError(EGL_BAD_PARAMETER,
2460                                   "Width and Height are not supported for this <buftype>");
2461                     return false;
2462                 }
2463                 if (value < 0)
2464                 {
2465                     val->setError(EGL_BAD_PARAMETER, "Width and Height must be positive");
2466                     return false;
2467                 }
2468                 break;
2469 
2470             case EGL_TEXTURE_FORMAT:
2471                 switch (value)
2472                 {
2473                     case EGL_NO_TEXTURE:
2474                     case EGL_TEXTURE_RGB:
2475                     case EGL_TEXTURE_RGBA:
2476                         break;
2477                     default:
2478                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_FORMAT");
2479                         return false;
2480                 }
2481                 break;
2482 
2483             case EGL_TEXTURE_TARGET:
2484                 switch (value)
2485                 {
2486                     case EGL_NO_TEXTURE:
2487                     case EGL_TEXTURE_2D:
2488                         break;
2489                     case EGL_TEXTURE_RECTANGLE_ANGLE:
2490                         if (buftype != EGL_IOSURFACE_ANGLE)
2491                         {
2492                             val->setError(EGL_BAD_PARAMETER,
2493                                           "<buftype> doesn't support rectangle texture targets");
2494                             return false;
2495                         }
2496                         break;
2497 
2498                     default:
2499                         val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_TARGET");
2500                         return false;
2501                 }
2502                 break;
2503 
2504             case EGL_MIPMAP_TEXTURE:
2505                 break;
2506 
2507             case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
2508                 if (!displayExtensions.flexibleSurfaceCompatibility)
2509                 {
2510                     val->setError(
2511                         EGL_BAD_ATTRIBUTE,
2512                         "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
2513                         "without EGL_ANGLE_flexible_surface_compatibility support.");
2514                     return false;
2515                 }
2516                 break;
2517 
2518             case EGL_IOSURFACE_PLANE_ANGLE:
2519                 if (buftype != EGL_IOSURFACE_ANGLE)
2520                 {
2521                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support iosurface plane");
2522                     return false;
2523                 }
2524                 break;
2525 
2526             case EGL_TEXTURE_TYPE_ANGLE:
2527                 if (buftype != EGL_IOSURFACE_ANGLE)
2528                 {
2529                     val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support texture type");
2530                     return false;
2531                 }
2532                 break;
2533 
2534             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2535                 if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
2536                 {
2537                     val->setError(EGL_BAD_ATTRIBUTE,
2538                                   "<buftype> doesn't support texture internal format");
2539                     return false;
2540                 }
2541                 break;
2542 
2543             case EGL_GL_COLORSPACE:
2544                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2545                 {
2546                     val->setError(EGL_BAD_ATTRIBUTE,
2547                                   "<buftype> doesn't support setting GL colorspace");
2548                     return false;
2549                 }
2550                 break;
2551 
2552             case EGL_IOSURFACE_USAGE_HINT_ANGLE:
2553                 if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
2554                 {
2555                     val->setError(EGL_BAD_ATTRIBUTE,
2556                                   "IOSurface usage hint must only contain READ or WRITE");
2557                     return false;
2558                 }
2559                 break;
2560 
2561             case EGL_TEXTURE_OFFSET_X_ANGLE:
2562             case EGL_TEXTURE_OFFSET_Y_ANGLE:
2563                 if (buftype != EGL_D3D_TEXTURE_ANGLE)
2564                 {
2565                     val->setError(EGL_BAD_ATTRIBUTE,
2566                                   "<buftype> doesn't support setting texture offset");
2567                     return false;
2568                 }
2569                 if (value < 0)
2570                 {
2571                     val->setError(EGL_BAD_ATTRIBUTE, "Texture offset cannot be negative");
2572                     return false;
2573                 }
2574                 break;
2575 
2576             default:
2577                 val->setError(EGL_BAD_ATTRIBUTE);
2578                 return false;
2579         }
2580     }
2581 
2582     EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
2583     if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
2584     {
2585         val->setError(EGL_BAD_ATTRIBUTE, "invalid GL colorspace");
2586         return false;
2587     }
2588 
2589     if (!(config->surfaceType & EGL_PBUFFER_BIT))
2590     {
2591         val->setError(EGL_BAD_MATCH);
2592         return false;
2593     }
2594 
2595     EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
2596     EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
2597     if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
2598         (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
2599     {
2600         val->setError(EGL_BAD_MATCH);
2601         return false;
2602     }
2603     if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
2604         (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
2605     {
2606         // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
2607         // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
2608         // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
2609         // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
2610         // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
2611         // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
2612         // OSX?
2613         if (buftype != EGL_IOSURFACE_ANGLE)
2614         {
2615             val->setError(EGL_BAD_ATTRIBUTE);
2616             return false;
2617         }
2618     }
2619 
2620     if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
2621     {
2622         EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
2623         EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
2624 
2625         if (width == 0 || height == 0)
2626         {
2627             val->setError(EGL_BAD_ATTRIBUTE);
2628             return false;
2629         }
2630 
2631         const Caps &caps = display->getCaps();
2632         if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
2633             (!gl::isPow2(width) || !gl::isPow2(height)))
2634         {
2635             val->setError(EGL_BAD_MATCH);
2636             return false;
2637         }
2638     }
2639 
2640     if (buftype == EGL_IOSURFACE_ANGLE)
2641     {
2642         if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
2643         {
2644             val->setError(EGL_BAD_ATTRIBUTE,
2645                           "EGL_IOSURFACE requires the texture target to match the config");
2646             return false;
2647         }
2648         if (textureFormat != EGL_TEXTURE_RGBA)
2649         {
2650             val->setError(EGL_BAD_ATTRIBUTE, "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format");
2651             return false;
2652         }
2653 
2654         if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
2655             !attributes.contains(EGL_TEXTURE_FORMAT) ||
2656             !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
2657             !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
2658             !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
2659         {
2660             val->setError(EGL_BAD_PARAMETER, "Missing required attribute for EGL_IOSURFACE");
2661             return false;
2662         }
2663     }
2664 
2665     ANGLE_EGL_TRY_RETURN(val->eglThread,
2666                          display->validateClientBuffer(config, buftype, buffer, attributes),
2667                          val->entryPoint, val->labeledObject, false);
2668 
2669     return true;
2670 }
2671 
ValidateCreatePixmapSurface(const ValidationContext * val,const Display * display,const Config * config,EGLNativePixmapType pixmap,const AttributeMap & attributes)2672 bool ValidateCreatePixmapSurface(const ValidationContext *val,
2673                                  const Display *display,
2674                                  const Config *config,
2675                                  EGLNativePixmapType pixmap,
2676                                  const AttributeMap &attributes)
2677 {
2678     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
2679 
2680     const DisplayExtensions &displayExtensions = display->getExtensions();
2681 
2682     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2683          attributeIter != attributes.end(); attributeIter++)
2684     {
2685         EGLAttrib attribute = attributeIter->first;
2686         EGLAttrib value     = attributeIter->second;
2687 
2688         switch (attribute)
2689         {
2690             case EGL_GL_COLORSPACE:
2691                 ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
2692                 break;
2693 
2694             case EGL_VG_COLORSPACE:
2695                 break;
2696             case EGL_VG_ALPHA_FORMAT:
2697                 break;
2698 
2699             case EGL_TEXTURE_FORMAT:
2700                 if (!displayExtensions.textureFromPixmapNOK)
2701                 {
2702                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2703                     return false;
2704                 }
2705                 switch (value)
2706                 {
2707                     case EGL_NO_TEXTURE:
2708                     case EGL_TEXTURE_RGB:
2709                     case EGL_TEXTURE_RGBA:
2710                         break;
2711                     default:
2712                         val->setError(EGL_BAD_ATTRIBUTE);
2713                         return false;
2714                 }
2715                 break;
2716 
2717             case EGL_TEXTURE_TARGET:
2718                 if (!displayExtensions.textureFromPixmapNOK)
2719                 {
2720                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2721                     return false;
2722                 }
2723                 switch (value)
2724                 {
2725                     case EGL_NO_TEXTURE:
2726                     case EGL_TEXTURE_2D:
2727                         break;
2728                     default:
2729                         val->setError(EGL_BAD_ATTRIBUTE);
2730                         return false;
2731                 }
2732                 break;
2733 
2734             case EGL_MIPMAP_TEXTURE:
2735                 if (!displayExtensions.textureFromPixmapNOK)
2736                 {
2737                     val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
2738                     return false;
2739                 }
2740                 break;
2741 
2742             default:
2743                 val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute");
2744                 return false;
2745         }
2746     }
2747 
2748     if (!(config->surfaceType & EGL_PIXMAP_BIT))
2749     {
2750         val->setError(EGL_BAD_MATCH, "Congfig does not suport pixmaps.");
2751         return false;
2752     }
2753 
2754     ANGLE_EGL_TRY_RETURN(val->eglThread, display->valdiatePixmap(config, pixmap, attributes),
2755                          val->entryPoint, val->labeledObject, false);
2756 
2757     return true;
2758 }
2759 
ValidateMakeCurrent(const ValidationContext * val,const Display * display,const Surface * draw,const Surface * read,const gl::Context * context)2760 bool ValidateMakeCurrent(const ValidationContext *val,
2761                          const Display *display,
2762                          const Surface *draw,
2763                          const Surface *read,
2764                          const gl::Context *context)
2765 {
2766     if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
2767     {
2768         val->setError(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
2769         return false;
2770     }
2771 
2772     // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
2773     // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
2774     if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
2775     {
2776         if (display->getExtensions().surfacelessContext)
2777         {
2778             if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
2779             {
2780                 val->setError(EGL_BAD_MATCH,
2781                               "If ctx is not EGL_NOT_CONTEXT, draw or read must "
2782                               "both be EGL_NO_SURFACE, or both not");
2783                 return false;
2784             }
2785         }
2786         else
2787         {
2788             val->setError(EGL_BAD_MATCH,
2789                           "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
2790             return false;
2791         }
2792     }
2793 
2794     // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
2795     // EGL_BAD_MATCH error is generated.
2796     if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
2797     {
2798         val->setError(EGL_BAD_MATCH,
2799                       "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
2800         return false;
2801     }
2802 
2803     if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
2804     {
2805         val->setError(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
2806         return false;
2807     }
2808 
2809     // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
2810     if (!display->isInitialized() &&
2811         (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
2812     {
2813         val->setError(EGL_NOT_INITIALIZED, "'dpy' not initialized");
2814         return false;
2815     }
2816 
2817     if (context != EGL_NO_CONTEXT)
2818     {
2819         ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
2820     }
2821 
2822     if (display->isInitialized() && display->isDeviceLost())
2823     {
2824         val->setError(EGL_CONTEXT_LOST);
2825         return false;
2826     }
2827 
2828     if (draw != EGL_NO_SURFACE)
2829     {
2830         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, draw));
2831     }
2832 
2833     if (read != EGL_NO_SURFACE)
2834     {
2835         ANGLE_VALIDATION_TRY(ValidateSurface(val, display, read));
2836         ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
2837     }
2838 
2839     if (draw != read)
2840     {
2841         if (draw)
2842         {
2843             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, draw));
2844         }
2845         if (read)
2846         {
2847             ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
2848         }
2849     }
2850     return true;
2851 }
2852 
ValidateCreateImage(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)2853 bool ValidateCreateImage(const ValidationContext *val,
2854                          const Display *display,
2855                          const gl::Context *context,
2856                          EGLenum target,
2857                          EGLClientBuffer buffer,
2858                          const AttributeMap &attributes)
2859 {
2860 
2861     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
2862 
2863     const DisplayExtensions &displayExtensions = display->getExtensions();
2864 
2865     // TODO(geofflang): Complete validation from EGL_KHR_image_base:
2866     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
2867     // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
2868 
2869     for (AttributeMap::const_iterator attributeIter = attributes.begin();
2870          attributeIter != attributes.end(); attributeIter++)
2871     {
2872         EGLAttrib attribute = attributeIter->first;
2873         EGLAttrib value     = attributeIter->second;
2874 
2875         switch (attribute)
2876         {
2877             case EGL_IMAGE_PRESERVED:
2878                 switch (value)
2879                 {
2880                     case EGL_TRUE:
2881                     case EGL_FALSE:
2882                         break;
2883 
2884                     default:
2885                         val->setError(EGL_BAD_PARAMETER,
2886                                       "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.");
2887                         return false;
2888                 }
2889                 break;
2890 
2891             case EGL_GL_TEXTURE_LEVEL:
2892                 if (!displayExtensions.glTexture2DImage &&
2893                     !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
2894                 {
2895                     val->setError(EGL_BAD_PARAMETER,
2896                                   "EGL_GL_TEXTURE_LEVEL cannot be used "
2897                                   "without KHR_gl_texture_*_image support.");
2898                     return false;
2899                 }
2900 
2901                 if (value < 0)
2902                 {
2903                     val->setError(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL cannot be negative.");
2904                     return false;
2905                 }
2906                 break;
2907 
2908             case EGL_GL_TEXTURE_ZOFFSET:
2909                 if (!displayExtensions.glTexture3DImage)
2910                 {
2911                     val->setError(EGL_BAD_PARAMETER,
2912                                   "EGL_GL_TEXTURE_ZOFFSET cannot be used "
2913                                   "without KHR_gl_texture_3D_image support.");
2914                     return false;
2915                 }
2916                 break;
2917 
2918             case EGL_GL_COLORSPACE:
2919                 if (!displayExtensions.glColorspace)
2920                 {
2921                     val->setError(EGL_BAD_PARAMETER,
2922                                   "EGL_GL_COLORSPACE cannot be used "
2923                                   "without EGL_KHR_gl_colorspace support.");
2924                     return false;
2925                 }
2926                 switch (value)
2927                 {
2928                     case EGL_GL_COLORSPACE_DEFAULT_EXT:
2929                         break;
2930                     default:
2931                         ANGLE_VALIDATION_TRY(
2932                             ValidateColorspaceAttribute(val, displayExtensions, value));
2933                         break;
2934                 }
2935                 break;
2936 
2937             case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2938                 if (!displayExtensions.imageD3D11Texture)
2939                 {
2940                     val->setError(
2941                         EGL_BAD_PARAMETER,
2942                         "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE cannot "
2943                         "be used without EGL_ANGLE_image_d3d11_texture support.");
2944                     return false;
2945                 }
2946                 break;
2947 
2948             case EGL_D3D11_TEXTURE_PLANE_ANGLE:
2949                 if (!displayExtensions.imageD3D11Texture)
2950                 {
2951                     val->setError(EGL_BAD_ATTRIBUTE,
2952                                   "EGL_D3D11_TEXTURE_PLANE_ANGLE cannot be used without "
2953                                   "EGL_ANGLE_image_d3d11_texture support.");
2954                     return false;
2955                 }
2956                 break;
2957 
2958             case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
2959                 if (!displayExtensions.imageD3D11Texture)
2960                 {
2961                     val->setError(EGL_BAD_ATTRIBUTE,
2962                                   "EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
2963                                   "EGL_ANGLE_image_d3d11_texture support.");
2964                     return false;
2965                 }
2966                 break;
2967 
2968             case EGL_WIDTH:
2969             case EGL_HEIGHT:
2970                 if (target != EGL_LINUX_DMA_BUF_EXT)
2971                 {
2972                     val->setError(
2973                         EGL_BAD_PARAMETER,
2974                         "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT");
2975                     return false;
2976                 }
2977                 break;
2978 
2979             case EGL_LINUX_DRM_FOURCC_EXT:
2980             case EGL_DMA_BUF_PLANE0_FD_EXT:
2981             case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
2982             case EGL_DMA_BUF_PLANE0_PITCH_EXT:
2983             case EGL_DMA_BUF_PLANE1_FD_EXT:
2984             case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
2985             case EGL_DMA_BUF_PLANE1_PITCH_EXT:
2986             case EGL_DMA_BUF_PLANE2_FD_EXT:
2987             case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
2988             case EGL_DMA_BUF_PLANE2_PITCH_EXT:
2989                 if (!displayExtensions.imageDmaBufImportEXT)
2990                 {
2991                     val->setError(EGL_BAD_PARAMETER,
2992                                   "Parameter cannot be used without "
2993                                   "EGL_EXT_image_dma_buf_import support.");
2994                     return false;
2995                 }
2996                 break;
2997 
2998             case EGL_YUV_COLOR_SPACE_HINT_EXT:
2999                 if (!displayExtensions.imageDmaBufImportEXT)
3000                 {
3001                     val->setError(EGL_BAD_PARAMETER,
3002                                   "Parameter cannot be used without "
3003                                   "EGL_EXT_image_dma_buf_import support.");
3004                     return false;
3005                 }
3006 
3007                 switch (value)
3008                 {
3009                     case EGL_ITU_REC601_EXT:
3010                     case EGL_ITU_REC709_EXT:
3011                     case EGL_ITU_REC2020_EXT:
3012                         break;
3013 
3014                     default:
3015                         val->setError(EGL_BAD_PARAMETER,
3016                                       "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.");
3017                         return false;
3018                 }
3019                 break;
3020 
3021             case EGL_SAMPLE_RANGE_HINT_EXT:
3022                 if (!displayExtensions.imageDmaBufImportEXT)
3023                 {
3024                     val->setError(EGL_BAD_PARAMETER,
3025                                   "Parameter cannot be used without "
3026                                   "EGL_EXT_image_dma_buf_import support.");
3027                     return false;
3028                 }
3029 
3030                 switch (value)
3031                 {
3032                     case EGL_YUV_FULL_RANGE_EXT:
3033                     case EGL_YUV_NARROW_RANGE_EXT:
3034                         break;
3035 
3036                     default:
3037                         val->setError(EGL_BAD_PARAMETER,
3038                                       "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.");
3039                         return false;
3040                 }
3041                 break;
3042 
3043             case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
3044             case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
3045                 if (!displayExtensions.imageDmaBufImportEXT)
3046                 {
3047                     val->setError(EGL_BAD_PARAMETER,
3048                                   "Parameter cannot be used without "
3049                                   "EGL_EXT_image_dma_buf_import support.");
3050                     return false;
3051                 }
3052 
3053                 switch (value)
3054                 {
3055                     case EGL_YUV_CHROMA_SITING_0_EXT:
3056                     case EGL_YUV_CHROMA_SITING_0_5_EXT:
3057                         break;
3058 
3059                     default:
3060                         val->setError(
3061                             EGL_BAD_PARAMETER,
3062                             "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
3063                             "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.");
3064                         return false;
3065                 }
3066                 break;
3067 
3068             case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
3069             case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
3070             case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
3071             case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
3072             case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
3073             case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
3074             case EGL_DMA_BUF_PLANE3_FD_EXT:
3075             case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
3076             case EGL_DMA_BUF_PLANE3_PITCH_EXT:
3077             case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
3078             case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
3079                 if (!displayExtensions.imageDmaBufImportModifiersEXT)
3080                 {
3081                     val->setError(EGL_BAD_PARAMETER,
3082                                   "Parameter cannot be used without "
3083                                   "EGL_EXT_image_dma_buf_import_modifiers support.");
3084                     return false;
3085                 }
3086                 break;
3087 
3088             default:
3089                 val->setError(EGL_BAD_PARAMETER, "invalid attribute: 0x%X", attribute);
3090                 return false;
3091         }
3092     }
3093 
3094     switch (target)
3095     {
3096         case EGL_GL_TEXTURE_2D:
3097         {
3098             if (!displayExtensions.glTexture2DImage)
3099             {
3100                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
3101                 return false;
3102             }
3103 
3104             if (buffer == 0)
3105             {
3106                 val->setError(EGL_BAD_PARAMETER,
3107                               "buffer cannot reference a 2D texture with the name 0.");
3108                 return false;
3109             }
3110 
3111             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3112             const gl::Texture *texture =
3113                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3114             if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
3115             {
3116                 val->setError(EGL_BAD_PARAMETER, "target is not a 2D texture.");
3117                 return false;
3118             }
3119 
3120             if (texture->getBoundSurface() != nullptr)
3121             {
3122                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3123                 return false;
3124             }
3125 
3126             EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3127             if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
3128                 texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
3129             {
3130                 val->setError(EGL_BAD_PARAMETER,
3131                               "target 2D texture does not have a valid size at specified level.");
3132                 return false;
3133             }
3134 
3135             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3136         }
3137         break;
3138 
3139         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
3140         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
3141         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
3142         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
3143         case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
3144         case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
3145         {
3146             if (!displayExtensions.glTextureCubemapImage)
3147             {
3148                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
3149                 return false;
3150             }
3151 
3152             if (buffer == 0)
3153             {
3154                 val->setError(EGL_BAD_PARAMETER,
3155                               "buffer cannot reference a cubemap texture with the name 0.");
3156                 return false;
3157             }
3158 
3159             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3160             const gl::Texture *texture =
3161                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3162             if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
3163             {
3164                 val->setError(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
3165                 return false;
3166             }
3167 
3168             if (texture->getBoundSurface() != nullptr)
3169             {
3170                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3171                 return false;
3172             }
3173 
3174             EGLAttrib level               = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3175             gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
3176             if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
3177                 texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
3178             {
3179                 val->setError(EGL_BAD_PARAMETER,
3180                               "target cubemap texture does not have a valid "
3181                               "size at specified level and face.");
3182                 return false;
3183             }
3184 
3185             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3186 
3187             if (level == 0 && !texture->isMipmapComplete() &&
3188                 CubeTextureHasUnspecifiedLevel0Face(texture))
3189             {
3190                 val->setError(EGL_BAD_PARAMETER,
3191                               "if level is zero and the texture is incomplete, "
3192                               "it must have all of its faces specified at level "
3193                               "zero.");
3194                 return false;
3195             }
3196         }
3197         break;
3198 
3199         case EGL_GL_TEXTURE_3D:
3200         {
3201             if (!displayExtensions.glTexture3DImage)
3202             {
3203                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
3204                 return false;
3205             }
3206 
3207             if (buffer == 0)
3208             {
3209                 val->setError(EGL_BAD_PARAMETER,
3210                               "buffer cannot reference a 3D texture with the name 0.");
3211                 return false;
3212             }
3213 
3214             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3215             const gl::Texture *texture =
3216                 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3217             if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
3218             {
3219                 val->setError(EGL_BAD_PARAMETER, "target is not a 3D texture.");
3220                 return false;
3221             }
3222 
3223             if (texture->getBoundSurface() != nullptr)
3224             {
3225                 val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
3226                 return false;
3227             }
3228 
3229             EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
3230             EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
3231             if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3232                 texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
3233                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
3234             {
3235                 val->setError(EGL_BAD_PARAMETER,
3236                               "target 3D texture does not have a valid size at specified level.");
3237                 return false;
3238             }
3239 
3240             if (static_cast<size_t>(zOffset) >=
3241                 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
3242             {
3243                 val->setError(EGL_BAD_PARAMETER,
3244                               "target 3D texture does not have enough layers "
3245                               "for the specified Z offset at the specified "
3246                               "level.");
3247                 return false;
3248             }
3249 
3250             ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
3251         }
3252         break;
3253 
3254         case EGL_GL_RENDERBUFFER:
3255         {
3256             if (!displayExtensions.glRenderbufferImage)
3257             {
3258                 val->setError(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
3259                 return false;
3260             }
3261 
3262             if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
3263             {
3264                 val->setError(EGL_BAD_PARAMETER,
3265                               "EGL_GL_TEXTURE_LEVEL cannot be used in "
3266                               "conjunction with a renderbuffer target.");
3267                 return false;
3268             }
3269 
3270             if (buffer == 0)
3271             {
3272                 val->setError(EGL_BAD_PARAMETER,
3273                               "buffer cannot reference a renderbuffer with the name 0.");
3274                 return false;
3275             }
3276 
3277             ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3278             const gl::Renderbuffer *renderbuffer =
3279                 context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
3280             if (renderbuffer == nullptr)
3281             {
3282                 val->setError(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
3283                 return false;
3284             }
3285 
3286             if (renderbuffer->getSamples() > 0)
3287             {
3288                 val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
3289                 return false;
3290             }
3291         }
3292         break;
3293 
3294         case EGL_NATIVE_BUFFER_ANDROID:
3295         {
3296             if (!displayExtensions.imageNativeBuffer)
3297             {
3298                 val->setError(EGL_BAD_PARAMETER, "EGL_ANDROID_image_native_buffer not supported.");
3299                 return false;
3300             }
3301 
3302             if (context != nullptr)
3303             {
3304                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3305                 return false;
3306             }
3307 
3308             ANGLE_EGL_TRY_RETURN(
3309                 val->eglThread,
3310                 display->validateImageClientBuffer(context, target, buffer, attributes),
3311                 val->entryPoint, val->labeledObject, false);
3312         }
3313         break;
3314 
3315         case EGL_D3D11_TEXTURE_ANGLE:
3316             if (!displayExtensions.imageD3D11Texture)
3317             {
3318                 val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_image_d3d11_texture not supported.");
3319                 return false;
3320             }
3321 
3322             if (context != nullptr)
3323             {
3324                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3325                 return false;
3326             }
3327 
3328             ANGLE_EGL_TRY_RETURN(
3329                 val->eglThread,
3330                 display->validateImageClientBuffer(context, target, buffer, attributes),
3331                 val->entryPoint, val->labeledObject, false);
3332             break;
3333 
3334         case EGL_LINUX_DMA_BUF_EXT:
3335             if (!displayExtensions.imageDmaBufImportEXT)
3336             {
3337                 val->setError(EGL_BAD_PARAMETER, "EGL_EXT_image_dma_buf_import not supported.");
3338                 return false;
3339             }
3340 
3341             if (context != nullptr)
3342             {
3343                 val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
3344                 return false;
3345             }
3346 
3347             if (buffer != nullptr)
3348             {
3349                 val->setError(EGL_BAD_PARAMETER, "buffer must be NULL.");
3350                 return false;
3351             }
3352 
3353             {
3354                 EGLenum kRequiredParameters[] = {EGL_WIDTH,
3355                                                  EGL_HEIGHT,
3356                                                  EGL_LINUX_DRM_FOURCC_EXT,
3357                                                  EGL_DMA_BUF_PLANE0_FD_EXT,
3358                                                  EGL_DMA_BUF_PLANE0_OFFSET_EXT,
3359                                                  EGL_DMA_BUF_PLANE0_PITCH_EXT};
3360                 for (EGLenum requiredParameter : kRequiredParameters)
3361                 {
3362                     if (!attributes.contains(requiredParameter))
3363                     {
3364                         val->setError(EGL_BAD_PARAMETER,
3365                                       "Missing required parameter 0x%X for image target "
3366                                       "EGL_LINUX_DMA_BUF_EXT.",
3367                                       requiredParameter);
3368                         return false;
3369                     }
3370                 }
3371 
3372                 bool containPlane0ModifierLo =
3373                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
3374                 bool containPlane0ModifierHi =
3375                     attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
3376                 bool containPlane1ModifierLo =
3377                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
3378                 bool containPlane1ModifierHi =
3379                     attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
3380                 bool containPlane2ModifierLo =
3381                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
3382                 bool containPlane2ModifierHi =
3383                     attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
3384                 bool containPlane3ModifierLo =
3385                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
3386                 bool containPlane3ModifierHi =
3387                     attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
3388                 if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
3389                     (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
3390                     (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
3391                     (containPlane3ModifierLo ^ containPlane3ModifierHi))
3392                 {
3393                     val->setError(
3394                         EGL_BAD_PARAMETER,
3395                         "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
3396                         "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.");
3397                     return false;
3398                 }
3399             }
3400             break;
3401 
3402         case EGL_METAL_TEXTURE_ANGLE:
3403             if (!displayExtensions.mtlTextureClientBuffer)
3404             {
3405                 val->setError(EGL_BAD_PARAMETER,
3406                               "EGL_ANGLE_metal_texture_client_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             break;
3421 
3422         default:
3423             val->setError(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
3424             return false;
3425     }
3426 
3427     if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
3428     {
3429         val->setError(EGL_BAD_PARAMETER,
3430                       "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.");
3431         return false;
3432     }
3433 
3434     return true;
3435 }
3436 
ValidateDestroyImage(const ValidationContext * val,const Display * display,const Image * image)3437 bool ValidateDestroyImage(const ValidationContext *val, const Display *display, const Image *image)
3438 {
3439     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3440 
3441     return true;
3442 }
3443 
ValidateCreateImageKHR(const ValidationContext * val,const Display * display,const gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)3444 bool ValidateCreateImageKHR(const ValidationContext *val,
3445                             const Display *display,
3446                             const gl::Context *context,
3447                             EGLenum target,
3448                             EGLClientBuffer buffer,
3449                             const AttributeMap &attributes)
3450 {
3451     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3452 
3453     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3454     {
3455         // It is out of spec what happens when calling an extension function when the extension is
3456         // not available.
3457         // EGL_BAD_DISPLAY seems like a reasonable error.
3458         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
3459         return false;
3460     }
3461 
3462     return ValidateCreateImage(val, display, context, target, buffer, attributes);
3463 }
3464 
ValidateDestroyImageKHR(const ValidationContext * val,const Display * display,const Image * image)3465 bool ValidateDestroyImageKHR(const ValidationContext *val,
3466                              const Display *display,
3467                              const Image *image)
3468 {
3469     ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
3470 
3471     if (!display->getExtensions().imageBase && !display->getExtensions().image)
3472     {
3473         // It is out of spec what happens when calling an extension function when the extension is
3474         // not available.
3475         // EGL_BAD_DISPLAY seems like a reasonable error.
3476         val->setError(EGL_BAD_DISPLAY);
3477         return false;
3478     }
3479 
3480     return true;
3481 }
3482 
ValidateCreateDeviceANGLE(const ValidationContext * val,EGLint device_type,const void * native_device,const EGLAttrib * attrib_list)3483 bool ValidateCreateDeviceANGLE(const ValidationContext *val,
3484                                EGLint device_type,
3485                                const void *native_device,
3486                                const EGLAttrib *attrib_list)
3487 {
3488     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3489     if (!clientExtensions.deviceCreation)
3490     {
3491         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3492         return false;
3493     }
3494 
3495     if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
3496     {
3497         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
3498         return false;
3499     }
3500 
3501     switch (device_type)
3502     {
3503         case EGL_D3D11_DEVICE_ANGLE:
3504             if (!clientExtensions.deviceCreationD3D11)
3505             {
3506                 val->setError(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
3507                 return false;
3508             }
3509             break;
3510         default:
3511             val->setError(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
3512             return false;
3513     }
3514 
3515     return true;
3516 }
3517 
ValidateReleaseDeviceANGLE(const ValidationContext * val,const Device * device)3518 bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *device)
3519 {
3520     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3521     if (!clientExtensions.deviceCreation)
3522     {
3523         val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
3524         return false;
3525     }
3526 
3527     if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
3528     {
3529         val->setError(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
3530         return false;
3531     }
3532 
3533     Display *owningDisplay = device->getOwningDisplay();
3534     if (owningDisplay != nullptr)
3535     {
3536         val->setError(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
3537         return false;
3538     }
3539 
3540     return true;
3541 }
3542 
ValidateCreateSync(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3543 bool ValidateCreateSync(const ValidationContext *val,
3544                         const Display *display,
3545                         EGLenum type,
3546                         const AttributeMap &attribs)
3547 {
3548     return ValidateCreateSyncBase(val, display, type, attribs, false);
3549 }
3550 
ValidateCreateSyncKHR(const ValidationContext * val,const Display * display,EGLenum type,const AttributeMap & attribs)3551 bool ValidateCreateSyncKHR(const ValidationContext *val,
3552                            const Display *display,
3553                            EGLenum type,
3554                            const AttributeMap &attribs)
3555 {
3556     return ValidateCreateSyncBase(val, display, type, attribs, true);
3557 }
3558 
ValidateDestroySync(const ValidationContext * val,const Display * display,const Sync * sync)3559 bool ValidateDestroySync(const ValidationContext *val, const Display *display, const Sync *sync)
3560 {
3561     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3562     return true;
3563 }
3564 
ValidateDestroySyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked)3565 bool ValidateDestroySyncKHR(const ValidationContext *val,
3566                             const Display *dpyPacked,
3567                             const Sync *syncPacked)
3568 {
3569     return ValidateDestroySync(val, dpyPacked, syncPacked);
3570 }
3571 
ValidateClientWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags,EGLTime timeout)3572 bool ValidateClientWaitSync(const ValidationContext *val,
3573                             const Display *display,
3574                             const Sync *sync,
3575                             EGLint flags,
3576                             EGLTime timeout)
3577 {
3578     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3579     return true;
3580 }
3581 
ValidateClientWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags,EGLTimeKHR timeout)3582 bool ValidateClientWaitSyncKHR(const ValidationContext *val,
3583                                const Display *dpyPacked,
3584                                const Sync *syncPacked,
3585                                EGLint flags,
3586                                EGLTimeKHR timeout)
3587 {
3588     return ValidateClientWaitSync(val, dpyPacked, syncPacked, flags, timeout);
3589 }
3590 
ValidateWaitSync(const ValidationContext * val,const Display * display,const Sync * sync,EGLint flags)3591 bool ValidateWaitSync(const ValidationContext *val,
3592                       const Display *display,
3593                       const Sync *sync,
3594                       EGLint flags)
3595 {
3596     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3597 
3598     const DisplayExtensions &extensions = display->getExtensions();
3599     if (!extensions.waitSync)
3600     {
3601         val->setError(EGL_BAD_ACCESS, "EGL_KHR_wait_sync extension is not available");
3602         return false;
3603     }
3604 
3605     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
3606 
3607     gl::Context *context = val->eglThread->getContext();
3608     if (context == nullptr)
3609     {
3610         val->setError(EGL_BAD_MATCH, "No context is current.");
3611         return false;
3612     }
3613 
3614     if (!context->getExtensions().eglSyncOES)
3615     {
3616         val->setError(EGL_BAD_MATCH,
3617                       "Server-side waits cannot be performed without "
3618                       "GL_OES_EGL_sync support.");
3619         return false;
3620     }
3621 
3622     if (flags != 0)
3623     {
3624         val->setError(EGL_BAD_PARAMETER, "flags must be zero");
3625         return false;
3626     }
3627 
3628     return true;
3629 }
3630 
ValidateWaitSyncKHR(const ValidationContext * val,const Display * dpyPacked,const Sync * syncPacked,EGLint flags)3631 bool ValidateWaitSyncKHR(const ValidationContext *val,
3632                          const Display *dpyPacked,
3633                          const Sync *syncPacked,
3634                          EGLint flags)
3635 {
3636     return ValidateWaitSync(val, dpyPacked, syncPacked, flags);
3637 }
3638 
ValidateGetSyncAttrib(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLAttrib * value)3639 bool ValidateGetSyncAttrib(const ValidationContext *val,
3640                            const Display *display,
3641                            const Sync *sync,
3642                            EGLint attribute,
3643                            const EGLAttrib *value)
3644 {
3645     if (value == nullptr)
3646     {
3647         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
3648         return false;
3649     }
3650     return ValidateGetSyncAttribBase(val, display, sync, attribute);
3651 }
3652 
ValidateGetSyncAttribKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLint attribute,const EGLint * value)3653 bool ValidateGetSyncAttribKHR(const ValidationContext *val,
3654                               const Display *display,
3655                               const Sync *sync,
3656                               EGLint attribute,
3657                               const EGLint *value)
3658 {
3659     if (value == nullptr)
3660     {
3661         val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
3662         return false;
3663     }
3664     return ValidateGetSyncAttribBase(val, display, sync, attribute);
3665 }
3666 
ValidateCreateStreamKHR(const ValidationContext * val,const Display * display,const AttributeMap & attributes)3667 bool ValidateCreateStreamKHR(const ValidationContext *val,
3668                              const Display *display,
3669                              const AttributeMap &attributes)
3670 {
3671     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3672 
3673     const DisplayExtensions &displayExtensions = display->getExtensions();
3674     if (!displayExtensions.stream)
3675     {
3676         val->setError(EGL_BAD_ALLOC, "Stream extension not active");
3677         return false;
3678     }
3679 
3680     for (const auto &attributeIter : attributes)
3681     {
3682         EGLAttrib attribute = attributeIter.first;
3683         EGLAttrib value     = attributeIter.second;
3684 
3685         ANGLE_VALIDATION_TRY(ValidateStreamAttribute(val, attribute, value, displayExtensions));
3686     }
3687 
3688     return true;
3689 }
3690 
ValidateDestroyStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream)3691 bool ValidateDestroyStreamKHR(const ValidationContext *val,
3692                               const Display *display,
3693                               const Stream *stream)
3694 {
3695     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
3696     return true;
3697 }
3698 
ValidateStreamAttribKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,EGLint value)3699 bool ValidateStreamAttribKHR(const ValidationContext *val,
3700                              const Display *display,
3701                              const Stream *stream,
3702                              EGLenum attribute,
3703                              EGLint value)
3704 {
3705     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
3706 
3707     if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
3708     {
3709         val->setError(EGL_BAD_STATE_KHR, "Bad stream state");
3710         return false;
3711     }
3712 
3713     return ValidateStreamAttribute(val, attribute, value, display->getExtensions());
3714 }
3715 
ValidateQueryStreamKHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLint * value)3716 bool ValidateQueryStreamKHR(const ValidationContext *val,
3717                             const Display *display,
3718                             const Stream *stream,
3719                             EGLenum attribute,
3720                             const EGLint *value)
3721 {
3722     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
3723 
3724     switch (attribute)
3725     {
3726         case EGL_STREAM_STATE_KHR:
3727         case EGL_CONSUMER_LATENCY_USEC_KHR:
3728             break;
3729         case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
3730             if (!display->getExtensions().streamConsumerGLTexture)
3731             {
3732                 val->setError(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
3733                 return false;
3734             }
3735             break;
3736         default:
3737             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
3738             return false;
3739     }
3740 
3741     return true;
3742 }
3743 
ValidateQueryStreamu64KHR(const ValidationContext * val,const Display * display,const Stream * stream,EGLenum attribute,const EGLuint64KHR * value)3744 bool ValidateQueryStreamu64KHR(const ValidationContext *val,
3745                                const Display *display,
3746                                const Stream *stream,
3747                                EGLenum attribute,
3748                                const EGLuint64KHR *value)
3749 {
3750     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
3751 
3752     switch (attribute)
3753     {
3754         case EGL_CONSUMER_FRAME_KHR:
3755         case EGL_PRODUCER_FRAME_KHR:
3756             break;
3757         default:
3758             val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
3759             return false;
3760     }
3761 
3762     return true;
3763 }
3764 
ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext * val,const Display * display,const Stream * stream)3765 bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
3766                                                 const Display *display,
3767                                                 const Stream *stream)
3768 {
3769     gl::Context *context = val->eglThread->getContext();
3770     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3771 
3772     const DisplayExtensions &displayExtensions = display->getExtensions();
3773     if (!displayExtensions.streamConsumerGLTexture)
3774     {
3775         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
3776         return false;
3777     }
3778 
3779     if (!context->getExtensions().eglStreamConsumerExternalNV)
3780     {
3781         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
3782         return false;
3783     }
3784 
3785     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3786     {
3787         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
3788         return false;
3789     }
3790 
3791     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
3792     {
3793         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
3794         return false;
3795     }
3796 
3797     // Lookup the texture and ensure it is correct
3798     gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
3799     if (texture == nullptr || texture->id().value == 0)
3800     {
3801         val->setError(EGL_BAD_ACCESS, "No external texture bound");
3802         return false;
3803     }
3804 
3805     return true;
3806 }
3807 
ValidateStreamConsumerAcquireKHR(const ValidationContext * val,const Display * display,const Stream * stream)3808 bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
3809                                       const Display *display,
3810                                       const Stream *stream)
3811 {
3812     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3813 
3814     const DisplayExtensions &displayExtensions = display->getExtensions();
3815     if (!displayExtensions.streamConsumerGLTexture)
3816     {
3817         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
3818         return false;
3819     }
3820 
3821     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3822     {
3823         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
3824         return false;
3825     }
3826 
3827     gl::Context *context = val->eglThread->getContext();
3828     if (!context)
3829     {
3830         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
3831         return false;
3832     }
3833 
3834     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3835 
3836     if (!stream->isConsumerBoundToContext(context))
3837     {
3838         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
3839         return false;
3840     }
3841 
3842     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
3843         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
3844     {
3845         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
3846         return false;
3847     }
3848 
3849     // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
3850     // However, the timeout is effectively ignored since it has no useful functionality with the
3851     // current producers that are implemented, so we don't allow that state
3852     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3853         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3854     {
3855         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
3856         return false;
3857     }
3858 
3859     return true;
3860 }
3861 
ValidateStreamConsumerReleaseKHR(const ValidationContext * val,const Display * display,const Stream * stream)3862 bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
3863                                       const Display *display,
3864                                       const Stream *stream)
3865 {
3866     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3867 
3868     const DisplayExtensions &displayExtensions = display->getExtensions();
3869     if (!displayExtensions.streamConsumerGLTexture)
3870     {
3871         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
3872         return false;
3873     }
3874 
3875     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3876     {
3877         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
3878         return false;
3879     }
3880 
3881     gl::Context *context = val->eglThread->getContext();
3882     if (!context)
3883     {
3884         val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
3885         return false;
3886     }
3887 
3888     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3889 
3890     if (!stream->isConsumerBoundToContext(context))
3891     {
3892         val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
3893         return false;
3894     }
3895 
3896     if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
3897         stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
3898     {
3899         val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
3900         return false;
3901     }
3902 
3903     if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3904         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3905     {
3906         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
3907         return false;
3908     }
3909 
3910     return true;
3911 }
3912 
ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)3913 bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
3914                                                       const Display *display,
3915                                                       const Stream *stream,
3916                                                       const AttributeMap &attribs)
3917 {
3918     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
3919 
3920     const DisplayExtensions &displayExtensions = display->getExtensions();
3921     if (!displayExtensions.streamConsumerGLTexture)
3922     {
3923         val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
3924         return false;
3925     }
3926 
3927     gl::Context *context = val->eglThread->getContext();
3928     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
3929 
3930     // Although technically not a requirement in spec, the context needs to be checked for support
3931     // for external textures or future logic will cause assertations. This extension is also
3932     // effectively useless without external textures.
3933     if (!context->getExtensions().eglStreamConsumerExternalNV)
3934     {
3935         val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
3936         return false;
3937     }
3938 
3939     if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
3940     {
3941         val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
3942         return false;
3943     }
3944 
3945     if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
3946     {
3947         val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
3948         return false;
3949     }
3950 
3951     const gl::Caps &glCaps = context->getCaps();
3952 
3953     EGLAttrib colorBufferType = EGL_RGB_BUFFER;
3954     EGLAttrib planeCount      = -1;
3955     EGLAttrib plane[3];
3956     for (int i = 0; i < 3; i++)
3957     {
3958         plane[i] = -1;
3959     }
3960     for (const auto &attributeIter : attribs)
3961     {
3962         EGLAttrib attribute = attributeIter.first;
3963         EGLAttrib value     = attributeIter.second;
3964 
3965         switch (attribute)
3966         {
3967             case EGL_COLOR_BUFFER_TYPE:
3968                 if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
3969                 {
3970                     val->setError(EGL_BAD_PARAMETER, "Invalid color buffer type");
3971                     return false;
3972                 }
3973                 colorBufferType = value;
3974                 break;
3975             case EGL_YUV_NUMBER_OF_PLANES_EXT:
3976                 // planeCount = -1 is a tag for the default plane count so the value must be checked
3977                 // to be positive here to ensure future logic doesn't break on invalid negative
3978                 // inputs
3979                 if (value < 0)
3980                 {
3981                     val->setError(EGL_BAD_MATCH, "Invalid plane count");
3982                     return false;
3983                 }
3984                 planeCount = value;
3985                 break;
3986             default:
3987                 if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
3988                     attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
3989                 {
3990                     if ((value < 0 ||
3991                          value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
3992                         value != EGL_NONE)
3993                     {
3994                         val->setError(EGL_BAD_ACCESS, "Invalid texture unit");
3995                         return false;
3996                     }
3997                     plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
3998                 }
3999                 else
4000                 {
4001                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4002                     return false;
4003                 }
4004         }
4005     }
4006 
4007     if (colorBufferType == EGL_RGB_BUFFER)
4008     {
4009         if (planeCount > 0)
4010         {
4011             val->setError(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
4012             return false;
4013         }
4014         for (int i = 0; i < 3; i++)
4015         {
4016             if (plane[i] != -1)
4017             {
4018                 val->setError(EGL_BAD_MATCH, "Planes cannot be specified");
4019                 return false;
4020             }
4021         }
4022 
4023         // Lookup the texture and ensure it is correct
4024         gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
4025         if (texture == nullptr || texture->id().value == 0)
4026         {
4027             val->setError(EGL_BAD_ACCESS, "No external texture bound");
4028             return false;
4029         }
4030     }
4031     else
4032     {
4033         if (planeCount == -1)
4034         {
4035             planeCount = 2;
4036         }
4037         if (planeCount < 1 || planeCount > 3)
4038         {
4039             val->setError(EGL_BAD_MATCH, "Invalid YUV plane count");
4040             return false;
4041         }
4042         for (EGLAttrib i = planeCount; i < 3; i++)
4043         {
4044             if (plane[i] != -1)
4045             {
4046                 val->setError(EGL_BAD_MATCH, "Invalid plane specified");
4047                 return false;
4048             }
4049         }
4050 
4051         // Set to ensure no texture is referenced more than once
4052         std::set<gl::Texture *> textureSet;
4053         for (EGLAttrib i = 0; i < planeCount; i++)
4054         {
4055             if (plane[i] == -1)
4056             {
4057                 val->setError(EGL_BAD_MATCH, "Not all planes specified");
4058                 return false;
4059             }
4060             if (plane[i] != EGL_NONE)
4061             {
4062                 gl::Texture *texture = context->getState().getSamplerTexture(
4063                     static_cast<unsigned int>(plane[i]), gl::TextureType::External);
4064                 if (texture == nullptr || texture->id().value == 0)
4065                 {
4066                     val->setError(
4067                         EGL_BAD_ACCESS,
4068                         "No external texture bound at one or more specified texture units");
4069                     return false;
4070                 }
4071                 if (textureSet.find(texture) != textureSet.end())
4072                 {
4073                     val->setError(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
4074                     return false;
4075                 }
4076                 textureSet.insert(texture);
4077             }
4078         }
4079     }
4080 
4081     return true;
4082 }
4083 
ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const AttributeMap & attribs)4084 bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
4085                                                  const Display *display,
4086                                                  const Stream *stream,
4087                                                  const AttributeMap &attribs)
4088 {
4089     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4090 
4091     const DisplayExtensions &displayExtensions = display->getExtensions();
4092     if (!displayExtensions.streamProducerD3DTexture)
4093     {
4094         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4095         return false;
4096     }
4097 
4098     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4099 
4100     if (!attribs.isEmpty())
4101     {
4102         val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4103         return false;
4104     }
4105 
4106     if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
4107     {
4108         val->setError(EGL_BAD_STATE_KHR, "Stream not in connecting state");
4109         return false;
4110     }
4111 
4112     switch (stream->getConsumerType())
4113     {
4114         case Stream::ConsumerType::GLTextureYUV:
4115             if (stream->getPlaneCount() != 2)
4116             {
4117                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4118                 return false;
4119             }
4120             break;
4121 
4122         case Stream::ConsumerType::GLTextureRGB:
4123             if (stream->getPlaneCount() != 1)
4124             {
4125                 val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4126                 return false;
4127             }
4128             break;
4129 
4130         default:
4131             val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
4132             return false;
4133     }
4134 
4135     return true;
4136 }
4137 
ValidateStreamPostD3DTextureANGLE(const ValidationContext * val,const Display * display,const Stream * stream,const void * texture,const AttributeMap & attribs)4138 bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
4139                                        const Display *display,
4140                                        const Stream *stream,
4141                                        const void *texture,
4142                                        const AttributeMap &attribs)
4143 {
4144     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4145 
4146     const DisplayExtensions &displayExtensions = display->getExtensions();
4147     if (!displayExtensions.streamProducerD3DTexture)
4148     {
4149         val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
4150         return false;
4151     }
4152 
4153     ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
4154 
4155     for (auto &attributeIter : attribs)
4156     {
4157         EGLAttrib attribute = attributeIter.first;
4158         EGLAttrib value     = attributeIter.second;
4159 
4160         switch (attribute)
4161         {
4162             case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
4163                 if (value < 0)
4164                 {
4165                     val->setError(EGL_BAD_PARAMETER, "Invalid subresource index");
4166                     return false;
4167                 }
4168                 break;
4169             case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
4170                 if (value < 0)
4171                 {
4172                     val->setError(EGL_BAD_PARAMETER, "Invalid plane offset");
4173                     return false;
4174                 }
4175                 break;
4176             default:
4177                 val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
4178                 return false;
4179         }
4180     }
4181 
4182     if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
4183         stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
4184         stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
4185     {
4186         val->setError(EGL_BAD_STATE_KHR, "Stream not fully configured");
4187         return false;
4188     }
4189 
4190     if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
4191     {
4192         val->setError(EGL_BAD_MATCH, "Incompatible stream producer");
4193         return false;
4194     }
4195 
4196     if (texture == nullptr)
4197     {
4198         val->setError(EGL_BAD_PARAMETER, "Texture is null");
4199         return false;
4200     }
4201 
4202     ANGLE_EGL_TRY_RETURN(val->eglThread, stream->validateD3D11Texture(texture, attribs),
4203                          val->entryPoint, val->labeledObject, false);
4204 
4205     return true;
4206 }
4207 
ValidateSyncControlCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface)4208 bool ValidateSyncControlCHROMIUM(const ValidationContext *val,
4209                                  const Display *display,
4210                                  const Surface *eglSurface)
4211 {
4212     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4213     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4214 
4215     const DisplayExtensions &displayExtensions = display->getExtensions();
4216     if (!displayExtensions.syncControlCHROMIUM)
4217     {
4218         val->setError(EGL_BAD_ACCESS, "syncControlCHROMIUM extension not active");
4219         return false;
4220     }
4221 
4222     return true;
4223 }
4224 
ValidateSyncControlRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface)4225 bool ValidateSyncControlRateANGLE(const ValidationContext *val,
4226                                   const Display *display,
4227                                   const Surface *eglSurface)
4228 {
4229     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4230     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4231 
4232     const DisplayExtensions &displayExtensions = display->getExtensions();
4233     if (!displayExtensions.syncControlRateANGLE)
4234     {
4235         val->setError(EGL_BAD_ACCESS, "syncControlRateANGLE extension not active");
4236         return false;
4237     }
4238 
4239     return true;
4240 }
4241 
ValidateGetMscRateANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLint * numerator,const EGLint * denominator)4242 bool ValidateGetMscRateANGLE(const ValidationContext *val,
4243                              const Display *display,
4244                              const Surface *eglSurface,
4245                              const EGLint *numerator,
4246                              const EGLint *denominator)
4247 {
4248     ANGLE_VALIDATION_TRY(ValidateSyncControlRateANGLE(val, display, eglSurface));
4249 
4250     if (numerator == nullptr)
4251     {
4252         val->setError(EGL_BAD_PARAMETER, "numerator is null");
4253         return false;
4254     }
4255     if (denominator == nullptr)
4256     {
4257         val->setError(EGL_BAD_PARAMETER, "denominator is null");
4258         return false;
4259     }
4260 
4261     return true;
4262 }
4263 
ValidateGetSyncValuesCHROMIUM(const ValidationContext * val,const Display * display,const Surface * eglSurface,const EGLuint64KHR * ust,const EGLuint64KHR * msc,const EGLuint64KHR * sbc)4264 bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
4265                                    const Display *display,
4266                                    const Surface *eglSurface,
4267                                    const EGLuint64KHR *ust,
4268                                    const EGLuint64KHR *msc,
4269                                    const EGLuint64KHR *sbc)
4270 {
4271     ANGLE_VALIDATION_TRY(ValidateSyncControlCHROMIUM(val, display, eglSurface));
4272 
4273     if (ust == nullptr)
4274     {
4275         val->setError(EGL_BAD_PARAMETER, "ust is null");
4276         return false;
4277     }
4278     if (msc == nullptr)
4279     {
4280         val->setError(EGL_BAD_PARAMETER, "msc is null");
4281         return false;
4282     }
4283     if (sbc == nullptr)
4284     {
4285         val->setError(EGL_BAD_PARAMETER, "sbc is null");
4286         return false;
4287     }
4288 
4289     return true;
4290 }
4291 
ValidateDestroySurface(const ValidationContext * val,const Display * display,const Surface * surface)4292 bool ValidateDestroySurface(const ValidationContext *val,
4293                             const Display *display,
4294                             const Surface *surface)
4295 {
4296     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4297     return true;
4298 }
4299 
ValidateDestroyContext(const ValidationContext * val,const Display * display,const gl::Context * glCtx)4300 bool ValidateDestroyContext(const ValidationContext *val,
4301                             const Display *display,
4302                             const gl::Context *glCtx)
4303 {
4304     ANGLE_VALIDATION_TRY(ValidateContext(val, display, glCtx));
4305     return true;
4306 }
4307 
ValidateSwapBuffers(const ValidationContext * val,const Display * display,const Surface * eglSurface)4308 bool ValidateSwapBuffers(const ValidationContext *val,
4309                          const Display *display,
4310                          const Surface *eglSurface)
4311 {
4312     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
4313 
4314     if (display->isDeviceLost())
4315     {
4316         val->setError(EGL_CONTEXT_LOST);
4317         return false;
4318     }
4319 
4320     if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
4321         val->eglThread->getCurrentDrawSurface() != eglSurface)
4322     {
4323         val->setError(EGL_BAD_SURFACE);
4324         return false;
4325     }
4326 
4327     return true;
4328 }
4329 
ValidateSwapBuffersWithDamageKHR(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint * rects,EGLint n_rects)4330 bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
4331                                       const Display *display,
4332                                       const Surface *surface,
4333                                       const EGLint *rects,
4334                                       EGLint n_rects)
4335 {
4336     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4337 
4338     if (!display->getExtensions().swapBuffersWithDamage)
4339     {
4340         // It is out of spec what happens when calling an extension function when the extension is
4341         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4342         val->setError(EGL_BAD_DISPLAY, "EGL_KHR_swap_buffers_with_damage is not available.");
4343         return false;
4344     }
4345 
4346     if (surface == EGL_NO_SURFACE)
4347     {
4348         val->setError(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
4349         return false;
4350     }
4351 
4352     if (n_rects < 0)
4353     {
4354         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
4355         return false;
4356     }
4357 
4358     if (n_rects > 0 && rects == nullptr)
4359     {
4360         val->setError(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
4361         return false;
4362     }
4363 
4364     // TODO(jmadill): Validate Surface is bound to the thread.
4365 
4366     return true;
4367 }
4368 
ValidateWaitNative(const ValidationContext * val,const EGLint engine)4369 bool ValidateWaitNative(const ValidationContext *val, const EGLint engine)
4370 {
4371     if (val->eglThread->getDisplay() == nullptr)
4372     {
4373         // EGL spec says this about eglWaitNative -
4374         //    eglWaitNative is ignored if there is no current EGL rendering context.
4375         return true;
4376     }
4377 
4378     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
4379 
4380     if (engine != EGL_CORE_NATIVE_ENGINE)
4381     {
4382         val->setError(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value");
4383         return false;
4384     }
4385 
4386     return true;
4387 }
4388 
ValidateCopyBuffers(const ValidationContext * val,const Display * display,const Surface * surface,EGLNativePixmapType target)4389 bool ValidateCopyBuffers(const ValidationContext *val,
4390                          const Display *display,
4391                          const Surface *surface,
4392                          EGLNativePixmapType target)
4393 {
4394     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4395 
4396     if (display->isDeviceLost())
4397     {
4398         val->setError(EGL_CONTEXT_LOST);
4399         return false;
4400     }
4401 
4402     return true;
4403 }
4404 
ValidateBindTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4405 bool ValidateBindTexImage(const ValidationContext *val,
4406                           const Display *display,
4407                           const Surface *surface,
4408                           const EGLint buffer)
4409 {
4410     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4411 
4412     if (buffer != EGL_BACK_BUFFER)
4413     {
4414         val->setError(EGL_BAD_PARAMETER);
4415         return false;
4416     }
4417 
4418     if (surface->getType() == EGL_WINDOW_BIT)
4419     {
4420         val->setError(EGL_BAD_SURFACE);
4421         return false;
4422     }
4423 
4424     if (surface->getBoundTexture())
4425     {
4426         val->setError(EGL_BAD_ACCESS);
4427         return false;
4428     }
4429 
4430     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4431     {
4432         val->setError(EGL_BAD_MATCH);
4433         return false;
4434     }
4435 
4436     gl::Context *context = val->eglThread->getContext();
4437     if (context)
4438     {
4439         gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
4440         gl::Texture *textureObject = context->getTextureByType(type);
4441         ASSERT(textureObject != nullptr);
4442 
4443         if (textureObject->getImmutableFormat())
4444         {
4445             val->setError(EGL_BAD_MATCH);
4446             return false;
4447         }
4448     }
4449 
4450     return true;
4451 }
4452 
ValidateReleaseTexImage(const ValidationContext * val,const Display * display,const Surface * surface,const EGLint buffer)4453 bool ValidateReleaseTexImage(const ValidationContext *val,
4454                              const Display *display,
4455                              const Surface *surface,
4456                              const EGLint buffer)
4457 {
4458     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4459 
4460     if (buffer != EGL_BACK_BUFFER)
4461     {
4462         val->setError(EGL_BAD_PARAMETER);
4463         return false;
4464     }
4465 
4466     if (surface->getType() == EGL_WINDOW_BIT)
4467     {
4468         val->setError(EGL_BAD_SURFACE);
4469         return false;
4470     }
4471 
4472     if (surface->getTextureFormat() == TextureFormat::NoTexture)
4473     {
4474         val->setError(EGL_BAD_MATCH);
4475         return false;
4476     }
4477 
4478     return true;
4479 }
4480 
ValidateSwapInterval(const ValidationContext * val,const Display * display,EGLint interval)4481 bool ValidateSwapInterval(const ValidationContext *val, const Display *display, EGLint interval)
4482 {
4483     const gl::Context *context = val->eglThread->getContext();
4484     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
4485 
4486     Surface *drawSurface = val->eglThread->getCurrentDrawSurface();
4487     if (drawSurface == nullptr)
4488     {
4489         val->setError(EGL_BAD_SURFACE);
4490         return false;
4491     }
4492 
4493     return true;
4494 }
4495 
ValidateBindAPI(const ValidationContext * val,const EGLenum api)4496 bool ValidateBindAPI(const ValidationContext *val, const EGLenum api)
4497 {
4498     switch (api)
4499     {
4500         case EGL_OPENGL_API:
4501         case EGL_OPENVG_API:
4502             val->setError(EGL_BAD_PARAMETER);
4503             return false;  // Not supported by this implementation
4504         case EGL_OPENGL_ES_API:
4505             break;
4506         default:
4507             val->setError(EGL_BAD_PARAMETER);
4508             return false;
4509     }
4510 
4511     return true;
4512 }
4513 
ValidatePresentationTimeANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLnsecsANDROID time)4514 bool ValidatePresentationTimeANDROID(const ValidationContext *val,
4515                                      const Display *display,
4516                                      const Surface *surface,
4517                                      EGLnsecsANDROID time)
4518 {
4519     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4520 
4521     if (!display->getExtensions().presentationTime)
4522     {
4523         // It is out of spec what happens when calling an extension function when the extension is
4524         // not available. EGL_BAD_DISPLAY seems like a reasonable error.
4525         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_presentation_time is not available.");
4526         return false;
4527     }
4528 
4529     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4530 
4531     return true;
4532 }
4533 
ValidateSetBlobCacheFuncsANDROID(const ValidationContext * val,const Display * display,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)4534 bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
4535                                       const Display *display,
4536                                       EGLSetBlobFuncANDROID set,
4537                                       EGLGetBlobFuncANDROID get)
4538 {
4539     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4540 
4541     if (display->areBlobCacheFuncsSet())
4542     {
4543         val->setError(EGL_BAD_PARAMETER,
4544                       "Blob cache functions can only be set once in the lifetime of a Display");
4545         return false;
4546     }
4547 
4548     if (set == nullptr || get == nullptr)
4549     {
4550         val->setError(EGL_BAD_PARAMETER, "Blob cache callbacks cannot be null.");
4551         return false;
4552     }
4553 
4554     return true;
4555 }
4556 
ValidateGetConfigAttrib(const ValidationContext * val,const Display * display,const Config * config,EGLint attribute,const EGLint * value)4557 bool ValidateGetConfigAttrib(const ValidationContext *val,
4558                              const Display *display,
4559                              const Config *config,
4560                              EGLint attribute,
4561                              const EGLint *value)
4562 {
4563     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
4564     ANGLE_TRY(ValidateConfigAttribute(val, display, static_cast<EGLAttrib>(attribute)));
4565     return true;
4566 }
4567 
ValidateChooseConfig(const ValidationContext * val,const Display * display,const AttributeMap & attribs,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)4568 bool ValidateChooseConfig(const ValidationContext *val,
4569                           const Display *display,
4570                           const AttributeMap &attribs,
4571                           const EGLConfig *configs,
4572                           EGLint configSize,
4573                           const EGLint *numConfig)
4574 {
4575     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4576     ANGLE_VALIDATION_TRY(ValidateConfigAttributes(val, display, attribs));
4577 
4578     if (numConfig == nullptr)
4579     {
4580         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
4581         return false;
4582     }
4583 
4584     return true;
4585 }
4586 
ValidateGetConfigs(const ValidationContext * val,const Display * display,const EGLConfig * configs,EGLint configSize,const EGLint * numConfig)4587 bool ValidateGetConfigs(const ValidationContext *val,
4588                         const Display *display,
4589                         const EGLConfig *configs,
4590                         EGLint configSize,
4591                         const EGLint *numConfig)
4592 {
4593     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4594 
4595     if (numConfig == nullptr)
4596     {
4597         val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
4598         return false;
4599     }
4600 
4601     return true;
4602 }
4603 
ValidateGetPlatformDisplay(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)4604 bool ValidateGetPlatformDisplay(const ValidationContext *val,
4605                                 EGLenum platform,
4606                                 const void *native_display,
4607                                 const AttributeMap &attribMap)
4608 {
4609     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
4610 }
4611 
ValidateGetPlatformDisplayEXT(const ValidationContext * val,EGLenum platform,const void * native_display,const AttributeMap & attribMap)4612 bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
4613                                    EGLenum platform,
4614                                    const void *native_display,
4615                                    const AttributeMap &attribMap)
4616 {
4617     return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
4618 }
4619 
ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativeWindow,const AttributeMap & attributes)4620 bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
4621                                             const Display *display,
4622                                             const Config *configuration,
4623                                             const void *nativeWindow,
4624                                             const AttributeMap &attributes)
4625 {
4626     if (!Display::GetClientExtensions().platformBase)
4627     {
4628         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
4629         return false;
4630     }
4631 
4632     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
4633 
4634     val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformWindowSurfaceEXT unimplemented.");
4635     return false;
4636 }
4637 
ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext * val,const Display * display,const Config * configuration,const void * nativePixmap,const AttributeMap & attributes)4638 bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
4639                                             const Display *display,
4640                                             const Config *configuration,
4641                                             const void *nativePixmap,
4642                                             const AttributeMap &attributes)
4643 {
4644     if (!Display::GetClientExtensions().platformBase)
4645     {
4646         val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
4647         return false;
4648     }
4649 
4650     ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
4651 
4652     val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.");
4653     return false;
4654 }
4655 
ValidateProgramCacheGetAttribANGLE(const ValidationContext * val,const Display * display,EGLenum attrib)4656 bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
4657                                         const Display *display,
4658                                         EGLenum attrib)
4659 {
4660     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4661 
4662     if (!display->getExtensions().programCacheControl)
4663     {
4664         val->setError(EGL_BAD_ACCESS, "Extension not supported");
4665         return false;
4666     }
4667 
4668     switch (attrib)
4669     {
4670         case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
4671         case EGL_PROGRAM_CACHE_SIZE_ANGLE:
4672             break;
4673 
4674         default:
4675             val->setError(EGL_BAD_PARAMETER, "Invalid program cache attribute.");
4676             return false;
4677     }
4678 
4679     return true;
4680 }
4681 
ValidateProgramCacheQueryANGLE(const ValidationContext * val,const Display * display,EGLint index,const void * key,const EGLint * keysize,const void * binary,const EGLint * binarysize)4682 bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
4683                                     const Display *display,
4684                                     EGLint index,
4685                                     const void *key,
4686                                     const EGLint *keysize,
4687                                     const void *binary,
4688                                     const EGLint *binarysize)
4689 {
4690     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4691 
4692     if (!display->getExtensions().programCacheControl)
4693     {
4694         val->setError(EGL_BAD_ACCESS, "Extension not supported");
4695         return false;
4696     }
4697 
4698     if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
4699     {
4700         val->setError(EGL_BAD_PARAMETER, "Program index out of range.");
4701         return false;
4702     }
4703 
4704     if (keysize == nullptr || binarysize == nullptr)
4705     {
4706         val->setError(EGL_BAD_PARAMETER, "keysize and binarysize must always be valid pointers.");
4707         return false;
4708     }
4709 
4710     if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
4711     {
4712         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
4713         return false;
4714     }
4715 
4716     if ((key == nullptr) != (binary == nullptr))
4717     {
4718         val->setError(EGL_BAD_PARAMETER, "key and binary must both be null or both non-null.");
4719         return false;
4720     }
4721 
4722     return true;
4723 }
4724 
ValidateProgramCachePopulateANGLE(const ValidationContext * val,const Display * display,const void * key,EGLint keysize,const void * binary,EGLint binarysize)4725 bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
4726                                        const Display *display,
4727                                        const void *key,
4728                                        EGLint keysize,
4729                                        const void *binary,
4730                                        EGLint binarysize)
4731 {
4732     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4733 
4734     if (!display->getExtensions().programCacheControl)
4735     {
4736         val->setError(EGL_BAD_ACCESS, "Extension not supported");
4737         return false;
4738     }
4739 
4740     if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
4741     {
4742         val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
4743         return false;
4744     }
4745 
4746     if (key == nullptr || binary == nullptr)
4747     {
4748         val->setError(EGL_BAD_PARAMETER, "null pointer in arguments.");
4749         return false;
4750     }
4751 
4752     // Upper bound for binarysize is arbitrary.
4753     if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
4754     {
4755         val->setError(EGL_BAD_PARAMETER, "binarysize out of valid range.");
4756         return false;
4757     }
4758 
4759     return true;
4760 }
4761 
ValidateProgramCacheResizeANGLE(const ValidationContext * val,const Display * display,EGLint limit,EGLint mode)4762 bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
4763                                      const Display *display,
4764                                      EGLint limit,
4765                                      EGLint mode)
4766 {
4767     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4768 
4769     if (!display->getExtensions().programCacheControl)
4770     {
4771         val->setError(EGL_BAD_ACCESS, "Extension not supported");
4772         return false;
4773     }
4774 
4775     if (limit < 0)
4776     {
4777         val->setError(EGL_BAD_PARAMETER, "limit must be non-negative.");
4778         return false;
4779     }
4780 
4781     switch (mode)
4782     {
4783         case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
4784         case EGL_PROGRAM_CACHE_TRIM_ANGLE:
4785             break;
4786 
4787         default:
4788             val->setError(EGL_BAD_PARAMETER, "Invalid cache resize mode.");
4789             return false;
4790     }
4791 
4792     return true;
4793 }
4794 
ValidateSurfaceAttrib(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,EGLint value)4795 bool ValidateSurfaceAttrib(const ValidationContext *val,
4796                            const Display *display,
4797                            const Surface *surface,
4798                            EGLint attribute,
4799                            EGLint value)
4800 {
4801     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
4802     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
4803 
4804     if (surface == EGL_NO_SURFACE)
4805     {
4806         val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
4807         return false;
4808     }
4809 
4810     switch (attribute)
4811     {
4812         case EGL_MIPMAP_LEVEL:
4813             break;
4814 
4815         case EGL_MULTISAMPLE_RESOLVE:
4816             switch (value)
4817             {
4818                 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
4819                     break;
4820 
4821                 case EGL_MULTISAMPLE_RESOLVE_BOX:
4822                     if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
4823                     {
4824                         val->setError(EGL_BAD_MATCH,
4825                                       "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.");
4826                         return false;
4827                     }
4828                     break;
4829 
4830                 default:
4831                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid multisample resolve type.");
4832                     return false;
4833             }
4834             break;
4835 
4836         case EGL_SWAP_BEHAVIOR:
4837             switch (value)
4838             {
4839                 case EGL_BUFFER_PRESERVED:
4840                     if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
4841                     {
4842                         val->setError(EGL_BAD_MATCH,
4843                                       "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.");
4844                         return false;
4845                     }
4846                     break;
4847 
4848                 case EGL_BUFFER_DESTROYED:
4849                     break;
4850 
4851                 default:
4852                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid swap behaviour.");
4853                     return false;
4854             }
4855             break;
4856 
4857         case EGL_WIDTH:
4858         case EGL_HEIGHT:
4859             if (!display->getExtensions().windowFixedSize)
4860             {
4861                 val->setError(EGL_BAD_ATTRIBUTE,
4862                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
4863                               "EGL_ANGLE_window_fixed_size support.");
4864                 return false;
4865             }
4866             if (!surface->isFixedSize())
4867             {
4868                 val->setError(EGL_BAD_MATCH,
4869                               "EGL_WIDTH or EGL_HEIGHT cannot be set without "
4870                               "EGL_FIXED_SIZE_ANGLE being enabled on the surface.");
4871                 return false;
4872             }
4873             break;
4874 
4875         case EGL_TIMESTAMPS_ANDROID:
4876             if (!display->getExtensions().getFrameTimestamps)
4877             {
4878                 val->setError(EGL_BAD_ATTRIBUTE,
4879                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
4880                               "EGL_ANDROID_get_frame_timestamps support.");
4881                 return false;
4882             }
4883             switch (value)
4884             {
4885                 case EGL_TRUE:
4886                 case EGL_FALSE:
4887                     break;
4888 
4889                 default:
4890                     val->setError(EGL_BAD_ATTRIBUTE, "Invalid value.");
4891                     return false;
4892             }
4893             break;
4894 
4895         default:
4896             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute.");
4897             return false;
4898     }
4899 
4900     return true;
4901 }
4902 
ValidateQuerySurface(const ValidationContext * val,const Display * display,const Surface * surface,EGLint attribute,const EGLint * value)4903 bool ValidateQuerySurface(const ValidationContext *val,
4904                           const Display *display,
4905                           const Surface *surface,
4906                           EGLint attribute,
4907                           const 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_GL_COLORSPACE:
4921         case EGL_VG_ALPHA_FORMAT:
4922         case EGL_VG_COLORSPACE:
4923         case EGL_CONFIG_ID:
4924         case EGL_HEIGHT:
4925         case EGL_HORIZONTAL_RESOLUTION:
4926         case EGL_LARGEST_PBUFFER:
4927         case EGL_MIPMAP_TEXTURE:
4928         case EGL_MIPMAP_LEVEL:
4929         case EGL_MULTISAMPLE_RESOLVE:
4930         case EGL_PIXEL_ASPECT_RATIO:
4931         case EGL_RENDER_BUFFER:
4932         case EGL_SWAP_BEHAVIOR:
4933         case EGL_TEXTURE_FORMAT:
4934         case EGL_TEXTURE_TARGET:
4935         case EGL_VERTICAL_RESOLUTION:
4936         case EGL_WIDTH:
4937             break;
4938 
4939         case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
4940             if (!display->getExtensions().postSubBuffer)
4941             {
4942                 val->setError(EGL_BAD_ATTRIBUTE,
4943                               "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
4944                               "without EGL_ANGLE_surface_orientation support.");
4945                 return false;
4946             }
4947             break;
4948 
4949         case EGL_FIXED_SIZE_ANGLE:
4950             if (!display->getExtensions().windowFixedSize)
4951             {
4952                 val->setError(EGL_BAD_ATTRIBUTE,
4953                               "EGL_FIXED_SIZE_ANGLE cannot be used without "
4954                               "EGL_ANGLE_window_fixed_size support.");
4955                 return false;
4956             }
4957             break;
4958 
4959         case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
4960             if (!display->getExtensions().flexibleSurfaceCompatibility)
4961             {
4962                 val->setError(EGL_BAD_ATTRIBUTE,
4963                               "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be "
4964                               "used without EGL_ANGLE_flexible_surface_compatibility support.");
4965                 return false;
4966             }
4967             break;
4968 
4969         case EGL_SURFACE_ORIENTATION_ANGLE:
4970             if (!display->getExtensions().surfaceOrientation)
4971             {
4972                 val->setError(EGL_BAD_ATTRIBUTE,
4973                               "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
4974                               "queried without "
4975                               "EGL_ANGLE_surface_orientation support.");
4976                 return false;
4977             }
4978             break;
4979 
4980         case EGL_DIRECT_COMPOSITION_ANGLE:
4981             if (!display->getExtensions().directComposition)
4982             {
4983                 val->setError(EGL_BAD_ATTRIBUTE,
4984                               "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
4985                               "used without "
4986                               "EGL_ANGLE_direct_composition support.");
4987                 return false;
4988             }
4989             break;
4990 
4991         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
4992             if (!display->getExtensions().robustResourceInitialization)
4993             {
4994                 val->setError(EGL_BAD_ATTRIBUTE,
4995                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
4996                               "used without EGL_ANGLE_robust_resource_initialization "
4997                               "support.");
4998                 return false;
4999             }
5000             break;
5001 
5002         case EGL_TIMESTAMPS_ANDROID:
5003             if (!display->getExtensions().getFrameTimestamps)
5004             {
5005                 val->setError(EGL_BAD_ATTRIBUTE,
5006                               "EGL_TIMESTAMPS_ANDROID cannot be used without "
5007                               "EGL_ANDROID_get_frame_timestamps support.");
5008                 return false;
5009             }
5010             break;
5011 
5012         case EGL_BUFFER_AGE_EXT:
5013         {
5014             if (!display->getExtensions().bufferAgeEXT)
5015             {
5016                 val->setError(EGL_BAD_ATTRIBUTE,
5017                               "EGL_BUFFER_AGE_EXT cannot be used without "
5018                               "EGL_EXT_buffer_age support.");
5019                 return false;
5020             }
5021             gl::Context *context = val->eglThread->getContext();
5022             if ((context == nullptr) || (context->getCurrentDrawSurface() != surface))
5023             {
5024                 val->setError(EGL_BAD_SURFACE,
5025                               "The surface must be current to the current context "
5026                               "in order to query buffer age per extension "
5027                               "EGL_EXT_buffer_age.");
5028                 return false;
5029             }
5030         }
5031         break;
5032 
5033         default:
5034             val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute.");
5035             return false;
5036     }
5037 
5038     return true;
5039 }
5040 
ValidateQueryContext(const ValidationContext * val,const Display * display,const gl::Context * context,EGLint attribute,const EGLint * value)5041 bool ValidateQueryContext(const ValidationContext *val,
5042                           const Display *display,
5043                           const gl::Context *context,
5044                           EGLint attribute,
5045                           const EGLint *value)
5046 {
5047     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
5048 
5049     switch (attribute)
5050     {
5051         case EGL_CONFIG_ID:
5052         case EGL_CONTEXT_CLIENT_TYPE:
5053         case EGL_CONTEXT_CLIENT_VERSION:
5054         case EGL_RENDER_BUFFER:
5055             break;
5056 
5057         case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
5058             if (!display->getExtensions().robustResourceInitialization)
5059             {
5060                 val->setError(EGL_BAD_ATTRIBUTE,
5061                               "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
5062                               "used without EGL_ANGLE_robust_resource_initialization "
5063                               "support.");
5064                 return false;
5065             }
5066             break;
5067 
5068         case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
5069             if (!display->getExtensions().contextPriority)
5070             {
5071                 val->setError(EGL_BAD_ATTRIBUTE,
5072                               "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
5073                               "extension EGL_IMG_context_priority.");
5074                 return false;
5075             }
5076             break;
5077 
5078         default:
5079             val->setError(EGL_BAD_ATTRIBUTE, "Invalid context attribute.");
5080             return false;
5081     }
5082 
5083     return true;
5084 }
5085 
ValidateDebugMessageControlKHR(const ValidationContext * val,EGLDEBUGPROCKHR callback,const AttributeMap & attribs)5086 bool ValidateDebugMessageControlKHR(const ValidationContext *val,
5087                                     EGLDEBUGPROCKHR callback,
5088                                     const AttributeMap &attribs)
5089 {
5090     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5091     if (!clientExtensions.debug)
5092     {
5093         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5094         return false;
5095     }
5096 
5097     for (const auto &attrib : attribs)
5098     {
5099         switch (attrib.first)
5100         {
5101             case EGL_DEBUG_MSG_CRITICAL_KHR:
5102             case EGL_DEBUG_MSG_ERROR_KHR:
5103             case EGL_DEBUG_MSG_WARN_KHR:
5104             case EGL_DEBUG_MSG_INFO_KHR:
5105                 if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
5106                 {
5107                     val->setError(EGL_BAD_ATTRIBUTE,
5108                                   "message controls must be EGL_TRUE or EGL_FALSE.");
5109                     return false;
5110                 }
5111                 break;
5112         }
5113     }
5114 
5115     return true;
5116 }
5117 
ValidateQueryDebugKHR(const ValidationContext * val,EGLint attribute,const EGLAttrib * value)5118 bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value)
5119 {
5120     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5121     if (!clientExtensions.debug)
5122     {
5123         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5124         return false;
5125     }
5126 
5127     switch (attribute)
5128     {
5129         case EGL_DEBUG_MSG_CRITICAL_KHR:
5130         case EGL_DEBUG_MSG_ERROR_KHR:
5131         case EGL_DEBUG_MSG_WARN_KHR:
5132         case EGL_DEBUG_MSG_INFO_KHR:
5133         case EGL_DEBUG_CALLBACK_KHR:
5134             break;
5135 
5136         default:
5137             val->setError(EGL_BAD_ATTRIBUTE, "unknown attribute.");
5138             return false;
5139     }
5140 
5141     return true;
5142 }
5143 
ValidateLabelObjectKHR(const ValidationContext * val,const Display * display,ObjectType objectType,EGLObjectKHR object,EGLLabelKHR label)5144 bool ValidateLabelObjectKHR(const ValidationContext *val,
5145                             const Display *display,
5146                             ObjectType objectType,
5147                             EGLObjectKHR object,
5148                             EGLLabelKHR label)
5149 {
5150     const ClientExtensions &clientExtensions = Display::GetClientExtensions();
5151     if (!clientExtensions.debug)
5152     {
5153         val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
5154         return false;
5155     }
5156 
5157     LabeledObject *labeledObject = nullptr;
5158     ANGLE_VALIDATION_TRY(ValidateLabeledObject(val, display, objectType, object, &labeledObject));
5159 
5160     return true;
5161 }
5162 
ValidateGetCompositorTimingSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,CompositorTiming name)5163 bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
5164                                                  const Display *display,
5165                                                  const Surface *surface,
5166                                                  CompositorTiming name)
5167 {
5168     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5169 
5170     if (!display->getExtensions().getFrameTimestamps)
5171     {
5172         val->setError(EGL_BAD_DISPLAY,
5173                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5174         return false;
5175     }
5176 
5177     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5178 
5179     if (!ValidCompositorTimingName(name))
5180     {
5181         val->setError(EGL_BAD_PARAMETER, "invalid timing name.");
5182         return false;
5183     }
5184 
5185     return true;
5186 }
5187 
ValidateGetCompositorTimingANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLint numTimestamps,const EGLint * names,const EGLnsecsANDROID * values)5188 bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
5189                                         const Display *display,
5190                                         const Surface *surface,
5191                                         EGLint numTimestamps,
5192                                         const EGLint *names,
5193                                         const EGLnsecsANDROID *values)
5194 {
5195     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5196 
5197     if (!display->getExtensions().getFrameTimestamps)
5198     {
5199         val->setError(EGL_BAD_DISPLAY,
5200                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5201         return false;
5202     }
5203 
5204     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5205 
5206     if (names == nullptr && numTimestamps > 0)
5207     {
5208         val->setError(EGL_BAD_PARAMETER, "names is NULL.");
5209         return false;
5210     }
5211 
5212     if (values == nullptr && numTimestamps > 0)
5213     {
5214         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5215         return false;
5216     }
5217 
5218     if (numTimestamps < 0)
5219     {
5220         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5221         return false;
5222     }
5223 
5224     for (EGLint i = 0; i < numTimestamps; i++)
5225     {
5226         CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
5227 
5228         if (!ValidCompositorTimingName(name))
5229         {
5230             val->setError(EGL_BAD_PARAMETER, "invalid compositor timing.");
5231             return false;
5232         }
5233 
5234         if (!surface->getSupportedCompositorTimings().test(name))
5235         {
5236             val->setError(EGL_BAD_PARAMETER, "compositor timing not supported by surface.");
5237             return false;
5238         }
5239     }
5240 
5241     return true;
5242 }
5243 
ValidateGetNextFrameIdANDROID(const ValidationContext * val,const Display * display,const Surface * surface,const EGLuint64KHR * frameId)5244 bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
5245                                    const Display *display,
5246                                    const Surface *surface,
5247                                    const EGLuint64KHR *frameId)
5248 {
5249     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5250 
5251     if (!display->getExtensions().getFrameTimestamps)
5252     {
5253         val->setError(EGL_BAD_DISPLAY,
5254                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5255         return false;
5256     }
5257 
5258     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5259 
5260     if (frameId == nullptr)
5261     {
5262         val->setError(EGL_BAD_PARAMETER, "frameId is NULL.");
5263         return false;
5264     }
5265 
5266     return true;
5267 }
5268 
ValidateGetFrameTimestampSupportedANDROID(const ValidationContext * val,const Display * display,const Surface * surface,Timestamp timestamp)5269 bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
5270                                                const Display *display,
5271                                                const Surface *surface,
5272                                                Timestamp timestamp)
5273 {
5274     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5275 
5276     if (!display->getExtensions().getFrameTimestamps)
5277     {
5278         val->setError(EGL_BAD_DISPLAY,
5279                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5280         return false;
5281     }
5282 
5283     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5284 
5285     if (!ValidTimestampType(timestamp))
5286     {
5287         val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5288         return false;
5289     }
5290 
5291     return true;
5292 }
5293 
ValidateGetFrameTimestampsANDROID(const ValidationContext * val,const Display * display,const Surface * surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,const EGLnsecsANDROID * values)5294 bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
5295                                        const Display *display,
5296                                        const Surface *surface,
5297                                        EGLuint64KHR frameId,
5298                                        EGLint numTimestamps,
5299                                        const EGLint *timestamps,
5300                                        const EGLnsecsANDROID *values)
5301 {
5302     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5303 
5304     if (!display->getExtensions().getFrameTimestamps)
5305     {
5306         val->setError(EGL_BAD_DISPLAY,
5307                       "EGL_ANDROID_get_frame_timestamps extension is not available.");
5308         return false;
5309     }
5310 
5311     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5312 
5313     if (!surface->isTimestampsEnabled())
5314     {
5315         val->setError(EGL_BAD_SURFACE, "timestamp collection is not enabled for this surface.");
5316         return false;
5317     }
5318 
5319     if (timestamps == nullptr && numTimestamps > 0)
5320     {
5321         val->setError(EGL_BAD_PARAMETER, "timestamps is NULL.");
5322         return false;
5323     }
5324 
5325     if (values == nullptr && numTimestamps > 0)
5326     {
5327         val->setError(EGL_BAD_PARAMETER, "values is NULL.");
5328         return false;
5329     }
5330 
5331     if (numTimestamps < 0)
5332     {
5333         val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
5334         return false;
5335     }
5336 
5337     for (EGLint i = 0; i < numTimestamps; i++)
5338     {
5339         Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
5340 
5341         if (!ValidTimestampType(timestamp))
5342         {
5343             val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
5344             return false;
5345         }
5346 
5347         if (!surface->getSupportedTimestamps().test(timestamp))
5348         {
5349             val->setError(EGL_BAD_PARAMETER, "timestamp not supported by surface.");
5350             return false;
5351         }
5352     }
5353 
5354     return true;
5355 }
5356 
ValidateQueryStringiANGLE(const ValidationContext * val,const Display * display,EGLint name,EGLint index)5357 bool ValidateQueryStringiANGLE(const ValidationContext *val,
5358                                const Display *display,
5359                                EGLint name,
5360                                EGLint index)
5361 {
5362     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5363 
5364     if (!Display::GetClientExtensions().featureControlANGLE)
5365     {
5366         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_feature_control extension is not available.");
5367         return false;
5368     }
5369 
5370     if (index < 0)
5371     {
5372         val->setError(EGL_BAD_PARAMETER, "index is negative.");
5373         return false;
5374     }
5375 
5376     switch (name)
5377     {
5378         case EGL_FEATURE_NAME_ANGLE:
5379         case EGL_FEATURE_CATEGORY_ANGLE:
5380         case EGL_FEATURE_DESCRIPTION_ANGLE:
5381         case EGL_FEATURE_BUG_ANGLE:
5382         case EGL_FEATURE_STATUS_ANGLE:
5383         case EGL_FEATURE_CONDITION_ANGLE:
5384             break;
5385         default:
5386             val->setError(EGL_BAD_PARAMETER, "name is not valid.");
5387             return false;
5388     }
5389 
5390     if (static_cast<size_t>(index) >= display->getFeatures().size())
5391     {
5392         val->setError(EGL_BAD_PARAMETER, "index is too big.");
5393         return false;
5394     }
5395 
5396     return true;
5397 }
5398 
ValidateQueryDisplayAttribEXT(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5399 bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
5400                                    const Display *display,
5401                                    const EGLint attribute,
5402                                    const EGLAttrib *value)
5403 {
5404     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5405     return true;
5406 }
5407 
ValidateQueryDisplayAttribANGLE(const ValidationContext * val,const Display * display,const EGLint attribute,const EGLAttrib * value)5408 bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
5409                                      const Display *display,
5410                                      const EGLint attribute,
5411                                      const EGLAttrib *value)
5412 {
5413     ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
5414     return true;
5415 }
5416 
ValidateGetNativeClientBufferANDROID(const ValidationContext * val,const AHardwareBuffer * buffer)5417 bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
5418                                           const AHardwareBuffer *buffer)
5419 {
5420     // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
5421     // despite it being a display extension.  No display is needed for the implementation though.
5422     if (buffer == nullptr)
5423     {
5424         val->setError(EGL_BAD_PARAMETER, "NULL buffer.");
5425         return false;
5426     }
5427 
5428     return true;
5429 }
5430 
ValidateCreateNativeClientBufferANDROID(const ValidationContext * val,const egl::AttributeMap & attribMap)5431 bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
5432                                              const egl::AttributeMap &attribMap)
5433 {
5434     if (attribMap.isEmpty() || attribMap.begin()->second == EGL_NONE)
5435     {
5436         val->setError(EGL_BAD_PARAMETER, "invalid attribute list.");
5437         return false;
5438     }
5439 
5440     int width     = attribMap.getAsInt(EGL_WIDTH, 0);
5441     int height    = attribMap.getAsInt(EGL_HEIGHT, 0);
5442     int redSize   = attribMap.getAsInt(EGL_RED_SIZE, 0);
5443     int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
5444     int blueSize  = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
5445     int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
5446     int usage     = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
5447 
5448     for (AttributeMap::const_iterator attributeIter = attribMap.begin();
5449          attributeIter != attribMap.end(); attributeIter++)
5450     {
5451         EGLAttrib attribute = attributeIter->first;
5452         switch (attribute)
5453         {
5454             case EGL_WIDTH:
5455             case EGL_HEIGHT:
5456                 // Validation done after the switch statement
5457                 break;
5458             case EGL_RED_SIZE:
5459             case EGL_GREEN_SIZE:
5460             case EGL_BLUE_SIZE:
5461             case EGL_ALPHA_SIZE:
5462                 if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
5463                 {
5464                     val->setError(EGL_BAD_PARAMETER, "incorrect channel size requested");
5465                     return false;
5466                 }
5467                 break;
5468             case EGL_NATIVE_BUFFER_USAGE_ANDROID:
5469                 // The buffer must be used for either a texture or a renderbuffer.
5470                 if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
5471                                EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
5472                                EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
5473                 {
5474                     val->setError(EGL_BAD_PARAMETER, "invalid usage flag");
5475                     return false;
5476                 }
5477                 break;
5478             case EGL_NONE:
5479                 break;
5480             default:
5481                 val->setError(EGL_BAD_ATTRIBUTE, "invalid attribute");
5482                 return false;
5483         }
5484     }
5485 
5486     // Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
5487     // for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
5488     if (width <= 0 || height <= 0)
5489     {
5490         val->setError(EGL_BAD_PARAMETER, "incorrect buffer dimensions requested");
5491         return false;
5492     }
5493 
5494     if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
5495     {
5496         val->setError(EGL_BAD_PARAMETER, "unsupported format");
5497         return false;
5498     }
5499     return true;
5500 }
5501 
ValidateDupNativeFenceFDANDROID(const ValidationContext * val,const Display * display,const Sync * sync)5502 bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
5503                                      const Display *display,
5504                                      const Sync *sync)
5505 {
5506     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5507 
5508     if (!display->getExtensions().nativeFenceSyncANDROID)
5509     {
5510         val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_native_fence_sync extension is not available.");
5511         return false;
5512     }
5513 
5514     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
5515 
5516     return true;
5517 }
5518 
ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext * val,const Display * display,const Surface * surface,EGLFrameTokenANGLE frametoken)5519 bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
5520                                             const Display *display,
5521                                             const Surface *surface,
5522                                             EGLFrameTokenANGLE frametoken)
5523 {
5524     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5525 
5526     if (!display->getExtensions().swapWithFrameToken)
5527     {
5528         val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available.");
5529         return false;
5530     }
5531 
5532     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
5533 
5534     return true;
5535 }
5536 
ValidateSignalSyncKHR(const ValidationContext * val,const Display * display,const Sync * sync,EGLenum mode)5537 bool ValidateSignalSyncKHR(const ValidationContext *val,
5538                            const Display *display,
5539                            const Sync *sync,
5540                            EGLenum mode)
5541 {
5542     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5543 
5544     ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
5545 
5546     if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
5547     {
5548         if (!display->getExtensions().reusableSyncKHR)
5549         {
5550             val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
5551             return false;
5552         }
5553 
5554         if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
5555         {
5556             val->setError(EGL_BAD_PARAMETER, "eglSignalSyncKHR invalid mode.");
5557             return false;
5558         }
5559 
5560         return true;
5561     }
5562 
5563     val->setError(EGL_BAD_MATCH);
5564     return false;
5565 }
5566 
ValidateQuerySurfacePointerANGLE(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint attribute,void * const * value)5567 bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
5568                                       const Display *display,
5569                                       const Surface *eglSurface,
5570                                       EGLint attribute,
5571                                       void *const *value)
5572 {
5573     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5574 
5575     if (!display->getExtensions().querySurfacePointer)
5576     {
5577         val->setError(EGL_BAD_ACCESS);
5578         return false;
5579     }
5580 
5581     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
5582 
5583     // validate the attribute parameter
5584     switch (attribute)
5585     {
5586         case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
5587             if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
5588             {
5589                 val->setError(EGL_BAD_ATTRIBUTE);
5590                 return false;
5591             }
5592             break;
5593         case EGL_DXGI_KEYED_MUTEX_ANGLE:
5594             if (!display->getExtensions().keyedMutex)
5595             {
5596                 val->setError(EGL_BAD_ATTRIBUTE);
5597                 return false;
5598             }
5599             break;
5600         default:
5601             val->setError(EGL_BAD_ATTRIBUTE);
5602             return false;
5603     }
5604 
5605     return true;
5606 }
5607 
ValidatePostSubBufferNV(const ValidationContext * val,const Display * display,const Surface * eglSurface,EGLint x,EGLint y,EGLint width,EGLint height)5608 bool ValidatePostSubBufferNV(const ValidationContext *val,
5609                              const Display *display,
5610                              const Surface *eglSurface,
5611                              EGLint x,
5612                              EGLint y,
5613                              EGLint width,
5614                              EGLint height)
5615 {
5616     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5617 
5618     if (!display->getExtensions().postSubBuffer)
5619     {
5620         val->setError(EGL_BAD_ACCESS);
5621         return false;
5622     }
5623 
5624     if (x < 0 || y < 0 || width < 0 || height < 0)
5625     {
5626         val->setError(EGL_BAD_PARAMETER);
5627         return false;
5628     }
5629 
5630     ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
5631 
5632     if (display->isDeviceLost())
5633     {
5634         val->setError(EGL_CONTEXT_LOST);
5635         return false;
5636     }
5637 
5638     return true;
5639 }
5640 
ValidateQueryDeviceAttribEXT(const ValidationContext * val,const Device * device,EGLint attribute,const EGLAttrib * value)5641 bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
5642                                   const Device *device,
5643                                   EGLint attribute,
5644                                   const EGLAttrib *value)
5645 {
5646     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
5647 
5648     if (!Display::GetClientExtensions().deviceQueryEXT)
5649     {
5650         val->setError(EGL_BAD_ACCESS, "EGL_EXT_device_query not supported.");
5651         return false;
5652     }
5653 
5654     // validate the attribute parameter
5655     switch (attribute)
5656     {
5657         case EGL_D3D11_DEVICE_ANGLE:
5658         case EGL_D3D9_DEVICE_ANGLE:
5659             if (!device->getExtensions().deviceD3D || device->getType() != attribute)
5660             {
5661                 val->setError(EGL_BAD_ATTRIBUTE);
5662                 return false;
5663             }
5664             break;
5665         case EGL_EAGL_CONTEXT_ANGLE:
5666             if (!device->getExtensions().deviceEAGL)
5667             {
5668                 val->setError(EGL_BAD_ATTRIBUTE);
5669                 return false;
5670             }
5671             break;
5672         case EGL_METAL_DEVICE_ANGLE:
5673             if (!device->getExtensions().deviceMetal)
5674             {
5675                 val->setError(EGL_BAD_ATTRIBUTE);
5676                 return false;
5677             }
5678             break;
5679         case EGL_CGL_CONTEXT_ANGLE:
5680         case EGL_CGL_PIXEL_FORMAT_ANGLE:
5681             if (!device->getExtensions().deviceCGL)
5682             {
5683                 val->setError(EGL_BAD_ATTRIBUTE);
5684                 return false;
5685             }
5686             break;
5687         default:
5688             val->setError(EGL_BAD_ATTRIBUTE);
5689             return false;
5690     }
5691     return true;
5692 }
5693 
ValidateQueryDeviceStringEXT(const ValidationContext * val,const Device * device,EGLint name)5694 bool ValidateQueryDeviceStringEXT(const ValidationContext *val, const Device *device, EGLint name)
5695 {
5696     ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
5697     return true;
5698 }
5699 
ValidateReleaseHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)5700 bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
5701                                       const Display *display,
5702                                       const gl::Context *context)
5703 {
5704     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
5705     return true;
5706 }
5707 
ValidateReacquireHighPowerGPUANGLE(const ValidationContext * val,const Display * display,const gl::Context * context)5708 bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
5709                                         const Display *display,
5710                                         const gl::Context *context)
5711 {
5712     ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
5713     return true;
5714 }
5715 
ValidateHandleGPUSwitchANGLE(const ValidationContext * val,const Display * display)5716 bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *display)
5717 {
5718     ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
5719     return true;
5720 }
5721 
ValidateGetCurrentDisplay(const ValidationContext * val)5722 bool ValidateGetCurrentDisplay(const ValidationContext *val)
5723 {
5724     return true;
5725 }
5726 
ValidateGetCurrentSurface(const ValidationContext * val,EGLint readdraw)5727 bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw)
5728 {
5729     return true;
5730 }
5731 
ValidateGetDisplay(const ValidationContext * val,EGLNativeDisplayType display_id)5732 bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id)
5733 {
5734     return true;
5735 }
5736 
ValidateGetError(const ValidationContext * val)5737 bool ValidateGetError(const ValidationContext *val)
5738 {
5739     return true;
5740 }
5741 
ValidateGetProcAddress(const ValidationContext * val,const char * procname)5742 bool ValidateGetProcAddress(const ValidationContext *val, const char *procname)
5743 {
5744     return true;
5745 }
5746 
ValidateQueryString(const ValidationContext * val,const Display * dpyPacked,EGLint name)5747 bool ValidateQueryString(const ValidationContext *val, const Display *dpyPacked, EGLint name)
5748 {
5749     if (name != EGL_EXTENSIONS || dpyPacked != nullptr)
5750     {
5751         ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpyPacked));
5752     }
5753 
5754     switch (name)
5755     {
5756         case EGL_CLIENT_APIS:
5757         case EGL_EXTENSIONS:
5758         case EGL_VENDOR:
5759         case EGL_VERSION:
5760             break;
5761         default:
5762             val->setError(EGL_BAD_PARAMETER);
5763             return false;
5764     }
5765     return true;
5766 }
5767 
ValidateWaitGL(const ValidationContext * val)5768 bool ValidateWaitGL(const ValidationContext *val)
5769 {
5770     if (val->eglThread->getDisplay() == nullptr)
5771     {
5772         // EGL spec says this about eglWaitGL -
5773         //    eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
5774         return true;
5775     }
5776 
5777     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
5778     return true;
5779 }
5780 
ValidateQueryAPI(const ValidationContext * val)5781 bool ValidateQueryAPI(const ValidationContext *val)
5782 {
5783     return true;
5784 }
5785 
ValidateReleaseThread(const ValidationContext * val)5786 bool ValidateReleaseThread(const ValidationContext *val)
5787 {
5788     return true;
5789 }
5790 
ValidateWaitClient(const ValidationContext * val)5791 bool ValidateWaitClient(const ValidationContext *val)
5792 {
5793     if (val->eglThread->getDisplay() == nullptr)
5794     {
5795         // EGL spec says this about eglWaitClient -
5796         //    If there is no current context for the current rendering API,
5797         //    the function has no effect but still returns EGL_TRUE.
5798         return true;
5799     }
5800 
5801     ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
5802     return true;
5803 }
5804 
ValidateGetCurrentContext(const ValidationContext * val)5805 bool ValidateGetCurrentContext(const ValidationContext *val)
5806 {
5807     return true;
5808 }
5809 
ValidateCreatePlatformPixmapSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_pixmap,const AttributeMap & attrib_listPacked)5810 bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
5811                                          const Display *dpyPacked,
5812                                          const Config *configPacked,
5813                                          const void *native_pixmap,
5814                                          const AttributeMap &attrib_listPacked)
5815 {
5816     EGLNativePixmapType nativePixmap =
5817         reinterpret_cast<EGLNativePixmapType>(const_cast<void *>(native_pixmap));
5818     return ValidateCreatePixmapSurface(val, dpyPacked, configPacked, nativePixmap,
5819                                        attrib_listPacked);
5820 }
5821 
ValidateCreatePlatformWindowSurface(const ValidationContext * val,const Display * dpyPacked,const Config * configPacked,const void * native_window,const AttributeMap & attrib_listPacked)5822 bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
5823                                          const Display *dpyPacked,
5824                                          const Config *configPacked,
5825                                          const void *native_window,
5826                                          const AttributeMap &attrib_listPacked)
5827 {
5828     EGLNativeWindowType nativeWindow =
5829         reinterpret_cast<EGLNativeWindowType>(const_cast<void *>(native_window));
5830     return ValidateCreateWindowSurface(val, dpyPacked, configPacked, nativeWindow,
5831                                        attrib_listPacked);
5832 }
5833 
5834 }  // namespace egl
5835