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