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