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