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