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