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