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.h"
10
11 #include "common/utilities.h"
12 #include "libANGLE/Config.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Device.h"
15 #include "libANGLE/Display.h"
16 #include "libANGLE/EGLSync.h"
17 #include "libANGLE/Image.h"
18 #include "libANGLE/Stream.h"
19 #include "libANGLE/Surface.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/Thread.h"
22 #include "libANGLE/formatutils.h"
23
24 #include <EGL/eglext.h>
25
26 namespace egl
27 {
28 namespace
29 {
GetMaximumMipLevel(const gl::Context * context,gl::TextureType type)30 size_t GetMaximumMipLevel(const gl::Context *context, gl::TextureType type)
31 {
32 const gl::Caps &caps = context->getCaps();
33
34 int maxDimension = 0;
35 switch (type)
36 {
37 case gl::TextureType::_2D:
38 case gl::TextureType::_2DArray:
39 case gl::TextureType::_2DMultisample:
40 maxDimension = caps.max2DTextureSize;
41 break;
42 case gl::TextureType::Rectangle:
43 maxDimension = caps.maxRectangleTextureSize;
44 break;
45 case gl::TextureType::CubeMap:
46 maxDimension = caps.maxCubeMapTextureSize;
47 break;
48 case gl::TextureType::_3D:
49 maxDimension = caps.max3DTextureSize;
50 break;
51
52 default:
53 UNREACHABLE();
54 }
55
56 return gl::log2(maxDimension);
57 }
58
TextureHasNonZeroMipLevelsSpecified(const gl::Context * context,const gl::Texture * texture)59 bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
60 {
61 size_t maxMip = GetMaximumMipLevel(context, texture->getType());
62 for (size_t level = 1; level < maxMip; level++)
63 {
64 if (texture->getType() == gl::TextureType::CubeMap)
65 {
66 for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
67 {
68 if (texture->getFormat(face, level).valid())
69 {
70 return true;
71 }
72 }
73 }
74 else
75 {
76 if (texture->getFormat(gl::NonCubeTextureTypeToTarget(texture->getType()), level)
77 .valid())
78 {
79 return true;
80 }
81 }
82 }
83
84 return false;
85 }
86
CubeTextureHasUnspecifiedLevel0Face(const gl::Texture * texture)87 bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
88 {
89 ASSERT(texture->getType() == gl::TextureType::CubeMap);
90 for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
91 {
92 if (!texture->getFormat(face, 0).valid())
93 {
94 return true;
95 }
96 }
97
98 return false;
99 }
100
ValidateStreamAttribute(const EGLAttrib attribute,const EGLAttrib value,const DisplayExtensions & extensions)101 Error ValidateStreamAttribute(const EGLAttrib attribute,
102 const EGLAttrib value,
103 const DisplayExtensions &extensions)
104 {
105 switch (attribute)
106 {
107 case EGL_STREAM_STATE_KHR:
108 case EGL_PRODUCER_FRAME_KHR:
109 case EGL_CONSUMER_FRAME_KHR:
110 return EglBadAccess() << "Attempt to initialize readonly parameter";
111 case EGL_CONSUMER_LATENCY_USEC_KHR:
112 // Technically not in spec but a latency < 0 makes no sense so we check it
113 if (value < 0)
114 {
115 return EglBadParameter() << "Latency must be positive";
116 }
117 break;
118 case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
119 if (!extensions.streamConsumerGLTexture)
120 {
121 return EglBadAttribute() << "Consumer GL extension not enabled";
122 }
123 // Again not in spec but it should be positive anyways
124 if (value < 0)
125 {
126 return EglBadParameter() << "Timeout must be positive";
127 }
128 break;
129 default:
130 return EglBadAttribute() << "Invalid stream attribute";
131 }
132 return NoError();
133 }
134
ValidateCreateImageMipLevelCommon(gl::Context * context,const gl::Texture * texture,EGLAttrib level)135 Error ValidateCreateImageMipLevelCommon(gl::Context *context,
136 const gl::Texture *texture,
137 EGLAttrib level)
138 {
139 // Note that the spec EGL_create_image spec does not explicitly specify an error
140 // when the level is outside the base/max level range, but it does mention that the
141 // level "must be a part of the complete texture object <buffer>". It can be argued
142 // that out-of-range levels are not a part of the complete texture.
143 const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
144 if (level > 0 &&
145 (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
146 static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
147 {
148 return EglBadParameter() << "texture must be complete if level is non-zero.";
149 }
150
151 if (level == 0 && !texture->isMipmapComplete() &&
152 TextureHasNonZeroMipLevelsSpecified(context, texture))
153 {
154 return EglBadParameter() << "if level is zero and the texture is incomplete, it must "
155 "have no mip levels specified except zero.";
156 }
157
158 return NoError();
159 }
160
ValidateConfigAttribute(const Display * display,EGLAttrib attribute)161 Error ValidateConfigAttribute(const Display *display, EGLAttrib attribute)
162 {
163 switch (attribute)
164 {
165 case EGL_BUFFER_SIZE:
166 case EGL_ALPHA_SIZE:
167 case EGL_BLUE_SIZE:
168 case EGL_GREEN_SIZE:
169 case EGL_RED_SIZE:
170 case EGL_DEPTH_SIZE:
171 case EGL_STENCIL_SIZE:
172 case EGL_CONFIG_CAVEAT:
173 case EGL_CONFIG_ID:
174 case EGL_LEVEL:
175 case EGL_NATIVE_RENDERABLE:
176 case EGL_NATIVE_VISUAL_ID:
177 case EGL_NATIVE_VISUAL_TYPE:
178 case EGL_SAMPLES:
179 case EGL_SAMPLE_BUFFERS:
180 case EGL_SURFACE_TYPE:
181 case EGL_TRANSPARENT_TYPE:
182 case EGL_TRANSPARENT_BLUE_VALUE:
183 case EGL_TRANSPARENT_GREEN_VALUE:
184 case EGL_TRANSPARENT_RED_VALUE:
185 case EGL_BIND_TO_TEXTURE_RGB:
186 case EGL_BIND_TO_TEXTURE_RGBA:
187 case EGL_MIN_SWAP_INTERVAL:
188 case EGL_MAX_SWAP_INTERVAL:
189 case EGL_LUMINANCE_SIZE:
190 case EGL_ALPHA_MASK_SIZE:
191 case EGL_COLOR_BUFFER_TYPE:
192 case EGL_RENDERABLE_TYPE:
193 case EGL_MATCH_NATIVE_PIXMAP:
194 case EGL_CONFORMANT:
195 case EGL_MAX_PBUFFER_WIDTH:
196 case EGL_MAX_PBUFFER_HEIGHT:
197 case EGL_MAX_PBUFFER_PIXELS:
198 break;
199
200 case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
201 if (!display->getExtensions().surfaceOrientation)
202 {
203 return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
204 }
205 break;
206
207 case EGL_COLOR_COMPONENT_TYPE_EXT:
208 if (!display->getExtensions().pixelFormatFloat)
209 {
210 return EglBadAttribute() << "EGL_EXT_pixel_format_float is not enabled.";
211 }
212 break;
213
214 case EGL_RECORDABLE_ANDROID:
215 if (!display->getExtensions().recordable)
216 {
217 return EglBadAttribute() << "EGL_ANDROID_recordable is not enabled.";
218 }
219 break;
220
221 case EGL_FRAMEBUFFER_TARGET_ANDROID:
222 if (!display->getExtensions().framebufferTargetANDROID)
223 {
224 return EglBadAttribute() << "EGL_ANDROID_framebuffer_target is not enabled.";
225 }
226 break;
227
228 case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
229 if (!display->getExtensions().iosurfaceClientBuffer)
230 {
231 return EglBadAttribute() << "EGL_ANGLE_iosurface_client_buffer is not enabled.";
232 }
233 break;
234
235 default:
236 return EglBadAttribute() << "Unknown attribute.";
237 }
238
239 return NoError();
240 }
241
ValidateConfigAttributeValue(const Display * display,EGLAttrib attribute,EGLAttrib value)242 Error ValidateConfigAttributeValue(const Display *display, EGLAttrib attribute, EGLAttrib value)
243 {
244 switch (attribute)
245 {
246
247 case EGL_BIND_TO_TEXTURE_RGB:
248 case EGL_BIND_TO_TEXTURE_RGBA:
249 switch (value)
250 {
251 case EGL_DONT_CARE:
252 case EGL_TRUE:
253 case EGL_FALSE:
254 break;
255 default:
256 return EglBadAttribute() << "EGL_bind_to_texture invalid attribute: " << value;
257 }
258 break;
259
260 case EGL_COLOR_BUFFER_TYPE:
261 switch (value)
262 {
263 case EGL_RGB_BUFFER:
264 case EGL_LUMINANCE_BUFFER:
265 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
266 case EGL_DONT_CARE:
267 break;
268 default:
269 return EglBadAttribute()
270 << "EGL_color_buffer_type invalid attribute: " << value;
271 }
272 break;
273
274 case EGL_NATIVE_RENDERABLE:
275 switch (value)
276 {
277 case EGL_DONT_CARE:
278 case EGL_TRUE:
279 case EGL_FALSE:
280 break;
281 default:
282 return EglBadAttribute()
283 << "EGL_native_renderable invalid attribute: " << value;
284 }
285 break;
286
287 case EGL_TRANSPARENT_TYPE:
288 switch (value)
289 {
290 case EGL_NONE:
291 case EGL_TRANSPARENT_RGB:
292 // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
293 case EGL_DONT_CARE:
294 break;
295 default:
296 return EglBadAttribute() << "EGL_transparent_type invalid attribute: " << value;
297 }
298 break;
299
300 case EGL_RECORDABLE_ANDROID:
301 switch (value)
302 {
303 case EGL_TRUE:
304 case EGL_FALSE:
305 case EGL_DONT_CARE:
306 break;
307 default:
308 return EglBadAttribute()
309 << "EGL_RECORDABLE_ANDROID invalid attribute: " << value;
310 }
311 break;
312
313 case EGL_COLOR_COMPONENT_TYPE_EXT:
314 switch (value)
315 {
316 case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
317 case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
318 case EGL_DONT_CARE:
319 break;
320 default:
321 return EglBadAttribute()
322 << "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: " << value;
323 }
324 break;
325
326 default:
327 break;
328 }
329
330 return NoError();
331 }
332
ValidateConfigAttributes(const Display * display,const AttributeMap & attributes)333 Error ValidateConfigAttributes(const Display *display, const AttributeMap &attributes)
334 {
335 for (const auto &attrib : attributes)
336 {
337 ANGLE_TRY(ValidateConfigAttribute(display, attrib.first));
338 ANGLE_TRY(ValidateConfigAttributeValue(display, attrib.first, attrib.second));
339 }
340
341 return NoError();
342 }
343
ValidateColorspaceAttribute(const DisplayExtensions & displayExtensions,EGLAttrib colorSpace)344 Error ValidateColorspaceAttribute(const DisplayExtensions &displayExtensions, EGLAttrib colorSpace)
345 {
346 switch (colorSpace)
347 {
348 case EGL_GL_COLORSPACE_SRGB:
349 break;
350 case EGL_GL_COLORSPACE_LINEAR:
351 break;
352 case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
353 if (!displayExtensions.glColorspaceDisplayP3Linear)
354 {
355 return EglBadAttribute() << "EXT_gl_colorspace_display_p3_linear is not available.";
356 }
357 break;
358 case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
359 if (!displayExtensions.glColorspaceDisplayP3)
360 {
361 return EglBadAttribute() << "EXT_gl_colorspace_display_p3 is not available.";
362 }
363 break;
364 case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
365 if (!displayExtensions.glColorspaceDisplayP3Passthrough)
366 {
367 return EglBadAttribute()
368 << "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.";
369 }
370 break;
371 case EGL_GL_COLORSPACE_SCRGB_EXT:
372 if (!displayExtensions.glColorspaceScrgb)
373 {
374 return EglBadAttribute() << "EXT_gl_colorspace_scrgb is not available.";
375 }
376 break;
377 case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
378 if (!displayExtensions.glColorspaceScrgbLinear)
379 {
380 return EglBadAttribute() << "EXT_gl_colorspace_scrgb_linear is not available.";
381 }
382 break;
383 default:
384 return EglBadAttribute();
385 }
386 return NoError();
387 }
ValidatePlatformType(const ClientExtensions & clientExtensions,EGLAttrib platformType)388 Error ValidatePlatformType(const ClientExtensions &clientExtensions, EGLAttrib platformType)
389 {
390 switch (platformType)
391 {
392 case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
393 break;
394
395 case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
396 case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
397 if (!clientExtensions.platformANGLED3D)
398 {
399 return EglBadAttribute() << "Direct3D platform is unsupported.";
400 }
401 break;
402
403 case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
404 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
405 if (!clientExtensions.platformANGLEOpenGL)
406 {
407 return EglBadAttribute() << "OpenGL platform is unsupported.";
408 }
409 break;
410
411 case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
412 if (!clientExtensions.platformANGLENULL)
413 {
414 return EglBadAttribute() << "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
415 "requires EGL_ANGLE_platform_angle_null.";
416 }
417 break;
418
419 case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
420 if (!clientExtensions.platformANGLEVulkan)
421 {
422 return EglBadAttribute() << "Vulkan platform is unsupported.";
423 }
424 break;
425
426 case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
427 if (!clientExtensions.platformANGLEMetal)
428 {
429 return EglBadAttribute() << "Metal platform is unsupported.";
430 }
431 break;
432
433 default:
434 return EglBadAttribute() << "Unknown platform type.";
435 }
436
437 return NoError();
438 }
439
ValidateGetPlatformDisplayCommon(EGLenum platform,void * native_display,const AttributeMap & attribMap)440 Error ValidateGetPlatformDisplayCommon(EGLenum platform,
441 void *native_display,
442 const AttributeMap &attribMap)
443 {
444 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
445
446 switch (platform)
447 {
448 case EGL_PLATFORM_ANGLE_ANGLE:
449 if (!clientExtensions.platformANGLE)
450 {
451 return EglBadParameter() << "Platform ANGLE extension is not active";
452 }
453 break;
454 case EGL_PLATFORM_DEVICE_EXT:
455 if (!clientExtensions.platformDevice)
456 {
457 return EglBadParameter() << "Platform Device extension is not active";
458 }
459 break;
460 default:
461 return EglBadConfig() << "Bad platform type.";
462 }
463
464 if (platform == EGL_PLATFORM_ANGLE_ANGLE)
465 {
466 EGLAttrib platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
467 bool enableAutoTrimSpecified = false;
468 bool enableD3D11on12 = false;
469 bool presentPathSpecified = false;
470
471 Optional<EGLAttrib> majorVersion;
472 Optional<EGLAttrib> minorVersion;
473 Optional<EGLAttrib> deviceType;
474 Optional<EGLAttrib> eglHandle;
475
476 for (const auto &curAttrib : attribMap)
477 {
478 const EGLAttrib value = curAttrib.second;
479
480 switch (curAttrib.first)
481 {
482 case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
483 {
484 ANGLE_TRY(ValidatePlatformType(clientExtensions, value));
485 platformType = value;
486 break;
487 }
488
489 case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
490 if (value != EGL_DONT_CARE)
491 {
492 majorVersion = value;
493 }
494 break;
495
496 case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
497 if (value != EGL_DONT_CARE)
498 {
499 minorVersion = value;
500 }
501 break;
502
503 case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
504 switch (value)
505 {
506 case EGL_TRUE:
507 case EGL_FALSE:
508 break;
509 default:
510 return EglBadAttribute() << "Invalid automatic trim attribute";
511 }
512 enableAutoTrimSpecified = true;
513 break;
514
515 case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
516 if (!clientExtensions.platformANGLED3D ||
517 !clientExtensions.platformANGLED3D11ON12)
518 {
519 return EglBadAttribute()
520 << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.";
521 }
522
523 switch (value)
524 {
525 case EGL_TRUE:
526 case EGL_FALSE:
527 break;
528 default:
529 return EglBadAttribute() << "Invalid D3D11on12 attribute";
530 }
531 enableD3D11on12 = true;
532 break;
533
534 case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
535 if (!clientExtensions.experimentalPresentPath)
536 {
537 return EglBadAttribute()
538 << "EGL_ANGLE_experimental_present_path extension not active";
539 }
540
541 switch (value)
542 {
543 case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
544 case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
545 break;
546 default:
547 return EglBadAttribute()
548 << "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE";
549 }
550 presentPathSpecified = true;
551 break;
552
553 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
554 switch (value)
555 {
556 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
557 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
558 break;
559
560 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
561 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
562 if (!clientExtensions.platformANGLED3D)
563 {
564 return EglBadAttribute()
565 << "EGL_ANGLE_platform_angle_d3d is not supported";
566 }
567 break;
568
569 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
570 if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
571 {
572 return EglBadAttribute() << "EGL_ANGLE_platform_angle_device_type_"
573 "egl_angle is not supported";
574 }
575 break;
576
577 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
578 if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
579 {
580 return EglBadAttribute() << "EGL_ANGLE_platform_angle_device_type_"
581 "swiftshader is not supported";
582 }
583 break;
584
585 default:
586 return EglBadAttribute() << "Invalid value for "
587 "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
588 "attrib";
589 }
590 deviceType = value;
591 break;
592
593 case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
594 if (!clientExtensions.platformANGLE)
595 {
596 return EglBadAttribute() << "EGL_ANGLE_platform_angle extension not active";
597 }
598 if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
599 {
600 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
601 "must be EGL_TRUE, EGL_FALSE, or "
602 "EGL_DONT_CARE.";
603 }
604 break;
605
606 case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
607 if (value != EGL_DONT_CARE)
608 {
609 eglHandle = value;
610 }
611 break;
612
613 case EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE:
614 if (!clientExtensions.platformANGLEContextVirtualization)
615 {
616 return EglBadAttribute() << "EGL_ANGLE_platform_angle_context_"
617 "virtualization extension not active";
618 }
619
620 switch (value)
621 {
622 case EGL_DONT_CARE:
623 case EGL_FALSE:
624 case EGL_TRUE:
625 break;
626
627 default:
628 return EglBadAttribute() << "Invalid value for "
629 "EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_"
630 "ANGLE attrib";
631 }
632 break;
633
634 default:
635 break;
636 }
637 }
638
639 if (!majorVersion.valid() && minorVersion.valid())
640 {
641 return EglBadAttribute()
642 << "Must specify major version if you specify a minor version.";
643 }
644
645 if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
646 platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
647 {
648 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
649 "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
650 }
651
652 if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
653 {
654 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
655 "requires a device type of "
656 "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
657 }
658
659 if (enableD3D11on12)
660 {
661 if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
662 {
663 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
664 "requires a platform type of "
665 "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
666 }
667
668 if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
669 deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
670 {
671 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
672 "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
673 "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE";
674 }
675 }
676
677 if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
678 {
679 return EglBadAttribute() << "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
680 "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.";
681 }
682
683 if (deviceType.valid())
684 {
685 switch (deviceType.value())
686 {
687 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
688 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
689 if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
690 platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
691 {
692 return EglBadAttribute()
693 << "This device type requires a "
694 "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
695 "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.";
696 }
697 break;
698
699 case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
700 if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
701 {
702 return EglBadAttribute()
703 << "This device type requires a "
704 "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.";
705 }
706 break;
707
708 default:
709 break;
710 }
711 }
712
713 if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
714 {
715 if ((majorVersion.valid() && majorVersion.value() != 1) ||
716 (minorVersion.valid() && minorVersion.value() != 0))
717 {
718 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
719 "only supports Vulkan 1.0.";
720 }
721 }
722
723 if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
724 platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
725 {
726 return EglBadAttribute() << "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
727 "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.";
728 }
729 }
730 else if (platform == EGL_PLATFORM_DEVICE_EXT)
731 {
732 Device *eglDevice = static_cast<Device *>(native_display);
733 if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
734 {
735 return EglBadAttribute() << "native_display should be a valid EGL device if "
736 "platform equals EGL_PLATFORM_DEVICE_EXT";
737 }
738 }
739 else
740 {
741 UNREACHABLE();
742 }
743
744 if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
745 {
746 if (!clientExtensions.featureControlANGLE)
747 {
748 return EglBadAttribute() << "EGL_ANGLE_feature_control is not supported";
749 }
750 else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
751 {
752 return EglBadAttribute()
753 << "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer";
754 }
755 }
756 if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
757 {
758 if (!clientExtensions.featureControlANGLE)
759 {
760 return EglBadAttribute() << "EGL_ANGLE_feature_control is not supported";
761 }
762 else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
763 {
764 return EglBadAttribute()
765 << "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer";
766 }
767 }
768
769 return NoError();
770 }
771
ValidateStream(const Display * display,const Stream * stream)772 Error ValidateStream(const Display *display, const Stream *stream)
773 {
774 ANGLE_TRY(ValidateDisplay(display));
775
776 const DisplayExtensions &displayExtensions = display->getExtensions();
777 if (!displayExtensions.stream)
778 {
779 return EglBadAccess() << "Stream extension not active";
780 }
781
782 if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
783 {
784 return EglBadStream() << "Invalid stream";
785 }
786
787 return NoError();
788 }
789
ValidateLabeledObject(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object,LabeledObject ** outLabeledObject)790 Error ValidateLabeledObject(Thread *thread,
791 const Display *display,
792 ObjectType objectType,
793 EGLObjectKHR object,
794 LabeledObject **outLabeledObject)
795 {
796 switch (objectType)
797 {
798 case ObjectType::Context:
799 {
800 gl::Context *context = static_cast<gl::Context *>(object);
801 ANGLE_TRY(ValidateContext(display, context));
802 *outLabeledObject = context;
803 break;
804 }
805
806 case ObjectType::Display:
807 {
808 ANGLE_TRY(ValidateDisplay(display));
809 if (display != object)
810 {
811 return EglBadParameter() << "when object type is EGL_OBJECT_DISPLAY_KHR, the "
812 "object must be the same as the display.";
813 }
814
815 *outLabeledObject = static_cast<Display *>(object);
816 break;
817 }
818
819 case ObjectType::Image:
820 {
821 Image *image = static_cast<Image *>(object);
822 ANGLE_TRY(ValidateImage(display, image));
823 *outLabeledObject = image;
824 break;
825 }
826
827 case ObjectType::Stream:
828 {
829 Stream *stream = static_cast<Stream *>(object);
830 ANGLE_TRY(ValidateStream(display, stream));
831 *outLabeledObject = stream;
832 break;
833 }
834
835 case ObjectType::Surface:
836 {
837 Surface *surface = static_cast<Surface *>(object);
838 ANGLE_TRY(ValidateSurface(display, surface));
839 *outLabeledObject = surface;
840 break;
841 }
842
843 case ObjectType::Sync:
844 {
845 Sync *sync = static_cast<Sync *>(object);
846 ANGLE_TRY(ValidateSync(display, sync));
847 *outLabeledObject = sync;
848 break;
849 }
850
851 case ObjectType::Thread:
852 {
853 *outLabeledObject = thread;
854 break;
855 }
856
857 default:
858 return EglBadParameter() << "unknown object type.";
859 }
860
861 return NoError();
862 }
863
864 // This is a common sub-check of Display status that's shared by multiple functions
ValidateDisplayPointer(const Display * display)865 Error ValidateDisplayPointer(const Display *display)
866 {
867 if (display == EGL_NO_DISPLAY)
868 {
869 return EglBadDisplay() << "display is EGL_NO_DISPLAY.";
870 }
871
872 if (!Display::isValidDisplay(display))
873 {
874 return EglBadDisplay() << "display is not a valid display.";
875 }
876
877 return NoError();
878 }
879
ValidCompositorTimingName(CompositorTiming name)880 bool ValidCompositorTimingName(CompositorTiming name)
881 {
882 switch (name)
883 {
884 case CompositorTiming::CompositeDeadline:
885 case CompositorTiming::CompositInterval:
886 case CompositorTiming::CompositToPresentLatency:
887 return true;
888
889 default:
890 return false;
891 }
892 }
893
ValidTimestampType(Timestamp timestamp)894 bool ValidTimestampType(Timestamp timestamp)
895 {
896 switch (timestamp)
897 {
898 case Timestamp::RequestedPresentTime:
899 case Timestamp::RenderingCompleteTime:
900 case Timestamp::CompositionLatchTime:
901 case Timestamp::FirstCompositionStartTime:
902 case Timestamp::LastCompositionStartTime:
903 case Timestamp::FirstCompositionGPUFinishedTime:
904 case Timestamp::DisplayPresentTime:
905 case Timestamp::DequeueReadyTime:
906 case Timestamp::ReadsDoneTime:
907 return true;
908
909 default:
910 return false;
911 }
912 }
913
914 } // anonymous namespace
915
ValidateDisplay(const Display * display)916 Error ValidateDisplay(const Display *display)
917 {
918 ANGLE_TRY(ValidateDisplayPointer(display));
919
920 if (!display->isInitialized())
921 {
922 return EglNotInitialized() << "display is not initialized.";
923 }
924
925 if (display->isDeviceLost())
926 {
927 return EglContextLost() << "display had a context loss";
928 }
929
930 return NoError();
931 }
932
ValidateSurface(const Display * display,const Surface * surface)933 Error ValidateSurface(const Display *display, const Surface *surface)
934 {
935 ANGLE_TRY(ValidateDisplay(display));
936
937 if (!display->isValidSurface(surface))
938 {
939 return EglBadSurface();
940 }
941
942 return NoError();
943 }
944
ValidateConfig(const Display * display,const Config * config)945 Error ValidateConfig(const Display *display, const Config *config)
946 {
947 ANGLE_TRY(ValidateDisplay(display));
948
949 if (!display->isValidConfig(config))
950 {
951 return EglBadConfig();
952 }
953
954 return NoError();
955 }
956
ValidateContext(const Display * display,const gl::Context * context)957 Error ValidateContext(const Display *display, const gl::Context *context)
958 {
959 ANGLE_TRY(ValidateDisplay(display));
960
961 if (!display->isValidContext(context))
962 {
963 return EglBadContext();
964 }
965
966 return NoError();
967 }
968
ValidateImage(const Display * display,const Image * image)969 Error ValidateImage(const Display *display, const Image *image)
970 {
971 ANGLE_TRY(ValidateDisplay(display));
972
973 if (!display->isValidImage(image))
974 {
975 return EglBadParameter() << "image is not valid.";
976 }
977
978 return NoError();
979 }
980
ValidateDevice(const Device * device)981 Error ValidateDevice(const Device *device)
982 {
983 if (device == EGL_NO_DEVICE_EXT)
984 {
985 return EglBadAccess() << "device is EGL_NO_DEVICE.";
986 }
987
988 if (!Device::IsValidDevice(device))
989 {
990 return EglBadAccess() << "device is not valid.";
991 }
992
993 return NoError();
994 }
995
ValidateSync(const Display * display,const Sync * sync)996 Error ValidateSync(const Display *display, const Sync *sync)
997 {
998 ANGLE_TRY(ValidateDisplay(display));
999
1000 if (!display->isValidSync(sync))
1001 {
1002 return EglBadParameter() << "sync object is not valid.";
1003 }
1004
1005 return NoError();
1006 }
1007
GetThreadIfValid(const Thread * thread)1008 const Thread *GetThreadIfValid(const Thread *thread)
1009 {
1010 // Threads should always be valid
1011 return thread;
1012 }
1013
GetDisplayIfValid(const Display * display)1014 const Display *GetDisplayIfValid(const Display *display)
1015 {
1016 if (ValidateDisplay(display).isError())
1017 {
1018 return nullptr;
1019 }
1020
1021 return display;
1022 }
1023
GetSurfaceIfValid(const Display * display,const Surface * surface)1024 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
1025 {
1026 if (ValidateSurface(display, surface).isError())
1027 {
1028 return nullptr;
1029 }
1030
1031 return surface;
1032 }
1033
GetImageIfValid(const Display * display,const Image * image)1034 const Image *GetImageIfValid(const Display *display, const Image *image)
1035 {
1036 if (ValidateImage(display, image).isError())
1037 {
1038 return nullptr;
1039 }
1040
1041 return image;
1042 }
1043
GetStreamIfValid(const Display * display,const Stream * stream)1044 const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
1045 {
1046 if (ValidateStream(display, stream).isError())
1047 {
1048 return nullptr;
1049 }
1050
1051 return stream;
1052 }
1053
GetContextIfValid(const Display * display,const gl::Context * context)1054 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
1055 {
1056 if (ValidateContext(display, context).isError())
1057 {
1058 return nullptr;
1059 }
1060
1061 return context;
1062 }
1063
GetDeviceIfValid(const Device * device)1064 const Device *GetDeviceIfValid(const Device *device)
1065 {
1066 if (ValidateDevice(device).isError())
1067 {
1068 return nullptr;
1069 }
1070
1071 return device;
1072 }
1073
GetSyncIfValid(const Display * display,const Sync * sync)1074 const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
1075 {
1076 if (ValidateSync(display, sync).isError())
1077 {
1078 return nullptr;
1079 }
1080
1081 return sync;
1082 }
1083
GetLabeledObjectIfValid(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object)1084 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
1085 const Display *display,
1086 ObjectType objectType,
1087 EGLObjectKHR object)
1088 {
1089 LabeledObject *labeledObject = nullptr;
1090 if (ValidateLabeledObject(thread, display, objectType, object, &labeledObject).isError())
1091 {
1092 return nullptr;
1093 }
1094
1095 return labeledObject;
1096 }
1097
ValidateInitialize(const Display * display)1098 Error ValidateInitialize(const Display *display)
1099 {
1100 return ValidateDisplayPointer(display);
1101 }
1102
ValidateTerminate(const Display * display)1103 Error ValidateTerminate(const Display *display)
1104 {
1105 return ValidateDisplayPointer(display);
1106 }
1107
ValidateCreateContext(Display * display,Config * configuration,gl::Context * shareContext,const AttributeMap & attributes)1108 Error ValidateCreateContext(Display *display,
1109 Config *configuration,
1110 gl::Context *shareContext,
1111 const AttributeMap &attributes)
1112 {
1113 if (configuration)
1114 {
1115 ANGLE_TRY(ValidateConfig(display, configuration));
1116 }
1117 else
1118 {
1119 ANGLE_TRY(ValidateDisplay(display));
1120 const DisplayExtensions &displayExtensions = display->getExtensions();
1121 if (!displayExtensions.noConfigContext)
1122 {
1123 return EglBadConfig();
1124 }
1125 }
1126
1127 // Get the requested client version (default is 1) and check it is 2 or 3.
1128 EGLAttrib clientMajorVersion = 1;
1129 EGLAttrib clientMinorVersion = 0;
1130 EGLAttrib contextFlags = 0;
1131 bool resetNotification = false;
1132 for (AttributeMap::const_iterator attributeIter = attributes.begin();
1133 attributeIter != attributes.end(); attributeIter++)
1134 {
1135 EGLAttrib attribute = attributeIter->first;
1136 EGLAttrib value = attributeIter->second;
1137
1138 switch (attribute)
1139 {
1140 case EGL_CONTEXT_CLIENT_VERSION:
1141 clientMajorVersion = value;
1142 break;
1143
1144 case EGL_CONTEXT_MINOR_VERSION:
1145 clientMinorVersion = value;
1146 break;
1147
1148 case EGL_CONTEXT_FLAGS_KHR:
1149 contextFlags = value;
1150 break;
1151
1152 case EGL_CONTEXT_OPENGL_DEBUG:
1153 break;
1154
1155 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
1156 // Only valid for OpenGL (non-ES) contexts
1157 return EglBadAttribute();
1158
1159 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
1160 if (!display->getExtensions().createContextRobustness)
1161 {
1162 return EglBadAttribute();
1163 }
1164 if (value != EGL_TRUE && value != EGL_FALSE)
1165 {
1166 return EglBadAttribute();
1167 }
1168 break;
1169
1170 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
1171 return EglBadAttribute()
1172 << "EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR is not"
1173 << " valid for GLES with EGL 1.4 and KHR_create_context. Use"
1174 << " EXT_create_context_robustness.";
1175 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
1176 if (!display->getExtensions().createContextRobustness)
1177 {
1178 return EglBadAttribute();
1179 }
1180 if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
1181 {
1182 resetNotification = true;
1183 }
1184 else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
1185 {
1186 return EglBadAttribute();
1187 }
1188 break;
1189
1190 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
1191 if (!display->getExtensions().createContextNoError)
1192 {
1193 return EglBadAttribute() << "Invalid Context attribute.";
1194 }
1195 if (value != EGL_TRUE && value != EGL_FALSE)
1196 {
1197 return EglBadAttribute() << "Attribute must be EGL_TRUE or EGL_FALSE.";
1198 }
1199 break;
1200
1201 case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
1202 if (!display->getExtensions().createContextWebGLCompatibility)
1203 {
1204 return EglBadAttribute() << "Attribute "
1205 "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
1206 "EGL_ANGLE_create_context_webgl_compatibility.";
1207 }
1208 if (value != EGL_TRUE && value != EGL_FALSE)
1209 {
1210 return EglBadAttribute() << "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
1211 "EGL_TRUE or EGL_FALSE.";
1212 }
1213 break;
1214
1215 case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
1216 if (!display->getExtensions().createContextBindGeneratesResource)
1217 {
1218 return EglBadAttribute()
1219 << "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
1220 "EGL_CHROMIUM_create_context_bind_generates_resource.";
1221 }
1222 if (value != EGL_TRUE && value != EGL_FALSE)
1223 {
1224 return EglBadAttribute() << "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
1225 "must be EGL_TRUE or EGL_FALSE.";
1226 }
1227 break;
1228
1229 case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
1230 if (!display->getExtensions().displayTextureShareGroup)
1231 {
1232 return EglBadAttribute() << "Attribute "
1233 "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
1234 "EGL_ANGLE_display_texture_share_group.";
1235 }
1236 if (value != EGL_TRUE && value != EGL_FALSE)
1237 {
1238 return EglBadAttribute() << "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
1239 "EGL_TRUE or EGL_FALSE.";
1240 }
1241 if (shareContext &&
1242 (shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE)))
1243 {
1244 return EglBadAttribute() << "All contexts within a share group must be "
1245 "created with the same value of "
1246 "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.";
1247 }
1248 break;
1249
1250 case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
1251 if (!display->getExtensions().createContextClientArrays)
1252 {
1253 return EglBadAttribute()
1254 << "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
1255 "EGL_ANGLE_create_context_client_arrays.";
1256 }
1257 if (value != EGL_TRUE && value != EGL_FALSE)
1258 {
1259 return EglBadAttribute() << "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
1260 "be EGL_TRUE or EGL_FALSE.";
1261 }
1262 break;
1263
1264 case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
1265 if (!display->getExtensions().programCacheControl)
1266 {
1267 return EglBadAttribute()
1268 << "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
1269 "requires EGL_ANGLE_program_cache_control.";
1270 }
1271 if (value != EGL_TRUE && value != EGL_FALSE)
1272 {
1273 return EglBadAttribute()
1274 << "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
1275 "be EGL_TRUE or EGL_FALSE.";
1276 }
1277 break;
1278
1279 case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1280 if (!display->getExtensions().robustResourceInitialization)
1281 {
1282 return EglBadAttribute()
1283 << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1284 "requires EGL_ANGLE_robust_resource_initialization.";
1285 }
1286 if (value != EGL_TRUE && value != EGL_FALSE)
1287 {
1288 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1289 "either EGL_TRUE or EGL_FALSE.";
1290 }
1291 break;
1292
1293 case EGL_EXTENSIONS_ENABLED_ANGLE:
1294 if (!display->getExtensions().createContextExtensionsEnabled)
1295 {
1296 return EglBadAttribute()
1297 << "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
1298 "requires EGL_ANGLE_create_context_extensions_enabled.";
1299 }
1300 if (value != EGL_TRUE && value != EGL_FALSE)
1301 {
1302 return EglBadAttribute() << "EGL_EXTENSIONS_ENABLED_ANGLE must be "
1303 "either EGL_TRUE or EGL_FALSE.";
1304 }
1305 break;
1306
1307 case EGL_POWER_PREFERENCE_ANGLE:
1308 if (!display->getExtensions().powerPreference)
1309 {
1310 return EglBadAttribute() << "Attribute EGL_POWER_PREFERENCE_ANGLE "
1311 "requires EGL_ANGLE_power_preference.";
1312 }
1313 if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
1314 {
1315 return EglBadAttribute()
1316 << "EGL_POWER_PREFERENCE_ANGLE must be "
1317 "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.";
1318 }
1319 break;
1320
1321 case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
1322 if (!display->getExtensions().createContextBackwardsCompatible)
1323 {
1324 return EglBadAttribute()
1325 << "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
1326 "requires EGL_ANGLE_create_context_backwards_compatible.";
1327 }
1328 if (value != EGL_TRUE && value != EGL_FALSE)
1329 {
1330 return EglBadAttribute()
1331 << "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
1332 "either EGL_TRUE or EGL_FALSE.";
1333 }
1334 break;
1335
1336 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
1337 if (!display->getExtensions().contextPriority)
1338 {
1339 return EglBadAttribute() << "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
1340 "extension EGL_IMG_context_priority.";
1341 }
1342 switch (value)
1343 {
1344 case EGL_CONTEXT_PRIORITY_LOW_IMG:
1345 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
1346 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
1347 break;
1348 default:
1349 return EglBadAttribute() << "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
1350 "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
1351 "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
1352 "EGL_CONTEXT_PRIORITY_HIGH_IMG.";
1353 }
1354 break;
1355
1356 default:
1357 return EglBadAttribute() << "Unknown attribute.";
1358 }
1359 }
1360
1361 switch (clientMajorVersion)
1362 {
1363 case 1:
1364 if (clientMinorVersion != 0 && clientMinorVersion != 1)
1365 {
1366 return EglBadAttribute();
1367 }
1368 if (configuration == EGL_NO_CONFIG_KHR)
1369 {
1370 return EglBadMatch();
1371 }
1372 if ((configuration != EGL_NO_CONFIG_KHR) &&
1373 !(configuration->renderableType & EGL_OPENGL_ES_BIT))
1374 {
1375 return EglBadMatch();
1376 }
1377 break;
1378
1379 case 2:
1380 if (clientMinorVersion != 0)
1381 {
1382 return EglBadAttribute();
1383 }
1384 if ((configuration != EGL_NO_CONFIG_KHR) &&
1385 !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
1386 {
1387 return EglBadMatch();
1388 }
1389 break;
1390 case 3:
1391 if (clientMinorVersion != 0 && clientMinorVersion != 1)
1392 {
1393 return EglBadAttribute();
1394 }
1395 if ((configuration != EGL_NO_CONFIG_KHR) &&
1396 !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
1397 {
1398 return EglBadMatch();
1399 }
1400 if (display->getMaxSupportedESVersion() <
1401 gl::Version(static_cast<GLuint>(clientMajorVersion),
1402 static_cast<GLuint>(clientMinorVersion)))
1403 {
1404 return EglBadAttribute() << "Requested GLES version is not supported.";
1405 }
1406 break;
1407 default:
1408 return EglBadAttribute();
1409 break;
1410 }
1411
1412 // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
1413 const EGLint validContextFlags =
1414 (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
1415 if ((contextFlags & ~validContextFlags) != 0)
1416 {
1417 return EglBadAttribute();
1418 }
1419
1420 if (shareContext)
1421 {
1422 // Shared context is invalid or is owned by another display
1423 if (!display->isValidContext(shareContext))
1424 {
1425 return EglBadMatch();
1426 }
1427
1428 if (shareContext->isResetNotificationEnabled() != resetNotification)
1429 {
1430 return EglBadMatch();
1431 }
1432 }
1433
1434 return NoError();
1435 }
1436
ValidateCreateWindowSurface(Display * display,Config * config,EGLNativeWindowType window,const AttributeMap & attributes)1437 Error ValidateCreateWindowSurface(Display *display,
1438 Config *config,
1439 EGLNativeWindowType window,
1440 const AttributeMap &attributes)
1441 {
1442 ANGLE_TRY(ValidateConfig(display, config));
1443
1444 if (!display->isValidNativeWindow(window))
1445 {
1446 return EglBadNativeWindow();
1447 }
1448
1449 const DisplayExtensions &displayExtensions = display->getExtensions();
1450
1451 for (AttributeMap::const_iterator attributeIter = attributes.begin();
1452 attributeIter != attributes.end(); attributeIter++)
1453 {
1454 EGLAttrib attribute = attributeIter->first;
1455 EGLAttrib value = attributeIter->second;
1456
1457 switch (attribute)
1458 {
1459 case EGL_RENDER_BUFFER:
1460 switch (value)
1461 {
1462 case EGL_BACK_BUFFER:
1463 break;
1464 case EGL_SINGLE_BUFFER:
1465 return EglBadMatch(); // Rendering directly to front buffer not supported
1466 default:
1467 return EglBadAttribute();
1468 }
1469 break;
1470
1471 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
1472 if (!displayExtensions.postSubBuffer)
1473 {
1474 return EglBadAttribute();
1475 }
1476 break;
1477
1478 case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1479 if (!displayExtensions.flexibleSurfaceCompatibility)
1480 {
1481 return EglBadAttribute();
1482 }
1483 break;
1484
1485 case EGL_WIDTH:
1486 case EGL_HEIGHT:
1487 if (!displayExtensions.windowFixedSize)
1488 {
1489 return EglBadAttribute();
1490 }
1491 if (value < 0)
1492 {
1493 return EglBadParameter();
1494 }
1495 break;
1496
1497 case EGL_FIXED_SIZE_ANGLE:
1498 if (!displayExtensions.windowFixedSize)
1499 {
1500 return EglBadAttribute();
1501 }
1502 break;
1503
1504 case EGL_SURFACE_ORIENTATION_ANGLE:
1505 if (!displayExtensions.surfaceOrientation)
1506 {
1507 return EglBadAttribute() << "EGL_ANGLE_surface_orientation is not enabled.";
1508 }
1509 break;
1510
1511 case EGL_VG_COLORSPACE:
1512 return EglBadMatch();
1513
1514 case EGL_GL_COLORSPACE:
1515 ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
1516 break;
1517
1518 case EGL_VG_ALPHA_FORMAT:
1519 return EglBadMatch();
1520
1521 case EGL_DIRECT_COMPOSITION_ANGLE:
1522 if (!displayExtensions.directComposition)
1523 {
1524 return EglBadAttribute();
1525 }
1526 break;
1527
1528 case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1529 if (!display->getExtensions().robustResourceInitialization)
1530 {
1531 return EglBadAttribute()
1532 << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1533 "requires EGL_ANGLE_robust_resource_initialization.";
1534 }
1535 if (value != EGL_TRUE && value != EGL_FALSE)
1536 {
1537 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1538 "either EGL_TRUE or EGL_FALSE.";
1539 }
1540 break;
1541
1542 case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
1543 if (!display->getExtensions().ggpStreamDescriptor)
1544 {
1545 return EglBadAttribute() << "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
1546 "EGL_ANGLE_ggp_stream_descriptor.";
1547 }
1548 break;
1549
1550 default:
1551 return EglBadAttribute();
1552 }
1553 }
1554
1555 if (Display::hasExistingWindowSurface(window))
1556 {
1557 return EglBadAlloc();
1558 }
1559
1560 return NoError();
1561 }
1562
ValidateCreatePbufferSurface(Display * display,Config * config,const AttributeMap & attributes)1563 Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap &attributes)
1564 {
1565 ANGLE_TRY(ValidateConfig(display, config));
1566
1567 const DisplayExtensions &displayExtensions = display->getExtensions();
1568
1569 for (AttributeMap::const_iterator attributeIter = attributes.begin();
1570 attributeIter != attributes.end(); attributeIter++)
1571 {
1572 EGLAttrib attribute = attributeIter->first;
1573 EGLAttrib value = attributeIter->second;
1574
1575 switch (attribute)
1576 {
1577 case EGL_WIDTH:
1578 case EGL_HEIGHT:
1579 if (value < 0)
1580 {
1581 return EglBadParameter();
1582 }
1583 break;
1584
1585 case EGL_LARGEST_PBUFFER:
1586 break;
1587
1588 case EGL_TEXTURE_FORMAT:
1589 switch (value)
1590 {
1591 case EGL_NO_TEXTURE:
1592 case EGL_TEXTURE_RGB:
1593 case EGL_TEXTURE_RGBA:
1594 break;
1595 default:
1596 return EglBadAttribute();
1597 }
1598 break;
1599
1600 case EGL_TEXTURE_TARGET:
1601 switch (value)
1602 {
1603 case EGL_NO_TEXTURE:
1604 case EGL_TEXTURE_2D:
1605 break;
1606 default:
1607 return EglBadAttribute();
1608 }
1609 break;
1610
1611 case EGL_MIPMAP_TEXTURE:
1612 break;
1613
1614 case EGL_VG_COLORSPACE:
1615 break;
1616
1617 case EGL_GL_COLORSPACE:
1618 ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
1619 break;
1620
1621 case EGL_VG_ALPHA_FORMAT:
1622 break;
1623
1624 case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1625 if (!displayExtensions.flexibleSurfaceCompatibility)
1626 {
1627 return EglBadAttribute()
1628 << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
1629 "without EGL_ANGLE_flexible_surface_compatibility support.";
1630 }
1631 break;
1632
1633 case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
1634 if (!display->getExtensions().robustResourceInitialization)
1635 {
1636 return EglBadAttribute()
1637 << "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
1638 "requires EGL_ANGLE_robust_resource_initialization.";
1639 }
1640 if (value != EGL_TRUE && value != EGL_FALSE)
1641 {
1642 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
1643 "either EGL_TRUE or EGL_FALSE.";
1644 }
1645 break;
1646
1647 default:
1648 return EglBadAttribute();
1649 }
1650 }
1651
1652 if (!(config->surfaceType & EGL_PBUFFER_BIT))
1653 {
1654 return EglBadMatch();
1655 }
1656
1657 const Caps &caps = display->getCaps();
1658
1659 EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
1660 EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
1661
1662 if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
1663 (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
1664 {
1665 return EglBadMatch();
1666 }
1667
1668 if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
1669 (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
1670 {
1671 return EglBadAttribute();
1672 }
1673
1674 EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
1675 EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
1676 if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
1677 (!gl::isPow2(width) || !gl::isPow2(height)))
1678 {
1679 return EglBadMatch();
1680 }
1681
1682 return NoError();
1683 }
1684
ValidateCreatePbufferFromClientBuffer(Display * display,EGLenum buftype,EGLClientBuffer buffer,Config * config,const AttributeMap & attributes)1685 Error ValidateCreatePbufferFromClientBuffer(Display *display,
1686 EGLenum buftype,
1687 EGLClientBuffer buffer,
1688 Config *config,
1689 const AttributeMap &attributes)
1690 {
1691 ANGLE_TRY(ValidateConfig(display, config));
1692
1693 const DisplayExtensions &displayExtensions = display->getExtensions();
1694
1695 switch (buftype)
1696 {
1697 case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
1698 if (!displayExtensions.d3dShareHandleClientBuffer)
1699 {
1700 return EglBadParameter();
1701 }
1702 if (buffer == nullptr)
1703 {
1704 return EglBadParameter();
1705 }
1706 break;
1707
1708 case EGL_D3D_TEXTURE_ANGLE:
1709 if (!displayExtensions.d3dTextureClientBuffer)
1710 {
1711 return EglBadParameter();
1712 }
1713 if (buffer == nullptr)
1714 {
1715 return EglBadParameter();
1716 }
1717 break;
1718
1719 case EGL_IOSURFACE_ANGLE:
1720 if (!displayExtensions.iosurfaceClientBuffer)
1721 {
1722 return EglBadParameter() << "<buftype> EGL_IOSURFACE_ANGLE requires the "
1723 "EGL_ANGLE_iosurface_client_buffer extension.";
1724 }
1725 if (buffer == nullptr)
1726 {
1727 return EglBadParameter() << "<buffer> must be non null";
1728 }
1729 break;
1730
1731 default:
1732 return EglBadParameter();
1733 }
1734
1735 for (AttributeMap::const_iterator attributeIter = attributes.begin();
1736 attributeIter != attributes.end(); attributeIter++)
1737 {
1738 EGLAttrib attribute = attributeIter->first;
1739 EGLAttrib value = attributeIter->second;
1740
1741 switch (attribute)
1742 {
1743 case EGL_WIDTH:
1744 case EGL_HEIGHT:
1745 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
1746 buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE)
1747 {
1748 return EglBadParameter()
1749 << "Width and Height are not supported for thie <buftype>";
1750 }
1751 if (value < 0)
1752 {
1753 return EglBadParameter() << "Width and Height must be positive";
1754 }
1755 break;
1756
1757 case EGL_TEXTURE_FORMAT:
1758 switch (value)
1759 {
1760 case EGL_NO_TEXTURE:
1761 case EGL_TEXTURE_RGB:
1762 case EGL_TEXTURE_RGBA:
1763 break;
1764 default:
1765 return EglBadAttribute() << "Invalid value for EGL_TEXTURE_FORMAT";
1766 }
1767 break;
1768
1769 case EGL_TEXTURE_TARGET:
1770 switch (value)
1771 {
1772 case EGL_NO_TEXTURE:
1773 case EGL_TEXTURE_2D:
1774 break;
1775 case EGL_TEXTURE_RECTANGLE_ANGLE:
1776 if (buftype != EGL_IOSURFACE_ANGLE)
1777 {
1778 return EglBadParameter()
1779 << "<buftype> doesn't support rectangle texture targets";
1780 }
1781 break;
1782
1783 default:
1784 return EglBadAttribute() << "Invalid value for EGL_TEXTURE_TARGET";
1785 }
1786 break;
1787
1788 case EGL_MIPMAP_TEXTURE:
1789 break;
1790
1791 case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
1792 if (!displayExtensions.flexibleSurfaceCompatibility)
1793 {
1794 return EglBadAttribute()
1795 << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be used "
1796 "without EGL_ANGLE_flexible_surface_compatibility support.";
1797 }
1798 break;
1799
1800 case EGL_IOSURFACE_PLANE_ANGLE:
1801 if (buftype != EGL_IOSURFACE_ANGLE)
1802 {
1803 return EglBadAttribute() << "<buftype> doesn't support iosurface plane";
1804 }
1805 break;
1806
1807 case EGL_TEXTURE_TYPE_ANGLE:
1808 if (buftype != EGL_IOSURFACE_ANGLE)
1809 {
1810 return EglBadAttribute() << "<buftype> doesn't support texture type";
1811 }
1812 break;
1813
1814 case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
1815 if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
1816 {
1817 return EglBadAttribute() << "<buftype> doesn't support texture internal format";
1818 }
1819 break;
1820 case EGL_GL_COLORSPACE:
1821 if (buftype != EGL_D3D_TEXTURE_ANGLE)
1822 {
1823 return EglBadAttribute() << "<buftype> doesn't support setting GL colorspace";
1824 }
1825 break;
1826 case EGL_IOSURFACE_USAGE_HINT_ANGLE:
1827 if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
1828 {
1829 return EglBadAttribute()
1830 << "IOSurface usage hint must only contain READ or WRITE";
1831 }
1832 break;
1833 default:
1834 return EglBadAttribute();
1835 }
1836 }
1837
1838 EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
1839 if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
1840 {
1841 return EglBadAttribute() << "invalid GL colorspace";
1842 }
1843
1844 if (!(config->surfaceType & EGL_PBUFFER_BIT))
1845 {
1846 return EglBadMatch();
1847 }
1848
1849 EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
1850 EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
1851 if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
1852 (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
1853 {
1854 return EglBadMatch();
1855 }
1856 if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
1857 (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
1858 {
1859 // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
1860 // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
1861 // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
1862 // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
1863 // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
1864 // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
1865 // OSX?
1866 if (buftype != EGL_IOSURFACE_ANGLE)
1867 {
1868 return EglBadAttribute();
1869 }
1870 }
1871
1872 if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
1873 {
1874 EGLint width = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
1875 EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
1876
1877 if (width == 0 || height == 0)
1878 {
1879 return EglBadAttribute();
1880 }
1881
1882 const Caps &caps = display->getCaps();
1883 if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
1884 (!gl::isPow2(width) || !gl::isPow2(height)))
1885 {
1886 return EglBadMatch();
1887 }
1888 }
1889
1890 if (buftype == EGL_IOSURFACE_ANGLE)
1891 {
1892 if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
1893 {
1894 return EglBadAttribute()
1895 << "EGL_IOSURFACE requires the texture target to match the config";
1896 }
1897 if (textureFormat != EGL_TEXTURE_RGBA)
1898 {
1899 return EglBadAttribute() << "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format";
1900 }
1901
1902 if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
1903 !attributes.contains(EGL_TEXTURE_FORMAT) ||
1904 !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
1905 !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
1906 !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
1907 {
1908 return EglBadParameter() << "Missing required attribute for EGL_IOSURFACE";
1909 }
1910 }
1911
1912 ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
1913
1914 return NoError();
1915 }
1916
ValidateMakeCurrent(Display * display,Surface * draw,Surface * read,gl::Context * context)1917 Error ValidateMakeCurrent(Display *display, Surface *draw, Surface *read, gl::Context *context)
1918 {
1919 if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
1920 {
1921 return EglBadMatch() << "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE";
1922 }
1923
1924 // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
1925 // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
1926 if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
1927 {
1928 if (display->getExtensions().surfacelessContext)
1929 {
1930 if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
1931 {
1932 return EglBadMatch() << "If ctx is not EGL_NOT_CONTEXT, draw or read must "
1933 "both be EGL_NO_SURFACE, or both not";
1934 }
1935 }
1936 else
1937 {
1938 return EglBadMatch()
1939 << "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE";
1940 }
1941 }
1942
1943 // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
1944 // EGL_BAD_MATCH error is generated.
1945 if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
1946 {
1947 return EglBadMatch()
1948 << "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE";
1949 }
1950
1951 if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
1952 {
1953 return EglBadDisplay() << "'dpy' not a valid EGLDisplay handle";
1954 }
1955
1956 // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
1957 if (!display->isInitialized() &&
1958 (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
1959 {
1960 return EglNotInitialized() << "'dpy' not initialized";
1961 }
1962
1963 if (context != EGL_NO_CONTEXT)
1964 {
1965 ANGLE_TRY(ValidateContext(display, context));
1966 }
1967
1968 if (display->isInitialized() && display->isDeviceLost())
1969 {
1970 return EglContextLost();
1971 }
1972
1973 if (draw != EGL_NO_SURFACE)
1974 {
1975 ANGLE_TRY(ValidateSurface(display, draw));
1976 }
1977
1978 if (read != EGL_NO_SURFACE)
1979 {
1980 ANGLE_TRY(ValidateSurface(display, read));
1981 ANGLE_TRY(ValidateCompatibleSurface(display, context, read));
1982 }
1983
1984 if (draw != read)
1985 {
1986 if (draw)
1987 {
1988 ANGLE_TRY(ValidateCompatibleSurface(display, context, draw));
1989 }
1990 if (read)
1991 {
1992 ANGLE_TRY(ValidateCompatibleSurface(display, context, read));
1993 }
1994 }
1995 return NoError();
1996 }
1997
ValidateCompatibleSurface(const Display * display,gl::Context * context,const Surface * surface)1998 Error ValidateCompatibleSurface(const Display *display,
1999 gl::Context *context,
2000 const Surface *surface)
2001 {
2002 const Config *contextConfig = context->getConfig();
2003 const Config *surfaceConfig = surface->getConfig();
2004
2005 // Surface compatible with client API - only OPENGL_ES supported
2006 switch (context->getClientMajorVersion())
2007 {
2008 case 1:
2009 if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
2010 {
2011 return EglBadMatch() << "Surface not compatible with OpenGL ES 1.x.";
2012 }
2013 break;
2014 case 2:
2015 if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
2016 {
2017 return EglBadMatch() << "Surface not compatible with OpenGL ES 2.x.";
2018 }
2019 break;
2020 case 3:
2021 if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
2022 {
2023 return EglBadMatch() << "Surface not compatible with OpenGL ES 3.x.";
2024 }
2025 break;
2026 default:
2027 return EglBadMatch() << "Surface not compatible with Context API.";
2028 }
2029
2030 // EGL KHR no config context
2031 if (context->getConfig() == EGL_NO_CONFIG_KHR)
2032 {
2033 const DisplayExtensions &displayExtensions = display->getExtensions();
2034 if (displayExtensions.noConfigContext)
2035 {
2036 return NoError();
2037 }
2038 return EglBadMatch() << "Context with no config is not supported.";
2039 }
2040
2041 if (!surface->flexibleSurfaceCompatibilityRequested())
2042 {
2043 // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
2044
2045 bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
2046 if (!colorBufferCompat)
2047 {
2048 return EglBadMatch() << "Color buffer types are not compatible.";
2049 }
2050
2051 bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
2052 surfaceConfig->greenSize == contextConfig->greenSize &&
2053 surfaceConfig->blueSize == contextConfig->blueSize &&
2054 surfaceConfig->alphaSize == contextConfig->alphaSize &&
2055 surfaceConfig->luminanceSize == contextConfig->luminanceSize;
2056 if (!colorCompat)
2057 {
2058 return EglBadMatch() << "Color buffer sizes are not compatible.";
2059 }
2060
2061 bool componentTypeCompat =
2062 surfaceConfig->colorComponentType == contextConfig->colorComponentType;
2063 if (!componentTypeCompat)
2064 {
2065 return EglBadMatch() << "Color buffer component types are not compatible.";
2066 }
2067
2068 bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
2069 surfaceConfig->stencilSize == contextConfig->stencilSize;
2070 if (!dsCompat)
2071 {
2072 return EglBadMatch() << "Depth-stencil buffer types are not compatible.";
2073 }
2074 }
2075
2076 bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
2077 if (!surfaceTypeCompat)
2078 {
2079 return EglBadMatch() << "Surface type is not compatible.";
2080 }
2081
2082 return NoError();
2083 }
2084
ValidateCreateImage(const Display * display,gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)2085 Error ValidateCreateImage(const Display *display,
2086 gl::Context *context,
2087 EGLenum target,
2088 EGLClientBuffer buffer,
2089 const AttributeMap &attributes)
2090 {
2091
2092 ANGLE_TRY(ValidateDisplay(display));
2093
2094 const DisplayExtensions &displayExtensions = display->getExtensions();
2095
2096 // TODO(geofflang): Complete validation from EGL_KHR_image_base:
2097 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
2098 // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
2099
2100 for (AttributeMap::const_iterator attributeIter = attributes.begin();
2101 attributeIter != attributes.end(); attributeIter++)
2102 {
2103 EGLAttrib attribute = attributeIter->first;
2104 EGLAttrib value = attributeIter->second;
2105
2106 switch (attribute)
2107 {
2108 case EGL_IMAGE_PRESERVED:
2109 switch (value)
2110 {
2111 case EGL_TRUE:
2112 case EGL_FALSE:
2113 break;
2114
2115 default:
2116 return EglBadParameter()
2117 << "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.";
2118 }
2119 break;
2120
2121 case EGL_GL_TEXTURE_LEVEL:
2122 if (!displayExtensions.glTexture2DImage &&
2123 !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
2124 {
2125 return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be used "
2126 "without KHR_gl_texture_*_image support.";
2127 }
2128
2129 if (value < 0)
2130 {
2131 return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be negative.";
2132 }
2133 break;
2134
2135 case EGL_GL_TEXTURE_ZOFFSET:
2136 if (!displayExtensions.glTexture3DImage)
2137 {
2138 return EglBadParameter() << "EGL_GL_TEXTURE_ZOFFSET cannot be used "
2139 "without KHR_gl_texture_3D_image support.";
2140 }
2141 break;
2142
2143 case EGL_GL_COLORSPACE:
2144 if (!displayExtensions.glColorspace)
2145 {
2146 return EglBadParameter() << "EGL_GL_COLORSPACE cannot be used "
2147 "without EGL_KHR_gl_colorspace support.";
2148 }
2149 switch (value)
2150 {
2151 case EGL_GL_COLORSPACE_DEFAULT_EXT:
2152 break;
2153 default:
2154 ANGLE_TRY(ValidateColorspaceAttribute(displayExtensions, value));
2155 break;
2156 }
2157 break;
2158
2159 case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
2160 if (!displayExtensions.imageD3D11Texture)
2161 {
2162 return EglBadParameter()
2163 << "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE cannot "
2164 "be used without EGL_ANGLE_image_d3d11_texture support.";
2165 }
2166 break;
2167
2168 default:
2169 return EglBadParameter()
2170 << "invalid attribute: 0x" << std::hex << std::uppercase << attribute;
2171 }
2172 }
2173
2174 switch (target)
2175 {
2176 case EGL_GL_TEXTURE_2D:
2177 {
2178 if (!displayExtensions.glTexture2DImage)
2179 {
2180 return EglBadParameter() << "KHR_gl_texture_2D_image not supported.";
2181 }
2182
2183 if (buffer == 0)
2184 {
2185 return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0.";
2186 }
2187
2188 ANGLE_TRY(ValidateContext(display, context));
2189 const gl::Texture *texture =
2190 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2191 if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
2192 {
2193 return EglBadParameter() << "target is not a 2D texture.";
2194 }
2195
2196 if (texture->getBoundSurface() != nullptr)
2197 {
2198 return EglBadAccess() << "texture has a surface bound to it.";
2199 }
2200
2201 EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2202 if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
2203 texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
2204 {
2205 return EglBadParameter()
2206 << "target 2D texture does not have a valid size at specified level.";
2207 }
2208
2209 ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2210 }
2211 break;
2212
2213 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
2214 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
2215 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
2216 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
2217 case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
2218 case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
2219 {
2220 if (!displayExtensions.glTextureCubemapImage)
2221 {
2222 return EglBadParameter() << "KHR_gl_texture_cubemap_image not supported.";
2223 }
2224
2225 if (buffer == 0)
2226 {
2227 return EglBadParameter()
2228 << "buffer cannot reference a cubemap texture with the name 0.";
2229 }
2230
2231 ANGLE_TRY(ValidateContext(display, context));
2232 const gl::Texture *texture =
2233 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2234 if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
2235 {
2236 return EglBadParameter() << "target is not a cubemap texture.";
2237 }
2238
2239 if (texture->getBoundSurface() != nullptr)
2240 {
2241 return EglBadAccess() << "texture has a surface bound to it.";
2242 }
2243
2244 EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2245 gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
2246 if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
2247 texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
2248 {
2249 return EglBadParameter() << "target cubemap texture does not have a valid "
2250 "size at specified level and face.";
2251 }
2252
2253 ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2254
2255 if (level == 0 && !texture->isMipmapComplete() &&
2256 CubeTextureHasUnspecifiedLevel0Face(texture))
2257 {
2258 return EglBadParameter() << "if level is zero and the texture is incomplete, "
2259 "it must have all of its faces specified at level "
2260 "zero.";
2261 }
2262 }
2263 break;
2264
2265 case EGL_GL_TEXTURE_3D:
2266 {
2267 if (!displayExtensions.glTexture3DImage)
2268 {
2269 return EglBadParameter() << "KHR_gl_texture_3D_image not supported.";
2270 }
2271
2272 if (buffer == 0)
2273 {
2274 return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0.";
2275 }
2276
2277 ANGLE_TRY(ValidateContext(display, context));
2278 const gl::Texture *texture =
2279 context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2280 if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
2281 {
2282 return EglBadParameter() << "target is not a 3D texture.";
2283 }
2284
2285 if (texture->getBoundSurface() != nullptr)
2286 {
2287 return EglBadAccess() << "texture has a surface bound to it.";
2288 }
2289
2290 EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
2291 EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
2292 if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
2293 texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
2294 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
2295 {
2296 return EglBadParameter()
2297 << "target 3D texture does not have a valid size at specified level.";
2298 }
2299
2300 if (static_cast<size_t>(zOffset) >=
2301 texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
2302 {
2303 return EglBadParameter() << "target 3D texture does not have enough layers "
2304 "for the specified Z offset at the specified "
2305 "level.";
2306 }
2307
2308 ANGLE_TRY(ValidateCreateImageMipLevelCommon(context, texture, level));
2309 }
2310 break;
2311
2312 case EGL_GL_RENDERBUFFER:
2313 {
2314 if (!displayExtensions.glRenderbufferImage)
2315 {
2316 return EglBadParameter() << "KHR_gl_renderbuffer_image not supported.";
2317 }
2318
2319 if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
2320 {
2321 return EglBadParameter() << "EGL_GL_TEXTURE_LEVEL cannot be used in "
2322 "conjunction with a renderbuffer target.";
2323 }
2324
2325 if (buffer == 0)
2326 {
2327 return EglBadParameter()
2328 << "buffer cannot reference a renderbuffer with the name 0.";
2329 }
2330
2331 ANGLE_TRY(ValidateContext(display, context));
2332 const gl::Renderbuffer *renderbuffer =
2333 context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
2334 if (renderbuffer == nullptr)
2335 {
2336 return EglBadParameter() << "target is not a renderbuffer.";
2337 }
2338
2339 if (renderbuffer->getSamples() > 0)
2340 {
2341 return EglBadParameter() << "target renderbuffer cannot be multisampled.";
2342 }
2343 }
2344 break;
2345
2346 case EGL_NATIVE_BUFFER_ANDROID:
2347 {
2348 if (!displayExtensions.imageNativeBuffer)
2349 {
2350 return EglBadParameter() << "EGL_ANDROID_image_native_buffer not supported.";
2351 }
2352
2353 if (context != nullptr)
2354 {
2355 return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
2356 }
2357
2358 ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
2359 }
2360 break;
2361
2362 case EGL_D3D11_TEXTURE_ANGLE:
2363 if (!displayExtensions.imageD3D11Texture)
2364 {
2365 return EglBadParameter() << "EGL_ANGLE_image_d3d11_texture not supported.";
2366 }
2367
2368 if (context != nullptr)
2369 {
2370 return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
2371 }
2372
2373 ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
2374 break;
2375
2376 default:
2377 return EglBadParameter()
2378 << "invalid target: 0x" << std::hex << std::uppercase << target;
2379 }
2380
2381 if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
2382 {
2383 return EglBadParameter() << "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.";
2384 }
2385
2386 return NoError();
2387 }
2388
ValidateDestroyImage(const Display * display,const Image * image)2389 Error ValidateDestroyImage(const Display *display, const Image *image)
2390 {
2391 ANGLE_TRY(ValidateImage(display, image));
2392
2393 return NoError();
2394 }
2395
ValidateCreateImageKHR(const Display * display,gl::Context * context,EGLenum target,EGLClientBuffer buffer,const AttributeMap & attributes)2396 Error ValidateCreateImageKHR(const Display *display,
2397 gl::Context *context,
2398 EGLenum target,
2399 EGLClientBuffer buffer,
2400 const AttributeMap &attributes)
2401 {
2402 ANGLE_TRY(ValidateDisplay(display));
2403
2404 if (!display->getExtensions().imageBase && !display->getExtensions().image)
2405 {
2406 // It is out of spec what happens when calling an extension function when the extension is
2407 // not available.
2408 // EGL_BAD_DISPLAY seems like a reasonable error.
2409 return EglBadDisplay() << "EGL_KHR_image not supported.";
2410 }
2411
2412 return ValidateCreateImage(display, context, target, buffer, attributes);
2413 }
2414
ValidateDestroyImageKHR(const Display * display,const Image * image)2415 Error ValidateDestroyImageKHR(const Display *display, const Image *image)
2416 {
2417 ANGLE_TRY(ValidateImage(display, image));
2418
2419 if (!display->getExtensions().imageBase && !display->getExtensions().image)
2420 {
2421 // It is out of spec what happens when calling an extension function when the extension is
2422 // not available.
2423 // EGL_BAD_DISPLAY seems like a reasonable error.
2424 return EglBadDisplay();
2425 }
2426
2427 return NoError();
2428 }
2429
ValidateCreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)2430 Error ValidateCreateDeviceANGLE(EGLint device_type,
2431 void *native_device,
2432 const EGLAttrib *attrib_list)
2433 {
2434 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
2435 if (!clientExtensions.deviceCreation)
2436 {
2437 return EglBadAccess() << "Device creation extension not active";
2438 }
2439
2440 if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
2441 {
2442 return EglBadAttribute() << "Invalid attrib_list parameter";
2443 }
2444
2445 switch (device_type)
2446 {
2447 case EGL_D3D11_DEVICE_ANGLE:
2448 if (!clientExtensions.deviceCreationD3D11)
2449 {
2450 return EglBadAttribute() << "D3D11 device creation extension not active";
2451 }
2452 break;
2453 default:
2454 return EglBadAttribute() << "Invalid device_type parameter";
2455 }
2456
2457 return NoError();
2458 }
2459
ValidateReleaseDeviceANGLE(Device * device)2460 Error ValidateReleaseDeviceANGLE(Device *device)
2461 {
2462 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
2463 if (!clientExtensions.deviceCreation)
2464 {
2465 return EglBadAccess() << "Device creation extension not active";
2466 }
2467
2468 if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
2469 {
2470 return EglBadDevice() << "Invalid device parameter";
2471 }
2472
2473 Display *owningDisplay = device->getOwningDisplay();
2474 if (owningDisplay != nullptr)
2475 {
2476 return EglBadDevice() << "Device must have been created using eglCreateDevice";
2477 }
2478
2479 return NoError();
2480 }
2481
ValidateCreateSyncBase(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext,bool isExt)2482 Error ValidateCreateSyncBase(const Display *display,
2483 EGLenum type,
2484 const AttributeMap &attribs,
2485 const Display *currentDisplay,
2486 const gl::Context *currentContext,
2487 bool isExt)
2488 {
2489 ANGLE_TRY(ValidateDisplay(display));
2490
2491 switch (type)
2492 {
2493 case EGL_SYNC_FENCE_KHR:
2494 if (!attribs.isEmpty())
2495 {
2496 return EglBadAttribute() << "Invalid attribute";
2497 }
2498 break;
2499
2500 case EGL_SYNC_NATIVE_FENCE_ANDROID:
2501 if (!display->getExtensions().nativeFenceSyncANDROID)
2502 {
2503 return EglBadDisplay()
2504 << "EGL_ANDROID_native_fence_sync extension is not available.";
2505 }
2506
2507 for (const auto &attributeIter : attribs)
2508 {
2509 EGLAttrib attribute = attributeIter.first;
2510
2511 switch (attribute)
2512 {
2513 case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
2514 break;
2515
2516 default:
2517 return EglBadAttribute() << "Invalid attribute";
2518 }
2519 }
2520 break;
2521
2522 default:
2523 if (isExt)
2524 {
2525 return EglBadAttribute() << "Invalid type parameter";
2526 }
2527 else
2528 {
2529 return EglBadParameter() << "Invalid type parameter";
2530 }
2531 }
2532
2533 if (display != currentDisplay)
2534 {
2535 return EglBadMatch() << "CreateSync can only be called on the current display";
2536 }
2537
2538 ANGLE_TRY(ValidateContext(currentDisplay, currentContext));
2539
2540 if (!currentContext->getExtensions().eglSyncOES)
2541 {
2542 return EglBadMatch() << "EGL_SYNC_FENCE_KHR cannot be used without "
2543 "GL_OES_EGL_sync support.";
2544 }
2545
2546 return NoError();
2547 }
2548
ValidateGetSyncAttribBase(const Display * display,const Sync * sync,EGLint attribute)2549 Error ValidateGetSyncAttribBase(const Display *display, const Sync *sync, EGLint attribute)
2550 {
2551 ANGLE_TRY(ValidateSync(display, sync));
2552
2553 switch (attribute)
2554 {
2555 case EGL_SYNC_CONDITION_KHR:
2556 switch (sync->getType())
2557 {
2558 case EGL_SYNC_FENCE_KHR:
2559 case EGL_SYNC_NATIVE_FENCE_ANDROID:
2560 break;
2561
2562 default:
2563 return EglBadAttribute()
2564 << "EGL_SYNC_CONDITION_KHR is not valid for this sync type.";
2565 }
2566 break;
2567
2568 // The following attributes are accepted by all types
2569 case EGL_SYNC_TYPE_KHR:
2570 case EGL_SYNC_STATUS_KHR:
2571 break;
2572
2573 default:
2574 return EglBadAttribute() << "Invalid attribute";
2575 }
2576
2577 return NoError();
2578 }
2579
ValidateCreateSyncKHR(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext)2580 Error ValidateCreateSyncKHR(const Display *display,
2581 EGLenum type,
2582 const AttributeMap &attribs,
2583 const Display *currentDisplay,
2584 const gl::Context *currentContext)
2585 {
2586 ANGLE_TRY(ValidateDisplay(display));
2587
2588 const DisplayExtensions &extensions = display->getExtensions();
2589 if (!extensions.fenceSync)
2590 {
2591 return EglBadAccess() << "EGL_KHR_fence_sync extension is not available";
2592 }
2593
2594 return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, true);
2595 }
2596
ValidateCreateSync(const Display * display,EGLenum type,const AttributeMap & attribs,const Display * currentDisplay,const gl::Context * currentContext)2597 Error ValidateCreateSync(const Display *display,
2598 EGLenum type,
2599 const AttributeMap &attribs,
2600 const Display *currentDisplay,
2601 const gl::Context *currentContext)
2602 {
2603 return ValidateCreateSyncBase(display, type, attribs, currentDisplay, currentContext, false);
2604 }
2605
ValidateDestroySync(const Display * display,const Sync * sync)2606 Error ValidateDestroySync(const Display *display, const Sync *sync)
2607 {
2608 ANGLE_TRY(ValidateSync(display, sync));
2609 return NoError();
2610 }
2611
ValidateClientWaitSync(const Display * display,const Sync * sync,EGLint flags,EGLTime timeout)2612 Error ValidateClientWaitSync(const Display *display,
2613 const Sync *sync,
2614 EGLint flags,
2615 EGLTime timeout)
2616 {
2617 ANGLE_TRY(ValidateSync(display, sync));
2618 return NoError();
2619 }
2620
ValidateWaitSync(const Display * display,const gl::Context * context,const Sync * sync,EGLint flags)2621 Error ValidateWaitSync(const Display *display,
2622 const gl::Context *context,
2623 const Sync *sync,
2624 EGLint flags)
2625 {
2626 ANGLE_TRY(ValidateDisplay(display));
2627
2628 const DisplayExtensions &extensions = display->getExtensions();
2629 if (!extensions.waitSync)
2630 {
2631 return EglBadAccess() << "EGL_KHR_wait_sync extension is not available";
2632 }
2633
2634 ANGLE_TRY(ValidateSync(display, sync));
2635
2636 if (context == nullptr)
2637 {
2638 return EglBadMatch() << "No context is current.";
2639 }
2640
2641 if (!context->getExtensions().eglSyncOES)
2642 {
2643 return EglBadMatch() << "Server-side waits cannot be performed without "
2644 "GL_OES_EGL_sync support.";
2645 }
2646
2647 if (flags != 0)
2648 {
2649 return EglBadParameter() << "flags must be zero";
2650 }
2651
2652 return NoError();
2653 }
2654
ValidateGetSyncAttribKHR(const Display * display,const Sync * sync,EGLint attribute,EGLint * value)2655 Error ValidateGetSyncAttribKHR(const Display *display,
2656 const Sync *sync,
2657 EGLint attribute,
2658 EGLint *value)
2659 {
2660 if (value == nullptr)
2661 {
2662 return EglBadParameter() << "Invalid value parameter";
2663 }
2664 return ValidateGetSyncAttribBase(display, sync, attribute);
2665 }
2666
ValidateGetSyncAttrib(const Display * display,const Sync * sync,EGLint attribute,EGLAttrib * value)2667 Error ValidateGetSyncAttrib(const Display *display,
2668 const Sync *sync,
2669 EGLint attribute,
2670 EGLAttrib *value)
2671 {
2672 if (value == nullptr)
2673 {
2674 return EglBadParameter() << "Invalid value parameter";
2675 }
2676 return ValidateGetSyncAttribBase(display, sync, attribute);
2677 }
2678
ValidateCreateStreamKHR(const Display * display,const AttributeMap & attributes)2679 Error ValidateCreateStreamKHR(const Display *display, const AttributeMap &attributes)
2680 {
2681 ANGLE_TRY(ValidateDisplay(display));
2682
2683 const DisplayExtensions &displayExtensions = display->getExtensions();
2684 if (!displayExtensions.stream)
2685 {
2686 return EglBadAlloc() << "Stream extension not active";
2687 }
2688
2689 for (const auto &attributeIter : attributes)
2690 {
2691 EGLAttrib attribute = attributeIter.first;
2692 EGLAttrib value = attributeIter.second;
2693
2694 ANGLE_TRY(ValidateStreamAttribute(attribute, value, displayExtensions));
2695 }
2696
2697 return NoError();
2698 }
2699
ValidateDestroyStreamKHR(const Display * display,const Stream * stream)2700 Error ValidateDestroyStreamKHR(const Display *display, const Stream *stream)
2701 {
2702 ANGLE_TRY(ValidateStream(display, stream));
2703 return NoError();
2704 }
2705
ValidateStreamAttribKHR(const Display * display,const Stream * stream,EGLint attribute,EGLint value)2706 Error ValidateStreamAttribKHR(const Display *display,
2707 const Stream *stream,
2708 EGLint attribute,
2709 EGLint value)
2710 {
2711 ANGLE_TRY(ValidateStream(display, stream));
2712
2713 if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
2714 {
2715 return EglBadState() << "Bad stream state";
2716 }
2717
2718 return ValidateStreamAttribute(attribute, value, display->getExtensions());
2719 }
2720
ValidateQueryStreamKHR(const Display * display,const Stream * stream,EGLenum attribute,EGLint * value)2721 Error ValidateQueryStreamKHR(const Display *display,
2722 const Stream *stream,
2723 EGLenum attribute,
2724 EGLint *value)
2725 {
2726 ANGLE_TRY(ValidateStream(display, stream));
2727
2728 switch (attribute)
2729 {
2730 case EGL_STREAM_STATE_KHR:
2731 case EGL_CONSUMER_LATENCY_USEC_KHR:
2732 break;
2733 case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
2734 if (!display->getExtensions().streamConsumerGLTexture)
2735 {
2736 return EglBadAttribute() << "Consumer GLTexture extension not active";
2737 }
2738 break;
2739 default:
2740 return EglBadAttribute() << "Invalid attribute";
2741 }
2742
2743 return NoError();
2744 }
2745
ValidateQueryStreamu64KHR(const Display * display,const Stream * stream,EGLenum attribute,EGLuint64KHR * value)2746 Error ValidateQueryStreamu64KHR(const Display *display,
2747 const Stream *stream,
2748 EGLenum attribute,
2749 EGLuint64KHR *value)
2750 {
2751 ANGLE_TRY(ValidateStream(display, stream));
2752
2753 switch (attribute)
2754 {
2755 case EGL_CONSUMER_FRAME_KHR:
2756 case EGL_PRODUCER_FRAME_KHR:
2757 break;
2758 default:
2759 return EglBadAttribute() << "Invalid attribute";
2760 }
2761
2762 return NoError();
2763 }
2764
ValidateStreamConsumerGLTextureExternalKHR(const Display * display,gl::Context * context,const Stream * stream)2765 Error ValidateStreamConsumerGLTextureExternalKHR(const Display *display,
2766 gl::Context *context,
2767 const Stream *stream)
2768 {
2769 ANGLE_TRY(ValidateContext(display, context));
2770
2771 const DisplayExtensions &displayExtensions = display->getExtensions();
2772 if (!displayExtensions.streamConsumerGLTexture)
2773 {
2774 return EglBadAccess() << "Stream consumer extension not active";
2775 }
2776
2777 if (!context->getExtensions().eglStreamConsumerExternalNV)
2778 {
2779 return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
2780 }
2781
2782 if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
2783 {
2784 return EglBadStream() << "Invalid stream";
2785 }
2786
2787 if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
2788 {
2789 return EglBadState() << "Invalid stream state";
2790 }
2791
2792 // Lookup the texture and ensure it is correct
2793 gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
2794 if (texture == nullptr || texture->id().value == 0)
2795 {
2796 return EglBadAccess() << "No external texture bound";
2797 }
2798
2799 return NoError();
2800 }
2801
ValidateStreamConsumerAcquireKHR(const Display * display,gl::Context * context,const Stream * stream)2802 Error ValidateStreamConsumerAcquireKHR(const Display *display,
2803 gl::Context *context,
2804 const Stream *stream)
2805 {
2806 ANGLE_TRY(ValidateDisplay(display));
2807
2808 const DisplayExtensions &displayExtensions = display->getExtensions();
2809 if (!displayExtensions.streamConsumerGLTexture)
2810 {
2811 return EglBadAccess() << "Stream consumer extension not active";
2812 }
2813
2814 if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
2815 {
2816 return EglBadStream() << "Invalid stream";
2817 }
2818
2819 if (!context)
2820 {
2821 return EglBadAccess() << "No GL context current to calling thread.";
2822 }
2823
2824 ANGLE_TRY(ValidateContext(display, context));
2825
2826 if (!stream->isConsumerBoundToContext(context))
2827 {
2828 return EglBadAccess() << "Current GL context not associated with stream consumer";
2829 }
2830
2831 if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
2832 stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
2833 {
2834 return EglBadAccess() << "Invalid stream consumer type";
2835 }
2836
2837 // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
2838 // However, the timeout is effectively ignored since it has no useful functionality with the
2839 // current producers that are implemented, so we don't allow that state
2840 if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
2841 stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
2842 {
2843 return EglBadState() << "Invalid stream state";
2844 }
2845
2846 return NoError();
2847 }
2848
ValidateStreamConsumerReleaseKHR(const Display * display,gl::Context * context,const Stream * stream)2849 Error ValidateStreamConsumerReleaseKHR(const Display *display,
2850 gl::Context *context,
2851 const Stream *stream)
2852 {
2853 ANGLE_TRY(ValidateDisplay(display));
2854
2855 const DisplayExtensions &displayExtensions = display->getExtensions();
2856 if (!displayExtensions.streamConsumerGLTexture)
2857 {
2858 return EglBadAccess() << "Stream consumer extension not active";
2859 }
2860
2861 if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
2862 {
2863 return EglBadStream() << "Invalid stream";
2864 }
2865
2866 if (!context)
2867 {
2868 return EglBadAccess() << "No GL context current to calling thread.";
2869 }
2870
2871 ANGLE_TRY(ValidateContext(display, context));
2872
2873 if (!stream->isConsumerBoundToContext(context))
2874 {
2875 return EglBadAccess() << "Current GL context not associated with stream consumer";
2876 }
2877
2878 if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
2879 stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
2880 {
2881 return EglBadAccess() << "Invalid stream consumer type";
2882 }
2883
2884 if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
2885 stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
2886 {
2887 return EglBadState() << "Invalid stream state";
2888 }
2889
2890 return NoError();
2891 }
2892
ValidateStreamConsumerGLTextureExternalAttribsNV(const Display * display,gl::Context * context,const Stream * stream,const AttributeMap & attribs)2893 Error ValidateStreamConsumerGLTextureExternalAttribsNV(const Display *display,
2894 gl::Context *context,
2895 const Stream *stream,
2896 const AttributeMap &attribs)
2897 {
2898 ANGLE_TRY(ValidateDisplay(display));
2899
2900 const DisplayExtensions &displayExtensions = display->getExtensions();
2901 if (!displayExtensions.streamConsumerGLTexture)
2902 {
2903 return EglBadAccess() << "Stream consumer extension not active";
2904 }
2905
2906 ANGLE_TRY(ValidateContext(display, context));
2907
2908 // Although technically not a requirement in spec, the context needs to be checked for support
2909 // for external textures or future logic will cause assertations. This extension is also
2910 // effectively useless without external textures.
2911 if (!context->getExtensions().eglStreamConsumerExternalNV)
2912 {
2913 return EglBadAccess() << "EGL stream consumer external GL extension not enabled";
2914 }
2915
2916 if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
2917 {
2918 return EglBadStream() << "Invalid stream";
2919 }
2920
2921 if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
2922 {
2923 return EglBadState() << "Invalid stream state";
2924 }
2925
2926 const gl::Caps &glCaps = context->getCaps();
2927
2928 EGLAttrib colorBufferType = EGL_RGB_BUFFER;
2929 EGLAttrib planeCount = -1;
2930 EGLAttrib plane[3];
2931 for (int i = 0; i < 3; i++)
2932 {
2933 plane[i] = -1;
2934 }
2935 for (const auto &attributeIter : attribs)
2936 {
2937 EGLAttrib attribute = attributeIter.first;
2938 EGLAttrib value = attributeIter.second;
2939
2940 switch (attribute)
2941 {
2942 case EGL_COLOR_BUFFER_TYPE:
2943 if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
2944 {
2945 return EglBadParameter() << "Invalid color buffer type";
2946 }
2947 colorBufferType = value;
2948 break;
2949 case EGL_YUV_NUMBER_OF_PLANES_EXT:
2950 // planeCount = -1 is a tag for the default plane count so the value must be checked
2951 // to be positive here to ensure future logic doesn't break on invalid negative
2952 // inputs
2953 if (value < 0)
2954 {
2955 return EglBadMatch() << "Invalid plane count";
2956 }
2957 planeCount = value;
2958 break;
2959 default:
2960 if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
2961 attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
2962 {
2963 if ((value < 0 ||
2964 value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
2965 value != EGL_NONE)
2966 {
2967 return EglBadAccess() << "Invalid texture unit";
2968 }
2969 plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
2970 }
2971 else
2972 {
2973 return EglBadAttribute() << "Invalid attribute";
2974 }
2975 }
2976 }
2977
2978 if (colorBufferType == EGL_RGB_BUFFER)
2979 {
2980 if (planeCount > 0)
2981 {
2982 return EglBadMatch() << "Plane count must be 0 for RGB buffer";
2983 }
2984 for (int i = 0; i < 3; i++)
2985 {
2986 if (plane[i] != -1)
2987 {
2988 return EglBadMatch() << "Planes cannot be specified";
2989 }
2990 }
2991
2992 // Lookup the texture and ensure it is correct
2993 gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
2994 if (texture == nullptr || texture->id().value == 0)
2995 {
2996 return EglBadAccess() << "No external texture bound";
2997 }
2998 }
2999 else
3000 {
3001 if (planeCount == -1)
3002 {
3003 planeCount = 2;
3004 }
3005 if (planeCount < 1 || planeCount > 3)
3006 {
3007 return EglBadMatch() << "Invalid YUV plane count";
3008 }
3009 for (EGLAttrib i = planeCount; i < 3; i++)
3010 {
3011 if (plane[i] != -1)
3012 {
3013 return EglBadMatch() << "Invalid plane specified";
3014 }
3015 }
3016
3017 // Set to ensure no texture is referenced more than once
3018 std::set<gl::Texture *> textureSet;
3019 for (EGLAttrib i = 0; i < planeCount; i++)
3020 {
3021 if (plane[i] == -1)
3022 {
3023 return EglBadMatch() << "Not all planes specified";
3024 }
3025 if (plane[i] != EGL_NONE)
3026 {
3027 gl::Texture *texture = context->getState().getSamplerTexture(
3028 static_cast<unsigned int>(plane[i]), gl::TextureType::External);
3029 if (texture == nullptr || texture->id().value == 0)
3030 {
3031 return EglBadAccess()
3032 << "No external texture bound at one or more specified texture units";
3033 }
3034 if (textureSet.find(texture) != textureSet.end())
3035 {
3036 return EglBadAccess() << "Multiple planes bound to same texture object";
3037 }
3038 textureSet.insert(texture);
3039 }
3040 }
3041 }
3042
3043 return NoError();
3044 }
3045
ValidateCreateStreamProducerD3DTextureANGLE(const Display * display,const Stream * stream,const AttributeMap & attribs)3046 Error ValidateCreateStreamProducerD3DTextureANGLE(const Display *display,
3047 const Stream *stream,
3048 const AttributeMap &attribs)
3049 {
3050 ANGLE_TRY(ValidateDisplay(display));
3051
3052 const DisplayExtensions &displayExtensions = display->getExtensions();
3053 if (!displayExtensions.streamProducerD3DTexture)
3054 {
3055 return EglBadAccess() << "Stream producer extension not active";
3056 }
3057
3058 ANGLE_TRY(ValidateStream(display, stream));
3059
3060 if (!attribs.isEmpty())
3061 {
3062 return EglBadAttribute() << "Invalid attribute";
3063 }
3064
3065 if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
3066 {
3067 return EglBadState() << "Stream not in connecting state";
3068 }
3069
3070 switch (stream->getConsumerType())
3071 {
3072 case Stream::ConsumerType::GLTextureYUV:
3073 if (stream->getPlaneCount() != 2)
3074 {
3075 return EglBadMatch() << "Incompatible stream consumer type";
3076 }
3077 break;
3078
3079 case Stream::ConsumerType::GLTextureRGB:
3080 if (stream->getPlaneCount() != 1)
3081 {
3082 return EglBadMatch() << "Incompatible stream consumer type";
3083 }
3084 break;
3085
3086 default:
3087 return EglBadMatch() << "Incompatible stream consumer type";
3088 }
3089
3090 return NoError();
3091 }
3092
ValidateStreamPostD3DTextureANGLE(const Display * display,const Stream * stream,void * texture,const AttributeMap & attribs)3093 Error ValidateStreamPostD3DTextureANGLE(const Display *display,
3094 const Stream *stream,
3095 void *texture,
3096 const AttributeMap &attribs)
3097 {
3098 ANGLE_TRY(ValidateDisplay(display));
3099
3100 const DisplayExtensions &displayExtensions = display->getExtensions();
3101 if (!displayExtensions.streamProducerD3DTexture)
3102 {
3103 return EglBadAccess() << "Stream producer extension not active";
3104 }
3105
3106 ANGLE_TRY(ValidateStream(display, stream));
3107
3108 for (auto &attributeIter : attribs)
3109 {
3110 EGLAttrib attribute = attributeIter.first;
3111 EGLAttrib value = attributeIter.second;
3112
3113 switch (attribute)
3114 {
3115 case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
3116 if (value < 0)
3117 {
3118 return EglBadParameter() << "Invalid subresource index";
3119 }
3120 break;
3121 case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
3122 if (value < 0)
3123 {
3124 return EglBadParameter() << "Invalid plane offset";
3125 }
3126 break;
3127 default:
3128 return EglBadAttribute() << "Invalid attribute";
3129 }
3130 }
3131
3132 if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
3133 stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
3134 stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
3135 {
3136 return EglBadState() << "Stream not fully configured";
3137 }
3138
3139 if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
3140 {
3141 return EglBadMatch() << "Incompatible stream producer";
3142 }
3143
3144 if (texture == nullptr)
3145 {
3146 return EglBadParameter() << "Texture is null";
3147 }
3148
3149 return stream->validateD3D11Texture(texture, attribs);
3150 }
3151
ValidateSyncControlCHROMIUM(const Display * display,const Surface * eglSurface)3152 Error ValidateSyncControlCHROMIUM(const Display *display, const Surface *eglSurface)
3153 {
3154 ANGLE_TRY(ValidateDisplay(display));
3155 ANGLE_TRY(ValidateSurface(display, eglSurface));
3156
3157 const DisplayExtensions &displayExtensions = display->getExtensions();
3158 if (!displayExtensions.syncControlCHROMIUM)
3159 {
3160 return EglBadAccess() << "syncControlCHROMIUM extension not active";
3161 }
3162
3163 return NoError();
3164 }
3165
ValidateSyncControlRateANGLE(const Display * display,const Surface * eglSurface)3166 Error ValidateSyncControlRateANGLE(const Display *display, const Surface *eglSurface)
3167 {
3168 ANGLE_TRY(ValidateDisplay(display));
3169 ANGLE_TRY(ValidateSurface(display, eglSurface));
3170
3171 const DisplayExtensions &displayExtensions = display->getExtensions();
3172 if (!displayExtensions.syncControlRateANGLE)
3173 {
3174 return EglBadAccess() << "syncControlRateANGLE extension not active";
3175 }
3176
3177 return NoError();
3178 }
3179
ValidateGetMscRateANGLE(const Display * display,const Surface * eglSurface,const EGLint * numerator,const EGLint * denominator)3180 Error ValidateGetMscRateANGLE(const Display *display,
3181 const Surface *eglSurface,
3182 const EGLint *numerator,
3183 const EGLint *denominator)
3184 {
3185 ANGLE_TRY(ValidateSyncControlRateANGLE(display, eglSurface));
3186
3187 if (numerator == nullptr)
3188 {
3189 return EglBadParameter() << "numerator is null";
3190 }
3191 if (denominator == nullptr)
3192 {
3193 return EglBadParameter() << "denominator is null";
3194 }
3195
3196 return NoError();
3197 }
3198
ValidateGetSyncValuesCHROMIUM(const Display * display,const Surface * eglSurface,const EGLuint64KHR * ust,const EGLuint64KHR * msc,const EGLuint64KHR * sbc)3199 Error ValidateGetSyncValuesCHROMIUM(const Display *display,
3200 const Surface *eglSurface,
3201 const EGLuint64KHR *ust,
3202 const EGLuint64KHR *msc,
3203 const EGLuint64KHR *sbc)
3204 {
3205 ANGLE_TRY(ValidateSyncControlCHROMIUM(display, eglSurface));
3206
3207 if (ust == nullptr)
3208 {
3209 return EglBadParameter() << "ust is null";
3210 }
3211 if (msc == nullptr)
3212 {
3213 return EglBadParameter() << "msc is null";
3214 }
3215 if (sbc == nullptr)
3216 {
3217 return EglBadParameter() << "sbc is null";
3218 }
3219
3220 return NoError();
3221 }
3222
ValidateDestroySurface(const Display * display,const Surface * surface,const EGLSurface eglSurface)3223 Error ValidateDestroySurface(const Display *display,
3224 const Surface *surface,
3225 const EGLSurface eglSurface)
3226 {
3227 ANGLE_TRY(ValidateSurface(display, surface));
3228
3229 if (eglSurface == EGL_NO_SURFACE)
3230 {
3231 return EglBadSurface();
3232 }
3233
3234 return NoError();
3235 }
3236
ValidateDestroyContext(const Display * display,const gl::Context * glCtx,const EGLContext eglCtx)3237 Error ValidateDestroyContext(const Display *display,
3238 const gl::Context *glCtx,
3239 const EGLContext eglCtx)
3240 {
3241 ANGLE_TRY(ValidateContext(display, glCtx));
3242
3243 if (eglCtx == EGL_NO_CONTEXT)
3244 {
3245 return EglBadContext();
3246 }
3247
3248 return NoError();
3249 }
3250
ValidateSwapBuffers(Thread * thread,const Display * display,const Surface * eglSurface)3251 Error ValidateSwapBuffers(Thread *thread, const Display *display, const Surface *eglSurface)
3252 {
3253 ANGLE_TRY(ValidateSurface(display, eglSurface));
3254
3255 if (display->isDeviceLost())
3256 {
3257 return EglContextLost();
3258 }
3259
3260 if (eglSurface == EGL_NO_SURFACE || !thread->getContext() ||
3261 thread->getCurrentDrawSurface() != eglSurface)
3262 {
3263 return EglBadSurface();
3264 }
3265
3266 return NoError();
3267 }
3268
ValidateSwapBuffersWithDamageKHR(const Display * display,const Surface * surface,EGLint * rects,EGLint n_rects)3269 Error ValidateSwapBuffersWithDamageKHR(const Display *display,
3270 const Surface *surface,
3271 EGLint *rects,
3272 EGLint n_rects)
3273 {
3274 ANGLE_TRY(ValidateSurface(display, surface));
3275
3276 if (!display->getExtensions().swapBuffersWithDamage)
3277 {
3278 // It is out of spec what happens when calling an extension function when the extension is
3279 // not available. EGL_BAD_DISPLAY seems like a reasonable error.
3280 return EglBadDisplay() << "EGL_KHR_swap_buffers_with_damage is not available.";
3281 }
3282
3283 if (surface == EGL_NO_SURFACE)
3284 {
3285 return EglBadSurface() << "Swap surface cannot be EGL_NO_SURFACE.";
3286 }
3287
3288 if (n_rects < 0)
3289 {
3290 return EglBadParameter() << "n_rects cannot be negative.";
3291 }
3292
3293 if (n_rects > 0 && rects == nullptr)
3294 {
3295 return EglBadParameter() << "n_rects cannot be greater than zero when rects is NULL.";
3296 }
3297
3298 // TODO(jmadill): Validate Surface is bound to the thread.
3299
3300 return NoError();
3301 }
3302
ValidateWaitNative(const Display * display,const EGLint engine)3303 Error ValidateWaitNative(const Display *display, const EGLint engine)
3304 {
3305 ANGLE_TRY(ValidateDisplay(display));
3306
3307 if (engine != EGL_CORE_NATIVE_ENGINE)
3308 {
3309 return EglBadParameter() << "the 'engine' parameter has an unrecognized value";
3310 }
3311
3312 return NoError();
3313 }
3314
ValidateCopyBuffers(Display * display,const Surface * surface)3315 Error ValidateCopyBuffers(Display *display, const Surface *surface)
3316 {
3317 ANGLE_TRY(ValidateSurface(display, surface));
3318
3319 if (display->testDeviceLost())
3320 {
3321 return EglContextLost();
3322 }
3323
3324 return NoError();
3325 }
3326
3327 // Validate state for eglBindTexImage. If context is non-null then textureObject will be set to
3328 // surface's texture that will have an image bound to it
ValidateBindTexImage(const Display * display,const Surface * surface,const EGLSurface eglSurface,const EGLint buffer,const gl::Context * context,gl::Texture ** textureObject)3329 Error ValidateBindTexImage(const Display *display,
3330 const Surface *surface,
3331 const EGLSurface eglSurface,
3332 const EGLint buffer,
3333 const gl::Context *context,
3334 gl::Texture **textureObject)
3335 {
3336 ANGLE_TRY(ValidateSurface(display, surface));
3337
3338 if (buffer != EGL_BACK_BUFFER)
3339 {
3340 return EglBadParameter();
3341 }
3342
3343 if (eglSurface == EGL_NO_SURFACE || surface->getType() == EGL_WINDOW_BIT)
3344 {
3345 return EglBadSurface();
3346 }
3347
3348 if (surface->getBoundTexture())
3349 {
3350 return EglBadAccess();
3351 }
3352
3353 if (surface->getTextureFormat() == TextureFormat::NoTexture)
3354 {
3355 return EglBadMatch();
3356 }
3357
3358 if (context)
3359 {
3360 gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
3361 *textureObject = context->getTextureByType(type);
3362 ASSERT(*textureObject != nullptr);
3363
3364 if ((*textureObject)->getImmutableFormat())
3365 {
3366 return EglBadMatch();
3367 }
3368 }
3369
3370 return NoError();
3371 }
3372
ValidateReleaseTexImage(const Display * display,const Surface * surface,const EGLSurface eglSurface,const EGLint buffer)3373 Error ValidateReleaseTexImage(const Display *display,
3374 const Surface *surface,
3375 const EGLSurface eglSurface,
3376 const EGLint buffer)
3377 {
3378 ANGLE_TRY(ValidateSurface(display, surface));
3379
3380 if (buffer != EGL_BACK_BUFFER)
3381 {
3382 return EglBadParameter();
3383 }
3384
3385 if (eglSurface == EGL_NO_SURFACE || surface->getType() == EGL_WINDOW_BIT)
3386 {
3387 return EglBadSurface();
3388 }
3389
3390 if (surface->getTextureFormat() == TextureFormat::NoTexture)
3391 {
3392 return EglBadMatch();
3393 }
3394
3395 return NoError();
3396 }
3397
ValidateSwapInterval(const Display * display,const Surface * draw_surface,const gl::Context * context)3398 Error ValidateSwapInterval(const Display *display,
3399 const Surface *draw_surface,
3400 const gl::Context *context)
3401 {
3402 ANGLE_TRY(ValidateContext(display, context));
3403
3404 if (draw_surface == nullptr)
3405 {
3406 return EglBadSurface();
3407 }
3408
3409 return NoError();
3410 }
3411
ValidateBindAPI(const EGLenum api)3412 Error ValidateBindAPI(const EGLenum api)
3413 {
3414 switch (api)
3415 {
3416 case EGL_OPENGL_API:
3417 case EGL_OPENVG_API:
3418 return EglBadParameter(); // Not supported by this implementation
3419 case EGL_OPENGL_ES_API:
3420 break;
3421 default:
3422 return EglBadParameter();
3423 }
3424
3425 return NoError();
3426 }
3427
ValidatePresentationTimeANDROID(const Display * display,const Surface * surface,EGLnsecsANDROID time)3428 Error ValidatePresentationTimeANDROID(const Display *display,
3429 const Surface *surface,
3430 EGLnsecsANDROID time)
3431 {
3432 ANGLE_TRY(ValidateDisplay(display));
3433
3434 if (!display->getExtensions().presentationTime)
3435 {
3436 // It is out of spec what happens when calling an extension function when the extension is
3437 // not available. EGL_BAD_DISPLAY seems like a reasonable error.
3438 return EglBadDisplay() << "EGL_ANDROID_presentation_time is not available.";
3439 }
3440
3441 ANGLE_TRY(ValidateSurface(display, surface));
3442
3443 return NoError();
3444 }
3445
ValidateSetBlobCacheANDROID(const Display * display,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)3446 Error ValidateSetBlobCacheANDROID(const Display *display,
3447 EGLSetBlobFuncANDROID set,
3448 EGLGetBlobFuncANDROID get)
3449 {
3450 ANGLE_TRY(ValidateDisplay(display));
3451
3452 if (display->areBlobCacheFuncsSet())
3453 {
3454 return EglBadParameter()
3455 << "Blob cache functions can only be set once in the lifetime of a Display";
3456 }
3457
3458 if (set == nullptr || get == nullptr)
3459 {
3460 return EglBadParameter() << "Blob cache callbacks cannot be null.";
3461 }
3462
3463 return NoError();
3464 }
3465
ValidateGetConfigAttrib(const Display * display,const Config * config,EGLint attribute)3466 Error ValidateGetConfigAttrib(const Display *display, const Config *config, EGLint attribute)
3467 {
3468 ANGLE_TRY(ValidateConfig(display, config));
3469 ANGLE_TRY(ValidateConfigAttribute(display, static_cast<EGLAttrib>(attribute)));
3470 return NoError();
3471 }
3472
ValidateChooseConfig(const Display * display,const AttributeMap & attribs,EGLint configSize,EGLint * numConfig)3473 Error ValidateChooseConfig(const Display *display,
3474 const AttributeMap &attribs,
3475 EGLint configSize,
3476 EGLint *numConfig)
3477 {
3478 ANGLE_TRY(ValidateDisplay(display));
3479 ANGLE_TRY(ValidateConfigAttributes(display, attribs));
3480
3481 if (numConfig == nullptr)
3482 {
3483 return EglBadParameter() << "num_config cannot be null.";
3484 }
3485
3486 return NoError();
3487 }
3488
ValidateGetConfigs(const Display * display,EGLint configSize,EGLint * numConfig)3489 Error ValidateGetConfigs(const Display *display, EGLint configSize, EGLint *numConfig)
3490 {
3491 ANGLE_TRY(ValidateDisplay(display));
3492
3493 if (numConfig == nullptr)
3494 {
3495 return EglBadParameter() << "num_config cannot be null.";
3496 }
3497
3498 return NoError();
3499 }
3500
ValidateGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)3501 Error ValidateGetPlatformDisplay(EGLenum platform,
3502 void *native_display,
3503 const EGLAttrib *attrib_list)
3504 {
3505 const auto &attribMap = AttributeMap::CreateFromAttribArray(attrib_list);
3506 return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
3507 }
3508
ValidateGetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)3509 Error ValidateGetPlatformDisplayEXT(EGLenum platform,
3510 void *native_display,
3511 const EGLint *attrib_list)
3512 {
3513 const auto &attribMap = AttributeMap::CreateFromIntArray(attrib_list);
3514 return ValidateGetPlatformDisplayCommon(platform, native_display, attribMap);
3515 }
3516
ValidateCreatePlatformWindowSurfaceEXT(const Display * display,const Config * configuration,void * nativeWindow,const AttributeMap & attributes)3517 Error ValidateCreatePlatformWindowSurfaceEXT(const Display *display,
3518 const Config *configuration,
3519 void *nativeWindow,
3520 const AttributeMap &attributes)
3521 {
3522 if (!Display::GetClientExtensions().platformBase)
3523 {
3524 return EglBadAccess() << "EGL_EXT_platform_base not supported";
3525 }
3526
3527 ANGLE_TRY(ValidateConfig(display, configuration));
3528
3529 return EglBadDisplay() << "ValidateCreatePlatformWindowSurfaceEXT unimplemented.";
3530 }
3531
ValidateCreatePlatformPixmapSurfaceEXT(const Display * display,const Config * configuration,void * nativePixmap,const AttributeMap & attributes)3532 Error ValidateCreatePlatformPixmapSurfaceEXT(const Display *display,
3533 const Config *configuration,
3534 void *nativePixmap,
3535 const AttributeMap &attributes)
3536 {
3537 if (!Display::GetClientExtensions().platformBase)
3538 {
3539 return EglBadAccess() << "EGL_EXT_platform_base not supported";
3540 }
3541
3542 ANGLE_TRY(ValidateConfig(display, configuration));
3543
3544 return EglBadDisplay() << "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.";
3545 }
3546
ValidateProgramCacheGetAttribANGLE(const Display * display,EGLenum attrib)3547 Error ValidateProgramCacheGetAttribANGLE(const Display *display, EGLenum attrib)
3548 {
3549 ANGLE_TRY(ValidateDisplay(display));
3550
3551 if (!display->getExtensions().programCacheControl)
3552 {
3553 return EglBadAccess() << "Extension not supported";
3554 }
3555
3556 switch (attrib)
3557 {
3558 case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
3559 case EGL_PROGRAM_CACHE_SIZE_ANGLE:
3560 break;
3561
3562 default:
3563 return EglBadParameter() << "Invalid program cache attribute.";
3564 }
3565
3566 return NoError();
3567 }
3568
ValidateProgramCacheQueryANGLE(const Display * display,EGLint index,void * key,EGLint * keysize,void * binary,EGLint * binarysize)3569 Error ValidateProgramCacheQueryANGLE(const Display *display,
3570 EGLint index,
3571 void *key,
3572 EGLint *keysize,
3573 void *binary,
3574 EGLint *binarysize)
3575 {
3576 ANGLE_TRY(ValidateDisplay(display));
3577
3578 if (!display->getExtensions().programCacheControl)
3579 {
3580 return EglBadAccess() << "Extension not supported";
3581 }
3582
3583 if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
3584 {
3585 return EglBadParameter() << "Program index out of range.";
3586 }
3587
3588 if (keysize == nullptr || binarysize == nullptr)
3589 {
3590 return EglBadParameter() << "keysize and binarysize must always be valid pointers.";
3591 }
3592
3593 if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
3594 {
3595 return EglBadParameter() << "Invalid program key size.";
3596 }
3597
3598 if ((key == nullptr) != (binary == nullptr))
3599 {
3600 return EglBadParameter() << "key and binary must both be null or both non-null.";
3601 }
3602
3603 return NoError();
3604 }
3605
ValidateProgramCachePopulateANGLE(const Display * display,const void * key,EGLint keysize,const void * binary,EGLint binarysize)3606 Error ValidateProgramCachePopulateANGLE(const Display *display,
3607 const void *key,
3608 EGLint keysize,
3609 const void *binary,
3610 EGLint binarysize)
3611 {
3612 ANGLE_TRY(ValidateDisplay(display));
3613
3614 if (!display->getExtensions().programCacheControl)
3615 {
3616 return EglBadAccess() << "Extension not supported";
3617 }
3618
3619 if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
3620 {
3621 return EglBadParameter() << "Invalid program key size.";
3622 }
3623
3624 if (key == nullptr || binary == nullptr)
3625 {
3626 return EglBadParameter() << "null pointer in arguments.";
3627 }
3628
3629 // Upper bound for binarysize is arbitrary.
3630 if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
3631 {
3632 return EglBadParameter() << "binarysize out of valid range.";
3633 }
3634
3635 return NoError();
3636 }
3637
ValidateProgramCacheResizeANGLE(const Display * display,EGLint limit,EGLenum mode)3638 Error ValidateProgramCacheResizeANGLE(const Display *display, EGLint limit, EGLenum mode)
3639 {
3640 ANGLE_TRY(ValidateDisplay(display));
3641
3642 if (!display->getExtensions().programCacheControl)
3643 {
3644 return EglBadAccess() << "Extension not supported";
3645 }
3646
3647 if (limit < 0)
3648 {
3649 return EglBadParameter() << "limit must be non-negative.";
3650 }
3651
3652 switch (mode)
3653 {
3654 case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
3655 case EGL_PROGRAM_CACHE_TRIM_ANGLE:
3656 break;
3657
3658 default:
3659 return EglBadParameter() << "Invalid cache resize mode.";
3660 }
3661
3662 return NoError();
3663 }
3664
ValidateSurfaceAttrib(const Display * display,const Surface * surface,EGLint attribute,EGLint value)3665 Error ValidateSurfaceAttrib(const Display *display,
3666 const Surface *surface,
3667 EGLint attribute,
3668 EGLint value)
3669 {
3670 ANGLE_TRY(ValidateDisplay(display));
3671 ANGLE_TRY(ValidateSurface(display, surface));
3672
3673 if (surface == EGL_NO_SURFACE)
3674 {
3675 return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
3676 }
3677
3678 switch (attribute)
3679 {
3680 case EGL_MIPMAP_LEVEL:
3681 break;
3682
3683 case EGL_MULTISAMPLE_RESOLVE:
3684 switch (value)
3685 {
3686 case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
3687 break;
3688
3689 case EGL_MULTISAMPLE_RESOLVE_BOX:
3690 if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
3691 {
3692 return EglBadMatch()
3693 << "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.";
3694 }
3695 break;
3696
3697 default:
3698 return EglBadAttribute() << "Invalid multisample resolve type.";
3699 }
3700 break;
3701
3702 case EGL_SWAP_BEHAVIOR:
3703 switch (value)
3704 {
3705 case EGL_BUFFER_PRESERVED:
3706 if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
3707 {
3708 return EglBadMatch()
3709 << "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.";
3710 }
3711 break;
3712
3713 case EGL_BUFFER_DESTROYED:
3714 break;
3715
3716 default:
3717 return EglBadAttribute() << "Invalid swap behaviour.";
3718 }
3719 break;
3720
3721 case EGL_WIDTH:
3722 case EGL_HEIGHT:
3723 if (!display->getExtensions().windowFixedSize)
3724 {
3725 return EglBadAttribute() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
3726 "EGL_ANGLE_window_fixed_size support.";
3727 }
3728 if (!surface->isFixedSize())
3729 {
3730 return EglBadMatch() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
3731 "EGL_FIXED_SIZE_ANGLE being enabled on the surface.";
3732 }
3733 break;
3734
3735 case EGL_TIMESTAMPS_ANDROID:
3736 if (!display->getExtensions().getFrameTimestamps)
3737 {
3738 return EglBadAttribute() << "EGL_TIMESTAMPS_ANDROID cannot be used without "
3739 "EGL_ANDROID_get_frame_timestamps support.";
3740 }
3741 switch (value)
3742 {
3743 case EGL_TRUE:
3744 case EGL_FALSE:
3745 break;
3746
3747 default:
3748 return EglBadAttribute() << "Invalid value.";
3749 }
3750 break;
3751
3752 default:
3753 return EglBadAttribute() << "Invalid surface attribute.";
3754 }
3755
3756 return NoError();
3757 }
3758
ValidateQuerySurface(const Display * display,const Surface * surface,EGLint attribute,EGLint * value)3759 Error ValidateQuerySurface(const Display *display,
3760 const Surface *surface,
3761 EGLint attribute,
3762 EGLint *value)
3763 {
3764 ANGLE_TRY(ValidateDisplay(display));
3765 ANGLE_TRY(ValidateSurface(display, surface));
3766
3767 if (surface == EGL_NO_SURFACE)
3768 {
3769 return EglBadSurface() << "Surface cannot be EGL_NO_SURFACE.";
3770 }
3771
3772 switch (attribute)
3773 {
3774 case EGL_GL_COLORSPACE:
3775 case EGL_VG_ALPHA_FORMAT:
3776 case EGL_VG_COLORSPACE:
3777 case EGL_CONFIG_ID:
3778 case EGL_HEIGHT:
3779 case EGL_HORIZONTAL_RESOLUTION:
3780 case EGL_LARGEST_PBUFFER:
3781 case EGL_MIPMAP_TEXTURE:
3782 case EGL_MIPMAP_LEVEL:
3783 case EGL_MULTISAMPLE_RESOLVE:
3784 case EGL_PIXEL_ASPECT_RATIO:
3785 case EGL_RENDER_BUFFER:
3786 case EGL_SWAP_BEHAVIOR:
3787 case EGL_TEXTURE_FORMAT:
3788 case EGL_TEXTURE_TARGET:
3789 case EGL_VERTICAL_RESOLUTION:
3790 case EGL_WIDTH:
3791 break;
3792
3793 case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
3794 if (!display->getExtensions().postSubBuffer)
3795 {
3796 return EglBadAttribute() << "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
3797 "without EGL_ANGLE_surface_orientation support.";
3798 }
3799 break;
3800
3801 case EGL_FIXED_SIZE_ANGLE:
3802 if (!display->getExtensions().windowFixedSize)
3803 {
3804 return EglBadAttribute() << "EGL_FIXED_SIZE_ANGLE cannot be used without "
3805 "EGL_ANGLE_window_fixed_size support.";
3806 }
3807 break;
3808
3809 case EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE:
3810 if (!display->getExtensions().flexibleSurfaceCompatibility)
3811 {
3812 return EglBadAttribute()
3813 << "EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE cannot be "
3814 "used without EGL_ANGLE_flexible_surface_compatibility support.";
3815 }
3816 break;
3817
3818 case EGL_SURFACE_ORIENTATION_ANGLE:
3819 if (!display->getExtensions().surfaceOrientation)
3820 {
3821 return EglBadAttribute() << "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
3822 "queried without "
3823 "EGL_ANGLE_surface_orientation support.";
3824 }
3825 break;
3826
3827 case EGL_DIRECT_COMPOSITION_ANGLE:
3828 if (!display->getExtensions().directComposition)
3829 {
3830 return EglBadAttribute() << "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
3831 "used without "
3832 "EGL_ANGLE_direct_composition support.";
3833 }
3834 break;
3835
3836 case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
3837 if (!display->getExtensions().robustResourceInitialization)
3838 {
3839 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
3840 "used without EGL_ANGLE_robust_resource_initialization "
3841 "support.";
3842 }
3843 break;
3844
3845 case EGL_TIMESTAMPS_ANDROID:
3846 if (!display->getExtensions().getFrameTimestamps)
3847 {
3848 return EglBadAttribute() << "EGL_TIMESTAMPS_ANDROID cannot be used without "
3849 "EGL_ANDROID_get_frame_timestamps support.";
3850 }
3851 break;
3852
3853 default:
3854 return EglBadAttribute() << "Invalid surface attribute.";
3855 }
3856
3857 return NoError();
3858 }
3859
ValidateQueryContext(const Display * display,const gl::Context * context,EGLint attribute,EGLint * value)3860 Error ValidateQueryContext(const Display *display,
3861 const gl::Context *context,
3862 EGLint attribute,
3863 EGLint *value)
3864 {
3865 ANGLE_TRY(ValidateContext(display, context));
3866
3867 switch (attribute)
3868 {
3869 case EGL_CONFIG_ID:
3870 case EGL_CONTEXT_CLIENT_TYPE:
3871 case EGL_CONTEXT_CLIENT_VERSION:
3872 case EGL_RENDER_BUFFER:
3873 break;
3874
3875 case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
3876 if (!display->getExtensions().robustResourceInitialization)
3877 {
3878 return EglBadAttribute() << "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
3879 "used without EGL_ANGLE_robust_resource_initialization "
3880 "support.";
3881 }
3882 break;
3883
3884 default:
3885 return EglBadAttribute() << "Invalid context attribute.";
3886 }
3887
3888 return NoError();
3889 }
3890
ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const AttributeMap & attribs)3891 Error ValidateDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const AttributeMap &attribs)
3892 {
3893 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3894 if (!clientExtensions.debug)
3895 {
3896 return EglBadAccess() << "EGL_KHR_debug extension is not available.";
3897 }
3898
3899 for (const auto &attrib : attribs)
3900 {
3901 switch (attrib.first)
3902 {
3903 case EGL_DEBUG_MSG_CRITICAL_KHR:
3904 case EGL_DEBUG_MSG_ERROR_KHR:
3905 case EGL_DEBUG_MSG_WARN_KHR:
3906 case EGL_DEBUG_MSG_INFO_KHR:
3907 if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
3908 {
3909 return EglBadAttribute() << "message controls must be EGL_TRUE or EGL_FALSE.";
3910 }
3911 break;
3912 }
3913 }
3914
3915 return NoError();
3916 }
3917
ValidateQueryDebugKHR(EGLint attribute,EGLAttrib * value)3918 Error ValidateQueryDebugKHR(EGLint attribute, EGLAttrib *value)
3919 {
3920 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3921 if (!clientExtensions.debug)
3922 {
3923 return EglBadAccess() << "EGL_KHR_debug extension is not available.";
3924 }
3925
3926 switch (attribute)
3927 {
3928 case EGL_DEBUG_MSG_CRITICAL_KHR:
3929 case EGL_DEBUG_MSG_ERROR_KHR:
3930 case EGL_DEBUG_MSG_WARN_KHR:
3931 case EGL_DEBUG_MSG_INFO_KHR:
3932 case EGL_DEBUG_CALLBACK_KHR:
3933 break;
3934
3935 default:
3936 return EglBadAttribute() << "unknown attribute.";
3937 }
3938
3939 return NoError();
3940 }
3941
ValidateLabelObjectKHR(Thread * thread,const Display * display,ObjectType objectType,EGLObjectKHR object,EGLLabelKHR label)3942 Error ValidateLabelObjectKHR(Thread *thread,
3943 const Display *display,
3944 ObjectType objectType,
3945 EGLObjectKHR object,
3946 EGLLabelKHR label)
3947 {
3948 const ClientExtensions &clientExtensions = Display::GetClientExtensions();
3949 if (!clientExtensions.debug)
3950 {
3951 return EglBadAccess() << "EGL_KHR_debug extension is not available.";
3952 }
3953
3954 LabeledObject *labeledObject = nullptr;
3955 ANGLE_TRY(ValidateLabeledObject(thread, display, objectType, object, &labeledObject));
3956
3957 return NoError();
3958 }
3959
ValidateGetCompositorTimingSupportedANDROID(const Display * display,const Surface * surface,CompositorTiming name)3960 Error ValidateGetCompositorTimingSupportedANDROID(const Display *display,
3961 const Surface *surface,
3962 CompositorTiming name)
3963 {
3964 ANGLE_TRY(ValidateDisplay(display));
3965
3966 if (!display->getExtensions().getFrameTimestamps)
3967 {
3968 return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
3969 }
3970
3971 ANGLE_TRY(ValidateSurface(display, surface));
3972
3973 if (!ValidCompositorTimingName(name))
3974 {
3975 return EglBadParameter() << "invalid timing name.";
3976 }
3977
3978 return NoError();
3979 }
3980
ValidateGetCompositorTimingANDROID(const Display * display,const Surface * surface,EGLint numTimestamps,const EGLint * names,EGLnsecsANDROID * values)3981 Error ValidateGetCompositorTimingANDROID(const Display *display,
3982 const Surface *surface,
3983 EGLint numTimestamps,
3984 const EGLint *names,
3985 EGLnsecsANDROID *values)
3986 {
3987 ANGLE_TRY(ValidateDisplay(display));
3988
3989 if (!display->getExtensions().getFrameTimestamps)
3990 {
3991 return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
3992 }
3993
3994 ANGLE_TRY(ValidateSurface(display, surface));
3995
3996 if (names == nullptr && numTimestamps > 0)
3997 {
3998 return EglBadParameter() << "names is NULL.";
3999 }
4000
4001 if (values == nullptr && numTimestamps > 0)
4002 {
4003 return EglBadParameter() << "values is NULL.";
4004 }
4005
4006 if (numTimestamps < 0)
4007 {
4008 return EglBadParameter() << "numTimestamps must be at least 0.";
4009 }
4010
4011 for (EGLint i = 0; i < numTimestamps; i++)
4012 {
4013 CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
4014
4015 if (!ValidCompositorTimingName(name))
4016 {
4017 return EglBadParameter() << "invalid compositor timing.";
4018 }
4019
4020 if (!surface->getSupportedCompositorTimings().test(name))
4021 {
4022 return EglBadParameter() << "compositor timing not supported by surface.";
4023 }
4024 }
4025
4026 return NoError();
4027 }
4028
ValidateGetNextFrameIdANDROID(const Display * display,const Surface * surface,EGLuint64KHR * frameId)4029 Error ValidateGetNextFrameIdANDROID(const Display *display,
4030 const Surface *surface,
4031 EGLuint64KHR *frameId)
4032 {
4033 ANGLE_TRY(ValidateDisplay(display));
4034
4035 if (!display->getExtensions().getFrameTimestamps)
4036 {
4037 return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4038 }
4039
4040 ANGLE_TRY(ValidateSurface(display, surface));
4041
4042 if (frameId == nullptr)
4043 {
4044 return EglBadParameter() << "frameId is NULL.";
4045 }
4046
4047 return NoError();
4048 }
4049
ValidateGetFrameTimestampSupportedANDROID(const Display * display,const Surface * surface,Timestamp timestamp)4050 Error ValidateGetFrameTimestampSupportedANDROID(const Display *display,
4051 const Surface *surface,
4052 Timestamp timestamp)
4053 {
4054 ANGLE_TRY(ValidateDisplay(display));
4055
4056 if (!display->getExtensions().getFrameTimestamps)
4057 {
4058 return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4059 }
4060
4061 ANGLE_TRY(ValidateSurface(display, surface));
4062
4063 if (!ValidTimestampType(timestamp))
4064 {
4065 return EglBadParameter() << "invalid timestamp type.";
4066 }
4067
4068 return NoError();
4069 }
4070
ValidateGetFrameTimestampsANDROID(const Display * display,const Surface * surface,EGLuint64KHR frameId,EGLint numTimestamps,const EGLint * timestamps,EGLnsecsANDROID * values)4071 Error ValidateGetFrameTimestampsANDROID(const Display *display,
4072 const Surface *surface,
4073 EGLuint64KHR frameId,
4074 EGLint numTimestamps,
4075 const EGLint *timestamps,
4076 EGLnsecsANDROID *values)
4077 {
4078 ANGLE_TRY(ValidateDisplay(display));
4079
4080 if (!display->getExtensions().getFrameTimestamps)
4081 {
4082 return EglBadDisplay() << "EGL_ANDROID_get_frame_timestamps extension is not available.";
4083 }
4084
4085 ANGLE_TRY(ValidateSurface(display, surface));
4086
4087 if (!surface->isTimestampsEnabled())
4088 {
4089 return EglBadSurface() << "timestamp collection is not enabled for this surface.";
4090 }
4091
4092 if (timestamps == nullptr && numTimestamps > 0)
4093 {
4094 return EglBadParameter() << "timestamps is NULL.";
4095 }
4096
4097 if (values == nullptr && numTimestamps > 0)
4098 {
4099 return EglBadParameter() << "values is NULL.";
4100 }
4101
4102 if (numTimestamps < 0)
4103 {
4104 return EglBadParameter() << "numTimestamps must be at least 0.";
4105 }
4106
4107 for (EGLint i = 0; i < numTimestamps; i++)
4108 {
4109 Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
4110
4111 if (!ValidTimestampType(timestamp))
4112 {
4113 return EglBadParameter() << "invalid timestamp type.";
4114 }
4115
4116 if (!surface->getSupportedTimestamps().test(timestamp))
4117 {
4118 return EglBadParameter() << "timestamp not supported by surface.";
4119 }
4120 }
4121
4122 return NoError();
4123 }
4124
ValidateQueryStringiANGLE(const Display * display,EGLint name,EGLint index)4125 Error ValidateQueryStringiANGLE(const Display *display, EGLint name, EGLint index)
4126 {
4127 ANGLE_TRY(ValidateDisplay(display));
4128
4129 if (!Display::GetClientExtensions().featureControlANGLE)
4130 {
4131 return EglBadDisplay() << "EGL_ANGLE_feature_control extension is not available.";
4132 }
4133
4134 if (index < 0)
4135 {
4136 return EglBadParameter() << "index is negative.";
4137 }
4138
4139 switch (name)
4140 {
4141 case EGL_FEATURE_NAME_ANGLE:
4142 case EGL_FEATURE_CATEGORY_ANGLE:
4143 case EGL_FEATURE_DESCRIPTION_ANGLE:
4144 case EGL_FEATURE_BUG_ANGLE:
4145 case EGL_FEATURE_STATUS_ANGLE:
4146 case EGL_FEATURE_CONDITION_ANGLE:
4147 break;
4148 default:
4149 return EglBadParameter() << "name is not valid.";
4150 }
4151
4152 if (static_cast<size_t>(index) >= display->getFeatures().size())
4153 {
4154 return EglBadParameter() << "index is too big.";
4155 }
4156
4157 return NoError();
4158 }
4159
ValidateQueryDisplayAttribBase(const Display * display,const EGLint attribute)4160 Error ValidateQueryDisplayAttribBase(const Display *display, const EGLint attribute)
4161 {
4162 ANGLE_TRY(ValidateDisplay(display));
4163
4164 switch (attribute)
4165 {
4166 case EGL_DEVICE_EXT:
4167 if (!display->getExtensions().deviceQuery)
4168 {
4169 return EglBadDisplay() << "EGL_EXT_device_query extension is not available.";
4170 }
4171 break;
4172
4173 case EGL_FEATURE_COUNT_ANGLE:
4174 if (!Display::GetClientExtensions().featureControlANGLE)
4175 {
4176 return EglBadDisplay() << "EGL_ANGLE_feature_control extension is not available.";
4177 }
4178 break;
4179
4180 default:
4181 return EglBadAttribute() << "attribute is not valid.";
4182 }
4183
4184 return NoError();
4185 }
4186
ValidateQueryDisplayAttribEXT(const Display * display,const EGLint attribute)4187 Error ValidateQueryDisplayAttribEXT(const Display *display, const EGLint attribute)
4188 {
4189 ANGLE_TRY(ValidateQueryDisplayAttribBase(display, attribute));
4190
4191 return NoError();
4192 }
4193
ValidateQueryDisplayAttribANGLE(const Display * display,const EGLint attribute)4194 Error ValidateQueryDisplayAttribANGLE(const Display *display, const EGLint attribute)
4195 {
4196 ANGLE_TRY(ValidateQueryDisplayAttribBase(display, attribute));
4197
4198 return NoError();
4199 }
4200
ValidateGetNativeClientBufferANDROID(const AHardwareBuffer * buffer)4201 Error ValidateGetNativeClientBufferANDROID(const AHardwareBuffer *buffer)
4202 {
4203 // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
4204 // despite it being a display extension. No display is needed for the implementation though.
4205 if (buffer == nullptr)
4206 {
4207 return EglBadParameter() << "NULL buffer.";
4208 }
4209
4210 return NoError();
4211 }
4212
ValidateDupNativeFenceFDANDROID(const Display * display,const Sync * sync)4213 Error ValidateDupNativeFenceFDANDROID(const Display *display, const Sync *sync)
4214 {
4215 ANGLE_TRY(ValidateDisplay(display));
4216
4217 if (!display->getExtensions().nativeFenceSyncANDROID)
4218 {
4219 return EglBadDisplay() << "EGL_ANDROID_native_fence_sync extension is not available.";
4220 }
4221
4222 ANGLE_TRY(ValidateSync(display, sync));
4223
4224 if (sync->getNativeFenceFD() == EGL_NO_NATIVE_FENCE_FD_ANDROID)
4225 {
4226 return EglBadParameter() << "EGL_NATIVE_FENCE_FD_ANDROID attribute of sync is "
4227 "EGL_NO_NATIVE_FENCE_FD_ANDROID";
4228 }
4229
4230 return NoError();
4231 }
4232
ValidateSwapBuffersWithFrameTokenANGLE(const Display * display,const Surface * surface,EGLFrameTokenANGLE frametoken)4233 Error ValidateSwapBuffersWithFrameTokenANGLE(const Display *display,
4234 const Surface *surface,
4235 EGLFrameTokenANGLE frametoken)
4236 {
4237 ANGLE_TRY(ValidateDisplay(display));
4238
4239 if (!display->getExtensions().swapWithFrameToken)
4240 {
4241 return EglBadDisplay() << "EGL_ANGLE_swap_buffers_with_frame_token is not available.";
4242 }
4243
4244 ANGLE_TRY(ValidateSurface(display, surface));
4245
4246 return NoError();
4247 }
4248 } // namespace egl
4249