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