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