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