1 //
2 // Copyright 2015 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 // ImageTest:
7 // Tests the correctness of eglImage.
8 //
9
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/MultiThreadSteps.h"
12 #include "test_utils/gl_raii.h"
13 #include "util/EGLWindow.h"
14 #include "util/test_utils.h"
15
16 #include "common/android_util.h"
17
18 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 29
19 # define ANGLE_AHARDWARE_BUFFER_SUPPORT
20 // NDK header file for access to Android Hardware Buffers
21 # include <android/hardware_buffer.h>
22 # define ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
23 #endif
24
25 #if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 33
26 constexpr bool kHasAHBFrontBufferUsageSupport = 1;
27 #else
28 [[maybe_unused]] constexpr bool kHasAHBFrontBufferUsageSupport = 0;
29 #endif
30
31 namespace angle
32 {
33 namespace
34 {
35 constexpr char kOESExt[] = "GL_OES_EGL_image";
36 constexpr char kExternalExt[] = "GL_OES_EGL_image_external";
37 constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
38 constexpr char kYUVInternalFormatExt[] = "GL_ANGLE_yuv_internal_format";
39 constexpr char kYUVTargetExt[] = "GL_EXT_YUV_target";
40 constexpr char kRGBXInternalFormatExt[] = "GL_ANGLE_rgbx_internal_format";
41 constexpr char kBaseExt[] = "EGL_KHR_image_base";
42 constexpr char k2DTextureExt[] = "EGL_KHR_gl_texture_2D_image";
43 constexpr char k3DTextureExt[] = "EGL_KHR_gl_texture_3D_image";
44 constexpr char kPixmapExt[] = "EGL_KHR_image_pixmap";
45 constexpr char kRenderbufferExt[] = "EGL_KHR_gl_renderbuffer_image";
46 constexpr char kCubemapExt[] = "EGL_KHR_gl_texture_cubemap_image";
47 constexpr char kImageGLColorspaceExt[] = "EGL_EXT_image_gl_colorspace";
48 constexpr char kEGLImageArrayExt[] = "GL_EXT_EGL_image_array";
49 constexpr char kEGLAndroidImageNativeBufferExt[] = "EGL_ANDROID_image_native_buffer";
50 constexpr char kEGLImageStorageExt[] = "GL_EXT_EGL_image_storage";
51 constexpr char kEGLImageStorageCompressionExt[] = "GL_EXT_EGL_image_storage_compression";
52 constexpr char kTextureStorageCompressionExt[] = "GL_EXT_texture_storage_compression";
53 constexpr EGLint kDefaultAttribs[] = {
54 EGL_IMAGE_PRESERVED,
55 EGL_TRUE,
56 EGL_NONE,
57 };
58 constexpr EGLint kColorspaceAttribs[] = {
59 EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB_KHR, EGL_NONE,
60 };
61 constexpr EGLint kNativeClientBufferAttribs_RGBA8_Texture[] = {
62 EGL_WIDTH,
63 1,
64 EGL_HEIGHT,
65 1,
66 EGL_RED_SIZE,
67 8,
68 EGL_GREEN_SIZE,
69 8,
70 EGL_BLUE_SIZE,
71 8,
72 EGL_ALPHA_SIZE,
73 8,
74 EGL_NATIVE_BUFFER_USAGE_ANDROID,
75 EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID,
76 EGL_NONE};
77 constexpr EGLint kNativeClientBufferAttribs_RGBA8_Renderbuffer[] = {
78 EGL_WIDTH,
79 1,
80 EGL_HEIGHT,
81 1,
82 EGL_RED_SIZE,
83 8,
84 EGL_GREEN_SIZE,
85 8,
86 EGL_BLUE_SIZE,
87 8,
88 EGL_ALPHA_SIZE,
89 8,
90 EGL_NATIVE_BUFFER_USAGE_ANDROID,
91 EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID,
92 EGL_NONE};
93 // Color data in linear and sRGB colorspace
94 // 2D texture data
95 GLubyte kLinearColor[] = {132, 55, 219, 255};
96 GLubyte kSrgbColor[] = {190, 128, 238, 255};
97 // 3D texture data
98 GLubyte kLinearColor3D[] = {131, 242, 100, 255, 201, 89, 133, 255};
99 GLubyte kSrgbColor3D[] = {190, 249, 168, 255, 230, 159, 191, 255};
100 // Cubemap texture data
101 GLubyte kLinearColorCube[] = {75, 135, 205, 255, 201, 89, 133, 255, 111, 201, 108, 255,
102 30, 90, 230, 255, 180, 210, 70, 255, 77, 111, 99, 255};
103 GLubyte kSrgbColorCube[] = {148, 192, 232, 255, 230, 159, 191, 255, 176, 230, 174, 255,
104 96, 160, 244, 255, 219, 234, 143, 255, 149, 176, 167, 255};
105 GLfloat kCubeFaceX[] = {1.0, -1.0, 0.0, 0.0, 0.0, 0.0};
106 GLfloat kCubeFaceY[] = {0.0, 0.0, 1.0, -1.0, 0.0, 0.0};
107 GLfloat kCubeFaceZ[] = {0.0, 0.0, 0.0, 0.0, 1.0, -1.0};
108
109 constexpr int kColorspaceAttributeIndex = 2;
110 constexpr int k3DColorspaceAttributeIndex = 4;
111 constexpr int kTextureZOffsetAttributeIndex = 1;
112 constexpr size_t kCubeFaceCount = 6;
113
114 constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1;
115 constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2;
116 constexpr int AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3;
117 constexpr int AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31;
118 constexpr int AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP = 0x11;
119 constexpr int AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 = 0x23;
120 constexpr int AHARDWAREBUFFER_FORMAT_YV12 = 0x32315659;
121
122 [[maybe_unused]] constexpr uint64_t ANGLE_AHARDWAREBUFFER_USAGE_FRONT_BUFFER = (1ULL << 32);
123
124 } // anonymous namespace
125
126 class ImageTest : public ANGLETest<>
127 {
128 protected:
ImageTest()129 ImageTest()
130 {
131 setWindowWidth(128);
132 setWindowHeight(128);
133 setConfigRedBits(8);
134 setConfigGreenBits(8);
135 setConfigBlueBits(8);
136 setConfigAlphaBits(8);
137 setConfigDepthBits(24);
138 }
139
getVS() const140 const char *getVS() const
141 {
142 return R"(precision highp float;
143 attribute vec4 position;
144 varying vec2 texcoord;
145
146 void main()
147 {
148 gl_Position = position;
149 texcoord = (position.xy * 0.5) + 0.5;
150 texcoord.y = 1.0 - texcoord.y;
151 })";
152 }
153
getVS2DArray() const154 const char *getVS2DArray() const
155 {
156 return R"(#version 300 es
157 out vec2 texcoord;
158 in vec4 position;
159 void main()
160 {
161 gl_Position = vec4(position.xy, 0.0, 1.0);
162 texcoord = (position.xy * 0.5) + 0.5;
163 })";
164 }
165
getVS3D() const166 const char *getVS3D() const
167 {
168 return R"(#version 300 es
169 out vec2 texcoord;
170 in vec4 position;
171
172 void main()
173 {
174 gl_Position = vec4(position.xy, 0.0, 1.0);
175 texcoord = (position.xy * 0.5) + 0.5;
176 })";
177 }
178
getVSCube() const179 const char *getVSCube() const
180 {
181 return R"(#version 300 es
182 in vec4 position;
183 void main()
184 {
185 gl_Position = vec4(position.xy, 0.0, 1.0);
186 })";
187 }
188
getVSCubeArray() const189 const char *getVSCubeArray() const
190 {
191 return R"(#version 310 es
192 in vec4 position;
193 void main()
194 {
195 gl_Position = vec4(position.xy, 0.0, 1.0);
196 })";
197 }
198
getVSESSL3() const199 const char *getVSESSL3() const
200 {
201 return R"(#version 300 es
202 precision highp float;
203 in vec4 position;
204 out vec2 texcoord;
205
206 void main()
207 {
208 gl_Position = position;
209 texcoord = (position.xy * 0.5) + 0.5;
210 texcoord.y = 1.0 - texcoord.y;
211 })";
212 }
213
getTextureFS() const214 const char *getTextureFS() const
215 {
216 return R"(precision highp float;
217 uniform sampler2D tex;
218 varying vec2 texcoord;
219
220 void main()
221 {
222 gl_FragColor = texture2D(tex, texcoord);
223 })";
224 }
225
getTexture2DArrayFS() const226 const char *getTexture2DArrayFS() const
227 {
228 return R"(#version 300 es
229 precision highp float;
230 uniform highp sampler2DArray tex2DArray;
231 uniform uint layer;
232 in vec2 texcoord;
233 out vec4 fragColor;
234 void main()
235 {
236 fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, float(layer)));
237 })";
238 }
239
getTexture3DFS() const240 const char *getTexture3DFS() const
241 {
242 return R"(#version 300 es
243 precision highp float;
244 uniform highp sampler3D tex3D;
245 uniform uint layer;
246 in vec2 texcoord;
247 out vec4 fragColor;
248 void main()
249 {
250 fragColor = texture(tex3D, vec3(texcoord.x, texcoord.y, float(layer)));
251 })";
252 }
253
getTextureCubeFS() const254 const char *getTextureCubeFS() const
255 {
256 return R"(#version 300 es
257 precision highp float;
258 uniform highp samplerCube texCube;
259 uniform vec3 faceCoord;
260 out vec4 fragColor;
261 void main()
262 {
263 fragColor = texture(texCube, faceCoord);
264 })";
265 }
266
getTextureCubeArrayFS() const267 const char *getTextureCubeArrayFS() const
268 {
269 return R"(#version 310 es
270 #extension GL_OES_texture_cube_map_array : require
271 precision highp float;
272 uniform highp samplerCubeArray texCubeArray;
273 uniform vec3 faceCoord;
274 uniform uint layer;
275 out vec4 fragColor;
276 void main()
277 {
278 fragColor = texture(texCubeArray, vec4(faceCoord, float(layer)));
279 })";
280 }
281
getTextureExternalFS() const282 const char *getTextureExternalFS() const
283 {
284 return R"(#extension GL_OES_EGL_image_external : require
285 precision highp float;
286 uniform samplerExternalOES tex;
287 varying vec2 texcoord;
288
289 void main()
290 {
291 gl_FragColor = texture2D(tex, texcoord);
292 })";
293 }
294
getTextureExternalESSL3FS() const295 const char *getTextureExternalESSL3FS() const
296 {
297 return R"(#version 300 es
298 #extension GL_OES_EGL_image_external_essl3 : require
299 precision highp float;
300 uniform samplerExternalOES tex;
301 in vec2 texcoord;
302 out vec4 color;
303
304 void main()
305 {
306 color = texture(tex, texcoord);
307 })";
308 }
309
getTextureYUVVS() const310 const char *getTextureYUVVS() const
311 {
312 return R"(#version 300 es
313 #extension GL_EXT_YUV_target : require
314 precision highp float;
315 uniform __samplerExternal2DY2YEXT tex;
316 in vec4 position;
317 out vec4 color;
318
319 void main()
320 {
321 gl_Position = position;
322 vec2 texcoord = (position.xy * 0.5) + 0.5;
323 texcoord.y = 1.0 - texcoord.y;
324 color = texture(tex, texcoord);
325 })";
326 }
327
getPassThroughFS() const328 const char *getPassThroughFS() const
329 {
330 return R"(#version 300 es
331 precision highp float;
332 in vec4 color;
333 out vec4 frag_color;
334
335 void main()
336 {
337 frag_color = color;
338 })";
339 }
340
getTextureYUVFS() const341 const char *getTextureYUVFS() const
342 {
343 return R"(#version 300 es
344 #extension GL_EXT_YUV_target : require
345 precision highp float;
346 uniform __samplerExternal2DY2YEXT tex;
347 in vec2 texcoord;
348 out vec4 color;
349
350 void main()
351 {
352 color = texture(tex, texcoord);
353 })";
354 }
355
getRenderYUVFS() const356 const char *getRenderYUVFS() const
357 {
358 return R"(#version 300 es
359 #extension GL_EXT_YUV_target : require
360 precision highp float;
361 uniform vec4 u_color;
362 layout (yuv) out vec4 color;
363
364 void main()
365 {
366 color = u_color;
367 })";
368 }
369
testSetUp()370 void testSetUp() override
371 {
372 mTextureProgram = CompileProgram(getVS(), getTextureFS());
373 if (mTextureProgram == 0)
374 {
375 FAIL() << "shader compilation failed.";
376 }
377
378 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
379
380 if (getClientMajorVersion() >= 3)
381 {
382 m2DArrayTextureProgram = CompileProgram(getVS2DArray(), getTexture2DArrayFS());
383 if (m2DArrayTextureProgram == 0)
384 {
385 FAIL() << "shader compilation failed.";
386 }
387
388 m2DArrayTextureUniformLocation =
389 glGetUniformLocation(m2DArrayTextureProgram, "tex2DArray");
390 m2DArrayTextureLayerUniformLocation =
391 glGetUniformLocation(m2DArrayTextureProgram, "layer");
392 }
393
394 if (getClientMajorVersion() >= 3)
395 {
396 m3DTextureProgram = CompileProgram(getVS3D(), getTexture3DFS());
397 if (m3DTextureProgram == 0)
398 {
399 FAIL() << "shader compilation failed.";
400 }
401
402 m3DTextureUniformLocation = glGetUniformLocation(m3DTextureProgram, "tex3D");
403 m3DTextureLayerUniformLocation = glGetUniformLocation(m3DTextureProgram, "layer");
404 }
405
406 if (IsGLExtensionEnabled("GL_OES_EGL_image_external"))
407 {
408 mTextureExternalProgram = CompileProgram(getVS(), getTextureExternalFS());
409 ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
410
411 mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
412 }
413
414 if (IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3"))
415 {
416 mTextureExternalESSL3Program =
417 CompileProgram(getVSESSL3(), getTextureExternalESSL3FS());
418 ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
419
420 mTextureExternalESSL3UniformLocation =
421 glGetUniformLocation(mTextureExternalESSL3Program, "tex");
422 }
423
424 if (IsGLExtensionEnabled(kYUVTargetExt))
425 {
426 mTextureYUVProgram = CompileProgram(getVSESSL3(), getTextureYUVFS());
427 ASSERT_NE(0u, mTextureYUVProgram) << "shader compilation failed.";
428
429 mTextureYUVUniformLocation = glGetUniformLocation(mTextureYUVProgram, "tex");
430
431 mTextureYUVVSProgram = CompileProgram(getTextureYUVVS(), getPassThroughFS());
432 ASSERT_NE(0u, mTextureYUVVSProgram) << "shader compilation failed.";
433
434 mTextureYUVVSUniformLocation = glGetUniformLocation(mTextureYUVVSProgram, "tex");
435
436 mRenderYUVProgram = CompileProgram(getVSESSL3(), getRenderYUVFS());
437 ASSERT_NE(0u, mRenderYUVProgram) << "shader compilation failed.";
438
439 mRenderYUVUniformLocation = glGetUniformLocation(mRenderYUVProgram, "u_color");
440 }
441
442 if (IsGLExtensionEnabled(kEGLImageStorageExt))
443 {
444 mCubeTextureProgram = CompileProgram(getVSCube(), getTextureCubeFS());
445 if (mCubeTextureProgram == 0)
446 {
447 FAIL() << "shader compilation failed.";
448 }
449 mCubeTextureUniformLocation = glGetUniformLocation(mCubeTextureProgram, "texCube");
450 mCubeTextureFaceCoordUniformLocation =
451 glGetUniformLocation(mCubeTextureProgram, "faceCoord");
452
453 if ((getClientMajorVersion() >= 3 && getClientMinorVersion() >= 1) &&
454 IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"))
455 {
456 mCubeArrayTextureProgram =
457 CompileProgram(getVSCubeArray(), getTextureCubeArrayFS());
458 if (mCubeArrayTextureProgram == 0)
459 {
460 FAIL() << "shader compilation failed.";
461 }
462 mCubeArrayTextureUniformLocation =
463 glGetUniformLocation(mCubeArrayTextureProgram, "texCubeArray");
464 mCubeArrayTextureFaceCoordUniformLocation =
465 glGetUniformLocation(mCubeArrayTextureProgram, "faceCoord");
466 mCubeArrayTextureLayerUniformLocation =
467 glGetUniformLocation(mCubeArrayTextureProgram, "layer");
468 }
469 }
470
471 ASSERT_GL_NO_ERROR();
472 }
473
testTearDown()474 void testTearDown() override
475 {
476 glDeleteProgram(mTextureProgram);
477 glDeleteProgram(mTextureExternalProgram);
478 glDeleteProgram(mTextureExternalESSL3Program);
479 glClearColor(0, 0, 0, 0);
480 glClear(GL_COLOR_BUFFER_BIT);
481
482 ASSERT_GL_NO_ERROR();
483 }
484
485 // 1) For tests that sample from EGLImages with colorspace override -
486 // 1) Always upload color values in sRGB colorspace
487 // 2) The image should be treated as if it was an sRGB image resulting in
488 // the sampled value to be to decoded to linear colorspace
489 //
490 // 2) For tests that render to EGLImages with colorspace override -
491 // 1) Always upload color values in linear colorspace
492 // 2) The image should be treated as if it was an sRGB image resulting in
493 // the rendered color to be encoded in sRGB colorspace
494
495 enum class EglImageUsage
496 {
497 Sampling,
498 Rendering
499 };
500
attribListHasSrgbColorspace(const EGLint * attribs,const int colorspaceAttributeIndex) const501 bool attribListHasSrgbColorspace(const EGLint *attribs,
502 const int colorspaceAttributeIndex) const
503 {
504 return (attribs[colorspaceAttributeIndex] == EGL_GL_COLORSPACE &&
505 attribs[colorspaceAttributeIndex + 1] == EGL_GL_COLORSPACE_SRGB_KHR);
506 }
507
getExpected2DColorForAttribList(const EGLint * attribs,EglImageUsage usage=EglImageUsage::Sampling) const508 GLubyte *getExpected2DColorForAttribList(const EGLint *attribs,
509 EglImageUsage usage = EglImageUsage::Sampling) const
510 {
511 const bool srgbColorspace = attribListHasSrgbColorspace(attribs, kColorspaceAttributeIndex);
512 return (usage == EglImageUsage::Sampling) ? (srgbColorspace ? kLinearColor : kSrgbColor)
513 : (srgbColorspace ? kSrgbColor : kLinearColor);
514 }
515
getExpected3DColorForAttribList(const EGLint * attribs,EglImageUsage usage=EglImageUsage::Sampling) const516 GLubyte *getExpected3DColorForAttribList(const EGLint *attribs,
517 EglImageUsage usage = EglImageUsage::Sampling) const
518 {
519 const bool srgbColorspace =
520 attribListHasSrgbColorspace(attribs, k3DColorspaceAttributeIndex);
521 return (usage == EglImageUsage::Sampling)
522 ? (srgbColorspace ? kLinearColor3D : kSrgbColor3D)
523 : (srgbColorspace ? kSrgbColor3D : kLinearColor3D);
524 }
525
getExpectedCubeColorForAttribList(const EGLint * attribs,EglImageUsage usage=EglImageUsage::Sampling) const526 GLubyte *getExpectedCubeColorForAttribList(const EGLint *attribs,
527 EglImageUsage usage = EglImageUsage::Sampling) const
528 {
529 const bool srgbColorspace = attribListHasSrgbColorspace(attribs, kColorspaceAttributeIndex);
530 return (usage == EglImageUsage::Sampling)
531 ? (srgbColorspace ? kLinearColorCube : kSrgbColorCube)
532 : (srgbColorspace ? kSrgbColorCube : kLinearColorCube);
533 }
534
createEGLImage2DTextureStorage(size_t width,size_t height,GLenum format,const GLint * attribs,GLTexture & sourceTexture,EGLImageKHR * outSourceImage)535 void createEGLImage2DTextureStorage(size_t width,
536 size_t height,
537 GLenum format,
538 const GLint *attribs,
539 GLTexture &sourceTexture,
540 EGLImageKHR *outSourceImage)
541 {
542
543 glBindTexture(GL_TEXTURE_2D, sourceTexture);
544 glTexStorageAttribs2DEXT(GL_TEXTURE_2D, 1, format, static_cast<GLsizei>(width),
545 static_cast<GLsizei>(height), attribs);
546
547 ASSERT_GL_NO_ERROR();
548 // Disable mipmapping
549 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
550 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
551
552 ASSERT_GL_NO_ERROR();
553
554 // Create an image from the source texture
555 EGLWindow *window = getEGLWindow();
556
557 EGLImageKHR image =
558 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
559 reinterpretHelper<EGLClientBuffer>(sourceTexture), nullptr);
560
561 ASSERT_EGL_SUCCESS();
562
563 *outSourceImage = image;
564 }
565
createEGLImage2DTextureSource(size_t width,size_t height,GLenum format,GLenum type,const EGLint * attribs,void * data,GLTexture & sourceTexture,EGLImageKHR * outSourceImage)566 void createEGLImage2DTextureSource(size_t width,
567 size_t height,
568 GLenum format,
569 GLenum type,
570 const EGLint *attribs,
571 void *data,
572 GLTexture &sourceTexture,
573 EGLImageKHR *outSourceImage)
574 {
575 // Create a source 2D texture
576 glBindTexture(GL_TEXTURE_2D, sourceTexture);
577
578 glTexImage2D(GL_TEXTURE_2D, 0, format, static_cast<GLsizei>(width),
579 static_cast<GLsizei>(height), 0, format, type, data);
580
581 // Disable mipmapping
582 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
583 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
584
585 ASSERT_GL_NO_ERROR();
586
587 // Create an image from the source texture
588 EGLWindow *window = getEGLWindow();
589
590 EGLImageKHR image =
591 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
592 reinterpretHelper<EGLClientBuffer>(sourceTexture), attribs);
593
594 ASSERT_EGL_SUCCESS();
595
596 *outSourceImage = image;
597 }
598
createEGLImageCubemapTextureSource(size_t width,size_t height,GLenum format,GLenum type,const EGLint * attribs,uint8_t * data,size_t dataStride,EGLenum imageTarget,GLTexture & sourceTexture,EGLImageKHR * outSourceImage)599 void createEGLImageCubemapTextureSource(size_t width,
600 size_t height,
601 GLenum format,
602 GLenum type,
603 const EGLint *attribs,
604 uint8_t *data,
605 size_t dataStride,
606 EGLenum imageTarget,
607 GLTexture &sourceTexture,
608 EGLImageKHR *outSourceImage)
609 {
610 // Create a source cube map texture
611 glBindTexture(GL_TEXTURE_CUBE_MAP, sourceTexture);
612
613 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
614 {
615 glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format,
616 static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, format, type,
617 data + (faceIdx * dataStride));
618 }
619
620 // Disable mipmapping
621 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
622 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
623
624 ASSERT_GL_NO_ERROR();
625
626 // Create an image from the source texture
627 EGLWindow *window = getEGLWindow();
628
629 EGLImageKHR image =
630 eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
631 reinterpretHelper<EGLClientBuffer>(sourceTexture), attribs);
632
633 ASSERT_EGL_SUCCESS();
634
635 *outSourceImage = image;
636 }
637
createEGLImage3DTextureSource(size_t width,size_t height,size_t depth,GLenum format,GLenum type,const EGLint * attribs,void * data,GLTexture & sourceTexture,EGLImageKHR * outSourceImage)638 void createEGLImage3DTextureSource(size_t width,
639 size_t height,
640 size_t depth,
641 GLenum format,
642 GLenum type,
643 const EGLint *attribs,
644 void *data,
645 GLTexture &sourceTexture,
646 EGLImageKHR *outSourceImage)
647 {
648 // Create a source 3D texture
649 glBindTexture(GL_TEXTURE_3D, sourceTexture);
650
651 glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast<GLsizei>(width),
652 static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type,
653 data);
654
655 // Disable mipmapping
656 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
657 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
658
659 ASSERT_GL_NO_ERROR();
660
661 // Create an image from the source texture
662 EGLWindow *window = getEGLWindow();
663
664 EGLImageKHR image =
665 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
666 reinterpretHelper<EGLClientBuffer>(sourceTexture), attribs);
667
668 ASSERT_EGL_SUCCESS();
669
670 *outSourceImage = image;
671 }
672
createEGLImageRenderbufferSource(size_t width,size_t height,GLenum internalFormat,const EGLint * attribs,GLRenderbuffer & sourceRenderbuffer,EGLImageKHR * outSourceImage)673 void createEGLImageRenderbufferSource(size_t width,
674 size_t height,
675 GLenum internalFormat,
676 const EGLint *attribs,
677 GLRenderbuffer &sourceRenderbuffer,
678 EGLImageKHR *outSourceImage)
679 {
680 // Create a source renderbuffer
681 glBindRenderbuffer(GL_RENDERBUFFER, sourceRenderbuffer);
682 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, static_cast<GLsizei>(width),
683 static_cast<GLsizei>(height));
684
685 // Create an image from the source renderbuffer
686 EGLWindow *window = getEGLWindow();
687
688 EGLImageKHR image =
689 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
690 reinterpretHelper<EGLClientBuffer>(sourceRenderbuffer), attribs);
691
692 ASSERT_EGL_SUCCESS();
693
694 *outSourceImage = image;
695 }
696
createEGLImageTargetTexture2D(EGLImageKHR image,GLTexture & targetTexture)697 void createEGLImageTargetTexture2D(EGLImageKHR image, GLTexture &targetTexture)
698 {
699 // Create a target texture from the image
700 glBindTexture(GL_TEXTURE_2D, targetTexture);
701 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
702
703 // Disable mipmapping
704 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
705 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
706
707 ASSERT_GL_NO_ERROR();
708 }
709
createEGLImageTargetTexture2DArray(EGLImageKHR image,GLTexture & targetTexture)710 void createEGLImageTargetTexture2DArray(EGLImageKHR image, GLTexture &targetTexture)
711 {
712 // Create a target texture from the image
713 glBindTexture(GL_TEXTURE_2D_ARRAY, targetTexture);
714 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D_ARRAY, image);
715
716 // Disable mipmapping
717 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
718 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
719
720 ASSERT_GL_NO_ERROR();
721 }
722
createEGLImageTargetTextureExternal(EGLImageKHR image,GLuint targetTexture)723 void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint targetTexture)
724 {
725 // Create a target texture from the image
726 glBindTexture(GL_TEXTURE_EXTERNAL_OES, targetTexture);
727 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
728
729 // Disable mipmapping
730 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
731 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
732
733 ASSERT_GL_NO_ERROR();
734 }
735
createEGLImageTargetTextureStorage(EGLImageKHR image,GLenum targetType,GLuint targetTexture,const GLint * attribs)736 void createEGLImageTargetTextureStorage(EGLImageKHR image,
737 GLenum targetType,
738 GLuint targetTexture,
739 const GLint *attribs)
740 {
741 // Create a target texture from the image
742 glBindTexture(targetType, targetTexture);
743 glEGLImageTargetTexStorageEXT(targetType, image, attribs);
744
745 ASSERT_GL_NO_ERROR();
746
747 // Disable mipmapping
748 glTexParameteri(targetType, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
749 glTexParameteri(targetType, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
750
751 ASSERT_GL_NO_ERROR();
752 }
753
getLayerPitch(size_t height,size_t rowStride)754 size_t getLayerPitch(size_t height, size_t rowStride)
755 {
756 // Undocumented alignment of layer stride. This is potentially platform dependent, but
757 // allows functionality to be tested.
758 constexpr size_t kLayerAlignment = 4096;
759
760 const size_t layerSize = height * rowStride;
761 return (layerSize + kLayerAlignment - 1) & ~(kLayerAlignment - 1);
762 }
763
764 struct AHBPlaneData
765 {
766 const GLubyte *data;
767 size_t bytesPerPixel;
768 };
769
writeAHBData(AHardwareBuffer * aHardwareBuffer,size_t width,size_t height,size_t depth,bool isYUV,const std::vector<AHBPlaneData> & data)770 bool writeAHBData(AHardwareBuffer *aHardwareBuffer,
771 size_t width,
772 size_t height,
773 size_t depth,
774 bool isYUV,
775 const std::vector<AHBPlaneData> &data)
776 {
777 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
778 ASSERT(!data.empty());
779 # if defined(ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT)
780 AHardwareBuffer_Planes planeInfo;
781 int res = AHardwareBuffer_lockPlanes(
782 aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1, nullptr, &planeInfo);
783 if (res != 0)
784 {
785 WARN() << "AHardwareBuffer_lockPlanes failed";
786 return false;
787 }
788
789 EXPECT_EQ(data.size(), planeInfo.planeCount);
790
791 for (size_t planeIdx = 0; planeIdx < data.size(); planeIdx++)
792 {
793 const AHBPlaneData &planeData = data[planeIdx];
794 const AHardwareBuffer_Plane &plane = planeInfo.planes[planeIdx];
795
796 size_t planeHeight = (isYUV && planeIdx > 0) ? (height / 2) : height;
797 size_t planeWidth = (isYUV && planeIdx > 0) ? (width / 2) : width;
798 size_t layerPitch = getLayerPitch(planeHeight, plane.rowStride);
799
800 for (size_t z = 0; z < depth; z++)
801 {
802 const uint8_t *srcDepthSlice =
803 reinterpret_cast<const uint8_t *>(planeData.data) +
804 z * planeHeight * planeWidth * planeData.bytesPerPixel;
805
806 for (size_t y = 0; y < planeHeight; y++)
807 {
808 const uint8_t *srcRow =
809 srcDepthSlice + y * planeWidth * planeData.bytesPerPixel;
810
811 for (size_t x = 0; x < planeWidth; x++)
812 {
813 const uint8_t *src = srcRow + x * planeData.bytesPerPixel;
814 uint8_t *dst = reinterpret_cast<uint8_t *>(plane.data) + z * layerPitch +
815 y * plane.rowStride + x * plane.pixelStride;
816 memcpy(dst, src, planeData.bytesPerPixel);
817 }
818 }
819 }
820 }
821
822 res = AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
823 EXPECT_EQ(res, 0);
824 # else
825 EXPECT_EQ(1u, data.size());
826 void *mappedMemory = nullptr;
827 int res = AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
828 nullptr, &mappedMemory);
829 EXPECT_EQ(res, 0);
830
831 // Need to grab the stride the implementation might have enforced
832 AHardwareBuffer_Desc aHardwareBufferDescription = {};
833 AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);
834 const size_t stride = aHardwareBufferDescription.stride * data[0].bytesPerPixel;
835 size_t layerPitch = getLayerPitch(height, stride);
836
837 uint32_t rowSize = stride * height;
838 for (size_t z = 0; z < depth; z++)
839 {
840 for (uint32_t y = 0; y < height; y++)
841 {
842 size_t dstPtrOffset = z * layerPitch + y * stride;
843 size_t srcPtrOffset = (z * height + y) * width * data[0].bytesPerPixel;
844
845 uint8_t *dst = reinterpret_cast<uint8_t *>(mappedMemory) + dstPtrOffset;
846 memcpy(dst, data[0].data + srcPtrOffset, rowSize);
847 }
848 }
849
850 res = AHardwareBuffer_unlock(aHardwareBuffer, nullptr);
851 EXPECT_EQ(res, 0);
852 # endif
853 return true;
854 #else
855 return false;
856 #endif
857 }
858
859 enum AHBUsage
860 {
861 kAHBUsageGPUSampledImage = 1 << 0,
862 kAHBUsageGPUFramebuffer = 1 << 1,
863 kAHBUsageGPUCubeMap = 1 << 2,
864 kAHBUsageGPUMipMapComplete = 1 << 3,
865 kAHBUsageFrontBuffer = 1 << 4,
866 };
867
868 constexpr static uint32_t kDefaultAHBUsage = kAHBUsageGPUSampledImage | kAHBUsageGPUFramebuffer;
869 constexpr static uint32_t kDefaultAHBYUVUsage = kAHBUsageGPUSampledImage;
870
871 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
createAndroidHardwareBufferDesc(size_t width,size_t height,size_t depth,int androidFormat,uint32_t usage)872 AHardwareBuffer_Desc createAndroidHardwareBufferDesc(size_t width,
873 size_t height,
874 size_t depth,
875 int androidFormat,
876 uint32_t usage)
877 {
878 // The height and width are number of pixels of size format
879 AHardwareBuffer_Desc aHardwareBufferDescription = {};
880 aHardwareBufferDescription.width = width;
881 aHardwareBufferDescription.height = height;
882 aHardwareBufferDescription.layers = depth;
883 aHardwareBufferDescription.format = androidFormat;
884 aHardwareBufferDescription.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY;
885 if ((usage & kAHBUsageGPUSampledImage) != 0)
886 {
887 aHardwareBufferDescription.usage |= AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
888 }
889 if ((usage & kAHBUsageGPUFramebuffer) != 0)
890 {
891 aHardwareBufferDescription.usage |= AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER;
892 }
893 if ((usage & kAHBUsageGPUCubeMap) != 0)
894 {
895 aHardwareBufferDescription.usage |= AHARDWAREBUFFER_USAGE_GPU_CUBE_MAP;
896 }
897 if ((usage & kAHBUsageGPUMipMapComplete) != 0)
898 {
899 aHardwareBufferDescription.usage |= AHARDWAREBUFFER_USAGE_GPU_MIPMAP_COMPLETE;
900 }
901 if ((usage & kAHBUsageFrontBuffer) != 0)
902 {
903 aHardwareBufferDescription.usage |= ANGLE_AHARDWAREBUFFER_USAGE_FRONT_BUFFER;
904 }
905 aHardwareBufferDescription.stride = 0;
906 aHardwareBufferDescription.rfu0 = 0;
907 aHardwareBufferDescription.rfu1 = 0;
908 return aHardwareBufferDescription;
909 }
910 #endif
911
isAndroidHardwareBufferConfigurationSupported(size_t width,size_t height,size_t depth,int androidFormat,uint32_t usage)912 bool isAndroidHardwareBufferConfigurationSupported(size_t width,
913 size_t height,
914 size_t depth,
915 int androidFormat,
916 uint32_t usage)
917 {
918 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
919 const AHardwareBuffer_Desc aHardwareBufferDescription =
920 createAndroidHardwareBufferDesc(width, height, depth, androidFormat, usage);
921 return AHardwareBuffer_isSupported(&aHardwareBufferDescription);
922 #else
923 return false;
924 #endif
925 }
926
createAndroidHardwareBuffer(size_t width,size_t height,size_t depth,int androidFormat,uint32_t usage,const std::vector<AHBPlaneData> & data)927 AHardwareBuffer *createAndroidHardwareBuffer(size_t width,
928 size_t height,
929 size_t depth,
930 int androidFormat,
931 uint32_t usage,
932 const std::vector<AHBPlaneData> &data)
933 {
934 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
935 const AHardwareBuffer_Desc aHardwareBufferDescription =
936 createAndroidHardwareBufferDesc(width, height, depth, androidFormat, usage);
937
938 // Allocate memory from Android Hardware Buffer
939 AHardwareBuffer *aHardwareBuffer = nullptr;
940 EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
941
942 if (!data.empty())
943 {
944 const bool isYUV = androidFormat == AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420 ||
945 androidFormat == AHARDWAREBUFFER_FORMAT_YV12;
946 writeAHBData(aHardwareBuffer, width, height, depth, isYUV, data);
947 }
948
949 return aHardwareBuffer;
950 #else
951 return nullptr;
952 #endif // ANGLE_PLATFORM_ANDROID
953 }
954
destroyAndroidHardwareBuffer(AHardwareBuffer * aHardwarebuffer)955 void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwarebuffer)
956 {
957 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
958 AHardwareBuffer_release(aHardwarebuffer);
959 #endif
960 }
961
createEGLImageAndroidHardwareBufferSource(size_t width,size_t height,size_t depth,int androidPixelFormat,uint32_t usage,const EGLint * attribs,const std::vector<AHBPlaneData> & data,AHardwareBuffer ** outSourceAHB,EGLImageKHR * outSourceImage)962 void createEGLImageAndroidHardwareBufferSource(size_t width,
963 size_t height,
964 size_t depth,
965 int androidPixelFormat,
966 uint32_t usage,
967 const EGLint *attribs,
968 const std::vector<AHBPlaneData> &data,
969 AHardwareBuffer **outSourceAHB,
970 EGLImageKHR *outSourceImage)
971 {
972 // Set Android Memory
973 AHardwareBuffer *aHardwareBuffer =
974 createAndroidHardwareBuffer(width, height, depth, androidPixelFormat, usage, data);
975 EXPECT_NE(aHardwareBuffer, nullptr);
976
977 // Create an image from the source AHB
978 EGLWindow *window = getEGLWindow();
979
980 EGLImageKHR image = eglCreateImageKHR(
981 window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
982 angle::android::AHardwareBufferToClientBuffer(aHardwareBuffer), attribs);
983 ASSERT_EGL_SUCCESS();
984
985 *outSourceAHB = aHardwareBuffer;
986 *outSourceImage = image;
987 }
988
createEGLImageANWBClientBufferSource(size_t width,size_t height,size_t depth,const EGLint * attribsANWB,const EGLint * attribsImage,const std::vector<AHBPlaneData> & data,EGLImageKHR * outSourceImage)989 void createEGLImageANWBClientBufferSource(size_t width,
990 size_t height,
991 size_t depth,
992 const EGLint *attribsANWB,
993 const EGLint *attribsImage,
994 const std::vector<AHBPlaneData> &data,
995 EGLImageKHR *outSourceImage)
996 {
997 // Set Android Memory
998
999 EGLClientBuffer eglClientBuffer = eglCreateNativeClientBufferANDROID(attribsANWB);
1000 EXPECT_NE(eglClientBuffer, nullptr);
1001
1002 // allocate AHB memory
1003 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
1004 AHardwareBuffer *pAHardwareBuffer = angle::android::ANativeWindowBufferToAHardwareBuffer(
1005 angle::android::ClientBufferToANativeWindowBuffer(eglClientBuffer));
1006 if (!data.empty())
1007 {
1008 bool success = writeAHBData(pAHardwareBuffer, width, height, depth, false, data);
1009 if (!success)
1010 {
1011 return;
1012 }
1013 }
1014 #endif // ANGLE_AHARDWARE_BUFFER_SUPPORT
1015
1016 // Create an image from the source eglClientBuffer
1017 EGLWindow *window = getEGLWindow();
1018
1019 EGLImageKHR image =
1020 eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
1021 eglClientBuffer, attribsImage);
1022 ASSERT_EGL_SUCCESS();
1023
1024 *outSourceImage = image;
1025 }
1026
createEGLImageTargetRenderbuffer(EGLImageKHR image,GLuint targetRenderbuffer)1027 void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint targetRenderbuffer)
1028 {
1029 // Create a target texture from the image
1030 glBindRenderbuffer(GL_RENDERBUFFER, targetRenderbuffer);
1031 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
1032
1033 ASSERT_GL_NO_ERROR();
1034 }
1035
1036 void ValidationGLEGLImage_helper(const EGLint *attribs);
1037 void SourceAHBTarget2D_helper(const EGLint *attribs);
1038 void SourceAHBTarget2DImageStorageGenerateMipmap_helper(const EGLint *attribs);
1039 void SourceAHBTarget2DArray_helper(const EGLint *attribs);
1040 void SourceAHBTargetExternal_helper(const EGLint *attribs);
1041 void SourceAHBTargetExternalESSL3_helper(const EGLint *attribs);
1042 void SourceNativeClientBufferTargetExternal_helper(const EGLint *attribs);
1043 void SourceNativeClientBufferTargetRenderbuffer_helper(const EGLint *attribs);
1044 void Source2DTarget2D_helper(const EGLint *attribs);
1045 void Source2DTarget2DArray_helper(const EGLint *attribs);
1046 void Source2DTargetRenderbuffer_helper(const EGLint *attribs);
1047 void Source2DTargetExternal_helper(const EGLint *attribs);
1048 void Source2DTargetExternalESSL3_helper(const EGLint *attribs);
1049 void SourceCubeTarget2D_helper(const EGLint *attribs);
1050 void SourceCubeTargetRenderbuffer_helper(const EGLint *attribs);
1051 void SourceCubeTargetExternal_helper(const EGLint *attribs);
1052 void SourceCubeTargetExternalESSL3_helper(const EGLint *attribs);
1053 void Source3DTargetTexture_helper(EGLint *attribs);
1054 void Source3DTargetRenderbuffer_helper(EGLint *attribs);
1055 void Source3DTargetExternal_helper(EGLint *attribs);
1056 void Source3DTargetExternalESSL3_helper(EGLint *attribs);
1057 void SourceRenderbufferTargetTexture_helper(const EGLint *attribs);
1058 void SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs);
1059 void SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs);
1060 void FixedRatedCompressionBasicHelper(const GLint *attribs);
1061 void FixedRatedCompressionImageAttribCheck(EGLImageKHR image,
1062 const GLint *attribs,
1063 const GLint expectResult);
1064 void SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs);
1065 void ImageStorageGenerateMipmap_helper(const EGLint *attribs,
1066 const GLsizei width,
1067 const GLsizei height,
1068 AHardwareBuffer *srcAhb,
1069 GLuint srcTexture,
1070 EGLImageKHR *imageOut);
1071 void ImageCheckingTextureAccessHelper(GLenum target, bool mipmap);
1072 void verifyImageStorageMipmap(const EGLint *attribs,
1073 EGLImageKHR image,
1074 const GLsizei mipLevelCount);
1075 void verifyImageStorageMipmapWithBlend(const EGLint *attribs,
1076 EGLImageKHR image,
1077 const GLsizei mipLevelCount);
verifyResultsTexture(GLuint texture,const GLubyte referenceColor[4],GLenum textureTarget,GLuint program,GLuint textureUniform)1078 void verifyResultsTexture(GLuint texture,
1079 const GLubyte referenceColor[4],
1080 GLenum textureTarget,
1081 GLuint program,
1082 GLuint textureUniform)
1083 {
1084 // Draw a quad with the target texture
1085 glUseProgram(program);
1086 glBindTexture(textureTarget, texture);
1087 glUniform1i(textureUniform, 0);
1088
1089 drawQuad(program, "position", 0.5f);
1090
1091 // Expect that the rendered quad's color is the same as the reference color with a tolerance
1092 // of 2
1093 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
1094 referenceColor[3], 2);
1095 }
1096
verifyResultsTextureLeftAndRight(GLuint texture,const GLubyte leftColor[4],const GLubyte rightColor[4],GLenum textureTarget,GLuint program,GLuint textureUniform)1097 void verifyResultsTextureLeftAndRight(GLuint texture,
1098 const GLubyte leftColor[4],
1099 const GLubyte rightColor[4],
1100 GLenum textureTarget,
1101 GLuint program,
1102 GLuint textureUniform)
1103 {
1104 verifyResultsTexture(texture, leftColor, textureTarget, program, textureUniform);
1105
1106 // verifyResultsTexture only verifies top-left. Here also verifies top-right.
1107 EXPECT_PIXEL_NEAR(getWindowWidth() - 1, 0, rightColor[0], rightColor[1], rightColor[2],
1108 rightColor[3], 1);
1109 }
1110
verifyResults2D(GLuint texture,const GLubyte data[4])1111 void verifyResults2D(GLuint texture, const GLubyte data[4])
1112 {
1113 verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
1114 mTextureUniformLocation);
1115 }
1116
verifyResults3D(GLuint texture,const GLubyte data[4],uint32_t layerIndex=0)1117 void verifyResults3D(GLuint texture, const GLubyte data[4], uint32_t layerIndex = 0)
1118 {
1119 glUseProgram(m3DTextureProgram);
1120 glUniform1ui(m3DTextureLayerUniformLocation, layerIndex);
1121
1122 verifyResultsTexture(texture, data, GL_TEXTURE_3D, m3DTextureProgram,
1123 m3DTextureUniformLocation);
1124 }
1125
verifyResults2DLeftAndRight(GLuint texture,const GLubyte left[4],const GLubyte right[4])1126 void verifyResults2DLeftAndRight(GLuint texture, const GLubyte left[4], const GLubyte right[4])
1127 {
1128 verifyResultsTextureLeftAndRight(texture, left, right, GL_TEXTURE_2D, mTextureProgram,
1129 mTextureUniformLocation);
1130 }
1131
verifyResults2DArray(GLuint texture,const GLubyte data[4],uint32_t layerIndex=0)1132 void verifyResults2DArray(GLuint texture, const GLubyte data[4], uint32_t layerIndex = 0)
1133 {
1134 glUseProgram(m2DArrayTextureProgram);
1135 glUniform1ui(m2DArrayTextureLayerUniformLocation, layerIndex);
1136
1137 verifyResultsTexture(texture, data, GL_TEXTURE_2D_ARRAY, m2DArrayTextureProgram,
1138 m2DArrayTextureUniformLocation);
1139 }
1140
verifyResultsCube(GLuint texture,const GLubyte data[4],uint32_t faceIndex=0)1141 void verifyResultsCube(GLuint texture, const GLubyte data[4], uint32_t faceIndex = 0)
1142 {
1143 glUseProgram(mCubeTextureProgram);
1144 glUniform3f(mCubeTextureFaceCoordUniformLocation, kCubeFaceX[faceIndex],
1145 kCubeFaceY[faceIndex], kCubeFaceZ[faceIndex]);
1146
1147 verifyResultsTexture(texture, data, GL_TEXTURE_CUBE_MAP, mCubeTextureProgram,
1148 mCubeTextureUniformLocation);
1149 }
1150
verifyResultsCubeArray(GLuint texture,const GLubyte data[4],uint32_t faceIndex=0,uint32_t layerIndex=0)1151 void verifyResultsCubeArray(GLuint texture,
1152 const GLubyte data[4],
1153 uint32_t faceIndex = 0,
1154 uint32_t layerIndex = 0)
1155 {
1156 glUseProgram(mCubeArrayTextureProgram);
1157 glUniform1ui(mCubeArrayTextureLayerUniformLocation, layerIndex);
1158 glUniform3f(mCubeArrayTextureFaceCoordUniformLocation, kCubeFaceX[faceIndex],
1159 kCubeFaceY[faceIndex], kCubeFaceZ[faceIndex]);
1160
1161 verifyResultsTexture(texture, data, GL_TEXTURE_CUBE_MAP_ARRAY, mCubeArrayTextureProgram,
1162 mCubeArrayTextureUniformLocation);
1163 }
1164
verifyResultsExternal(GLuint texture,const GLubyte data[4])1165 void verifyResultsExternal(GLuint texture, const GLubyte data[4])
1166 {
1167 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
1168 mTextureExternalUniformLocation);
1169 }
1170
verifyResultsExternalESSL3(GLuint texture,const GLubyte data[4])1171 void verifyResultsExternalESSL3(GLuint texture, const GLubyte data[4])
1172 {
1173 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
1174 mTextureExternalESSL3UniformLocation);
1175 }
1176
verifyResultsExternalYUV(GLuint texture,const GLubyte data[4])1177 void verifyResultsExternalYUV(GLuint texture, const GLubyte data[4])
1178 {
1179 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureYUVProgram,
1180 mTextureYUVUniformLocation);
1181 }
1182
verifyResultsExternalYUVVS(GLuint texture,const GLubyte data[4])1183 void verifyResultsExternalYUVVS(GLuint texture, const GLubyte data[4])
1184 {
1185 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureYUVVSProgram,
1186 mTextureYUVVSUniformLocation);
1187 }
1188
verifyResultsRenderbuffer(GLuint renderbuffer,GLubyte referenceColor[4])1189 void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte referenceColor[4])
1190 {
1191 // Bind the renderbuffer to a framebuffer
1192 GLFramebuffer framebuffer;
1193 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1194 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1195 renderbuffer);
1196
1197 // Expect renderbuffer to match referenceColor with a tolerance of 1.
1198 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
1199 referenceColor[3], 1);
1200 }
1201
verifyResultsRenderbufferWithClearAndDraw(GLuint texture,GLuint renderbuffer,GLubyte clearColor[4],GLubyte referenceColor[4])1202 void verifyResultsRenderbufferWithClearAndDraw(GLuint texture,
1203 GLuint renderbuffer,
1204 GLubyte clearColor[4],
1205 GLubyte referenceColor[4])
1206 {
1207 // Bind the renderbuffer to a framebuffer
1208 GLFramebuffer framebuffer;
1209 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
1210 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1211 renderbuffer);
1212
1213 // Clear the renderbuffer with the clear color
1214 glClearColor(clearColor[0] / 255.0f, clearColor[1] / 255.0f, clearColor[2] / 255.0f,
1215 clearColor[3] / 255.0f);
1216 glClear(GL_COLOR_BUFFER_BIT);
1217
1218 // Expect renderbuffer to match referenceColor with a tolerance of 1.
1219 EXPECT_PIXEL_NEAR(0, 0, referenceColor[0], referenceColor[1], referenceColor[2],
1220 referenceColor[3], 1);
1221
1222 // Sample source texture and draw onto renderbuffer and expect rendered quad's color
1223 // is the same as the reference color with a tolerance of 1
1224 verifyResultsTexture(texture, referenceColor, GL_TEXTURE_2D, mTextureProgram,
1225 mTextureUniformLocation);
1226 }
1227
1228 enum class AHBVerifyRegion
1229 {
1230 Entire,
1231 LeftHalf,
1232 RightHalf,
1233 };
1234
verifyResultAHB(AHardwareBuffer * source,const std::vector<AHBPlaneData> & data,AHBVerifyRegion verifyRegion=AHBVerifyRegion::Entire)1235 void verifyResultAHB(AHardwareBuffer *source,
1236 const std::vector<AHBPlaneData> &data,
1237 AHBVerifyRegion verifyRegion = AHBVerifyRegion::Entire)
1238 {
1239 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
1240 AHardwareBuffer_Desc aHardwareBufferDescription;
1241 AHardwareBuffer_describe(source, &aHardwareBufferDescription);
1242 bool isYUV = (aHardwareBufferDescription.format == AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
1243 const uint32_t width = aHardwareBufferDescription.width;
1244 const uint32_t height = aHardwareBufferDescription.height;
1245 const uint32_t depth = aHardwareBufferDescription.layers;
1246
1247 # if defined(ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT)
1248 AHardwareBuffer_Planes planeInfo;
1249 ASSERT_EQ(0, AHardwareBuffer_lockPlanes(source, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
1250 nullptr, &planeInfo));
1251 ASSERT_EQ(data.size(), planeInfo.planeCount);
1252
1253 for (size_t planeIdx = 0; planeIdx < data.size(); planeIdx++)
1254 {
1255 const AHBPlaneData &planeData = data[planeIdx];
1256 const AHardwareBuffer_Plane &plane = planeInfo.planes[planeIdx];
1257
1258 const size_t planeHeight = (isYUV && planeIdx > 0) ? (height / 2) : height;
1259 const size_t planeWidth = (isYUV && planeIdx > 0) ? (width / 2) : width;
1260 size_t layerPitch = getLayerPitch(planeHeight, plane.rowStride);
1261
1262 uint32_t xStart = 0;
1263 uint32_t xEnd = planeWidth;
1264
1265 switch (verifyRegion)
1266 {
1267 case AHBVerifyRegion::Entire:
1268 break;
1269 case AHBVerifyRegion::LeftHalf:
1270 xEnd = planeWidth / 2;
1271 break;
1272 case AHBVerifyRegion::RightHalf:
1273 xStart = planeWidth / 2;
1274 break;
1275 }
1276
1277 for (size_t z = 0; z < depth; z++)
1278 {
1279 const uint8_t *referenceDepthSlice =
1280 reinterpret_cast<const uint8_t *>(planeData.data) +
1281 z * planeHeight * (xEnd - xStart) * planeData.bytesPerPixel;
1282 for (size_t y = 0; y < planeHeight; y++)
1283 {
1284 const uint8_t *referenceRow =
1285 referenceDepthSlice + y * (xEnd - xStart) * planeData.bytesPerPixel;
1286 for (size_t x = xStart; x < xEnd; x++)
1287 {
1288 const uint8_t *referenceData =
1289 referenceRow + (x - xStart) * planeData.bytesPerPixel;
1290 std::vector<uint8_t> reference(referenceData,
1291 referenceData + planeData.bytesPerPixel);
1292
1293 const uint8_t *ahbData = reinterpret_cast<uint8_t *>(plane.data) +
1294 z * layerPitch + y * plane.rowStride +
1295 x * plane.pixelStride;
1296 std::vector<uint8_t> ahb(ahbData, ahbData + planeData.bytesPerPixel);
1297
1298 EXPECT_EQ(reference, ahb)
1299 << "at (" << x << ", " << y << ") on plane " << planeIdx;
1300 }
1301 }
1302 }
1303 }
1304 ASSERT_EQ(0, AHardwareBuffer_unlock(source, nullptr));
1305 # else
1306 ASSERT_EQ(1u, data.size());
1307 ASSERT_FALSE(isYUV);
1308
1309 const uint32_t rowStride = aHardwareBufferDescription.stride * data[0].bytesPerPixel;
1310 size_t layerPitch = getLayerPitch(height, rowStride);
1311
1312 void *mappedMemory = nullptr;
1313 ASSERT_EQ(0, AHardwareBuffer_lock(source, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY, -1,
1314 nullptr, &mappedMemory));
1315
1316 uint32_t xStart = 0;
1317 uint32_t xEnd = width;
1318
1319 switch (verifyRegion)
1320 {
1321 case AHBVerifyRegion::Entire:
1322 break;
1323 case AHBVerifyRegion::LeftHalf:
1324 xEnd = width / 2;
1325 break;
1326 case AHBVerifyRegion::RightHalf:
1327 xStart = width / 2;
1328 break;
1329 }
1330 for (size_t z = 0; z < depth; z++)
1331 {
1332 const uint8_t *referenceDepthSlice =
1333 reinterpret_cast<const uint8_t *>(data[0].data) +
1334 z * height * (xEnd - xStart) * data[0].bytesPerPixel;
1335 for (size_t y = 0; y < height; y++)
1336 {
1337 const uint8_t *referenceRow =
1338 referenceDepthSlice + y * (xEnd - xStart) * data[0].bytesPerPixel;
1339 for (size_t x = xStart; x < xEnd; x++)
1340 {
1341 const uint8_t *referenceData =
1342 referenceRow + (x - xStart) * data[0].bytesPerPixel;
1343 std::vector<uint8_t> reference(referenceData,
1344 referenceData + data[0].bytesPerPixel);
1345
1346 const uint8_t *ahbData = reinterpret_cast<uint8_t *>(mappedMemory) +
1347 z * layerPitch + y * rowStride +
1348 x * data[0].bytesPerPixel;
1349 std::vector<uint8_t> ahb(ahbData, ahbData + data[0].bytesPerPixel);
1350
1351 EXPECT_EQ(reference, ahb) << "at (" << x << ", " << y << ")";
1352 }
1353 }
1354 }
1355 ASSERT_EQ(0, AHardwareBuffer_unlock(source, nullptr));
1356 # endif
1357 #endif
1358 }
1359
1360 template <typename destType, typename sourcetype>
reinterpretHelper(const sourcetype & source)1361 destType reinterpretHelper(const sourcetype &source)
1362 {
1363 static_assert(sizeof(destType) == sizeof(size_t),
1364 "destType should be the same size as a size_t");
1365 size_t sourceSizeT = static_cast<size_t>(source.get());
1366 return reinterpret_cast<destType>(sourceSizeT);
1367 }
1368
hasImageGLColorspaceExt() const1369 bool hasImageGLColorspaceExt() const
1370 {
1371 // Possible GLES driver bug on Pixel2 devices: http://anglebug.com/42263865
1372 if (IsPixel2() && IsOpenGLES())
1373 {
1374 return false;
1375 }
1376 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kImageGLColorspaceExt);
1377 }
1378
hasAndroidImageNativeBufferExt() const1379 bool hasAndroidImageNativeBufferExt() const
1380 {
1381 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
1382 kEGLAndroidImageNativeBufferExt);
1383 }
1384
hasEglImageStorageExt() const1385 bool hasEglImageStorageExt() const { return IsGLExtensionEnabled(kEGLImageStorageExt); }
1386
hasEglImageStorageCompressionExt() const1387 bool hasEglImageStorageCompressionExt() const
1388 {
1389 return IsGLExtensionEnabled(kEGLImageStorageCompressionExt);
1390 }
1391
hasTextureStorageCompressionExt() const1392 bool hasTextureStorageCompressionExt() const
1393 {
1394 return IsGLExtensionEnabled(kTextureStorageCompressionExt);
1395 }
1396
hasAndroidHardwareBufferSupport() const1397 bool hasAndroidHardwareBufferSupport() const
1398 {
1399 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
1400 return true;
1401 #else
1402 return false;
1403 #endif
1404 }
1405
hasAhbLockPlanesSupport() const1406 bool hasAhbLockPlanesSupport() const
1407 {
1408 #if defined(ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT)
1409 return true;
1410 #else
1411 return false;
1412 #endif
1413 }
1414
hasEglImageArrayExt() const1415 bool hasEglImageArrayExt() const { return IsGLExtensionEnabled(kEGLImageArrayExt); }
1416
hasOESExt() const1417 bool hasOESExt() const { return IsGLExtensionEnabled(kOESExt); }
1418
hasExternalExt() const1419 bool hasExternalExt() const { return IsGLExtensionEnabled(kExternalExt); }
1420
hasExternalESSL3Ext() const1421 bool hasExternalESSL3Ext() const { return IsGLExtensionEnabled(kExternalESSL3Ext); }
1422
hasYUVInternalFormatExt() const1423 bool hasYUVInternalFormatExt() const { return IsGLExtensionEnabled(kYUVInternalFormatExt); }
1424
hasYUVTargetExt() const1425 bool hasYUVTargetExt() const { return IsGLExtensionEnabled(kYUVTargetExt); }
1426
hasRGBXInternalFormatExt() const1427 bool hasRGBXInternalFormatExt() const { return IsGLExtensionEnabled(kRGBXInternalFormatExt); }
1428
hasBaseExt() const1429 bool hasBaseExt() const
1430 {
1431 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kBaseExt);
1432 }
1433
has2DTextureExt() const1434 bool has2DTextureExt() const
1435 {
1436 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k2DTextureExt);
1437 }
1438
has3DTextureExt() const1439 bool has3DTextureExt() const
1440 {
1441 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k3DTextureExt);
1442 }
1443
hasPixmapExt() const1444 bool hasPixmapExt() const
1445 {
1446 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kPixmapExt);
1447 }
1448
hasRenderbufferExt() const1449 bool hasRenderbufferExt() const
1450 {
1451 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kRenderbufferExt);
1452 }
1453
hasCubemapExt() const1454 bool hasCubemapExt() const
1455 {
1456 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kCubemapExt);
1457 }
1458
getPerfCounters()1459 angle::VulkanPerfCounters getPerfCounters()
1460 {
1461 ASSERT(IsVulkan());
1462
1463 if (mCounterNameToIndexMap.empty())
1464 {
1465 mCounterNameToIndexMap = BuildCounterNameToIndexMap();
1466 }
1467
1468 return GetPerfCounters(mCounterNameToIndexMap);
1469 }
1470
externalTextureTracerTestHelper(const EGLint * attribsToRecoverInMEC)1471 void externalTextureTracerTestHelper(const EGLint *attribsToRecoverInMEC)
1472 {
1473 const EGLWindow *eglWindow = getEGLWindow();
1474 // Frame 1 begins
1475 // Create the Image
1476 GLTexture sourceTexture1;
1477 EGLImageKHR image1;
1478
1479 GLubyte data[] = {132, 55, 219, 255};
1480 // Create a source 2D texture
1481 glBindTexture(GL_TEXTURE_2D, sourceTexture1);
1482
1483 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(1), static_cast<GLsizei>(1), 0,
1484 GL_RGBA, GL_UNSIGNED_BYTE, data);
1485
1486 // Disable mipmapping
1487 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1489
1490 ASSERT_GL_NO_ERROR();
1491
1492 image1 = eglCreateImageKHR(
1493 eglWindow->getDisplay(), eglWindow->getContext(), EGL_GL_TEXTURE_2D_KHR,
1494 reinterpretHelper<EGLClientBuffer>(sourceTexture1), attribsToRecoverInMEC);
1495
1496 ASSERT_EGL_SUCCESS();
1497
1498 // Create the target
1499 GLTexture targetTexture1;
1500 // Create a target texture from the image
1501 glBindTexture(GL_TEXTURE_EXTERNAL_OES, targetTexture1);
1502 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image1);
1503
1504 // Disable mipmapping
1505 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1506 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1507
1508 ASSERT_GL_NO_ERROR();
1509
1510 // Calls On EndFrame(), with MidExecutionSetup to restore external texture targetTexture1
1511 // above
1512 EGLDisplay display = eglWindow->getDisplay();
1513 EGLSurface surface = eglWindow->getSurface();
1514 eglSwapBuffers(display, surface);
1515 // Frame 1 ends
1516
1517 // Frame 2 begins
1518 // Create another eglImage with another associated texture
1519 // Draw using the eglImage texture targetTexture1 created in frame 1
1520 GLTexture sourceTexture2;
1521 EGLImageKHR image2;
1522
1523 // Create a source 2D texture
1524 glBindTexture(GL_TEXTURE_2D, sourceTexture2);
1525
1526 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, static_cast<GLsizei>(1), static_cast<GLsizei>(1), 0,
1527 GL_RGBA, GL_UNSIGNED_BYTE, data);
1528
1529 // Disable mipmapping
1530 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1531 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1532
1533 ASSERT_GL_NO_ERROR();
1534
1535 constexpr EGLint defaultAttribs[] = {
1536 EGL_IMAGE_PRESERVED,
1537 EGL_TRUE,
1538 EGL_NONE,
1539 };
1540 image2 = eglCreateImageKHR(
1541 eglWindow->getDisplay(), eglWindow->getContext(), EGL_GL_TEXTURE_2D_KHR,
1542 reinterpretHelper<EGLClientBuffer>(sourceTexture2), defaultAttribs);
1543
1544 ASSERT_EGL_SUCCESS();
1545
1546 // Create the target
1547 GLTexture targetTexture2;
1548 // Create a target texture from the image
1549 glBindTexture(GL_TEXTURE_EXTERNAL_OES, targetTexture2);
1550 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image2);
1551
1552 // Disable mipmapping
1553 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1554 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1555
1556 ASSERT_GL_NO_ERROR();
1557 glUseProgram(mTextureExternalProgram);
1558 glBindTexture(GL_TEXTURE_EXTERNAL_OES, targetTexture1);
1559 glUniform1i(mTextureExternalUniformLocation, 0);
1560
1561 drawQuad(mTextureExternalProgram, "position", 0.5f);
1562
1563 // Calls On EndFrame() to save the gl calls creating external texture targetTexture2;
1564 // We use this as a reference to check the gl calls we restore for targetTexture1
1565 // in MidExecutionSetup
1566 eglSwapBuffers(display, surface);
1567 // Frame 2 ends
1568
1569 // Frame 3 begins
1570 // Draw a quad with the targetTexture2
1571 glUseProgram(mTextureExternalProgram);
1572 glBindTexture(GL_TEXTURE_EXTERNAL_OES, targetTexture2);
1573 glUniform1i(mTextureExternalUniformLocation, 0);
1574
1575 drawQuad(mTextureExternalProgram, "position", 0.5f);
1576
1577 eglSwapBuffers(display, surface);
1578 // Frame 3 ends
1579
1580 // Clean up
1581 eglDestroyImageKHR(eglWindow->getDisplay(), image1);
1582 eglDestroyImageKHR(eglWindow->getDisplay(), image2);
1583 }
1584
1585 void framebufferAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,
1586 bool deleteSourceTextureLast);
1587 void framebufferResolveAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,
1588 bool deleteSourceTextureLast);
1589 void useAHBByGLThenForeignThenGLHelper(
1590 std::function<void(const GLTexture &, uint32_t, uint32_t)> firstUse,
1591 std::function<void(const GLTexture &, uint32_t, uint32_t)> secondUse);
1592
1593 EGLint default3DAttribs[5] = {
1594 EGL_GL_TEXTURE_ZOFFSET_KHR, static_cast<EGLint>(0), EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE,
1595 };
1596 EGLint colorspace3DAttribs[7] = {
1597 EGL_GL_TEXTURE_ZOFFSET_KHR,
1598 static_cast<EGLint>(0),
1599 EGL_IMAGE_PRESERVED,
1600 EGL_TRUE,
1601 EGL_GL_COLORSPACE,
1602 EGL_GL_COLORSPACE_SRGB_KHR,
1603 EGL_NONE,
1604 };
1605 GLuint mTextureProgram;
1606 GLuint m2DArrayTextureProgram;
1607 GLuint m3DTextureProgram;
1608 GLuint mCubeTextureProgram;
1609 GLuint mCubeArrayTextureProgram;
1610 GLint mTextureUniformLocation;
1611 GLuint m2DArrayTextureUniformLocation;
1612 GLuint m2DArrayTextureLayerUniformLocation;
1613 GLuint m3DTextureUniformLocation;
1614 GLuint m3DTextureLayerUniformLocation;
1615 GLuint mCubeTextureUniformLocation;
1616 GLuint mCubeTextureFaceCoordUniformLocation;
1617 GLuint mCubeArrayTextureUniformLocation;
1618 GLuint mCubeArrayTextureFaceCoordUniformLocation;
1619 GLuint mCubeArrayTextureLayerUniformLocation;
1620
1621 GLuint mTextureExternalProgram = 0;
1622 GLint mTextureExternalUniformLocation = -1;
1623
1624 GLuint mTextureExternalESSL3Program = 0;
1625 GLint mTextureExternalESSL3UniformLocation = -1;
1626
1627 GLuint mTextureYUVProgram = 0;
1628 GLint mTextureYUVUniformLocation = -1;
1629
1630 GLuint mTextureYUVVSProgram = 0;
1631 GLint mTextureYUVVSUniformLocation = -1;
1632
1633 GLuint mRenderYUVProgram = 0;
1634 GLint mRenderYUVUniformLocation = -1;
1635
1636 CounterNameToIndexMap mCounterNameToIndexMap;
1637 };
1638
1639 class ImageTestES3 : public ImageTest
1640 {};
1641
1642 class ImageTestES31 : public ImageTest
1643 {};
1644
1645 // Tests that the extension is exposed on the platforms we think it should be. Please modify this as
1646 // you change extension availability.
TEST_P(ImageTest,ANGLEExtensionAvailability)1647 TEST_P(ImageTest, ANGLEExtensionAvailability)
1648 {
1649 // EGL support is based on driver extension availability.
1650 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());
1651 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsOzone());
1652
1653 if (IsD3D11() || IsD3D9())
1654 {
1655 EXPECT_TRUE(hasOESExt());
1656 EXPECT_TRUE(hasExternalExt());
1657 EXPECT_TRUE(hasBaseExt());
1658 EXPECT_TRUE(has2DTextureExt());
1659 EXPECT_TRUE(hasRenderbufferExt());
1660 EXPECT_FALSE(has3DTextureExt());
1661
1662 if (IsD3D11())
1663 {
1664 EXPECT_TRUE(hasCubemapExt());
1665
1666 if (getClientMajorVersion() >= 3)
1667 {
1668 EXPECT_TRUE(hasExternalESSL3Ext());
1669 }
1670 else
1671 {
1672 EXPECT_FALSE(hasExternalESSL3Ext());
1673 }
1674 }
1675 else
1676 {
1677 EXPECT_FALSE(hasCubemapExt());
1678 EXPECT_FALSE(hasExternalESSL3Ext());
1679 }
1680 }
1681 else if (IsVulkan())
1682 {
1683 EXPECT_TRUE(hasOESExt());
1684 EXPECT_TRUE(hasExternalExt());
1685 EXPECT_TRUE(hasBaseExt());
1686 EXPECT_TRUE(has2DTextureExt());
1687 EXPECT_TRUE(hasCubemapExt());
1688 EXPECT_TRUE(hasRenderbufferExt());
1689 if (getClientMajorVersion() >= 3)
1690 {
1691 EXPECT_TRUE(hasExternalESSL3Ext());
1692 }
1693 else
1694 {
1695 EXPECT_FALSE(hasExternalESSL3Ext());
1696 }
1697 }
1698 else if (IsMetal())
1699 {
1700 // NOTE(hqle): Metal currently doesn't implement any image extensions besides
1701 // EGL_ANGLE_metal_texture_client_buffer
1702 EXPECT_TRUE(hasOESExt());
1703 EXPECT_TRUE(hasBaseExt());
1704 EXPECT_FALSE(hasExternalExt());
1705 EXPECT_FALSE(hasExternalESSL3Ext());
1706 EXPECT_FALSE(has2DTextureExt());
1707 EXPECT_FALSE(has3DTextureExt());
1708 EXPECT_FALSE(hasRenderbufferExt());
1709 }
1710 else
1711 {
1712 EXPECT_FALSE(hasOESExt());
1713 EXPECT_FALSE(hasExternalExt());
1714 EXPECT_FALSE(hasExternalESSL3Ext());
1715 EXPECT_FALSE(hasBaseExt());
1716 EXPECT_FALSE(has2DTextureExt());
1717 EXPECT_FALSE(has3DTextureExt());
1718 EXPECT_FALSE(hasRenderbufferExt());
1719 }
1720
1721 // These extensions are not yet available on any platform.
1722 EXPECT_FALSE(hasPixmapExt());
1723 }
1724
1725 // Check validation from the EGL_KHR_image_base extension
TEST_P(ImageTest,ValidationImageBase)1726 TEST_P(ImageTest, ValidationImageBase)
1727 {
1728 EGLWindow *window = getEGLWindow();
1729 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
1730
1731 GLTexture glTexture2D;
1732 glBindTexture(GL_TEXTURE_2D, glTexture2D);
1733 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1734
1735 EGLDisplay display = window->getDisplay();
1736 EGLContext context = window->getContext();
1737 EGLConfig config = window->getConfig();
1738 EGLImageKHR image = EGL_NO_IMAGE_KHR;
1739 EGLClientBuffer texture2D = reinterpretHelper<EGLClientBuffer>(glTexture2D);
1740
1741 // Test validation of eglCreateImageKHR
1742
1743 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
1744 // generated.
1745 image = eglCreateImageKHR(reinterpret_cast<EGLDisplay>(0xBAADF00D), context,
1746 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
1747 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1748 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
1749
1750 // If <ctx> is neither the handle of a valid EGLContext object on <dpy> nor EGL_NO_CONTEXT, the
1751 // error EGL_BAD_CONTEXT is generated.
1752 image = eglCreateImageKHR(display, reinterpret_cast<EGLContext>(0xBAADF00D),
1753 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
1754 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1755 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
1756
1757 // Test EGL_NO_CONTEXT with a 2D texture target which does require a context.
1758 image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
1759 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1760 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
1761
1762 // If an attribute specified in <attrib_list> is not one of the attributes listed in Table bbb,
1763 // the error EGL_BAD_PARAMETER is generated.
1764 EGLint badAttributes[] = {
1765 static_cast<EGLint>(0xDEADBEEF),
1766 0,
1767 EGL_NONE,
1768 };
1769
1770 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, badAttributes);
1771 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1772 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1773
1774 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> has an off -
1775 // screen buffer bound to it(e.g., by a
1776 // previous call to eglBindTexImage), the error EGL_BAD_ACCESS is generated.
1777 EGLint surfaceType = 0;
1778 eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
1779
1780 EGLint bindToTextureRGBA = 0;
1781 eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
1782 if ((surfaceType & EGL_PBUFFER_BIT) != 0 && bindToTextureRGBA == EGL_TRUE)
1783 {
1784 EGLint pbufferAttributes[] = {
1785 EGL_WIDTH, 1,
1786 EGL_HEIGHT, 1,
1787 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
1788 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
1789 EGL_NONE, EGL_NONE,
1790 };
1791 EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbufferAttributes);
1792 ASSERT_NE(pbuffer, EGL_NO_SURFACE);
1793 EXPECT_EGL_SUCCESS();
1794
1795 eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
1796 EXPECT_EGL_SUCCESS();
1797
1798 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
1799 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1800 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
1801
1802 eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
1803 eglDestroySurface(display, pbuffer);
1804 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1805 EXPECT_EGL_SUCCESS();
1806 EXPECT_GL_NO_ERROR();
1807 }
1808
1809 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and
1810 // <attrib_list> is itself an EGLImage sibling, the error EGL_BAD_ACCESS is generated.
1811 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
1812 EXPECT_NE(image, EGL_NO_IMAGE_KHR);
1813 EXPECT_EGL_SUCCESS();
1814
1815 /* TODO(geofflang): Enable this validation when it passes.
1816 EGLImageKHR image2 = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1817 reinterpret_cast<EGLClientBuffer>(texture2D), nullptr);
1818 EXPECT_EQ(image2, EGL_NO_IMAGE_KHR);
1819 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
1820 */
1821
1822 // Test validation of eglDestroyImageKHR
1823 // Note: image is now a valid EGL image
1824 EGLBoolean result = EGL_FALSE;
1825
1826 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
1827 // generated.
1828 result = eglDestroyImageKHR(reinterpret_cast<EGLDisplay>(0xBAADF00D), image);
1829 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
1830 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
1831
1832 // If <image> is not a valid EGLImageKHR object created with respect to <dpy>, the error
1833 // EGL_BAD_PARAMETER is generated.
1834 result = eglDestroyImageKHR(display, reinterpret_cast<EGLImageKHR>(0xBAADF00D));
1835 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
1836 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1837
1838 // Clean up and validate image is destroyed
1839 result = eglDestroyImageKHR(display, image);
1840 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_TRUE));
1841 EXPECT_EGL_SUCCESS();
1842
1843 EXPECT_GL_NO_ERROR();
1844 }
1845
1846 // Check validation from the EGL_KHR_gl_texture_2D_image, EGL_KHR_gl_texture_cubemap_image,
1847 // EGL_KHR_gl_texture_3D_image and EGL_KHR_gl_renderbuffer_image extensions
TEST_P(ImageTest,ValidationGLImage)1848 TEST_P(ImageTest, ValidationGLImage)
1849 {
1850 EGLWindow *window = getEGLWindow();
1851 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt());
1852
1853 EGLDisplay display = window->getDisplay();
1854 EGLContext context = window->getContext();
1855 EGLImageKHR image = EGL_NO_IMAGE_KHR;
1856
1857 if (has2DTextureExt())
1858 {
1859 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR or
1860 // EGL_GL_TEXTURE_3D_KHR and <buffer> is not the name of a texture object of type <target>,
1861 // the error EGL_BAD_PARAMETER is generated.
1862 GLTexture textureCube;
1863 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
1864 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1865 face++)
1866 {
1867 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1868 }
1869
1870 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1871 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
1872 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1873 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1874
1875 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR,
1876 // EGL_GL_TEXTURE_CUBE_MAP_*_KHR or EGL_GL_TEXTURE_3D_KHR, <buffer> is the name of an
1877 // incomplete GL texture object, and any mipmap levels other than mipmap level 0 are
1878 // specified, the error EGL_BAD_PARAMETER is generated.
1879 GLTexture incompleteTexture;
1880 glBindTexture(GL_TEXTURE_2D, incompleteTexture);
1881 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1882 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1883
1884 EGLint level0Attribute[] = {
1885 EGL_GL_TEXTURE_LEVEL_KHR,
1886 0,
1887 EGL_NONE,
1888 };
1889 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1890 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
1891 level0Attribute);
1892 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1893 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1894
1895 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR or
1896 // EGL_GL_TEXTURE_3D_KHR, <buffer> is not the name of a complete GL texture object, and
1897 // mipmap level 0 is not specified, the error EGL_BAD_PARAMETER is generated.
1898 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1899 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1900 reinterpretHelper<EGLClientBuffer>(incompleteTexture), nullptr);
1901 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1902 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1903
1904 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR,
1905 // EGL_GL_RENDERBUFFER_KHR or EGL_GL_TEXTURE_3D_KHR and <buffer> refers to the default GL
1906 // texture object(0) for the corresponding GL target, the error EGL_BAD_PARAMETER is
1907 // generated.
1908 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, 0, nullptr);
1909 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1910 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1911
1912 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR, or
1913 // EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
1914 // EGL_GL_TEXTURE_LEVEL_KHR is not a valid mipmap level for the specified GL texture object
1915 // <buffer>, the error EGL_BAD_MATCH is generated.
1916 EGLint level2Attribute[] = {
1917 EGL_GL_TEXTURE_LEVEL_KHR,
1918 2,
1919 EGL_NONE,
1920 };
1921 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1922 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
1923 level2Attribute);
1924 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1925 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1926 }
1927 else
1928 {
1929 GLTexture texture2D;
1930 glBindTexture(GL_TEXTURE_2D, texture2D);
1931 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1932
1933 // From EGL_KHR_image_base:
1934 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
1935 // generated.
1936 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
1937 reinterpretHelper<EGLClientBuffer>(texture2D), nullptr);
1938 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1939 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1940 }
1941
1942 if (hasCubemapExt())
1943 {
1944 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_CUBE_MAP_*_KHR, <buffer> is
1945 // not the name of a complete GL texture object, and one or more faces do not have mipmap
1946 // level 0 specified, the error EGL_BAD_PARAMETER is generated.
1947 GLTexture incompleteTextureCube;
1948 glBindTexture(GL_TEXTURE_CUBE_MAP, incompleteTextureCube);
1949 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1950 nullptr);
1951 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1952 nullptr);
1953 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1954 nullptr);
1955 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1956 nullptr);
1957 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1958 nullptr);
1959
1960 EGLint level0Attribute[] = {
1961 EGL_GL_TEXTURE_LEVEL_KHR,
1962 0,
1963 EGL_NONE,
1964 };
1965 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
1966 reinterpretHelper<EGLClientBuffer>(incompleteTextureCube),
1967 level0Attribute);
1968 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1969 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1970 }
1971 else
1972 {
1973 GLTexture textureCube;
1974 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
1975 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1976 face++)
1977 {
1978 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1979 }
1980
1981 // From EGL_KHR_image_base:
1982 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
1983 // generated.
1984 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
1985 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
1986 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1987 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1988 }
1989
1990 if (has3DTextureExt() && getClientMajorVersion() >= 3)
1991 {
1992 // If <target> is EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
1993 // EGL_GL_TEXTURE_ZOFFSET_KHR exceeds the depth of the specified mipmap level - of - detail
1994 // in <buffer>, the error EGL_BAD_PARAMETER is generated.
1995 GLTexture texture3D;
1996 glBindTexture(GL_TEXTURE_3D, texture3D);
1997 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1998
1999 EGLint zOffset3Parameter[] = {
2000 EGL_GL_TEXTURE_ZOFFSET_KHR,
2001 3,
2002 EGL_NONE,
2003 };
2004 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
2005 reinterpretHelper<EGLClientBuffer>(texture3D), zOffset3Parameter);
2006 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2007 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2008
2009 EGLint zOffsetNegative1Parameter[] = {
2010 EGL_GL_TEXTURE_ZOFFSET_KHR,
2011 -1,
2012 EGL_NONE,
2013 };
2014 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
2015 reinterpretHelper<EGLClientBuffer>(texture3D),
2016 zOffsetNegative1Parameter);
2017 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2018 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2019 }
2020 else
2021 {
2022 if (has2DTextureExt())
2023 {
2024 GLTexture texture2D;
2025 glBindTexture(GL_TEXTURE_2D, texture2D);
2026 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2027
2028 // Verify EGL_GL_TEXTURE_ZOFFSET_KHR is not a valid parameter
2029 EGLint zOffset0Parameter[] = {
2030 EGL_GL_TEXTURE_ZOFFSET_KHR,
2031 0,
2032 EGL_NONE,
2033 };
2034
2035 image =
2036 eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
2037 reinterpretHelper<EGLClientBuffer>(texture2D), zOffset0Parameter);
2038 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2039 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2040 }
2041
2042 if (getClientMajorVersion() >= 3)
2043 {
2044 GLTexture texture3D;
2045 glBindTexture(GL_TEXTURE_3D, texture3D);
2046 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
2047
2048 // From EGL_KHR_image_base:
2049 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
2050 // generated.
2051 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
2052 reinterpretHelper<EGLClientBuffer>(texture3D), nullptr);
2053 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2054 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2055 }
2056 }
2057
2058 if (hasRenderbufferExt())
2059 {
2060 // If <target> is EGL_GL_RENDERBUFFER_KHR and <buffer> is not the name of a renderbuffer
2061 // object, or if <buffer> is the name of a multisampled renderbuffer object, the error
2062 // EGL_BAD_PARAMETER is generated.
2063 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
2064 reinterpret_cast<EGLClientBuffer>(0), nullptr);
2065 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2066 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2067
2068 if (IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample"))
2069 {
2070 GLRenderbuffer renderbuffer;
2071 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
2072 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
2073 EXPECT_GL_NO_ERROR();
2074
2075 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
2076 reinterpret_cast<EGLClientBuffer>(0), nullptr);
2077 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2078 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2079 }
2080 }
2081 else
2082 {
2083 GLRenderbuffer renderbuffer;
2084 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
2085 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
2086
2087 // From EGL_KHR_image_base:
2088 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
2089 // generated.
2090 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
2091 reinterpretHelper<EGLClientBuffer>(renderbuffer), nullptr);
2092 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2093 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
2094 }
2095 }
2096
2097 // Check validation from the GL_OES_EGL_image extension
TEST_P(ImageTest,ValidationGLEGLImage)2098 TEST_P(ImageTest, ValidationGLEGLImage)
2099 {
2100 ValidationGLEGLImage_helper(kDefaultAttribs);
2101 }
2102
TEST_P(ImageTest,ValidationGLEGLImage_Colorspace)2103 TEST_P(ImageTest, ValidationGLEGLImage_Colorspace)
2104 {
2105 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2106 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2107 ValidationGLEGLImage_helper(kColorspaceAttribs);
2108 }
2109
ValidationGLEGLImage_helper(const EGLint * attribs)2110 void ImageTest::ValidationGLEGLImage_helper(const EGLint *attribs)
2111 {
2112 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2113
2114 // Create the Image
2115 GLTexture source;
2116 EGLImageKHR image;
2117 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kLinearColor, source,
2118 &image);
2119
2120 // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
2121 glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
2122 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2123
2124 // If <image> does not refer to a valid eglImageOES object, the error INVALID_VALUE is
2125 // generated.
2126 GLTexture texture;
2127 glBindTexture(GL_TEXTURE_2D, texture);
2128 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, reinterpret_cast<GLeglImageOES>(0xBAADF00D));
2129 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2130
2131 // <target> must be RENDERBUFFER_OES, and <image> must be the handle of a valid EGLImage
2132 // resource, cast into the type
2133 // eglImageOES.
2134 glEGLImageTargetRenderbufferStorageOES(GL_TEXTURE_2D, image);
2135 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2136
2137 // If a renderbuffer is not bound, the error INVALID_OPERATION is generated.
2138 // (Not in specification.)
2139 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
2140 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2141
2142 // If the GL is unable to create a renderbuffer using the specified eglImageOES, the error
2143 // INVALID_OPERATION is generated.If <image>
2144 // does not refer to a valid eglImageOES object, the error INVALID_VALUE is generated.
2145 GLRenderbuffer renderbuffer;
2146 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
2147 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
2148 reinterpret_cast<GLeglImageOES>(0xBAADF00D));
2149 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2150
2151 // Clean up
2152 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image);
2153 }
2154
2155 // Check validation from the GL_OES_EGL_image_external extension
TEST_P(ImageTest,ValidationGLEGLImageExternal)2156 TEST_P(ImageTest, ValidationGLEGLImageExternal)
2157 {
2158 ANGLE_SKIP_TEST_IF(!hasExternalExt());
2159
2160 GLTexture texture;
2161 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
2162
2163 // In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
2164 // TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
2165 // to CLAMP_TO_EDGE
2166 auto getTexParam = [](GLenum target, GLenum pname) {
2167 GLint value = 0;
2168 glGetTexParameteriv(target, pname, &value);
2169 EXPECT_GL_NO_ERROR();
2170 return value;
2171 };
2172 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
2173 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
2174 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
2175 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
2176
2177 // "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
2178 // TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
2179 // only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
2180 // TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
2181 // INVALID_ENUM error.
2182 GLenum validMinFilters[]{
2183 GL_NEAREST,
2184 GL_LINEAR,
2185 };
2186 for (auto minFilter : validMinFilters)
2187 {
2188 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
2189 EXPECT_GL_NO_ERROR();
2190 }
2191
2192 GLenum invalidMinFilters[]{
2193 GL_NEAREST_MIPMAP_LINEAR,
2194 GL_NEAREST_MIPMAP_NEAREST,
2195 GL_LINEAR_MIPMAP_LINEAR,
2196 GL_LINEAR_MIPMAP_NEAREST,
2197 };
2198 for (auto minFilter : invalidMinFilters)
2199 {
2200 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
2201 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2202 }
2203
2204 GLenum validWrapModes[]{
2205 GL_CLAMP_TO_EDGE,
2206 };
2207 for (auto wrapMode : validWrapModes)
2208 {
2209 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
2210 EXPECT_GL_NO_ERROR();
2211 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
2212 EXPECT_GL_NO_ERROR();
2213 }
2214
2215 if (IsGLExtensionEnabled("GL_EXT_EGL_image_external_wrap_modes"))
2216 {
2217 GLenum validWrapModesEXT[]{GL_REPEAT, GL_MIRRORED_REPEAT};
2218 for (auto wrapMode : validWrapModesEXT)
2219 {
2220 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
2221 EXPECT_GL_NO_ERROR();
2222 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
2223 EXPECT_GL_NO_ERROR();
2224 }
2225 }
2226 else
2227 {
2228 GLenum invalidWrapModes[]{
2229 GL_REPEAT,
2230 GL_MIRRORED_REPEAT,
2231 };
2232 for (auto wrapMode : invalidWrapModes)
2233 {
2234 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
2235 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2236 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
2237 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2238 }
2239 }
2240
2241 // When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
2242 // INVALID_ENUM error.
2243 glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
2244 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2245 }
2246
2247 // Check validation from the GL_OES_EGL_image_external_essl3 extension
TEST_P(ImageTest,ValidationGLEGLImageExternalESSL3)2248 TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
2249 {
2250 ANGLE_SKIP_TEST_IF(!hasExternalESSL3Ext());
2251
2252 // Make sure this extension is not exposed without ES3.
2253 ASSERT_GE(getClientMajorVersion(), 3);
2254
2255 GLTexture texture;
2256 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
2257
2258 // It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
2259 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
2260 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2261
2262 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
2263 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2264
2265 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
2266 EXPECT_GL_NO_ERROR();
2267 }
2268
2269 // Check validation from the GL_EXT_EGL_image_storage extension
TEST_P(ImageTest,ValidationGLEGLImageStorage)2270 TEST_P(ImageTest, ValidationGLEGLImageStorage)
2271 {
2272 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
2273
2274 // Make sure this extension is not exposed without ES3.
2275 ASSERT_GE(getClientMajorVersion(), 3);
2276
2277 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2278
2279 // Create the Image
2280 GLTexture source2D;
2281 EGLImageKHR image2D;
2282 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, kLinearColor,
2283 source2D, &image2D);
2284
2285 // <target> must be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D,
2286 // GL_TEXTURE_CUBE_MAP, GL_TEXTURE_CUBE_MAP_ARRAY. On OpenGL implementations
2287 // (non-ES), <target> can also be GL_TEXTURE_1D or GL_TEXTURE_1D_ARRAY.
2288 // If the implementation supports OES_EGL_image_external, <target> can be
2289 // GL_TEXTURE_EXTERNAL_OES
2290 glEGLImageTargetTexStorageEXT(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image2D, nullptr);
2291 EXPECT_GL_ERROR(GL_INVALID_ENUM);
2292
2293 // If <image> is NULL, the error INVALID_VALUE is generated. If <image> is
2294 // neither NULL nor a valid value, the behavior is undefined, up to and
2295 // including program termination.
2296 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, nullptr, nullptr);
2297 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2298
2299 // If the GL is unable to specify a texture object using the supplied
2300 // eglImageOES <image> the error INVALID_OPERATION is generated.
2301 glEGLImageTargetTexStorageEXT(GL_TEXTURE_3D, image2D, nullptr);
2302 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2303
2304 GLint nonNullAttrib[1] = {GL_TEXTURE_2D};
2305
2306 // If <attrib_list> is neither NULL nor a pointer to the value GL_NONE, the
2307 // error INVALID_VALUE is generated.
2308 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, image2D, nonNullAttrib);
2309 EXPECT_GL_ERROR(GL_INVALID_VALUE);
2310
2311 // Clean up
2312 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image2D);
2313 }
2314
TEST_P(ImageTest,Source2DTarget2D)2315 TEST_P(ImageTest, Source2DTarget2D)
2316 {
2317 Source2DTarget2D_helper(kDefaultAttribs);
2318 }
2319
TEST_P(ImageTest,Source2DTarget2D_Colorspace)2320 TEST_P(ImageTest, Source2DTarget2D_Colorspace)
2321 {
2322 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2323 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2324 Source2DTarget2D_helper(kColorspaceAttribs);
2325 }
2326
Source2DTarget2D_helper(const EGLint * attribs)2327 void ImageTest::Source2DTarget2D_helper(const EGLint *attribs)
2328 {
2329 EGLWindow *window = getEGLWindow();
2330 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2331
2332 // Create the Image
2333 GLTexture source;
2334 EGLImageKHR image;
2335 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs,
2336 static_cast<void *>(kSrgbColor), source, &image);
2337
2338 // Create the target
2339 GLTexture target;
2340 createEGLImageTargetTexture2D(image, target);
2341
2342 // Verify that the target texture has the expected color
2343 verifyResults2D(target, getExpected2DColorForAttribList(attribs));
2344
2345 // Clean up
2346 eglDestroyImageKHR(window->getDisplay(), image);
2347 }
2348
ImageStorageGenerateMipmap_helper(const EGLint * attribs,const GLsizei width,const GLsizei height,AHardwareBuffer * srcAhb,GLuint srcTexture,EGLImageKHR * imageOut)2349 void ImageTest::ImageStorageGenerateMipmap_helper(const EGLint *attribs,
2350 const GLsizei width,
2351 const GLsizei height,
2352 AHardwareBuffer *srcAhb,
2353 GLuint srcTexture,
2354 EGLImageKHR *imageOut)
2355 {
2356 ASSERT(srcAhb != nullptr || glIsTexture(srcTexture));
2357
2358 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2359 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2360
2361 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2362 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
2363
2364 constexpr int kNumTiles = 8;
2365 const int tileWidth = width / kNumTiles;
2366 const int tileHeight = height / kNumTiles;
2367
2368 // Create EGLImage and then a target texture from that image
2369 EGLWindow *window = getEGLWindow();
2370 if (srcAhb != nullptr)
2371 {
2372 *imageOut =
2373 eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
2374 angle::android::AHardwareBufferToClientBuffer(srcAhb), attribs);
2375 }
2376 else
2377 {
2378 *imageOut =
2379 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
2380 reinterpret_cast<EGLClientBuffer>(srcTexture), attribs);
2381 }
2382 ASSERT_EGL_SUCCESS();
2383
2384 GLTexture dstTexture;
2385 glBindTexture(GL_TEXTURE_2D, dstTexture);
2386 // Setup for mipmapping
2387 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2388 ASSERT_GL_NO_ERROR();
2389
2390 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, *imageOut, nullptr);
2391 ASSERT_GL_NO_ERROR();
2392
2393 // Create framebuffer, attach level 0 of target texture and render pattern
2394 GLFramebuffer fbo;
2395 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2396 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstTexture, 0);
2397 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2398 glEnable(GL_SCISSOR_TEST);
2399 for (int i = 0; i < kNumTiles; ++i)
2400 {
2401 for (int j = 0; j < kNumTiles; ++j)
2402 {
2403 const float v = (i & 1) ^ (j & 1) ? 0.5f : 0.f;
2404 glClearColor(v, 0.f, v, v);
2405 glScissor(i * tileWidth, j * tileHeight, tileWidth, tileHeight);
2406 glClear(GL_COLOR_BUFFER_BIT);
2407 }
2408 }
2409 glDisable(GL_SCISSOR_TEST);
2410
2411 // Generate mipmap for target texture
2412 glGenerateMipmap(GL_TEXTURE_2D);
2413 }
2414
verifyImageStorageMipmap(const EGLint * attribs,EGLImageKHR image,const GLsizei mipLevelCount)2415 void ImageTest::verifyImageStorageMipmap(const EGLint *attribs,
2416 EGLImageKHR image,
2417 const GLsizei mipLevelCount)
2418 {
2419 if (image == EGL_NO_IMAGE_KHR)
2420 {
2421 // Early return if image isn't valid
2422 return;
2423 }
2424
2425 GLubyte linearColor[] = {64, 0, 64, 64};
2426 GLubyte srgbColor[] = {137, 0, 137, 64};
2427 GLubyte *expectedColor =
2428 attribListHasSrgbColorspace(attribs, kColorspaceAttributeIndex) ? srgbColor : linearColor;
2429
2430 GLTexture targetTexture;
2431 glBindTexture(GL_TEXTURE_2D, targetTexture);
2432 // Setup for mipmapping
2433 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2434 ASSERT_GL_NO_ERROR();
2435
2436 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, image, nullptr);
2437 ASSERT_GL_NO_ERROR();
2438
2439 // Create target framebuffer, attach "(mipLevelCount - 1)" level of target texture and verify
2440 // data
2441 GLFramebuffer fbo;
2442 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2443 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture,
2444 mipLevelCount - 1);
2445 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2446 EXPECT_PIXEL_NEAR(0, 0, expectedColor[0], expectedColor[1], expectedColor[2], expectedColor[3],
2447 1);
2448
2449 // Verify that the target texture generates linear color when sampled
2450 glActiveTexture(GL_TEXTURE0);
2451 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2452 glBindTexture(GL_TEXTURE_2D, targetTexture);
2453 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, mipLevelCount - 1);
2454 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mipLevelCount - 1);
2455 ASSERT_GL_NO_ERROR();
2456
2457 verifyResults2D(targetTexture, linearColor);
2458 }
2459
verifyImageStorageMipmapWithBlend(const EGLint * attribs,EGLImageKHR image,const GLsizei mipLevelCount)2460 void ImageTest::verifyImageStorageMipmapWithBlend(const EGLint *attribs,
2461 EGLImageKHR image,
2462 const GLsizei mipLevelCount)
2463 {
2464 if (image == EGL_NO_IMAGE_KHR)
2465 {
2466 // Early return if image isn't valid
2467 return;
2468 }
2469
2470 // Need to have at least miplevel 1
2471 ASSERT(mipLevelCount >= 1);
2472 // Verification used by only those tests with colorspace overrides
2473 ASSERT(attribListHasSrgbColorspace(attribs, kColorspaceAttributeIndex));
2474
2475 GLTexture targetTexture;
2476 glBindTexture(GL_TEXTURE_2D, targetTexture);
2477 // Setup for mipmapping
2478 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
2479 ASSERT_GL_NO_ERROR();
2480
2481 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, image, nullptr);
2482 ASSERT_GL_NO_ERROR();
2483
2484 // Create target framebuffer, attach mipLevel == 1 of target texture and verify
2485 // data with blending enabled.
2486 GLFramebuffer fbo;
2487 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2488 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, targetTexture, 1);
2489 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2490
2491 // Blend green color with contents of mipLevel 1
2492 // source color at (7, 11) of mipLevel 1 = [137, 0, 137, 64]
2493 GLubyte blendedColor[] = {137, 255, 137, 255};
2494 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2495 glUseProgram(program);
2496 glEnable(GL_BLEND);
2497 glBlendFunc(GL_ONE, GL_ONE);
2498 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2499
2500 EXPECT_PIXEL_NEAR(7, 11, blendedColor[0], blendedColor[1], blendedColor[2], blendedColor[3], 1);
2501 }
2502
SourceAHBTarget2DImageStorageGenerateMipmap_helper(const EGLint * attribs)2503 void ImageTest::SourceAHBTarget2DImageStorageGenerateMipmap_helper(const EGLint *attribs)
2504 {
2505 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2506
2507 constexpr GLsizei kWidth = 40;
2508 constexpr GLsizei kHeight = 32;
2509 constexpr GLsizei kDepth = 1;
2510 const GLsizei mipLevelCount = static_cast<GLsizei>(std::log2(std::max(kWidth, kHeight)) + 1);
2511
2512 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
2513 kWidth, kHeight, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2514 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete));
2515
2516 // Create source AHB
2517 AHardwareBuffer *aHardwareBuffer =
2518 createAndroidHardwareBuffer(kWidth, kHeight, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2519 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete, {});
2520 EXPECT_NE(aHardwareBuffer, nullptr);
2521
2522 EGLImageKHR image = EGL_NO_IMAGE_KHR;
2523 ImageStorageGenerateMipmap_helper(attribs, kWidth, kHeight, aHardwareBuffer, 0, &image);
2524 verifyImageStorageMipmap(attribs, image, mipLevelCount);
2525
2526 // Clean up image
2527 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image);
2528
2529 // Clean up AHB
2530 destroyAndroidHardwareBuffer(aHardwareBuffer);
2531 }
2532
2533 // Test interaction between AHB, GL_EXT_EGL_image_storage and glGenerateMipmap
TEST_P(ImageTestES3,SourceAHBTarget2DGenerateMipmap)2534 TEST_P(ImageTestES3, SourceAHBTarget2DGenerateMipmap)
2535 {
2536 SourceAHBTarget2DImageStorageGenerateMipmap_helper(kDefaultAttribs);
2537 }
2538
2539 // Test interaction between AHB, GL_EXT_EGL_image_storage and glGenerateMipmap with colorspace
2540 // overrides This mirrors the SingleLayer_ColorTest_MipmapComplete_R8G8B8A8_UNORM_sRGB Android CTS
2541 // test
TEST_P(ImageTestES3,SourceAHBTarget2DGenerateMipmap_Colorspace)2542 TEST_P(ImageTestES3, SourceAHBTarget2DGenerateMipmap_Colorspace)
2543 {
2544 SourceAHBTarget2DImageStorageGenerateMipmap_helper(kColorspaceAttribs);
2545 }
2546
2547 // Test to ensure that Vulkan backend's LOAD_OP is correct for non-0 miplevels. A bug in
2548 // content tracking of mip levels will cause rendering artifacts and result in test failure.
TEST_P(ImageTestES3,SourceAHBTarget2DGenerateMipmapColorspaceBlend)2549 TEST_P(ImageTestES3, SourceAHBTarget2DGenerateMipmapColorspaceBlend)
2550 {
2551 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2552
2553 constexpr GLsizei kWidth = 40;
2554 constexpr GLsizei kHeight = 32;
2555 constexpr GLsizei kDepth = 1;
2556 const GLsizei mipLevelCount = static_cast<GLsizei>(std::log2(std::max(kWidth, kHeight)) + 1);
2557
2558 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
2559 kWidth, kHeight, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2560 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete));
2561
2562 // Create source AHB
2563 AHardwareBuffer *aHardwareBuffer =
2564 createAndroidHardwareBuffer(kWidth, kHeight, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2565 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete, {});
2566 EXPECT_NE(aHardwareBuffer, nullptr);
2567
2568 EGLImageKHR image = EGL_NO_IMAGE_KHR;
2569 ImageStorageGenerateMipmap_helper(kColorspaceAttribs, kWidth, kHeight, aHardwareBuffer, 0,
2570 &image);
2571 verifyImageStorageMipmapWithBlend(kColorspaceAttribs, image, mipLevelCount);
2572
2573 // Clean up image
2574 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image);
2575
2576 // Clean up AHB
2577 destroyAndroidHardwareBuffer(aHardwareBuffer);
2578 }
2579
2580 // Test that drawing to an AHB works.
TEST_P(ImageTestES3,SourceAHBTarget2DDraw)2581 TEST_P(ImageTestES3, SourceAHBTarget2DDraw)
2582 {
2583 EGLWindow *window = getEGLWindow();
2584
2585 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2586 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2587
2588 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
2589 AHardwareBuffer *source;
2590 EGLImageKHR image;
2591 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2592 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
2593 &image);
2594
2595 // Create a texture target to bind the egl image
2596 GLTexture target;
2597 createEGLImageTargetTexture2D(image, target);
2598
2599 // Draw to the target and verify results.
2600 GLFramebuffer fbo;
2601 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2602 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
2603 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2604
2605 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
2606 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
2607 ASSERT_GL_NO_ERROR();
2608
2609 // Verify results for completeness.
2610 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
2611
2612 // Clean up
2613 eglDestroyImageKHR(window->getDisplay(), image);
2614 destroyAndroidHardwareBuffer(source);
2615 }
2616
2617 // Test that using an image through a texture, detaching it, then using it again with another
2618 // texture works. This is similar to the usage pattern of |SourceAHBTarget2DGenerateMipmap|, but
2619 // doesn't require the |kAHBUsageGPUMipMapComplete| flags.
TEST_P(ImageTestES3,SourceAHBTarget2DUseAfterDetach)2620 TEST_P(ImageTestES3, SourceAHBTarget2DUseAfterDetach)
2621 {
2622 EGLWindow *window = getEGLWindow();
2623
2624 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2625 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2626
2627 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
2628 AHardwareBuffer *source;
2629 EGLImageKHR image;
2630 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
2631 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
2632 &image);
2633
2634 // Create a texture target to bind the egl image
2635 GLTexture target;
2636 createEGLImageTargetTexture2D(image, target);
2637
2638 // Clear the texture, use a temporary framebuffer.
2639 {
2640 GLFramebuffer fbo;
2641 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2642 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
2643 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
2644 glClearColor(1, 0, 0, 1);
2645 glClear(GL_COLOR_BUFFER_BIT);
2646 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2647 }
2648
2649 // Use the texture in a command buffer, but don't let it get submitted (use the default
2650 // framebuffer).
2651 ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
2652 GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform());
2653 ASSERT_NE(-1, texLocation);
2654 glUseProgram(drawTexture);
2655 glUniform1i(texLocation, 0);
2656 ASSERT_GL_NO_ERROR();
2657
2658 glBindTexture(GL_TEXTURE_2D, target);
2659 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2660
2661 // Release the texture. In the Vulkan backend, the image is scheduled to be transitioned to the
2662 // FORIENG queue because this is an AHB.
2663 glBindTexture(GL_TEXTURE_2D, 0);
2664 target.reset();
2665
2666 // Now attach another texture to the same image.
2667 GLTexture target2;
2668 glBindTexture(GL_TEXTURE_2D, target2);
2669 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
2670 ASSERT_GL_NO_ERROR();
2671
2672 // Use the new texture. In the Vulkan backend, the management of transfer to FOREIGN queue and
2673 // back should be correct.
2674 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
2675 ASSERT_GL_NO_ERROR();
2676
2677 // Verify results for completeness.
2678 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
2679
2680 // Clean up
2681 eglDestroyImageKHR(window->getDisplay(), image);
2682 destroyAndroidHardwareBuffer(source);
2683 }
2684
2685 // Try to orphan image created with the GL_EXT_EGL_image_storage extension
TEST_P(ImageTestES3,Source2DTarget2DStorageOrphan)2686 TEST_P(ImageTestES3, Source2DTarget2DStorageOrphan)
2687 {
2688 EGLWindow *window = getEGLWindow();
2689 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2690 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
2691
2692 // Create the Image
2693 GLTexture source;
2694 EGLImageKHR image;
2695 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2696 static_cast<void *>(&kLinearColor), source, &image);
2697
2698 // Create the target
2699 GLTexture target;
2700 createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, target, nullptr);
2701
2702 // Expect that the target texture has the same color as the source texture
2703 verifyResults2D(target, kLinearColor);
2704
2705 // Try to orphan this target texture
2706 glBindTexture(GL_TEXTURE_2D, target);
2707 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kLinearColor);
2708 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2709
2710 // Clean up
2711 eglDestroyImageKHR(window->getDisplay(), image);
2712 }
2713
2714 // Try to orphan 3D image created with the GL_EXT_EGL_image_storage extension
TEST_P(ImageTestES3,Source3DTarget3DStorageOrphan)2715 TEST_P(ImageTestES3, Source3DTarget3DStorageOrphan)
2716 {
2717 EGLWindow *window = getEGLWindow();
2718 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
2719 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
2720
2721 constexpr size_t depth = 2;
2722 EGLint attribs[3] = {EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE};
2723
2724 // Create the Image
2725 GLTexture source;
2726 EGLImageKHR image;
2727
2728 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs,
2729 static_cast<void *>(&kLinearColor), source, &image);
2730
2731 // Create the target
2732 GLTexture target;
2733 createEGLImageTargetTextureStorage(image, GL_TEXTURE_3D, target, nullptr);
2734
2735 for (size_t layer = 0; layer < depth; layer++)
2736 {
2737 // Expect that the target texture has the same color as the source texture
2738 verifyResults3D(target, kLinearColor);
2739 }
2740
2741 // Try to orphan this target texture
2742 glBindTexture(GL_TEXTURE_3D, target);
2743 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2744 kLinearColor);
2745 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
2746
2747 // Clean up
2748 eglDestroyImageKHR(window->getDisplay(), image);
2749 }
2750
2751 // Create target texture from EGL image and then trigger texture respecification.
TEST_P(ImageTest,Source2DTarget2DTargetTextureRespecifyColorspace)2752 TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifyColorspace)
2753 {
2754 EGLWindow *window = getEGLWindow();
2755 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2756 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_format_sRGB_override"));
2757
2758 // Create the Image
2759 GLTexture source;
2760 EGLImageKHR image;
2761 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2762 static_cast<void *>(&kSrgbColor), source, &image);
2763
2764 // Create the target
2765 GLTexture target;
2766 createEGLImageTargetTexture2D(image, target);
2767
2768 // Expect that the target texture has the same color as the source texture
2769 verifyResults2D(target, kSrgbColor);
2770
2771 // Respecify texture colorspace and verify results
2772 glBindTexture(GL_TEXTURE_2D, target);
2773 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_SRGB);
2774 ASSERT_GL_NO_ERROR();
2775 // Expect that the target texture decodes the sRGB color to linear when sampling
2776 verifyResults2D(target, kLinearColor);
2777
2778 // Reset texture parameter and verify results again
2779 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT, GL_NONE);
2780 ASSERT_GL_NO_ERROR();
2781 // Expect that the target texture has the same color as the source texture
2782 verifyResults2D(target, kSrgbColor);
2783
2784 // Clean up
2785 eglDestroyImageKHR(window->getDisplay(), image);
2786 }
2787
2788 // Create target texture from EGL image and then trigger texture respecification.
TEST_P(ImageTest,Source2DTarget2DTargetTextureRespecifySize)2789 TEST_P(ImageTest, Source2DTarget2DTargetTextureRespecifySize)
2790 {
2791 EGLWindow *window = getEGLWindow();
2792 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2793
2794 // Create the Image
2795 GLTexture source;
2796 EGLImageKHR image;
2797 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2798 static_cast<void *>(&kLinearColor), source, &image);
2799
2800 // Create the target
2801 GLTexture target;
2802 createEGLImageTargetTexture2D(image, target);
2803
2804 // Expect that the target texture has the same color as the source texture
2805 verifyResults2D(target, kLinearColor);
2806
2807 // Respecify texture size and verify results
2808 std::array<GLubyte, 16> referenceColor;
2809 referenceColor.fill(127);
2810 glBindTexture(GL_TEXTURE_2D, target);
2811 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2812 referenceColor.data());
2813 ASSERT_GL_NO_ERROR();
2814
2815 // Expect that the target texture has the reference color values
2816 verifyResults2D(target, referenceColor.data());
2817
2818 // Clean up
2819 eglDestroyImageKHR(window->getDisplay(), image);
2820 }
2821
2822 // Create target texture from EGL image and then trigger texture respecification.
TEST_P(ImageTestES3,Source2DTarget2DTargetTextureRespecifyLevel)2823 TEST_P(ImageTestES3, Source2DTarget2DTargetTextureRespecifyLevel)
2824 {
2825 EGLWindow *window = getEGLWindow();
2826 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2827
2828 // Create the Image
2829 GLTexture source;
2830 EGLImageKHR image;
2831 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2832 static_cast<void *>(&kLinearColor), source, &image);
2833
2834 // Create the target
2835 GLTexture target;
2836 createEGLImageTargetTexture2D(image, target);
2837
2838 // Expect that the target texture has the same color as the source texture
2839 verifyResults2D(target, kLinearColor);
2840
2841 // Respecify texture levels and verify results
2842 glBindTexture(GL_TEXTURE_2D, target);
2843 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
2844 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 4);
2845 ASSERT_GL_NO_ERROR();
2846
2847 // Expect that the target texture has the reference color values
2848 verifyResults2D(target, kLinearColor);
2849
2850 // Clean up
2851 eglDestroyImageKHR(window->getDisplay(), image);
2852 }
2853
2854 // Create target texture from EGL image and then trigger texture respecification which releases the
2855 // last image ref.
TEST_P(ImageTest,ImageOrphanRefCountingBug)2856 TEST_P(ImageTest, ImageOrphanRefCountingBug)
2857 {
2858 EGLWindow *window = getEGLWindow();
2859 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2860
2861 // Create the first Image
2862 GLTexture source1;
2863 EGLImageKHR image1;
2864 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2865 static_cast<void *>(&kLinearColor), source1, &image1);
2866
2867 // Create the target
2868 GLTexture target;
2869 createEGLImageTargetTexture2D(image1, target);
2870
2871 // Delete the source and image. A ref is still held by the target texture
2872 source1.reset();
2873 eglDestroyImageKHR(window->getDisplay(), image1);
2874
2875 // Create the second Image
2876 GLTexture source2;
2877 EGLImageKHR image2;
2878 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
2879 static_cast<void *>(&kLinearColor), source2, &image2);
2880
2881 // Respecify the target with the second image.
2882 glBindTexture(GL_TEXTURE_2D, target);
2883 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image2);
2884
2885 // Clean up
2886 eglDestroyImageKHR(window->getDisplay(), image2);
2887 }
2888
2889 // Testing source 2D texture, target 2D array texture
TEST_P(ImageTest,Source2DTarget2DArray)2890 TEST_P(ImageTest, Source2DTarget2DArray)
2891 {
2892 Source2DTarget2DArray_helper(kDefaultAttribs);
2893 }
2894
2895 // Testing source 2D texture with colorspace, target 2D array texture
TEST_P(ImageTest,Source2DTarget2DArray_Colorspace)2896 TEST_P(ImageTest, Source2DTarget2DArray_Colorspace)
2897 {
2898 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2899 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2900 Source2DTarget2DArray_helper(kColorspaceAttribs);
2901 }
2902
Source2DTarget2DArray_helper(const EGLint * attribs)2903 void ImageTest::Source2DTarget2DArray_helper(const EGLint *attribs)
2904 {
2905 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2906 EGLWindow *window = getEGLWindow();
2907 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
2908 !hasEglImageArrayExt());
2909
2910 // Create the Image
2911 GLTexture source;
2912 EGLImageKHR image;
2913 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor, source,
2914 &image);
2915
2916 // Create the target
2917 GLTexture target;
2918 createEGLImageTargetTexture2DArray(image, target);
2919
2920 // Verify that the target texture has the expected color
2921 verifyResults2DArray(target, getExpected2DColorForAttribList(attribs));
2922
2923 // Clean up
2924 eglDestroyImageKHR(window->getDisplay(), image);
2925 }
2926
2927 // Testing source AHB EGL image, if the client buffer is null, the test will not crash
TEST_P(ImageTest,SourceAHBInvalid)2928 TEST_P(ImageTest, SourceAHBInvalid)
2929 {
2930 EGLWindow *window = getEGLWindow();
2931
2932 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !IsVulkan());
2933 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2934
2935 // Create the Image
2936 EGLImageKHR image = eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT,
2937 EGL_NATIVE_BUFFER_ANDROID, nullptr, nullptr);
2938 ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
2939 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
2940 }
2941
2942 // Testing source AHB EGL image, if the client buffer is not a ANativeWindowBuffer,
2943 // eglCreateImageKHR should return NO_IMAGE and generate error EGL_BAD_PARAMETER.
TEST_P(ImageTest,SourceAHBCorrupt)2944 TEST_P(ImageTest, SourceAHBCorrupt)
2945 {
2946 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !IsVulkan());
2947 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
2948
2949 #if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
2950 EGLWindow *window = getEGLWindow();
2951
2952 const AHardwareBuffer_Desc aHardwareBufferDescription = createAndroidHardwareBufferDesc(
2953 16, 16, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, kAHBUsageGPUSampledImage);
2954
2955 // Allocate memory from Android Hardware Buffer
2956 AHardwareBuffer *aHardwareBuffer = nullptr;
2957 EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
2958
2959 std::memset(
2960 reinterpret_cast<void *>(angle::android::AHardwareBufferToClientBuffer(aHardwareBuffer)), 0,
2961 sizeof(int));
2962 EGLImageKHR ahbImage = eglCreateImageKHR(
2963 window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
2964 angle::android::AHardwareBufferToClientBuffer(aHardwareBuffer), kDefaultAttribs);
2965
2966 ASSERT_EGL_ERROR(EGL_BAD_PARAMETER);
2967 EXPECT_EQ(ahbImage, EGL_NO_IMAGE_KHR);
2968
2969 AHardwareBuffer_release(aHardwareBuffer);
2970 #endif
2971 }
2972
2973 // Helper function to check if it is reasonable to access texture resource
ImageCheckingTextureAccessHelper(GLenum target,bool mipmap)2974 void ImageTest::ImageCheckingTextureAccessHelper(GLenum target, bool mipmap)
2975 {
2976 constexpr GLsizei width = 2, height = 2, depth = 2;
2977 GLTexture source;
2978 EGLenum eglTarget;
2979 EGLWindow *window = getEGLWindow();
2980
2981 glBindTexture(target, source);
2982 switch (target)
2983 {
2984 case GL_TEXTURE_2D:
2985 eglTarget = EGL_GL_TEXTURE_2D_KHR;
2986 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
2987 nullptr);
2988 break;
2989 case GL_TEXTURE_3D:
2990 eglTarget = EGL_GL_TEXTURE_3D_KHR;
2991 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, width, height, depth, 0, GL_RGBA,
2992 GL_UNSIGNED_BYTE, nullptr);
2993 break;
2994 case GL_TEXTURE_CUBE_MAP:
2995 eglTarget = EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR;
2996 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
2997 {
2998 glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, width, height, 0,
2999 GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
3000 }
3001 break;
3002 default:
3003 return;
3004 }
3005
3006 if (mipmap)
3007 {
3008 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
3009 glGenerateMipmap(target);
3010 }
3011
3012 EGLImageKHR image = eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3013 reinterpretHelper<EGLClientBuffer>(source), nullptr);
3014 ASSERT_EGL_SUCCESS();
3015 EXPECT_NE(image, EGL_NO_IMAGE_KHR);
3016
3017 // If the texture is bound to egl image, EGL_BAD_ACCESS should be returned.
3018 EGLImageKHR invalidImage1 =
3019 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3020 reinterpretHelper<EGLClientBuffer>(source), nullptr);
3021 ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
3022 EXPECT_EQ(invalidImage1, EGL_NO_IMAGE_KHR);
3023
3024 // If the image is destroyed, the texture could be bound to egl image here.
3025 eglDestroyImageKHR(window->getDisplay(), image);
3026
3027 EGLImageKHR validImage1 =
3028 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3029 reinterpretHelper<EGLClientBuffer>(source), nullptr);
3030 ASSERT_EGL_SUCCESS();
3031 EXPECT_NE(validImage1, EGL_NO_IMAGE_KHR);
3032
3033 if (target == GL_TEXTURE_3D)
3034 {
3035 constexpr EGLint zOffsetAttribs[] = {
3036 EGL_GL_TEXTURE_ZOFFSET,
3037 1,
3038 EGL_NONE,
3039 };
3040 EGLImageKHR validImage2 =
3041 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3042 reinterpretHelper<EGLClientBuffer>(source), zOffsetAttribs);
3043 ASSERT_EGL_SUCCESS();
3044 EXPECT_NE(validImage2, EGL_NO_IMAGE_KHR);
3045 eglDestroyImageKHR(window->getDisplay(), validImage2);
3046 }
3047
3048 if (target == GL_TEXTURE_CUBE_MAP)
3049 {
3050 for (GLenum faceIdx = 1; faceIdx < 6; faceIdx++)
3051 {
3052 EGLImageKHR validImage2 =
3053 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget + faceIdx,
3054 reinterpretHelper<EGLClientBuffer>(source), nullptr);
3055 ASSERT_EGL_SUCCESS();
3056 EXPECT_NE(validImage2, EGL_NO_IMAGE_KHR);
3057 eglDestroyImageKHR(window->getDisplay(), validImage2);
3058 }
3059 }
3060
3061 if (mipmap)
3062 {
3063 constexpr EGLint mipmapAttribs[] = {
3064 EGL_GL_TEXTURE_LEVEL,
3065 1,
3066 EGL_NONE,
3067 };
3068 EGLImageKHR validImage3 =
3069 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3070 reinterpretHelper<EGLClientBuffer>(source), mipmapAttribs);
3071 ASSERT_EGL_SUCCESS();
3072 EXPECT_NE(validImage3, EGL_NO_IMAGE_KHR);
3073
3074 EGLImageKHR invalidImage2 =
3075 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3076 reinterpretHelper<EGLClientBuffer>(source), mipmapAttribs);
3077 ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
3078 EXPECT_EQ(invalidImage2, EGL_NO_IMAGE_KHR);
3079
3080 eglDestroyImageKHR(window->getDisplay(), validImage3);
3081 EGLImageKHR validImage4 =
3082 eglCreateImageKHR(window->getDisplay(), window->getContext(), eglTarget,
3083 reinterpretHelper<EGLClientBuffer>(source), mipmapAttribs);
3084 ASSERT_EGL_SUCCESS();
3085 EXPECT_NE(validImage4, EGL_NO_IMAGE_KHR);
3086 eglDestroyImageKHR(window->getDisplay(), validImage4);
3087 }
3088
3089 eglDestroyImageKHR(window->getDisplay(), validImage1);
3090 }
3091
3092 // Testing GLES resources when creating EGL image, if the client buffer itself is an EGL sibling,
3093 // eglCreateImageKHR should return NO_IMAGE and generate error EGL_BAD_ACCESS.
TEST_P(ImageTest,SourceBadAccess)3094 TEST_P(ImageTest, SourceBadAccess)
3095 {
3096 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !IsVulkan());
3097
3098 // Validate gles 2D texture
3099 if (has2DTextureExt())
3100 {
3101 ImageCheckingTextureAccessHelper(GL_TEXTURE_2D, false);
3102 ImageCheckingTextureAccessHelper(GL_TEXTURE_2D, true);
3103 }
3104
3105 // Validate gles 3D texture
3106 if (has3DTextureExt() && getClientMajorVersion() >= 3)
3107 {
3108 ImageCheckingTextureAccessHelper(GL_TEXTURE_3D, false);
3109 ImageCheckingTextureAccessHelper(GL_TEXTURE_3D, true);
3110 }
3111
3112 // Validate gles cube map texture
3113 if (hasCubemapExt())
3114 {
3115 ImageCheckingTextureAccessHelper(GL_TEXTURE_CUBE_MAP, false);
3116 ImageCheckingTextureAccessHelper(GL_TEXTURE_CUBE_MAP, true);
3117 }
3118
3119 // Validate gles renderbuffer
3120 if (hasRenderbufferExt())
3121 {
3122 EGLWindow *window = getEGLWindow();
3123 GLRenderbuffer source;
3124 EGLImageKHR image;
3125 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, kDefaultAttribs, source, &image);
3126
3127 EGLImageKHR invalidImage =
3128 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
3129 reinterpretHelper<EGLClientBuffer>(source), kDefaultAttribs);
3130 ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
3131 EXPECT_EQ(invalidImage, EGL_NO_IMAGE_KHR);
3132 eglDestroyImageKHR(window->getDisplay(), image);
3133
3134 EGLImageKHR validImage =
3135 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
3136 reinterpretHelper<EGLClientBuffer>(source), kDefaultAttribs);
3137 ASSERT_EGL_SUCCESS();
3138 EXPECT_NE(validImage, EGL_NO_IMAGE_KHR);
3139 eglDestroyImageKHR(window->getDisplay(), validImage);
3140 }
3141 }
3142
3143 // Testing source AHB EGL image, target 2D texture and delete when in use
3144 // If refcounted correctly, the test should pass without issues
TEST_P(ImageTest,SourceAHBTarget2DEarlyDelete)3145 TEST_P(ImageTest, SourceAHBTarget2DEarlyDelete)
3146 {
3147 EGLWindow *window = getEGLWindow();
3148
3149 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3150 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3151
3152 GLubyte data[4] = {7, 51, 197, 231};
3153
3154 // Create the Image
3155 AHardwareBuffer *source;
3156 EGLImageKHR image;
3157 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3158 kDefaultAHBUsage, kDefaultAttribs, {{data, 4}},
3159 &source, &image);
3160
3161 // Create a texture target to bind the egl image
3162 GLTexture target;
3163 createEGLImageTargetTexture2D(image, target);
3164
3165 // Delete the source AHB when in use
3166 destroyAndroidHardwareBuffer(source);
3167
3168 // Use texture target bound to egl image as source and render to framebuffer
3169 // Verify that data in framebuffer matches that in the egl image
3170 verifyResults2D(target, data);
3171
3172 // Clean up
3173 eglDestroyImageKHR(window->getDisplay(), image);
3174 }
3175
3176 // Testing source AHB EGL image, target 2D texture
TEST_P(ImageTest,SourceAHBTarget2D)3177 TEST_P(ImageTest, SourceAHBTarget2D)
3178 {
3179 SourceAHBTarget2D_helper(kDefaultAttribs);
3180 }
3181
3182 // Testing source AHB EGL image with colorspace, target 2D texture
TEST_P(ImageTest,SourceAHBTarget2D_Colorspace)3183 TEST_P(ImageTest, SourceAHBTarget2D_Colorspace)
3184 {
3185 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
3186 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
3187 SourceAHBTarget2D_helper(kColorspaceAttribs);
3188 }
3189
SourceAHBTarget2D_helper(const EGLint * attribs)3190 void ImageTest::SourceAHBTarget2D_helper(const EGLint *attribs)
3191 {
3192 EGLWindow *window = getEGLWindow();
3193
3194 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3195 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3196 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3197
3198 // Create the Image
3199 AHardwareBuffer *source;
3200 EGLImageKHR image;
3201 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3202 kDefaultAHBUsage, attribs, {{kSrgbColor, 4}}, &source,
3203 &image);
3204
3205 // Create a texture target to bind the egl image
3206 GLTexture target;
3207 createEGLImageTargetTexture2D(image, target);
3208
3209 // Use texture target bound to egl image as source and render to framebuffer
3210 // Verify that the target texture has the expected color
3211 verifyResults2D(target, getExpected2DColorForAttribList(attribs));
3212
3213 // Clean up
3214 eglDestroyImageKHR(window->getDisplay(), image);
3215 destroyAndroidHardwareBuffer(source);
3216 }
3217
3218 // Testing source AHB EGL images, target 2D external texture, cycling through YUV sources.
TEST_P(ImageTest,SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData)3219 TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvSourcesNoData)
3220 {
3221 // http://issuetracker.google.com/175021871
3222 ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
3223
3224 EGLWindow *window = getEGLWindow();
3225
3226 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3227 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3228
3229 // Create YCbCr source and image but without initial data
3230 AHardwareBuffer *ycbcrSource;
3231 EGLImageKHR ycbcrImage;
3232 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
3233 kDefaultAHBUsage, kDefaultAttribs, {}, &ycbcrSource,
3234 &ycbcrImage);
3235 EXPECT_NE(ycbcrSource, nullptr);
3236 EXPECT_NE(ycbcrImage, EGL_NO_IMAGE_KHR);
3237
3238 // Create YCrCb source and image but without initial data
3239 AHardwareBuffer *ycrcbSource;
3240 EGLImageKHR ycrcbImage;
3241 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cr8Cb8_420_SP,
3242 kDefaultAHBUsage, kDefaultAttribs, {}, &ycrcbSource,
3243 &ycrcbImage);
3244 EXPECT_NE(ycrcbSource, nullptr);
3245 EXPECT_NE(ycrcbImage, EGL_NO_IMAGE_KHR);
3246
3247 // Create YV12 source and image but without initial data
3248 AHardwareBuffer *yv12Source;
3249 EGLImageKHR yv12Image;
3250 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YV12,
3251 kDefaultAHBUsage, kDefaultAttribs, {}, &yv12Source,
3252 &yv12Image);
3253 EXPECT_NE(yv12Source, nullptr);
3254 EXPECT_NE(yv12Image, EGL_NO_IMAGE_KHR);
3255
3256 // Create a texture target to bind the egl image
3257 GLTexture target;
3258 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
3259 // Disable mipmapping
3260 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3261 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3262 ASSERT_GL_NO_ERROR();
3263
3264 // Bind YCbCr image
3265 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycbcrImage);
3266 // Draw while sampling should result in no EGL/GL errors
3267 glUseProgram(mTextureExternalProgram);
3268 glUniform1i(mTextureExternalUniformLocation, 0);
3269 drawQuad(mTextureExternalProgram, "position", 0.5f);
3270 ASSERT_GL_NO_ERROR();
3271
3272 // Bind YCrCb image
3273 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycrcbImage);
3274 // Draw while sampling should result in no EGL/GL errors
3275 glUseProgram(mTextureExternalProgram);
3276 glUniform1i(mTextureExternalUniformLocation, 0);
3277 drawQuad(mTextureExternalProgram, "position", 0.5f);
3278 ASSERT_GL_NO_ERROR();
3279
3280 // Bind YV12 image
3281 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yv12Image);
3282 // Draw while sampling should result in no EGL/GL errors
3283 glUseProgram(mTextureExternalProgram);
3284 glUniform1i(mTextureExternalUniformLocation, 0);
3285 drawQuad(mTextureExternalProgram, "position", 0.5f);
3286 ASSERT_GL_NO_ERROR();
3287
3288 // Clean up
3289 eglDestroyImageKHR(window->getDisplay(), ycbcrImage);
3290 destroyAndroidHardwareBuffer(ycbcrSource);
3291 eglDestroyImageKHR(window->getDisplay(), ycrcbImage);
3292 destroyAndroidHardwareBuffer(ycrcbSource);
3293 eglDestroyImageKHR(window->getDisplay(), yv12Image);
3294 destroyAndroidHardwareBuffer(yv12Source);
3295 }
3296
3297 // Testing source AHB EGL images, target 2D external texture, cycling through RGB and YUV sources.
TEST_P(ImageTest,SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources)3298 TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvSources)
3299 {
3300 // http://issuetracker.google.com/175021871
3301 ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
3302
3303 EGLWindow *window = getEGLWindow();
3304
3305 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3306 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3307 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3308
3309 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
3310 1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage));
3311 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
3312 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage));
3313
3314 // Create RGB Image
3315 GLubyte rgbColor[4] = {0, 0, 255, 255};
3316
3317 AHardwareBuffer *rgbSource;
3318 EGLImageKHR rgbImage;
3319 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3320 kDefaultAHBUsage, kDefaultAttribs, {{rgbColor, 4}},
3321 &rgbSource, &rgbImage);
3322
3323 // Create YUV Image
3324 // 3 planes of data
3325 GLubyte dataY[4] = {40, 40, 40, 40};
3326 GLubyte dataCb[1] = {
3327 240,
3328 };
3329 GLubyte dataCr[1] = {
3330 109,
3331 };
3332
3333 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3334
3335 AHardwareBuffer *yuvSource;
3336 EGLImageKHR yuvImage;
3337 createEGLImageAndroidHardwareBufferSource(
3338 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
3339 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &yuvSource, &yuvImage);
3340
3341 // Create a texture target to bind the egl image
3342 GLTexture target;
3343 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
3344 // Disable mipmapping
3345 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3346 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3347 ASSERT_GL_NO_ERROR();
3348
3349 // Bind YUV image
3350 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage);
3351 // Expect render target to have the same color as expectedRgbColor
3352 verifyResultsExternal(target, expectedRgbColor);
3353
3354 // Bind RGB image
3355 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, rgbImage);
3356 // Expect render target to have the same color as rgbColor
3357 verifyResultsExternal(target, rgbColor);
3358
3359 // Bind YUV image
3360 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage);
3361 // Expect render target to have the same color as expectedRgbColor
3362 verifyResultsExternal(target, expectedRgbColor);
3363
3364 // Clean up
3365 eglDestroyImageKHR(window->getDisplay(), yuvImage);
3366 destroyAndroidHardwareBuffer(yuvSource);
3367 eglDestroyImageKHR(window->getDisplay(), rgbImage);
3368 destroyAndroidHardwareBuffer(rgbSource);
3369 }
3370
3371 // Testing source AHB EGL images, target 2D external textures, cycling through RGB and YUV targets.
TEST_P(ImageTest,SourceAHBTarget2DExternalCycleThroughRgbAndYuvTargets)3372 TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughRgbAndYuvTargets)
3373 {
3374 // http://issuetracker.google.com/175021871
3375 ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
3376
3377 EGLWindow *window = getEGLWindow();
3378
3379 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3380 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3381 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3382
3383 // Create RGBA Image
3384 GLubyte rgbaColor[4] = {0, 0, 255, 255};
3385
3386 AHardwareBuffer *rgbaSource;
3387 EGLImageKHR rgbaImage;
3388 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3389 kDefaultAHBUsage, kDefaultAttribs, {{rgbaColor, 4}},
3390 &rgbaSource, &rgbaImage);
3391
3392 // Create YUV Image
3393 // 3 planes of data
3394 GLubyte dataY[4] = {40, 40, 40, 40};
3395 GLubyte dataCb[1] = {
3396 240,
3397 };
3398 GLubyte dataCr[1] = {
3399 109,
3400 };
3401
3402 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3403
3404 AHardwareBuffer *yuvSource;
3405 EGLImageKHR yuvImage;
3406 createEGLImageAndroidHardwareBufferSource(
3407 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
3408 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &yuvSource, &yuvImage);
3409
3410 // Create texture target siblings to bind the egl images
3411 // Create YUV target and bind the image
3412 GLTexture yuvTarget;
3413 glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTarget);
3414 // Disable mipmapping
3415 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3416 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3417 ASSERT_GL_NO_ERROR();
3418 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yuvImage);
3419 ASSERT_GL_NO_ERROR();
3420
3421 // Create RGBA target and bind the image
3422 GLTexture rgbaTarget;
3423 glBindTexture(GL_TEXTURE_EXTERNAL_OES, rgbaTarget);
3424 // Disable mipmapping
3425 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3426 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3427 ASSERT_GL_NO_ERROR();
3428 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, rgbaImage);
3429 ASSERT_GL_NO_ERROR();
3430
3431 // Cycle through targets
3432 // YUV target
3433 glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTarget);
3434 // Expect render target to have the same color as expectedRgbColor
3435 verifyResultsExternal(yuvTarget, expectedRgbColor);
3436
3437 // RGBA target
3438 glBindTexture(GL_TEXTURE_EXTERNAL_OES, rgbaTarget);
3439 // Expect render target to have the same color as rgbColor
3440 verifyResultsExternal(rgbaTarget, rgbaColor);
3441
3442 // YUV target
3443 glBindTexture(GL_TEXTURE_EXTERNAL_OES, yuvTarget);
3444 // Expect render target to have the same color as expectedRgbColor
3445 verifyResultsExternal(yuvTarget, expectedRgbColor);
3446
3447 // Clean up
3448 eglDestroyImageKHR(window->getDisplay(), yuvImage);
3449 destroyAndroidHardwareBuffer(yuvSource);
3450 eglDestroyImageKHR(window->getDisplay(), rgbaImage);
3451 destroyAndroidHardwareBuffer(rgbaSource);
3452 }
3453
3454 // Testing source AHB EGL images, target 2D external textures, cycling through YUV targets.
TEST_P(ImageTest,SourceAHBTarget2DExternalCycleThroughYuvTargetsNoData)3455 TEST_P(ImageTest, SourceAHBTarget2DExternalCycleThroughYuvTargetsNoData)
3456 {
3457 // http://issuetracker.google.com/175021871
3458 ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
3459
3460 EGLWindow *window = getEGLWindow();
3461
3462 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3463 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3464
3465 // Create YCbCr source and image but without initial data
3466 AHardwareBuffer *ycbcrSource;
3467 EGLImageKHR ycbcrImage;
3468 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
3469 kDefaultAHBUsage, kDefaultAttribs, {}, &ycbcrSource,
3470 &ycbcrImage);
3471 EXPECT_NE(ycbcrSource, nullptr);
3472 EXPECT_NE(ycbcrImage, EGL_NO_IMAGE_KHR);
3473
3474 // Create YV12 source and image but without initial data
3475 AHardwareBuffer *yv12Source;
3476 EGLImageKHR yv12Image;
3477 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_YV12,
3478 kDefaultAHBUsage, kDefaultAttribs, {}, &yv12Source,
3479 &yv12Image);
3480 EXPECT_NE(yv12Source, nullptr);
3481 EXPECT_NE(yv12Image, EGL_NO_IMAGE_KHR);
3482
3483 // Create texture target siblings to bind the egl images
3484 // Create YCbCr target and bind the image
3485 GLTexture ycbcrTarget;
3486 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ycbcrTarget);
3487 // Disable mipmapping
3488 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3489 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3490 ASSERT_GL_NO_ERROR();
3491 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, ycbcrImage);
3492 ASSERT_GL_NO_ERROR();
3493
3494 // Create YV12 target and bind the image
3495 GLTexture yv12Target;
3496 glBindTexture(GL_TEXTURE_EXTERNAL_OES, yv12Target);
3497 // Disable mipmapping
3498 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3499 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3500 ASSERT_GL_NO_ERROR();
3501 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, yv12Image);
3502 ASSERT_GL_NO_ERROR();
3503
3504 // Cycle through targets
3505 glUseProgram(mTextureExternalProgram);
3506 glUniform1i(mTextureExternalUniformLocation, 0);
3507
3508 // Bind YCbCr image
3509 // YCbCr target
3510 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ycbcrTarget);
3511 // Draw while sampling should result in no EGL/GL errors
3512 drawQuad(mTextureExternalProgram, "position", 0.5f);
3513 ASSERT_GL_NO_ERROR();
3514
3515 // YV12 target
3516 glBindTexture(GL_TEXTURE_EXTERNAL_OES, yv12Target);
3517 // Draw while sampling should result in no EGL/GL errors
3518 drawQuad(mTextureExternalProgram, "position", 0.5f);
3519 ASSERT_GL_NO_ERROR();
3520
3521 // Clean up
3522 eglDestroyImageKHR(window->getDisplay(), ycbcrImage);
3523 destroyAndroidHardwareBuffer(ycbcrSource);
3524 eglDestroyImageKHR(window->getDisplay(), yv12Image);
3525 destroyAndroidHardwareBuffer(yv12Source);
3526 }
3527
3528 // Testing source AHB EGL image, target 2D texture retaining initial data.
TEST_P(ImageTest,SourceAHBTarget2DRetainInitialData)3529 TEST_P(ImageTest, SourceAHBTarget2DRetainInitialData)
3530 {
3531 EGLWindow *window = getEGLWindow();
3532
3533 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3534 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3535 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3536
3537 GLubyte data[4] = {0, 255, 0, 255};
3538
3539 // Create the Image
3540 AHardwareBuffer *source;
3541 EGLImageKHR image;
3542 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3543 kDefaultAHBUsage, kDefaultAttribs, {{data, 4}},
3544 &source, &image);
3545
3546 // Create a texture target to bind the egl image
3547 GLTexture target;
3548 createEGLImageTargetTexture2D(image, target);
3549
3550 // Create a framebuffer, and blend into the texture.
3551 GLFramebuffer fbo;
3552 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3553 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
3554 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3555
3556 // Blend into the framebuffer.
3557 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
3558 glEnable(GL_BLEND);
3559 glBlendFunc(GL_ONE, GL_ONE);
3560 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
3561 ASSERT_GL_NO_ERROR();
3562
3563 glBindFramebuffer(GL_FRAMEBUFFER, 0);
3564 glDisable(GL_BLEND);
3565
3566 // Use texture target bound to egl image as source and render to framebuffer
3567 // Verify that data in framebuffer matches that in the egl image
3568 GLubyte expect[4] = {255, 255, 0, 255};
3569 verifyResults2D(target, expect);
3570
3571 // Clean up
3572 eglDestroyImageKHR(window->getDisplay(), image);
3573 destroyAndroidHardwareBuffer(source);
3574 }
3575
3576 // Test interaction between AHBs and GL_EXT_multisampled_render_to_texture
TEST_P(ImageTest,SourceAHBTarget2DMSRTTInteraction)3577 TEST_P(ImageTest, SourceAHBTarget2DMSRTTInteraction)
3578 {
3579 EGLWindow *window = getEGLWindow();
3580 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3581 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3582 ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
3583
3584 // Create the Image
3585 AHardwareBuffer *source;
3586 EGLImageKHR image;
3587 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3588 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
3589 &image);
3590
3591 // Create the target
3592 GLTexture target;
3593 createEGLImageTargetTexture2D(image, target);
3594
3595 // Bind target texture to mulisampled framebuffer
3596 GLFramebuffer fboMS;
3597 glBindFramebuffer(GL_FRAMEBUFFER, fboMS);
3598 glFramebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
3599 target, 0, 4);
3600 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
3601
3602 // Clear framebuffer
3603 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
3604 glClear(GL_COLOR_BUFFER_BIT);
3605 ASSERT_GL_NO_ERROR();
3606
3607 // Check clear result
3608 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
3609
3610 // Check the AHB is updated
3611 verifyResultAHB(source, {{GLColor::blue.data(), 4}});
3612
3613 // Clean up
3614 eglDestroyImageKHR(window->getDisplay(), image);
3615 }
3616 // Testing source AHB EGL image, target 2D array texture
TEST_P(ImageTest,SourceAHBTarget2DArray)3617 TEST_P(ImageTest, SourceAHBTarget2DArray)
3618 {
3619 SourceAHBTarget2DArray_helper(kDefaultAttribs);
3620 }
3621
3622 // Testing source AHB EGL image with colorspace, target 2D array texture
TEST_P(ImageTest,SourceAHBTarget2DArray_Colorspace)3623 TEST_P(ImageTest, SourceAHBTarget2DArray_Colorspace)
3624 {
3625 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
3626 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
3627 SourceAHBTarget2DArray_helper(kColorspaceAttribs);
3628 }
3629
SourceAHBTarget2DArray_helper(const EGLint * attribs)3630 void ImageTest::SourceAHBTarget2DArray_helper(const EGLint *attribs)
3631 {
3632 EGLWindow *window = getEGLWindow();
3633
3634 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
3635 !hasEglImageArrayExt());
3636 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3637 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3638
3639 // Create the Image
3640 AHardwareBuffer *source;
3641 EGLImageKHR image;
3642 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3643 kDefaultAHBUsage, attribs, {{kSrgbColor, 4}}, &source,
3644 &image);
3645
3646 // Create a texture target to bind the egl image
3647 GLTexture target;
3648 createEGLImageTargetTexture2DArray(image, target);
3649
3650 // Use texture target bound to egl image as source and render to framebuffer
3651 // Verify that the target texture has the expected color
3652 verifyResults2DArray(target, getExpected2DColorForAttribList(attribs));
3653
3654 // Clean up
3655 eglDestroyImageKHR(window->getDisplay(), image);
3656 destroyAndroidHardwareBuffer(source);
3657 }
3658
3659 // Testing source AHB EGL image, target external texture
TEST_P(ImageTest,SourceAHBTargetExternal)3660 TEST_P(ImageTest, SourceAHBTargetExternal)
3661 {
3662 SourceAHBTargetExternal_helper(kDefaultAttribs);
3663 }
3664
3665 // Testing source AHB EGL image with colorspace, target external texture
TEST_P(ImageTest,SourceAHBTargetExternal_Colorspace)3666 TEST_P(ImageTest, SourceAHBTargetExternal_Colorspace)
3667 {
3668 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
3669 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
3670 SourceAHBTargetExternal_helper(kColorspaceAttribs);
3671 }
3672
SourceAHBTargetExternal_helper(const EGLint * attribs)3673 void ImageTest::SourceAHBTargetExternal_helper(const EGLint *attribs)
3674 {
3675 EGLWindow *window = getEGLWindow();
3676 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
3677 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3678 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3679
3680 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
3681 ANGLE_SKIP_TEST_IF(IsOzone());
3682
3683 // Create the Image
3684 AHardwareBuffer *source;
3685 EGLImageKHR image;
3686 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
3687 kDefaultAHBUsage, attribs, {{kSrgbColor, 4}}, &source,
3688 &image);
3689
3690 // Create a texture target to bind the egl image
3691 GLTexture target;
3692 createEGLImageTargetTextureExternal(image, target);
3693
3694 // Use texture target bound to egl image as source and render to framebuffer
3695 // Verify that the target texture has the expected color
3696 verifyResultsExternal(target, getExpected2DColorForAttribList(attribs));
3697
3698 // Clean up
3699 eglDestroyImageKHR(window->getDisplay(), image);
3700 destroyAndroidHardwareBuffer(source);
3701 }
3702
3703 // Testing source AHB EGL image, target external ESSL3 texture
TEST_P(ImageTestES3,SourceAHBTargetExternalESSL3)3704 TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3)
3705 {
3706 SourceAHBTargetExternalESSL3_helper(kDefaultAttribs);
3707 }
3708
3709 // Test sampling from a YUV texture using GL_ANGLE_yuv_internal_format as external texture and then
3710 // switching to raw YUV sampling using EXT_yuv_target
TEST_P(ImageTestES3,SourceYUVTextureTargetExternalRGBSampleYUVSample)3711 TEST_P(ImageTestES3, SourceYUVTextureTargetExternalRGBSampleYUVSample)
3712 {
3713 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
3714 !hasYUVInternalFormatExt() || !hasYUVTargetExt());
3715
3716 // Create source YUV texture
3717 GLTexture yuvTexture;
3718 GLubyte yuvColor[6] = {7, 51, 197, 231, 128, 192};
3719 GLubyte expectedRgbColor[4] = {255, 159, 211, 255};
3720 constexpr size_t kWidth = 2;
3721 constexpr size_t kHeight = 2;
3722
3723 glBindTexture(GL_TEXTURE_2D, yuvTexture);
3724 glTexStorage2D(GL_TEXTURE_2D, 1, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, kWidth, kHeight);
3725 ASSERT_GL_NO_ERROR();
3726 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3727 GL_UNSIGNED_BYTE, yuvColor);
3728 ASSERT_GL_NO_ERROR();
3729 // Disable mipmapping
3730 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3731 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3732 ASSERT_GL_NO_ERROR();
3733
3734 // Create the Image
3735 EGLWindow *window = getEGLWindow();
3736 EGLImageKHR image =
3737 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
3738 reinterpretHelper<EGLClientBuffer>(yuvTexture), kDefaultAttribs);
3739 ASSERT_EGL_SUCCESS();
3740
3741 // Create a texture target to bind the egl image
3742 GLTexture target;
3743 createEGLImageTargetTextureExternal(image, target);
3744
3745 // Draw quad with program that samples YUV data with implicit RGB conversion
3746 glUseProgram(mTextureExternalProgram);
3747 glUniform1i(mTextureExternalUniformLocation, 0);
3748 drawQuad(mTextureExternalProgram, "position", 0.5f);
3749 // Expect that the rendered quad's color is converted to RGB
3750 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3751 expectedRgbColor[3], 1);
3752
3753 // Draw quad with program that samples raw YUV data
3754 glUseProgram(mTextureYUVProgram);
3755 glUniform1i(mTextureYUVUniformLocation, 0);
3756 drawQuad(mTextureYUVProgram, "position", 0.5f);
3757 // Expect that the rendered quad's color matches the raw YUV data
3758 EXPECT_PIXEL_NEAR(0, 0, yuvColor[2], yuvColor[4], yuvColor[5], 255, 1);
3759
3760 // Clean up
3761 eglDestroyImageKHR(window->getDisplay(), image);
3762 }
3763
3764 // Similar to SourceYUVTextureTargetExternalRGBSampleYUVSample, but added swizzle after
3765 // __samplerExternal2DY2YEXT from texture.
TEST_P(ImageTestES3,SourceYUVTextureTargetExternalRGBSampleYUVSampleWithSwizzle)3766 TEST_P(ImageTestES3, SourceYUVTextureTargetExternalRGBSampleYUVSampleWithSwizzle)
3767 {
3768 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
3769 !hasYUVInternalFormatExt() || !hasYUVTargetExt());
3770
3771 // Create source YUV texture
3772 GLTexture yuvTexture;
3773 GLubyte yuvColor[6] = {7, 51, 197, 231, 128, 192};
3774 constexpr size_t kWidth = 2;
3775 constexpr size_t kHeight = 2;
3776
3777 glBindTexture(GL_TEXTURE_2D, yuvTexture);
3778 glTexStorage2D(GL_TEXTURE_2D, 1, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, kWidth, kHeight);
3779 ASSERT_GL_NO_ERROR();
3780 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3781 GL_UNSIGNED_BYTE, yuvColor);
3782 ASSERT_GL_NO_ERROR();
3783 // Disable mipmapping
3784 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3785 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3786 ASSERT_GL_NO_ERROR();
3787
3788 // Create the Image
3789 EGLWindow *window = getEGLWindow();
3790 EGLImageKHR image =
3791 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
3792 reinterpretHelper<EGLClientBuffer>(yuvTexture), kDefaultAttribs);
3793 ASSERT_EGL_SUCCESS();
3794
3795 // Create a texture target to bind the egl image
3796 GLTexture target;
3797 createEGLImageTargetTextureExternal(image, target);
3798
3799 // Draw quad with program that samples raw YUV data and then swizzle
3800 const char *fragmentShaderSource = R"(#version 300 es
3801 #extension GL_EXT_YUV_target : require
3802 precision highp float;
3803 uniform __samplerExternal2DY2YEXT tex;
3804 in vec2 texcoord;
3805 out vec4 color;
3806
3807 void main()
3808 {
3809 color = vec4(texture(tex, texcoord).zyx, 1.0);
3810 })";
3811 ANGLE_GL_PROGRAM(textureYUVProgram, getVSESSL3(), fragmentShaderSource);
3812 ASSERT_NE(0u, textureYUVProgram) << "shader compilation failed.";
3813 glUseProgram(textureYUVProgram);
3814 GLint uniformLocation = glGetUniformLocation(textureYUVProgram, "tex");
3815 ASSERT_NE(-1, uniformLocation);
3816 glUniform1i(uniformLocation, 0);
3817 drawQuad(textureYUVProgram, "position", 0.5f);
3818 // Expect that the rendered quad's color matches the raw YUV data after component swizzle
3819 EXPECT_PIXEL_NEAR(0, 0, yuvColor[5], yuvColor[4], yuvColor[2], 255, 1);
3820
3821 // Clean up
3822 eglDestroyImageKHR(window->getDisplay(), image);
3823 }
3824
3825 // Test interaction between GL_ANGLE_yuv_internal_format and EXT_yuv_target when a program has
3826 // both __samplerExternal2DY2YEXT and samplerExternalOES samplers.
TEST_P(ImageTestES3,ProgramWithBothExternalY2YAndExternalOESSampler)3827 TEST_P(ImageTestES3, ProgramWithBothExternalY2YAndExternalOESSampler)
3828 {
3829 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
3830 !hasYUVInternalFormatExt() || !hasYUVTargetExt());
3831
3832 GLubyte yuvColor[6] = {40, 40, 40, 40, 240, 109};
3833 GLubyte expectedRgbColor[4] = {0, 0, 255, 255};
3834 constexpr size_t kWidth = 2;
3835 constexpr size_t kHeight = 2;
3836
3837 // Create 2 plane YUV texture source
3838 GLTexture yuvTexture0;
3839 glBindTexture(GL_TEXTURE_2D, yuvTexture0);
3840 glTexStorage2D(GL_TEXTURE_2D, 1, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, kWidth, kHeight);
3841 ASSERT_GL_NO_ERROR();
3842 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3843 GL_UNSIGNED_BYTE, yuvColor);
3844 ASSERT_GL_NO_ERROR();
3845 // Disable mipmapping
3846 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3847 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3848 ASSERT_GL_NO_ERROR();
3849
3850 // Create 2 plane YUV texture source
3851 GLTexture yuvTexture1;
3852 glBindTexture(GL_TEXTURE_2D, yuvTexture1);
3853 glTexStorage2D(GL_TEXTURE_2D, 1, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE, kWidth, kHeight);
3854 ASSERT_GL_NO_ERROR();
3855 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_G8_B8R8_2PLANE_420_UNORM_ANGLE,
3856 GL_UNSIGNED_BYTE, yuvColor);
3857 ASSERT_GL_NO_ERROR();
3858 // Disable mipmapping
3859 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3860 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3861 ASSERT_GL_NO_ERROR();
3862
3863 // Create the Images
3864 EGLWindow *window = getEGLWindow();
3865 EGLImageKHR image0 =
3866 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
3867 reinterpretHelper<EGLClientBuffer>(yuvTexture0), kDefaultAttribs);
3868 ASSERT_EGL_SUCCESS();
3869
3870 EGLImageKHR image1 =
3871 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
3872 reinterpretHelper<EGLClientBuffer>(yuvTexture1), kDefaultAttribs);
3873 ASSERT_EGL_SUCCESS();
3874
3875 // Create texture targets for EGLImages
3876 GLTexture target0;
3877 createEGLImageTargetTextureExternal(image0, target0);
3878
3879 GLTexture target1;
3880 createEGLImageTargetTextureExternal(image1, target1);
3881
3882 // Create program with 2 samplers
3883 const char *vertexShaderSource = R"(#version 300 es
3884 out vec2 texcoord;
3885 in vec4 position;
3886 void main()
3887 {
3888 gl_Position = vec4(position.xy, 0.0, 1.0);
3889 texcoord = (position.xy * 0.5) + 0.5;
3890 })";
3891 const char *fragmentShaderSource = R"(#version 300 es
3892 #extension GL_EXT_YUV_target : require
3893 #extension GL_OES_EGL_image_external_essl3 : require
3894 precision highp float;
3895 uniform __samplerExternal2DY2YEXT tex0;
3896 uniform samplerExternalOES tex1;
3897 uniform uint samplerSelector;
3898 in vec2 texcoord;
3899 out vec4 fragColor;
3900
3901 void main()
3902 {
3903 vec4 color0 = texture(tex0, texcoord);
3904 vec4 color1 = texture(tex1, texcoord);
3905 if (samplerSelector == 0u)
3906 {
3907 fragColor = color0;
3908 }
3909 else if (samplerSelector == 1u)
3910 {
3911 fragColor = color1;
3912 }
3913 else
3914 {
3915 fragColor = vec4(1.0);
3916 }
3917 })";
3918
3919 ANGLE_GL_PROGRAM(twoSamplersProgram, vertexShaderSource, fragmentShaderSource);
3920 glUseProgram(twoSamplersProgram);
3921 GLint tex0Location = glGetUniformLocation(twoSamplersProgram, "tex0");
3922 ASSERT_NE(-1, tex0Location);
3923 GLint tex1Location = glGetUniformLocation(twoSamplersProgram, "tex1");
3924 ASSERT_NE(-1, tex1Location);
3925 GLint samplerSelectorLocation = glGetUniformLocation(twoSamplersProgram, "samplerSelector");
3926 ASSERT_NE(-1, samplerSelectorLocation);
3927
3928 // Bind texture target to GL_TEXTURE_EXTERNAL_OES
3929 glActiveTexture(GL_TEXTURE0);
3930 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target0);
3931 ASSERT_GL_NO_ERROR();
3932
3933 // Bind texture target to GL_TEXTURE_EXTERNAL_OES
3934 glActiveTexture(GL_TEXTURE1);
3935 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target1);
3936 ASSERT_GL_NO_ERROR();
3937
3938 // Set sampler uniform values
3939 glUniform1i(tex0Location, 0);
3940 glUniform1i(tex1Location, 1);
3941
3942 // Set sampler selector uniform value and draw
3943 glUniform1ui(samplerSelectorLocation, 0);
3944 drawQuad(twoSamplersProgram, "position", 0.5f);
3945 ASSERT_GL_NO_ERROR();
3946 EXPECT_PIXEL_NEAR(0, 0, yuvColor[3], yuvColor[4], yuvColor[5], 255, 1);
3947
3948 // Switch sampler selector uniform value and draw
3949 glUniform1ui(samplerSelectorLocation, 1);
3950 drawQuad(twoSamplersProgram, "position", 0.5f);
3951 ASSERT_GL_NO_ERROR();
3952 EXPECT_PIXEL_NEAR(0, 0, expectedRgbColor[0], expectedRgbColor[1], expectedRgbColor[2],
3953 expectedRgbColor[3], 1);
3954
3955 // Clean up
3956 eglDestroyImageKHR(window->getDisplay(), image0);
3957 eglDestroyImageKHR(window->getDisplay(), image1);
3958 }
3959
3960 // Test sampling from a YUV AHB with a regular external sampler and pre-initialized data
TEST_P(ImageTest,SourceYUVAHBTargetExternalRGBSampleInitData)3961 TEST_P(ImageTest, SourceYUVAHBTargetExternalRGBSampleInitData)
3962 {
3963 EGLWindow *window = getEGLWindow();
3964
3965 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
3966 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
3967 // http://issuetracker.google.com/175021871
3968 ANGLE_SKIP_TEST_IF(IsPixel2() || IsPixel2XL());
3969 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
3970
3971 // 3 planes of data
3972 GLubyte dataY[4] = {7, 51, 197, 231};
3973 GLubyte dataCb[1] = {
3974 128,
3975 };
3976 GLubyte dataCr[1] = {
3977 192,
3978 };
3979
3980 // Create the Image
3981 AHardwareBuffer *source;
3982 EGLImageKHR image;
3983 createEGLImageAndroidHardwareBufferSource(
3984 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
3985 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
3986
3987 // Create a texture target to bind the egl image
3988 GLTexture target;
3989 createEGLImageTargetTextureExternal(image, target);
3990
3991 GLubyte pixelColor[4] = {255, 159, 211, 255};
3992 verifyResultsExternal(target, pixelColor);
3993
3994 // Clean up
3995 eglDestroyImageKHR(window->getDisplay(), image);
3996 destroyAndroidHardwareBuffer(source);
3997 }
3998
3999 // Test sampling from a YUV AHB with a regular external sampler without data. This gives coverage of
4000 // sampling even if we can't verify the results.
TEST_P(ImageTest,SourceYUVAHBTargetExternalRGBSampleNoData)4001 TEST_P(ImageTest, SourceYUVAHBTargetExternalRGBSampleNoData)
4002 {
4003 EGLWindow *window = getEGLWindow();
4004
4005 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4006 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4007
4008 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
4009 AHardwareBuffer *source;
4010 EGLImageKHR image;
4011 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
4012 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
4013 &image);
4014
4015 // Create a texture target to bind the egl image
4016 GLTexture target;
4017 createEGLImageTargetTextureExternal(image, target);
4018
4019 glUseProgram(mTextureExternalProgram);
4020 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
4021 glUniform1i(mTextureExternalUniformLocation, 0);
4022
4023 // Sample from the YUV texture with a nearest sampler
4024 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4025 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4026 drawQuad(mTextureExternalProgram, "position", 0.5f);
4027
4028 // Sample from the YUV texture with a linear sampler
4029 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4030 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4031 drawQuad(mTextureExternalProgram, "position", 0.5f);
4032
4033 // Clean up
4034 eglDestroyImageKHR(window->getDisplay(), image);
4035 destroyAndroidHardwareBuffer(source);
4036 }
4037
4038 // Test sampling from a YUV AHB using EXT_yuv_target
TEST_P(ImageTestES3,SourceYUVAHBTargetExternalYUVSample)4039 TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSample)
4040 {
4041 EGLWindow *window = getEGLWindow();
4042
4043 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4044 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4045 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4046
4047 // 3 planes of data
4048 GLubyte dataY[4] = {7, 51, 197, 231};
4049 GLubyte dataCb[1] = {
4050 128,
4051 };
4052 GLubyte dataCr[1] = {
4053 192,
4054 };
4055
4056 // Create the Image
4057 AHardwareBuffer *source;
4058 EGLImageKHR image;
4059 createEGLImageAndroidHardwareBufferSource(
4060 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
4061 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
4062
4063 // Create a texture target to bind the egl image
4064 GLTexture target;
4065 createEGLImageTargetTextureExternal(image, target);
4066
4067 GLubyte pixelColor[4] = {197, 128, 192, 255};
4068 verifyResultsExternalYUV(target, pixelColor);
4069
4070 // Clean up
4071 eglDestroyImageKHR(window->getDisplay(), image);
4072 destroyAndroidHardwareBuffer(source);
4073 }
4074
4075 // Test sampling from a YUV AHB using EXT_yuv_target in the vertex shader
TEST_P(ImageTestES3,SourceYUVAHBTargetExternalYUVSampleVS)4076 TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSampleVS)
4077 {
4078 EGLWindow *window = getEGLWindow();
4079
4080 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4081 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4082 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4083
4084 // 3 planes of data
4085 GLubyte dataY[4] = {7, 51, 197, 231};
4086 GLubyte dataCb[1] = {
4087 128,
4088 };
4089 GLubyte dataCr[1] = {
4090 192,
4091 };
4092
4093 // Create the Image
4094 AHardwareBuffer *source;
4095 EGLImageKHR image;
4096 createEGLImageAndroidHardwareBufferSource(
4097 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
4098 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
4099
4100 // Create a texture target to bind the egl image
4101 GLTexture target;
4102 createEGLImageTargetTextureExternal(image, target);
4103
4104 GLubyte pixelColor[4] = {197, 128, 192, 255};
4105 verifyResultsExternalYUVVS(target, pixelColor);
4106
4107 // Clean up
4108 eglDestroyImageKHR(window->getDisplay(), image);
4109 destroyAndroidHardwareBuffer(source);
4110 }
4111
4112 // Test using glCopySubTextureCHROMIUM with YUV AHB as the source
TEST_P(ImageTestES3,SourceYUVAHBTargetExternalCopySrc)4113 TEST_P(ImageTestES3, SourceYUVAHBTargetExternalCopySrc)
4114 {
4115 EGLWindow *window = getEGLWindow();
4116
4117 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4118 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4119 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4120 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_CHROMIUM_copy_texture"));
4121
4122 // 3 planes of data
4123 GLubyte dataY[4] = {7, 51, 197, 231};
4124 GLubyte dataCb[1] = {
4125 128,
4126 };
4127 GLubyte dataCr[1] = {
4128 192,
4129 };
4130
4131 // Create the Image
4132 AHardwareBuffer *source;
4133 EGLImageKHR image;
4134 createEGLImageAndroidHardwareBufferSource(
4135 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
4136 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
4137
4138 // Create a texture target to bind the egl image
4139 GLTexture yuv;
4140 createEGLImageTargetTextureExternal(image, yuv);
4141
4142 // Create a texture to be the destination of copy
4143 GLTexture copyDst;
4144 glBindTexture(GL_TEXTURE_2D, copyDst);
4145 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 2, 2);
4146 glCopySubTextureCHROMIUM(yuv, 0, GL_TEXTURE_2D, copyDst, 0, 0, 0, 0, 0, 2, 2, false, false,
4147 false);
4148 ASSERT_GL_NO_ERROR();
4149
4150 // Verify the results
4151 GLFramebuffer fbo;
4152 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4153 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, copyDst, 0);
4154 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4155 ASSERT_GL_NO_ERROR();
4156
4157 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(92, 0, 0, 255), 2);
4158 EXPECT_PIXEL_COLOR_NEAR(1, 0, GLColor(143, 0, 41, 255), 2);
4159 EXPECT_PIXEL_COLOR_NEAR(0, 1, GLColor(255, 159, 211, 255), 2);
4160 EXPECT_PIXEL_COLOR_NEAR(1, 1, GLColor(255, 198, 250, 255), 2);
4161 ASSERT_GL_NO_ERROR();
4162
4163 // Clean up
4164 eglDestroyImageKHR(window->getDisplay(), image);
4165 destroyAndroidHardwareBuffer(source);
4166 }
4167
TEST_P(ImageTestES3,SourceYUVAHBTargetExternalYUVSampleLinearFiltering)4168 TEST_P(ImageTestES3, SourceYUVAHBTargetExternalYUVSampleLinearFiltering)
4169 {
4170 EGLWindow *window = getEGLWindow();
4171
4172 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4173 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4174 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4175
4176 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
4177 2, 4, 1, AHARDWAREBUFFER_FORMAT_YV12, kDefaultAHBYUVUsage));
4178
4179 // [ Red, Red]
4180 // [ Red, Red]
4181 // [Black, Black]
4182 // [Black, Black]
4183
4184 // clang-format off
4185 GLubyte dataY[] = {
4186 81, 81,
4187 81, 81,
4188 16, 16,
4189 16, 16,
4190 };
4191 GLubyte dataCb[] = {
4192 90,
4193 128,
4194 };
4195 GLubyte dataCr[] = {
4196 240,
4197 128,
4198 };
4199 // clang-format on
4200
4201 // Create the Image
4202 AHardwareBuffer *ahbSource;
4203 EGLImageKHR ahbImage;
4204 createEGLImageAndroidHardwareBufferSource(
4205 2, 4, 1, AHARDWAREBUFFER_FORMAT_YV12, kDefaultAHBYUVUsage, kDefaultAttribs,
4206 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &ahbSource, &ahbImage);
4207
4208 ASSERT_GL_NO_ERROR();
4209
4210 // Create a texture target to bind the egl image
4211 GLTexture ahbTexture;
4212 createEGLImageTargetTextureExternal(ahbImage, ahbTexture);
4213
4214 // Configure linear filtering
4215 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ahbTexture);
4216 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
4217 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
4218
4219 // Draw fullscreen sampling from ahbTexture.
4220 glUseProgram(mTextureExternalProgram);
4221 glBindTexture(GL_TEXTURE_EXTERNAL_OES, ahbTexture);
4222 glUniform1i(mTextureExternalUniformLocation, 0);
4223 drawQuad(mTextureExternalProgram, "position", 0.5f);
4224
4225 // Framebuffer needs to be bigger than the AHB so there is an area in between that will result
4226 // in half-red.
4227 const int windowHeight = getWindowHeight();
4228 ASSERT_GE(windowHeight, 8);
4229
4230 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::black, 1);
4231 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight - 1, GLColor::red, 1);
4232
4233 // Approximately half-red:
4234 EXPECT_PIXEL_COLOR_NEAR(0, windowHeight / 2, GLColor(127, 0, 0, 255), 15.0);
4235
4236 // Clean up
4237 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4238 destroyAndroidHardwareBuffer(ahbSource);
4239 }
4240
4241 // Test rendering to a YUV AHB using EXT_yuv_target
TEST_P(ImageTestES3,RenderToYUVAHB)4242 TEST_P(ImageTestES3, RenderToYUVAHB)
4243 {
4244 EGLWindow *window = getEGLWindow();
4245
4246 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4247 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4248 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4249
4250 // 3 planes of data, initialize to all zeroes
4251 GLubyte dataY[4] = {0, 0, 0, 0};
4252 GLubyte dataCb[1] = {
4253 0,
4254 };
4255 GLubyte dataCr[1] = {
4256 0,
4257 };
4258
4259 // Create the Image
4260 AHardwareBuffer *source;
4261 EGLImageKHR image;
4262 createEGLImageAndroidHardwareBufferSource(
4263 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
4264 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
4265
4266 // Create a texture target to bind the egl image
4267 GLTexture target;
4268 createEGLImageTargetTextureExternal(image, target);
4269
4270 // Set up a framebuffer to render into the AHB
4271 GLFramebuffer fbo;
4272 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4273 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target,
4274 0);
4275 ASSERT_GL_NO_ERROR();
4276 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4277
4278 GLubyte drawColor[4] = {197, 128, 192, 255};
4279
4280 glUseProgram(mRenderYUVProgram);
4281 glUniform4f(mRenderYUVUniformLocation, drawColor[0] / 255.0f, drawColor[1] / 255.0f,
4282 drawColor[2] / 255.0f, drawColor[3] / 255.0f);
4283
4284 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
4285 drawQuad(mRenderYUVProgram, "position", 0.0f);
4286 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4287 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4288 drawQuad(mRenderYUVProgram, "position", 0.0f);
4289 ASSERT_GL_NO_ERROR();
4290
4291 // ReadPixels returns the RGB converted color
4292 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0);
4293
4294 // Finish before reading back AHB data
4295 glFinish();
4296
4297 GLubyte expectedDataY[4] = {drawColor[0], drawColor[0], drawColor[0], drawColor[0]};
4298 GLubyte expectedDataCb[1] = {
4299 drawColor[1],
4300 };
4301 GLubyte expectedDataCr[1] = {
4302 drawColor[2],
4303 };
4304 verifyResultAHB(source, {{expectedDataY, 1}, {expectedDataCb, 1}, {expectedDataCr, 1}});
4305
4306 // Clean up
4307 eglDestroyImageKHR(window->getDisplay(), image);
4308 destroyAndroidHardwareBuffer(source);
4309 }
4310
4311 // Test rendering to a YUV AHB using EXT_yuv_target with a normal depth attachment
TEST_P(ImageTestES3,RenderToYUVAHBWithDepth)4312 TEST_P(ImageTestES3, RenderToYUVAHBWithDepth)
4313 {
4314 EGLWindow *window = getEGLWindow();
4315
4316 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4317 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4318 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4319
4320 // 3 planes of data, initialize to all zeroes
4321 GLubyte dataY[4] = {0, 0, 0, 0};
4322 GLubyte dataCb[1] = {
4323 0,
4324 };
4325 GLubyte dataCr[1] = {
4326 0,
4327 };
4328
4329 // Create the Image
4330 AHardwareBuffer *source;
4331 EGLImageKHR image;
4332 createEGLImageAndroidHardwareBufferSource(
4333 2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420, kDefaultAHBUsage, kDefaultAttribs,
4334 {{dataY, 1}, {dataCb, 1}, {dataCr, 1}}, &source, &image);
4335
4336 // Create a texture target to bind the egl image
4337 GLTexture target;
4338 createEGLImageTargetTextureExternal(image, target);
4339
4340 // Create a depth texture
4341 GLTexture depthTexture;
4342 glBindTexture(GL_TEXTURE_2D, depthTexture);
4343 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
4344 nullptr);
4345 EXPECT_GL_NO_ERROR();
4346
4347 // Set up a framebuffer to render into the AHB
4348 GLFramebuffer fbo;
4349 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4350 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target,
4351 0);
4352 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4353 ASSERT_GL_NO_ERROR();
4354 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4355
4356 GLubyte drawColor[4] = {197, 128, 192, 255};
4357
4358 glUseProgram(mRenderYUVProgram);
4359 glUniform4f(mRenderYUVUniformLocation, drawColor[0] / 255.0f, drawColor[1] / 255.0f,
4360 drawColor[2] / 255.0f, drawColor[3] / 255.0f);
4361
4362 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
4363 drawQuad(mRenderYUVProgram, "position", 0.0f);
4364 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
4365 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4366 drawQuad(mRenderYUVProgram, "position", 0.0f);
4367 ASSERT_GL_NO_ERROR();
4368
4369 // ReadPixels returns the RGB converted color
4370 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0);
4371
4372 // Finish before reading back AHB data
4373 glFinish();
4374
4375 GLubyte expectedDataY[4] = {drawColor[0], drawColor[0], drawColor[0], drawColor[0]};
4376 GLubyte expectedDataCb[1] = {
4377 drawColor[1],
4378 };
4379 GLubyte expectedDataCr[1] = {
4380 drawColor[2],
4381 };
4382 verifyResultAHB(source, {{expectedDataY, 1}, {expectedDataCb, 1}, {expectedDataCr, 1}});
4383
4384 // Clean up
4385 eglDestroyImageKHR(window->getDisplay(), image);
4386 destroyAndroidHardwareBuffer(source);
4387 }
4388
4389 // Test clearing to a YUV AHB using EXT_yuv_target
TEST_P(ImageTestES3,ClearYUVAHB)4390 TEST_P(ImageTestES3, ClearYUVAHB)
4391 {
4392 EGLWindow *window = getEGLWindow();
4393
4394 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4395 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4396
4397 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
4398 AHardwareBuffer *source;
4399 EGLImageKHR image;
4400 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
4401 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
4402 &image);
4403
4404 // Create a texture target to bind the egl image
4405 GLTexture target;
4406 createEGLImageTargetTextureExternal(image, target);
4407
4408 // Set up a framebuffer to render into the AHB
4409 GLFramebuffer fbo;
4410 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4411 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target,
4412 0);
4413 ASSERT_GL_NO_ERROR();
4414 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4415
4416 // Clearing a YUV framebuffer reinterprets the rgba clear color as YUV values and writes them
4417 // directly to the buffer
4418 GLubyte clearColor[4] = {197, 128, 192, 255};
4419 glClearColor(clearColor[0] / 255.0f, clearColor[1] / 255.0f, clearColor[2] / 255.0f,
4420 clearColor[3] / 255.0f);
4421 glClear(GL_COLOR_BUFFER_BIT);
4422 ASSERT_GL_NO_ERROR();
4423
4424 // ReadPixels returns the RGB converted color
4425 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0);
4426
4427 // Clean up
4428 eglDestroyImageKHR(window->getDisplay(), image);
4429 destroyAndroidHardwareBuffer(source);
4430 }
4431
4432 // Test clearing to a YUV AHB using EXT_yuv_target with a normal depth attachment
TEST_P(ImageTestES3,ClearYUVAHBWithDepth)4433 TEST_P(ImageTestES3, ClearYUVAHBWithDepth)
4434 {
4435 EGLWindow *window = getEGLWindow();
4436
4437 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
4438 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4439
4440 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
4441 AHardwareBuffer *source;
4442 EGLImageKHR image;
4443 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
4444 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
4445 &image);
4446
4447 // Create a texture target to bind the egl image
4448 GLTexture target;
4449 createEGLImageTargetTextureExternal(image, target);
4450
4451 // Create a depth texture
4452 GLTexture depthTexture;
4453 glBindTexture(GL_TEXTURE_2D, depthTexture);
4454 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, 2, 2, 0, GL_DEPTH_COMPONENT, GL_FLOAT,
4455 nullptr);
4456 EXPECT_GL_NO_ERROR();
4457
4458 // Set up a framebuffer to render into the AHB
4459 GLFramebuffer fbo;
4460 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
4461 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES, target,
4462 0);
4463 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTexture, 0);
4464 ASSERT_GL_NO_ERROR();
4465 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4466
4467 // Clearing a YUV framebuffer reinterprets the rgba clear color as YUV values and writes them
4468 // directly to the buffer
4469 GLubyte clearColor[4] = {197, 128, 192, 255};
4470 glClearColor(clearColor[0] / 255.0f, clearColor[1] / 255.0f, clearColor[2] / 255.0f,
4471 clearColor[3] / 255.0f);
4472 glClear(GL_COLOR_BUFFER_BIT);
4473 ASSERT_GL_NO_ERROR();
4474
4475 // ReadPixels returns the RGB converted color
4476 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, 159, 212, 255), 1.0);
4477
4478 // Clean up
4479 eglDestroyImageKHR(window->getDisplay(), image);
4480 destroyAndroidHardwareBuffer(source);
4481 }
4482
4483 // Test glClear on FBO with AHB attachment is applied to the AHB image before we read back
TEST_P(ImageTestES3,AHBClearAppliedBeforeReadBack)4484 TEST_P(ImageTestES3, AHBClearAppliedBeforeReadBack)
4485 {
4486 EGLWindow *window = getEGLWindow();
4487
4488 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4489 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4490 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4491
4492 const GLubyte kRed[] = {255, 0, 0, 255};
4493 const GLubyte kBlack[] = {0, 0, 0, 0};
4494
4495 // Create one image backed by the AHB.
4496 AHardwareBuffer *ahb;
4497 EGLImageKHR ahbImage;
4498 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4499 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4500 &ahb, &ahbImage);
4501 GLTexture ahbTexture;
4502 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4503
4504 // Create one framebuffer backed by the AHB.
4505 {
4506 GLFramebuffer ahbFbo;
4507 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4508 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4509 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4510
4511 // Clear to red
4512 glClearColor(1, 0, 0, 1);
4513 glClear(GL_COLOR_BUFFER_BIT);
4514 glFinish();
4515 }
4516
4517 verifyResultAHB(ahb, {{kRed, 4}});
4518
4519 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4520 destroyAndroidHardwareBuffer(ahb);
4521 }
4522
4523 // Similar to AHBClearAppliedBeforeReadBack, but clear is applied glClearTexImage().
TEST_P(ImageTestES3,AHBClearAppliedViaClearTexImageBeforeReadBack)4524 TEST_P(ImageTestES3, AHBClearAppliedViaClearTexImageBeforeReadBack)
4525 {
4526 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clear_texture"));
4527 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4528 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4529 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4530 EGLWindow *window = getEGLWindow();
4531
4532 const GLubyte kRed[] = {255, 0, 0, 255};
4533 const GLubyte kBlack[] = {0, 0, 0, 0};
4534
4535 // Create one image backed by the AHB.
4536 AHardwareBuffer *ahb;
4537 EGLImageKHR ahbImage;
4538 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4539 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4540 &ahb, &ahbImage);
4541 GLTexture ahbTexture;
4542 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4543
4544 // Clear to red
4545 glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
4546 glFinish();
4547
4548 verifyResultAHB(ahb, {{kRed, 4}});
4549
4550 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4551 destroyAndroidHardwareBuffer(ahb);
4552 }
4553
4554 // Similar to AHBClearAppliedBeforeReadBack, but clear is applied twice.
TEST_P(ImageTestES3,AHBTwiceClearAppliedBeforeReadBack)4555 TEST_P(ImageTestES3, AHBTwiceClearAppliedBeforeReadBack)
4556 {
4557 EGLWindow *window = getEGLWindow();
4558
4559 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4560 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4561 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4562
4563 const GLubyte kRed[] = {255, 0, 0, 255};
4564 const GLubyte kBlack[] = {0, 0, 0, 0};
4565
4566 // Create one image backed by the AHB.
4567 AHardwareBuffer *ahb;
4568 EGLImageKHR ahbImage;
4569 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4570 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4571 &ahb, &ahbImage);
4572 GLTexture ahbTexture;
4573 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4574
4575 // Create one framebuffer backed by the AHB.
4576 {
4577 GLFramebuffer ahbFbo;
4578 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4579 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4580 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4581
4582 // Clear to green, then to red
4583 glClearColor(0, 1, 0, 1);
4584 glClear(GL_COLOR_BUFFER_BIT);
4585 glClearColor(1, 0, 0, 1);
4586 glClear(GL_COLOR_BUFFER_BIT);
4587 glFinish();
4588 }
4589
4590 verifyResultAHB(ahb, {{kRed, 4}});
4591
4592 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4593 destroyAndroidHardwareBuffer(ahb);
4594 }
4595
4596 // Similar to AHBTwiceClearAppliedBeforeReadBack, but clear is applied using glClearTexImage().
TEST_P(ImageTestES3,AHBTwiceClearViaClearTexImageAppliedBeforeReadBack)4597 TEST_P(ImageTestES3, AHBTwiceClearViaClearTexImageAppliedBeforeReadBack)
4598 {
4599 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_clear_texture"));
4600 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4601 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4602 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4603 EGLWindow *window = getEGLWindow();
4604
4605 const GLubyte kRed[] = {255, 0, 0, 255};
4606 const GLubyte kBlack[] = {0, 0, 0, 0};
4607
4608 // Create one image backed by the AHB.
4609 AHardwareBuffer *ahb;
4610 EGLImageKHR ahbImage;
4611 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4612 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4613 &ahb, &ahbImage);
4614 GLTexture ahbTexture;
4615 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4616
4617 // Clear to green, then to red
4618 glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
4619 glClearTexImageEXT(ahbTexture, 0, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::red);
4620 glFinish();
4621
4622 verifyResultAHB(ahb, {{kRed, 4}});
4623
4624 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4625 destroyAndroidHardwareBuffer(ahb);
4626 }
4627
4628 // Test that glClear on FBO with AHB attachment is applied to the AHB image before detaching the AHB
4629 // image from FBO
TEST_P(ImageTestES3,AHBClearAndDetachBeforeReadback)4630 TEST_P(ImageTestES3, AHBClearAndDetachBeforeReadback)
4631 {
4632 EGLWindow *window = getEGLWindow();
4633
4634 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4635 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4636 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4637
4638 const GLubyte kRed[] = {255, 0, 0, 255};
4639 const GLubyte kBlack[] = {0, 0, 0, 0};
4640
4641 // Create one image backed by the AHB.
4642 AHardwareBuffer *ahb;
4643 EGLImageKHR ahbImage;
4644 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4645 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4646 &ahb, &ahbImage);
4647 GLTexture ahbTexture;
4648 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4649
4650 // Create one framebuffer backed by the AHB.
4651 {
4652 GLFramebuffer ahbFbo;
4653 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4654 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4655 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4656
4657 // Clear to red
4658 glClearColor(1, 0, 0, 1);
4659 glClear(GL_COLOR_BUFFER_BIT);
4660
4661 // Detach the AHB image from the FBO color attachment
4662 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
4663 glFinish();
4664 }
4665
4666 verifyResultAHB(ahb, {{kRed, 4}});
4667
4668 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4669 destroyAndroidHardwareBuffer(ahb);
4670 }
4671
4672 // Test that glClear on FBO with AHB color attachment is applied to the AHB image before implicity
4673 // unbinding the AHB image from FBO
TEST_P(ImageTestES3,AHBClearAndAttachAnotherTextureBeforeReadback)4674 TEST_P(ImageTestES3, AHBClearAndAttachAnotherTextureBeforeReadback)
4675 {
4676 EGLWindow *window = getEGLWindow();
4677
4678 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4679 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4680 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4681
4682 const GLubyte kRed[] = {255, 0, 0, 255};
4683 const GLubyte kBlack[] = {0, 0, 0, 0};
4684
4685 // Create one image backed by the AHB.
4686 AHardwareBuffer *ahb;
4687 EGLImageKHR ahbImage;
4688 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4689 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4690 &ahb, &ahbImage);
4691 GLTexture ahbTexture;
4692 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4693
4694 // Create one framebuffer backed by the AHB.
4695 {
4696 GLFramebuffer ahbFbo;
4697 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4698 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4699 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4700
4701 // Clear to red
4702 glClearColor(1, 0, 0, 1);
4703 glClear(GL_COLOR_BUFFER_BIT);
4704
4705 // Attach a random texture to the same FBO color attachment slot that AHB image was attached
4706 // to, this should implicity detach the AHB image from the FBO.
4707 GLTexture newTexture;
4708 glBindTexture(GL_TEXTURE_2D, newTexture);
4709 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
4710 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, newTexture, 0);
4711 glFinish();
4712 }
4713
4714 verifyResultAHB(ahb, {{kRed, 4}});
4715
4716 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4717 destroyAndroidHardwareBuffer(ahb);
4718 }
4719
4720 // Test glClear to FBO with AHB color attachment is applied to the AHB image before we switch back
4721 // to the default FBO
TEST_P(ImageTestES3,AHBClearAndSwitchToDefaultFBOBeforeReadBack)4722 TEST_P(ImageTestES3, AHBClearAndSwitchToDefaultFBOBeforeReadBack)
4723 {
4724 EGLWindow *window = getEGLWindow();
4725
4726 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4727 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4728 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4729
4730 const GLubyte kRed[] = {255, 0, 0, 255};
4731 const GLubyte kBlack[] = {0, 0, 0, 0};
4732
4733 // Create one image backed by the AHB.
4734 AHardwareBuffer *ahb;
4735 EGLImageKHR ahbImage;
4736 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4737 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4738 &ahb, &ahbImage);
4739 GLTexture ahbTexture;
4740 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4741
4742 // Create one framebuffer backed by the AHB.
4743 {
4744 GLFramebuffer ahbFbo;
4745 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4746 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4747 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4748
4749 // Clear to red
4750 glClearColor(1, 0, 0, 1);
4751 glClear(GL_COLOR_BUFFER_BIT);
4752
4753 // Switch to default FBO
4754 glBindFramebuffer(GL_FRAMEBUFFER, 0);
4755 glFinish();
4756 }
4757
4758 verifyResultAHB(ahb, {{kRed, 4}});
4759
4760 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4761 destroyAndroidHardwareBuffer(ahb);
4762 }
4763
4764 // Test glClear on FBO with AHB color attachment is applied to the AHB image with glClientWaitSync
TEST_P(ImageTestES3,AHBClearWithGLClientWaitSyncBeforeReadBack)4765 TEST_P(ImageTestES3, AHBClearWithGLClientWaitSyncBeforeReadBack)
4766 {
4767 EGLWindow *window = getEGLWindow();
4768
4769 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4770 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4771 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
4772
4773 const GLubyte kRed[] = {255, 0, 0, 255};
4774 const GLubyte kBlack[] = {0, 0, 0, 0};
4775
4776 // Create one image backed by the AHB.
4777 AHardwareBuffer *ahb;
4778 EGLImageKHR ahbImage;
4779 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4780 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
4781 &ahb, &ahbImage);
4782 GLTexture ahbTexture;
4783 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4784
4785 // Create one framebuffer backed by the AHB.
4786 {
4787 GLFramebuffer ahbFbo;
4788 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4789 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4790 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4791
4792 // Clear to red
4793 glClearColor(1, 0, 0, 1);
4794 glClear(GL_COLOR_BUFFER_BIT);
4795
4796 // Create a GLSync object and immediately wait on it
4797 GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
4798 glClientWaitSync(sync, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
4799 }
4800
4801 verifyResultAHB(ahb, {{kRed, 4}});
4802
4803 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4804 destroyAndroidHardwareBuffer(ahb);
4805 }
4806
4807 // Test glDraw + glFlush on FBO with AHB attachment are applied to the AHB image before we read back
TEST_P(ImageTestES3,AHBDrawFlushAppliedBeforeReadBack)4808 TEST_P(ImageTestES3, AHBDrawFlushAppliedBeforeReadBack)
4809 {
4810 EGLWindow *window = getEGLWindow();
4811 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4812 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4813 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport() || !kHasAHBFrontBufferUsageSupport);
4814
4815 // Create a GLTexture backed by the AHB.
4816 AHardwareBuffer *ahb;
4817 EGLImageKHR ahbImage;
4818 const GLubyte kBlack[] = {0, 0, 0, 0};
4819 const GLubyte kRed[] = {255, 0, 0, 255};
4820 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4821 kDefaultAHBUsage | kAHBUsageFrontBuffer,
4822 kDefaultAttribs, {{kBlack, 4}}, &ahb, &ahbImage);
4823 GLTexture ahbTexture;
4824 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4825
4826 // Create one framebuffer backed by the AHB-based GLTexture
4827 GLFramebuffer ahbFbo;
4828 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4829 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4830 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4831
4832 // Draw to the FBO and call glFlush()
4833 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4834 glUseProgram(drawColor);
4835 GLint colorUniformLocation =
4836 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4837 ASSERT_NE(colorUniformLocation, -1);
4838
4839 glUniform4f(colorUniformLocation, kRed[0] / 255.0f, kRed[1] / 255.0f, kRed[2] / 255.0f,
4840 kRed[3] / 255.0f);
4841 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4842 glFlush();
4843 // unlike glFinish(), glFlush() does not wait for commands execution to complete.
4844 // sleep for 1 second before reading back from AHB.
4845 angle::Sleep(1000);
4846
4847 // Verify the result
4848 verifyResultAHB(ahb, {{kRed, 4}});
4849
4850 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4851 destroyAndroidHardwareBuffer(ahb);
4852 }
4853
4854 // Test that glDraw + glFlush on FBO with AHB attachment are applied to the AHB
4855 // image before detaching the AHB image from FBO
TEST_P(ImageTestES3,AHBDrawFlushAndDetachBeforeReadBack)4856 TEST_P(ImageTestES3, AHBDrawFlushAndDetachBeforeReadBack)
4857 {
4858 EGLWindow *window = getEGLWindow();
4859 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4860 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4861 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport() || !kHasAHBFrontBufferUsageSupport);
4862
4863 // Create a GLTexture backed by the AHB.
4864 AHardwareBuffer *ahb;
4865 EGLImageKHR ahbImage;
4866 const GLubyte kBlack[] = {0, 0, 0, 0};
4867 const GLubyte kRed[] = {255, 0, 0, 255};
4868 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4869 kDefaultAHBUsage | kAHBUsageFrontBuffer,
4870 kDefaultAttribs, {{kBlack, 4}}, &ahb, &ahbImage);
4871 GLTexture ahbTexture;
4872 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4873
4874 // Create one framebuffer backed by the AHB-based GLTexture
4875 GLFramebuffer ahbFbo;
4876 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4877 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4878 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4879
4880 // Draw to the FBO and call glFlush()
4881 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4882 glUseProgram(drawColor);
4883 GLint colorUniformLocation =
4884 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4885 ASSERT_NE(colorUniformLocation, -1);
4886
4887 glUniform4f(colorUniformLocation, kRed[0] / 255.0f, kRed[1] / 255.0f, kRed[2] / 255.0f,
4888 kRed[3] / 255.0f);
4889 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4890
4891 glFlush();
4892 // unlike glFinish(), glFlush() does not wait for commands execution to complete.
4893 // sleep for 1 second before reading back from AHB.
4894 angle::Sleep(1000);
4895
4896 // Detach the AHB image from the FBO color attachment
4897 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
4898
4899 // Verify the result
4900 verifyResultAHB(ahb, {{kRed, 4}});
4901
4902 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4903 destroyAndroidHardwareBuffer(ahb);
4904 }
4905
4906 // Test that glDraw + glFlush on FBO with AHB attachment are applied to the AHB
4907 // image before implicitly unbinding the AHB image from FBO
TEST_P(ImageTestES3,AHBDrawFlushAndAttachAnotherTextureBeforeReadBack)4908 TEST_P(ImageTestES3, AHBDrawFlushAndAttachAnotherTextureBeforeReadBack)
4909 {
4910 EGLWindow *window = getEGLWindow();
4911 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4912 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4913 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport() || !kHasAHBFrontBufferUsageSupport);
4914
4915 // Create a GLTexture backed by the AHB.
4916 AHardwareBuffer *ahb;
4917 EGLImageKHR ahbImage;
4918 const GLubyte kBlack[] = {0, 0, 0, 0};
4919 const GLubyte kRed[] = {255, 0, 0, 255};
4920 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4921 kDefaultAHBUsage | kAHBUsageFrontBuffer,
4922 kDefaultAttribs, {{kBlack, 4}}, &ahb, &ahbImage);
4923 GLTexture ahbTexture;
4924 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4925
4926 // Create one framebuffer backed by the AHB-based GLTexture
4927 GLFramebuffer ahbFbo;
4928 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4929 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4930 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4931
4932 // Draw to the FBO and call glFlush()
4933 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4934 glUseProgram(drawColor);
4935 GLint colorUniformLocation =
4936 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4937 ASSERT_NE(colorUniformLocation, -1);
4938
4939 glUniform4f(colorUniformLocation, kRed[0] / 255.0f, kRed[1] / 255.0f, kRed[2] / 255.0f,
4940 kRed[3] / 255.0f);
4941 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4942
4943 glFlush();
4944 // unlike glFinish(), glFlush() does not wait for commands execution to complete.
4945 // sleep for 1 second before reading back from AHB.
4946 angle::Sleep(1000);
4947
4948 // Attach a random texture to the same FBO color attachment slot that AHB image was attached
4949 // to, this should implicity detach the AHB image from the FBO.
4950 GLTexture newTexture;
4951 glBindTexture(GL_TEXTURE_2D, newTexture);
4952 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
4953 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, newTexture, 0);
4954
4955 // Verify the result
4956 verifyResultAHB(ahb, {{kRed, 4}});
4957
4958 eglDestroyImageKHR(window->getDisplay(), ahbImage);
4959 destroyAndroidHardwareBuffer(ahb);
4960 }
4961
4962 // Test that glDraw + glFlush on FBO with AHB attachment are applied to the AHB
4963 // image before switching to the default FBO
TEST_P(ImageTestES3,AHBDrawFlushAndSwitchToDefaultFBOBeforeReadBack)4964 TEST_P(ImageTestES3, AHBDrawFlushAndSwitchToDefaultFBOBeforeReadBack)
4965 {
4966 EGLWindow *window = getEGLWindow();
4967 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
4968 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
4969 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport() || !kHasAHBFrontBufferUsageSupport);
4970
4971 // Create a GLTexture backed by the AHB.
4972 AHardwareBuffer *ahb;
4973 EGLImageKHR ahbImage;
4974 const GLubyte kBlack[] = {0, 0, 0, 0};
4975 const GLubyte kRed[] = {255, 0, 0, 255};
4976 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
4977 kDefaultAHBUsage | kAHBUsageFrontBuffer,
4978 kDefaultAttribs, {{kBlack, 4}}, &ahb, &ahbImage);
4979 GLTexture ahbTexture;
4980 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
4981
4982 // Create one framebuffer backed by the AHB-based GLTexture
4983 GLFramebuffer ahbFbo;
4984 glBindFramebuffer(GL_FRAMEBUFFER, ahbFbo);
4985 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
4986 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
4987
4988 // Draw to the FBO and call glFlush()
4989 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
4990 glUseProgram(drawColor);
4991 GLint colorUniformLocation =
4992 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
4993 ASSERT_NE(colorUniformLocation, -1);
4994
4995 glUniform4f(colorUniformLocation, kRed[0] / 255.0f, kRed[1] / 255.0f, kRed[2] / 255.0f,
4996 kRed[3] / 255.0f);
4997 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
4998
4999 glFlush();
5000 // unlike glFinish(), glFlush() does not wait for commands execution to complete.
5001 // sleep for 1 second before reading back from AHB.
5002 angle::Sleep(1000);
5003
5004 // Switch to default FBO
5005 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5006
5007 // Verify the result
5008 verifyResultAHB(ahb, {{kRed, 4}});
5009
5010 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5011 destroyAndroidHardwareBuffer(ahb);
5012 }
5013
5014 // Test that texture swizzle parameters work with EGL image-backed textures
TEST_P(ImageTestES3,AHBTextureSwizzleParameters)5015 TEST_P(ImageTestES3, AHBTextureSwizzleParameters)
5016 {
5017 EGLWindow *window = getEGLWindow();
5018 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5019 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5020 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5021
5022 // Create the Image
5023 AHardwareBuffer *ahb;
5024 EGLImageKHR ahbImage;
5025 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5026 kDefaultAHBUsage, kDefaultAttribs,
5027 {{kLinearColor, 4}}, &ahb, &ahbImage);
5028
5029 GLTexture ahbTexture;
5030 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5031
5032 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5033 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_GREEN);
5034 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, GL_BLUE);
5035 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
5036
5037 GLubyte expectedColor[] = {kLinearColor[1], kLinearColor[2], kLinearColor[0], kLinearColor[3]};
5038 verifyResults2D(ahbTexture, expectedColor);
5039
5040 // Clean up
5041 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5042 destroyAndroidHardwareBuffer(ahb);
5043 }
5044
5045 // Test that RGBX data are preserved when importing from AHB. Regression test for a bug in the
5046 // Vulkan backend where the image was cleared due to format emulation.
TEST_P(ImageTestES3,RGBXAHBImportPreservesData)5047 TEST_P(ImageTestES3, RGBXAHBImportPreservesData)
5048 {
5049 EGLWindow *window = getEGLWindow();
5050 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5051 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5052 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5053
5054 // Create the Image
5055 AHardwareBuffer *ahb;
5056 EGLImageKHR ahbImage;
5057 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5058 kDefaultAHBUsage, kDefaultAttribs,
5059 {{kLinearColor, 4}}, &ahb, &ahbImage);
5060
5061 GLTexture ahbTexture;
5062 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5063
5064 verifyResults2D(ahbTexture, kLinearColor);
5065 verifyResultAHB(ahb, {{kLinearColor, 4}});
5066
5067 // Clean up
5068 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5069 destroyAndroidHardwareBuffer(ahb);
5070 }
5071
5072 // Test that RGBX data are preserved when importing from AHB created with sRGB color space.
TEST_P(ImageTestES3,RGBXAHBImportPreservesData_Colorspace)5073 TEST_P(ImageTestES3, RGBXAHBImportPreservesData_Colorspace)
5074 {
5075 EGLWindow *window = getEGLWindow();
5076
5077 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5078 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5079 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5080
5081 const GLubyte kRed50SRGB[] = {188, 0, 0, 255};
5082 const GLubyte kRed50Linear[] = {128, 0, 0, 255};
5083
5084 // Create the Image
5085 AHardwareBuffer *ahb;
5086 EGLImageKHR ahbImage;
5087 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5088 kDefaultAHBUsage, kColorspaceAttribs,
5089 {{kRed50SRGB, 4}}, &ahb, &ahbImage);
5090
5091 GLTexture ahbTexture;
5092 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5093
5094 verifyResults2D(ahbTexture, kRed50Linear);
5095 verifyResultAHB(ahb, {{kRed50SRGB, 4}});
5096
5097 // Clean up
5098 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5099 destroyAndroidHardwareBuffer(ahb);
5100 }
5101
5102 // Tests that RGBX can be successfully loaded with 3-channel data and read back as 4-channel data.
TEST_P(ImageTestES3,RGBXAHBUploadDownload)5103 TEST_P(ImageTestES3, RGBXAHBUploadDownload)
5104 {
5105 EGLWindow *window = getEGLWindow();
5106
5107 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5108 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5109 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport() || !hasRGBXInternalFormatExt());
5110
5111 const size_t kWidth = 32;
5112 const size_t kHeight = 32;
5113
5114 const GLubyte kBlack[] = {0, 0, 0, 255};
5115 const GLubyte kCyan[] = {0, 255, 255};
5116
5117 std::vector<GLubyte> pixelsRGBABlack;
5118 for (size_t h = 0; h < kHeight; h++)
5119 {
5120 for (size_t w = 0; w < kWidth; w++)
5121 {
5122 pixelsRGBABlack.push_back(kBlack[0]);
5123 pixelsRGBABlack.push_back(kBlack[1]);
5124 pixelsRGBABlack.push_back(kBlack[2]);
5125 pixelsRGBABlack.push_back(kBlack[3]);
5126 }
5127 }
5128
5129 std::vector<GLubyte> pixelsRGBCyan;
5130 for (size_t h = 0; h < kHeight; h++)
5131 {
5132 for (size_t w = 0; w < kWidth; w++)
5133 {
5134 pixelsRGBCyan.push_back(kCyan[0]);
5135 pixelsRGBCyan.push_back(kCyan[1]);
5136 pixelsRGBCyan.push_back(kCyan[2]);
5137 }
5138 }
5139
5140 // Create the Image
5141 AHardwareBuffer *ahb;
5142 EGLImageKHR ahbImage;
5143 createEGLImageAndroidHardwareBufferSource(
5144 kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, kDefaultAHBUsage,
5145 kDefaultAttribs, {{pixelsRGBABlack.data(), 4}}, &ahb, &ahbImage);
5146
5147 GLTexture ahbTexture;
5148 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5149
5150 verifyResults2D(ahbTexture, kBlack);
5151 verifyResultAHB(ahb, {{pixelsRGBABlack.data(), 4}});
5152
5153 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5154 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kWidth, kHeight, GL_RGB, GL_UNSIGNED_BYTE,
5155 pixelsRGBCyan.data());
5156 ASSERT_GL_NO_ERROR();
5157
5158 GLFramebuffer ahbFramebuffer;
5159 glBindFramebuffer(GL_FRAMEBUFFER, ahbFramebuffer);
5160 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
5161 ASSERT_GL_NO_ERROR();
5162 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5163
5164 std::vector<GLubyte> readback;
5165 readback.resize(kWidth * kHeight * 4);
5166 glReadPixels(0, 0, kWidth, kHeight, GL_RGBX8_ANGLE, GL_UNSIGNED_BYTE, readback.data());
5167
5168 for (size_t y = 0; y < kHeight; y++)
5169 {
5170 const GLubyte *actualRowData = readback.data() + (y * kWidth * 4);
5171 for (size_t x = 0; x < kWidth; x++)
5172 {
5173 const GLubyte *actualPixelData = actualRowData + (x * 4);
5174 EXPECT_EQ(actualPixelData[0], kCyan[0]) << "at (" << x << ", " << y << ")";
5175 EXPECT_EQ(actualPixelData[1], kCyan[1]) << "at (" << x << ", " << y << ")";
5176 EXPECT_EQ(actualPixelData[2], kCyan[2]) << "at (" << x << ", " << y << ")";
5177 }
5178 }
5179
5180 // Clean up
5181 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5182 destroyAndroidHardwareBuffer(ahb);
5183 }
5184
5185 // Test that RGBA data are preserved when importing from AHB and glTexSubImage is able to update
5186 // data.
TEST_P(ImageTestES3,RGBAAHBUploadData)5187 TEST_P(ImageTestES3, RGBAAHBUploadData)
5188 {
5189 EGLWindow *window = getEGLWindow();
5190
5191 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5192 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5193 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5194
5195 const GLubyte kGarbage[] = {123, 123, 123, 123};
5196 const GLubyte kRed50Linear[] = {128, 0, 0, 127};
5197
5198 // Create the Image
5199 AHardwareBuffer *ahb;
5200 EGLImageKHR ahbImage;
5201 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5202 kDefaultAHBUsage, kDefaultAttribs, {{kGarbage, 4}},
5203 &ahb, &ahbImage);
5204
5205 GLTexture ahbTexture;
5206 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5207
5208 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5209 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kRed50Linear);
5210 glFinish();
5211
5212 verifyResults2D(ahbTexture, kRed50Linear);
5213 verifyResultAHB(ahb, {{kRed50Linear, 4}});
5214
5215 // Clean up
5216 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5217 destroyAndroidHardwareBuffer(ahb);
5218 }
5219
5220 // Test that RGBA data are preserved when importing from AHB with sRGB color space and glTexSubImage
5221 // is able to update data.
TEST_P(ImageTestES3,RGBAAHBUploadDataColorspace)5222 TEST_P(ImageTestES3, RGBAAHBUploadDataColorspace)
5223 {
5224 EGLWindow *window = getEGLWindow();
5225
5226 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5227 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5228 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5229
5230 const GLubyte kGarbage[] = {123, 123, 123, 123};
5231 const GLubyte kRed50SRGB[] = {188, 0, 0, 128};
5232 const GLubyte kRed50Linear[] = {128, 0, 0, 127};
5233
5234 // Create the Image
5235 AHardwareBuffer *ahb;
5236 EGLImageKHR ahbImage;
5237 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5238 kDefaultAHBUsage, kColorspaceAttribs, {{kGarbage, 4}},
5239 &ahb, &ahbImage);
5240
5241 GLTexture ahbTexture;
5242 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5243
5244 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5245 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kRed50SRGB);
5246 glFinish();
5247
5248 verifyResults2D(ahbTexture, kRed50Linear);
5249 verifyResultAHB(ahb, {{kRed50SRGB, 4}});
5250
5251 // Clean up
5252 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5253 destroyAndroidHardwareBuffer(ahb);
5254 }
5255
5256 // Test that RGBX data are preserved when importing from AHB and glTexSubImage is able to update
5257 // data.
TEST_P(ImageTestES3,RGBXAHBUploadData)5258 TEST_P(ImageTestES3, RGBXAHBUploadData)
5259 {
5260 EGLWindow *window = getEGLWindow();
5261
5262 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5263 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5264 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5265
5266 const GLubyte kGarbage[] = {123, 123, 123, 123};
5267 const GLubyte kRed50Linear[] = {128, 0, 0, 255};
5268
5269 // Create the Image
5270 AHardwareBuffer *ahb;
5271 EGLImageKHR ahbImage;
5272 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5273 kDefaultAHBUsage, kDefaultAttribs, {{kGarbage, 4}},
5274 &ahb, &ahbImage);
5275
5276 GLTexture ahbTexture;
5277 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5278
5279 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5280 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, kRed50Linear);
5281 glFinish();
5282
5283 verifyResults2D(ahbTexture, kRed50Linear);
5284 verifyResultAHB(ahb, {{kRed50Linear, 4}});
5285
5286 // Clean up
5287 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5288 destroyAndroidHardwareBuffer(ahb);
5289 }
5290
5291 // Test that RGBX data are preserved when importing from AHB created with sRGB color space and
5292 // glTexSubImage is able to update data.
TEST_P(ImageTestES3,RGBXAHBUploadDataColorspace)5293 TEST_P(ImageTestES3, RGBXAHBUploadDataColorspace)
5294 {
5295 EGLWindow *window = getEGLWindow();
5296
5297 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5298 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5299 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5300
5301 const GLubyte kGarbage[] = {123, 123, 123, 123};
5302 const GLubyte kRed50SRGB[] = {188, 0, 0, 255};
5303 const GLubyte kRed50Linear[] = {128, 0, 0, 255};
5304
5305 // Create the Image
5306 AHardwareBuffer *ahb;
5307 EGLImageKHR ahbImage;
5308 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5309 kDefaultAHBUsage, kColorspaceAttribs,
5310 {{kGarbage, sizeof(kGarbage)}}, &ahb, &ahbImage);
5311
5312 GLTexture ahbTexture;
5313 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5314
5315 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5316 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, kRed50SRGB);
5317 glFinish();
5318
5319 verifyResults2D(ahbTexture, kRed50Linear);
5320 verifyResultAHB(ahb, {{kRed50SRGB, sizeof(kRed50SRGB)}});
5321
5322 // Clean up
5323 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5324 destroyAndroidHardwareBuffer(ahb);
5325 }
5326
5327 // Test that RGB data are preserved when importing from AHB created with sRGB color space and
5328 // glTexSubImage is able to update data.
TEST_P(ImageTestES3,RGBAHBUploadDataColorspace)5329 TEST_P(ImageTestES3, RGBAHBUploadDataColorspace)
5330 {
5331 EGLWindow *window = getEGLWindow();
5332
5333 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5334 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5335 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5336 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
5337 1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM, kDefaultAHBUsage));
5338
5339 const GLubyte kGarbage[] = {123, 123, 123};
5340 const GLubyte kRed50SRGB[] = {188, 0, 0};
5341 const GLubyte kRed50Linear[] = {128, 0, 0, 255};
5342
5343 // Create the Image
5344 AHardwareBuffer *ahb;
5345 EGLImageKHR ahbImage;
5346 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM,
5347 kDefaultAHBUsage, kColorspaceAttribs,
5348 {{kGarbage, sizeof(kGarbage)}}, &ahb, &ahbImage);
5349
5350 GLTexture ahbTexture;
5351 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5352
5353 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5354 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, kRed50SRGB);
5355 glFinish();
5356
5357 verifyResults2D(ahbTexture, kRed50Linear);
5358 verifyResultAHB(ahb, {{kRed50SRGB, sizeof(kRed50SRGB)}});
5359
5360 // Clean up
5361 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5362 destroyAndroidHardwareBuffer(ahb);
5363 }
5364
5365 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5366 // being cleared with no GPU_FRAMEBUFFER usage specified.
TEST_P(ImageTestES3,RGBXAHBImportNoFramebufferUsage)5367 TEST_P(ImageTestES3, RGBXAHBImportNoFramebufferUsage)
5368 {
5369 EGLWindow *window = getEGLWindow();
5370
5371 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5372 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5373 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5374
5375 // Create the Image
5376 AHardwareBuffer *ahb;
5377 EGLImageKHR ahbImage;
5378 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5379 kAHBUsageGPUSampledImage, kDefaultAttribs,
5380 {{kLinearColor, 4}}, &ahb, &ahbImage);
5381
5382 GLTexture ahbTexture;
5383 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5384
5385 verifyResults2D(ahbTexture, kLinearColor);
5386 verifyResultAHB(ahb, {{kLinearColor, 4}});
5387
5388 // Clean up
5389 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5390 destroyAndroidHardwareBuffer(ahb);
5391 }
5392
5393 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5394 // being cleared with multiple layers.
TEST_P(ImageTestES3,RGBXAHBImportMultipleLayers)5395 TEST_P(ImageTestES3, RGBXAHBImportMultipleLayers)
5396 {
5397 EGLWindow *window = getEGLWindow();
5398
5399 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5400 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5401 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5402
5403 // Limit the test to single layer for now. writeAHBData is assuming alignment between layers
5404 // being 4096 which may not true on some GPUs. There is no API to retrieve such alignment from
5405 // driver. For now just limit to single layer so that we can still test single layer behavior
5406 // here.
5407 constexpr size_t kLayerCount = 1;
5408
5409 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
5410 1, 1, kLayerCount, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, kDefaultAHBUsage));
5411
5412 const GLubyte kInitColor[] = {132, 55, 219, 12, 77, 23, 190, 101, 231, 44, 143, 99};
5413
5414 // Create the Image
5415 AHardwareBuffer *ahb;
5416 EGLImageKHR ahbImage;
5417 createEGLImageAndroidHardwareBufferSource(
5418 1, 1, kLayerCount, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM, kDefaultAHBUsage, kDefaultAttribs,
5419 {{kInitColor, 4}}, &ahb, &ahbImage);
5420
5421 GLTexture ahbTexture;
5422 createEGLImageTargetTexture2DArray(ahbImage, ahbTexture);
5423
5424 // RGBX doesn't have alpha, so readback should return 255.
5425 const GLubyte kExpectedColor[] = {
5426 kInitColor[0], kInitColor[1], kInitColor[2], 255, kInitColor[4], kInitColor[5],
5427 kInitColor[6], 255, kInitColor[8], kInitColor[9], kInitColor[10], 255,
5428 };
5429 for (uint32_t layerIndex = 0; layerIndex < kLayerCount; ++layerIndex)
5430 {
5431 verifyResults2DArray(ahbTexture, kExpectedColor + 4 * layerIndex, layerIndex);
5432 }
5433 verifyResultAHB(ahb, {{kExpectedColor, 4}});
5434
5435 // Clean up
5436 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5437 destroyAndroidHardwareBuffer(ahb);
5438 }
5439
5440 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5441 // being cleared with glReadPixels.
TEST_P(ImageTestES3,RGBXAHBImportThenReadPixels)5442 TEST_P(ImageTestES3, RGBXAHBImportThenReadPixels)
5443 {
5444 EGLWindow *window = getEGLWindow();
5445
5446 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5447 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5448 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5449
5450 // Create the Image
5451 AHardwareBuffer *ahb;
5452 EGLImageKHR ahbImage;
5453 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5454 kDefaultAHBUsage, kDefaultAttribs,
5455 {{kLinearColor, 4}}, &ahb, &ahbImage);
5456
5457 GLTexture ahbTexture;
5458 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5459
5460 GLFramebuffer fbo;
5461 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5462 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
5463 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5464
5465 // RGBX doesn't have alpha, so readback should return 255. kLinearColor[3] is already 255.
5466 EXPECT_PIXEL_NEAR(0, 0, kLinearColor[0], kLinearColor[1], kLinearColor[2], kLinearColor[3], 1);
5467
5468 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5469
5470 verifyResults2D(ahbTexture, kLinearColor);
5471 verifyResultAHB(ahb, {{kLinearColor, 4}});
5472
5473 // Clean up
5474 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5475 destroyAndroidHardwareBuffer(ahb);
5476 }
5477
5478 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5479 // being cleared with a following clear.
TEST_P(ImageTestES3,RGBXAHBImportThenClear)5480 TEST_P(ImageTestES3, RGBXAHBImportThenClear)
5481 {
5482 EGLWindow *window = getEGLWindow();
5483
5484 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5485 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5486 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5487
5488 // Create the Image
5489 AHardwareBuffer *ahb;
5490 EGLImageKHR ahbImage;
5491 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5492 kDefaultAHBUsage, kDefaultAttribs,
5493 {{kLinearColor, 4}}, &ahb, &ahbImage);
5494
5495 GLTexture ahbTexture;
5496 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5497
5498 GLFramebuffer fbo;
5499 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5500 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
5501 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5502
5503 // Clear
5504 const GLubyte kClearColor[] = {63, 127, 191, 55};
5505 glClearColor(kClearColor[0] / 255.0f, kClearColor[1] / 255.0f, kClearColor[2] / 255.0f,
5506 kClearColor[3] / 255.0f);
5507 glClear(GL_COLOR_BUFFER_BIT);
5508
5509 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5510
5511 // RGBX doesn't have alpha, so readback should return 255.
5512 const GLubyte kExpectedColor[] = {kClearColor[0], kClearColor[1], kClearColor[2], 255};
5513 verifyResults2D(ahbTexture, kExpectedColor);
5514 verifyResultAHB(ahb, {{kExpectedColor, 4}});
5515
5516 // Clean up
5517 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5518 destroyAndroidHardwareBuffer(ahb);
5519 }
5520
5521 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5522 // being cleared with a following clear and a draw call.
TEST_P(ImageTestES3,RGBXAHBImportThenClearThenDraw)5523 TEST_P(ImageTestES3, RGBXAHBImportThenClearThenDraw)
5524 {
5525 EGLWindow *window = getEGLWindow();
5526
5527 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5528 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5529 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5530
5531 // Create the Image
5532 AHardwareBuffer *ahb;
5533 EGLImageKHR ahbImage;
5534 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5535 kDefaultAHBUsage, kDefaultAttribs,
5536 {{kLinearColor, 4}}, &ahb, &ahbImage);
5537
5538 GLTexture ahbTexture;
5539 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5540
5541 GLFramebuffer fbo;
5542 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5543 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
5544 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5545
5546 // Clear
5547 const GLubyte kClearColor[] = {63, 127, 191, 55};
5548 glClearColor(kClearColor[0] / 255.0f, kClearColor[1] / 255.0f, kClearColor[2] / 255.0f,
5549 kClearColor[3] / 255.0f);
5550 glClear(GL_COLOR_BUFFER_BIT);
5551
5552 // Draw with blend
5553 glEnable(GL_BLEND);
5554 glBlendFunc(GL_ONE, GL_ONE);
5555
5556 ANGLE_GL_PROGRAM(drawColor, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
5557 glUseProgram(drawColor);
5558 GLint colorUniformLocation =
5559 glGetUniformLocation(drawColor, angle::essl1_shaders::ColorUniform());
5560 ASSERT_NE(colorUniformLocation, -1);
5561
5562 glUniform4f(colorUniformLocation, 0.25f, 0.25f, 0.25f, 0.25f);
5563 drawQuad(drawColor, essl1_shaders::PositionAttrib(), 0.5f);
5564
5565 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5566 glDisable(GL_BLEND);
5567
5568 // RGBX doesn't have alpha, so readback should return 255.
5569 const GLubyte kExpectedColor[] = {static_cast<GLubyte>(kClearColor[0] + 64),
5570 static_cast<GLubyte>(kClearColor[1] + 64),
5571 static_cast<GLubyte>(kClearColor[2] + 64), 255};
5572 verifyResults2D(ahbTexture, kExpectedColor);
5573 verifyResultAHB(ahb, {{kExpectedColor, 4}});
5574
5575 // Clean up
5576 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5577 destroyAndroidHardwareBuffer(ahb);
5578 }
5579
5580 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5581 // being cleared with a following data upload.
TEST_P(ImageTestES3,RGBXAHBImportThenUpload)5582 TEST_P(ImageTestES3, RGBXAHBImportThenUpload)
5583 {
5584 EGLWindow *window = getEGLWindow();
5585
5586 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5587 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5588 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5589
5590 const GLubyte kInitColor[] = {132, 55, 219, 12, 132, 55, 219, 12};
5591
5592 // Create the Image
5593 AHardwareBuffer *ahb;
5594 EGLImageKHR ahbImage;
5595 createEGLImageAndroidHardwareBufferSource(2, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5596 kDefaultAHBUsage, kDefaultAttribs, {{kInitColor, 4}},
5597 &ahb, &ahbImage);
5598
5599 GLTexture ahbTexture;
5600 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5601
5602 // Upload data
5603 const GLubyte kUploadColor[] = {63, 127, 191, 55};
5604 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, kUploadColor);
5605 ASSERT_GL_NO_ERROR();
5606
5607 // RGBX doesn't have alpha, so readback should return 255.
5608 const GLubyte kExpectedColorRight[] = {kUploadColor[0], kUploadColor[1], kUploadColor[2], 255};
5609 const GLubyte kExpectedColorLeft[] = {kInitColor[0], kInitColor[1], kInitColor[2], 255};
5610 verifyResults2DLeftAndRight(ahbTexture, kExpectedColorLeft, kExpectedColorRight);
5611 verifyResultAHB(ahb, {{kExpectedColorLeft, 4}}, AHBVerifyRegion::LeftHalf);
5612 verifyResultAHB(ahb, {{kExpectedColorRight, 4}}, AHBVerifyRegion::RightHalf);
5613
5614 // Clean up
5615 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5616 destroyAndroidHardwareBuffer(ahb);
5617 }
5618
5619 // Tests interaction of emulated channel being cleared with a following data upload and immediately
5620 // ends to check that the image updates are processed and flushed without errors. It is similar to
5621 // RGBXAHBImportThenUpload, but there is no pixel reading or destroying the image to avoid extra
5622 // staged update flushes.
TEST_P(ImageTestES3,IncompleteRGBXAHBImportThenUploadThenEnd)5623 TEST_P(ImageTestES3, IncompleteRGBXAHBImportThenUploadThenEnd)
5624 {
5625 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5626 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5627 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5628
5629 const GLubyte kInitColor[] = {132, 55, 219, 12, 132, 55, 219, 12};
5630
5631 // Create the Image
5632 AHardwareBuffer *ahb;
5633 EGLImageKHR ahbImage;
5634 createEGLImageAndroidHardwareBufferSource(2, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5635 kDefaultAHBUsage, kDefaultAttribs, {{kInitColor, 4}},
5636 &ahb, &ahbImage);
5637
5638 GLTexture ahbTexture;
5639 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5640
5641 // Upload data
5642 const GLubyte kUploadColor[] = {63, 127, 191, 55};
5643 glTexSubImage2D(GL_TEXTURE_2D, 0, 1, 0, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, kUploadColor);
5644 ASSERT_GL_NO_ERROR();
5645
5646 // Clean up
5647 destroyAndroidHardwareBuffer(ahb);
5648 // This test relies on internal assertions to catch the issue regarding unflushed updates after
5649 // clearing emulated channels.
5650 }
5651
5652 // Test that RGBX data are preserved when importing from AHB. Tests interaction of emulated channel
5653 // being cleared with occlusion queries.
TEST_P(ImageTestES3,RGBXAHBImportOcclusionQueryNotCounted)5654 TEST_P(ImageTestES3, RGBXAHBImportOcclusionQueryNotCounted)
5655 {
5656 EGLWindow *window = getEGLWindow();
5657
5658 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5659 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5660 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5661
5662 GLQueryEXT query;
5663 glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, query);
5664
5665 // Create the Image
5666 AHardwareBuffer *ahb;
5667 EGLImageKHR ahbImage;
5668 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM,
5669 kDefaultAHBUsage, kDefaultAttribs,
5670 {{kLinearColor, 4}}, &ahb, &ahbImage);
5671
5672 GLTexture ahbTexture;
5673 createEGLImageTargetTexture2D(ahbImage, ahbTexture);
5674
5675 GLFramebuffer fbo;
5676 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
5677 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ahbTexture, 0);
5678 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5679
5680 // Perform a masked clear. Both the emulated clear and the masked clear should be performed,
5681 // neither of which should contribute to the occlusion query.
5682 const GLubyte kClearColor[] = {63, 127, 191, 55};
5683 glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
5684 glClearColor(kClearColor[0] / 255.0f, kClearColor[1] / 255.0f, kClearColor[2] / 255.0f,
5685 kClearColor[3] / 255.0f);
5686 glClear(GL_COLOR_BUFFER_BIT);
5687 glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
5688 ASSERT_GL_NO_ERROR();
5689
5690 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5691 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
5692
5693 // RGBX doesn't have alpha, so readback should return 255.
5694 const GLubyte kExpectedColor[] = {kClearColor[0], kLinearColor[1], kClearColor[2], 255};
5695 verifyResults2D(ahbTexture, kExpectedColor);
5696 verifyResultAHB(ahb, {{kExpectedColor, 4}});
5697
5698 GLuint result = GL_TRUE;
5699 glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result);
5700 EXPECT_GL_NO_ERROR();
5701
5702 EXPECT_GL_FALSE(result);
5703
5704 // Clean up
5705 eglDestroyImageKHR(window->getDisplay(), ahbImage);
5706 destroyAndroidHardwareBuffer(ahb);
5707 }
5708
5709 // Test repeatedly importing and releasing AHBs into textures to replicate behavior where
5710 // SurfaceFlinger optimistically imports AHBs but never actually ends up using them. Regression
5711 // test to check that AHB releases are not left pending and kept alive to avoid running out of
5712 // memory.
TEST_P(ImageTestES3,AHBImportReleaseStress)5713 TEST_P(ImageTestES3, AHBImportReleaseStress)
5714 {
5715 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
5716 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5717 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5718
5719 // Counters only available on Vulkan.
5720 ANGLE_SKIP_TEST_IF(!IsVulkan());
5721
5722 const GLubyte kBlack[] = {0, 0, 0, 0};
5723
5724 glFinish();
5725
5726 GLPerfMonitor monitor;
5727 glBeginPerfMonitorAMD(monitor);
5728
5729 const uint64_t initialPendingSubmissionGarbageObjects =
5730 getPerfCounters().pendingSubmissionGarbageObjects;
5731
5732 for (int i = 0; i < 20; i++)
5733 {
5734 AHardwareBuffer *ahb;
5735 EGLImageKHR ahbImage;
5736 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5737 kDefaultAHBUsage, kDefaultAttribs, {{kBlack, 4}},
5738 &ahb, &ahbImage);
5739
5740 {
5741 GLTexture ahbTexture;
5742 glBindTexture(GL_TEXTURE_2D, ahbTexture);
5743 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, ahbImage);
5744 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5746 ASSERT_GL_NO_ERROR();
5747
5748 // Intentionally not doing anything which may explicitly flush operations on the AHB.
5749 }
5750
5751 eglDestroyImageKHR(getEGLWindow()->getDisplay(), ahbImage);
5752 destroyAndroidHardwareBuffer(ahb);
5753 }
5754
5755 glEndPerfMonitorAMD(monitor);
5756
5757 EXPECT_LE(getPerfCounters().pendingSubmissionGarbageObjects,
5758 initialPendingSubmissionGarbageObjects + 10);
5759 }
5760
5761 // Test validation of using EXT_yuv_target
TEST_P(ImageTestES3,YUVValidation)5762 TEST_P(ImageTestES3, YUVValidation)
5763 {
5764 EGLWindow *window = getEGLWindow();
5765
5766 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasYUVTargetExt());
5767 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5768
5769 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
5770 AHardwareBuffer *yuvSource;
5771 EGLImageKHR yuvImage;
5772 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420,
5773 kDefaultAHBUsage, kDefaultAttribs, {}, &yuvSource,
5774 &yuvImage);
5775
5776 GLTexture yuvTexture;
5777 createEGLImageTargetTextureExternal(yuvImage, yuvTexture);
5778
5779 GLFramebuffer yuvFbo;
5780 glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo);
5781 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES,
5782 yuvTexture, 0);
5783 ASSERT_GL_NO_ERROR();
5784 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5785
5786 // Create an rgba image
5787 AHardwareBuffer *rgbaSource;
5788 EGLImageKHR rgbaImage;
5789 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5790 kDefaultAHBUsage, kDefaultAttribs, {}, &rgbaSource,
5791 &rgbaImage);
5792
5793 GLTexture rgbaExternalTexture;
5794 createEGLImageTargetTextureExternal(rgbaImage, rgbaExternalTexture);
5795
5796 GLFramebuffer rgbaExternalFbo;
5797 glBindFramebuffer(GL_FRAMEBUFFER, rgbaExternalFbo);
5798 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_EXTERNAL_OES,
5799 rgbaExternalTexture, 0);
5800 ASSERT_GL_NO_ERROR();
5801 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5802
5803 // Create a 2d rgb texture/framebuffer
5804 GLTexture rgb2DTexture;
5805 glBindTexture(GL_TEXTURE_2D, rgb2DTexture);
5806 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
5807
5808 GLFramebuffer rgb2DFbo;
5809 glBindFramebuffer(GL_FRAMEBUFFER, rgb2DFbo);
5810 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rgb2DTexture, 0);
5811 ASSERT_GL_NO_ERROR();
5812 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
5813
5814 // It's an error to sample from a non-yuv external texture with a yuv sampler
5815 glBindFramebuffer(GL_FRAMEBUFFER, 0);
5816 glUseProgram(mTextureYUVProgram);
5817 glBindTexture(GL_TEXTURE_EXTERNAL_OES, rgbaExternalTexture);
5818 glUniform1i(mTextureYUVUniformLocation, 0);
5819
5820 drawQuad(mTextureYUVProgram, "position", 0.5f);
5821 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5822
5823 // It's an error to render into a YUV framebuffer without a YUV writing program
5824 glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo);
5825 glUseProgram(mTextureExternalESSL3Program);
5826 glBindTexture(GL_TEXTURE_EXTERNAL_OES, rgbaExternalTexture);
5827 glUniform1i(mTextureExternalESSL3UniformLocation, 0);
5828
5829 drawQuad(mTextureExternalESSL3Program, "position", 0.5f);
5830 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5831
5832 // It's an error to render to a RGBA framebuffer with a YUV writing program
5833 glBindFramebuffer(GL_FRAMEBUFFER, rgb2DFbo);
5834 glUseProgram(mRenderYUVProgram);
5835
5836 drawQuad(mRenderYUVProgram, "position", 0.5f);
5837 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5838
5839 // It's an error to set disable r, g, or b color writes when rendering to a yuv framebuffer
5840 glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo);
5841 glUseProgram(mRenderYUVProgram);
5842
5843 glColorMask(false, true, true, true);
5844 drawQuad(mRenderYUVProgram, "position", 0.5f);
5845 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5846
5847 glColorMask(true, false, true, true);
5848 drawQuad(mRenderYUVProgram, "position", 0.5f);
5849 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5850
5851 glColorMask(true, true, false, true);
5852 drawQuad(mRenderYUVProgram, "position", 0.5f);
5853 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5854
5855 // It's an error to enable blending when rendering to a yuv framebuffer
5856 glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo);
5857 glUseProgram(mRenderYUVProgram);
5858
5859 glDisable(GL_BLEND);
5860 drawQuad(mRenderYUVProgram, "position", 0.5f);
5861 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5862
5863 // It's an error to blit to/from a yuv framebuffer
5864 glBindFramebuffer(GL_READ_FRAMEBUFFER, yuvFbo);
5865 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgb2DFbo);
5866 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5867 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5868
5869 glBindFramebuffer(GL_READ_FRAMEBUFFER, rgb2DFbo);
5870 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, yuvFbo);
5871 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
5872 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5873
5874 // It's an error to glCopyTexImage/glCopyTexSubImage from a YUV framebuffer
5875 glBindFramebuffer(GL_FRAMEBUFFER, yuvFbo);
5876 glBindTexture(GL_TEXTURE_2D, rgb2DTexture);
5877 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, 1, 1, 0);
5878 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5879 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
5880 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
5881
5882 // Clean up
5883 eglDestroyImageKHR(window->getDisplay(), yuvImage);
5884 destroyAndroidHardwareBuffer(yuvSource);
5885
5886 eglDestroyImageKHR(window->getDisplay(), rgbaImage);
5887 destroyAndroidHardwareBuffer(rgbaSource);
5888 }
5889
5890 // Testing source AHB EGL image with colorspace, target external ESSL3 texture
TEST_P(ImageTestES3,SourceAHBTargetExternalESSL3_Colorspace)5891 TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3_Colorspace)
5892 {
5893 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
5894 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
5895 SourceAHBTargetExternalESSL3_helper(kColorspaceAttribs);
5896 }
5897
SourceAHBTargetExternalESSL3_helper(const EGLint * attribs)5898 void ImageTest::SourceAHBTargetExternalESSL3_helper(const EGLint *attribs)
5899 {
5900 EGLWindow *window = getEGLWindow();
5901 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
5902 !hasExternalESSL3Ext());
5903 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5904 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
5905
5906 // Create the Image
5907 AHardwareBuffer *source;
5908 EGLImageKHR image;
5909 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5910 kDefaultAHBUsage, attribs, {{kSrgbColor, 4}}, &source,
5911 &image);
5912
5913 // Create a texture target to bind the egl image
5914 GLTexture target;
5915 createEGLImageTargetTextureExternal(image, target);
5916
5917 // Use texture target bound to egl image as source and render to framebuffer
5918 // Verify that the target texture has the expected color
5919 verifyResultsExternalESSL3(target, getExpected2DColorForAttribList(attribs));
5920
5921 // Clean up
5922 eglDestroyImageKHR(window->getDisplay(), image);
5923 destroyAndroidHardwareBuffer(source);
5924 }
5925
5926 // Testing source multi-layered AHB EGL image, target 2D array texture
TEST_P(ImageTestES3,SourceAHBArrayTarget2DArray)5927 TEST_P(ImageTestES3, SourceAHBArrayTarget2DArray)
5928 {
5929 EGLWindow *window = getEGLWindow();
5930
5931 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
5932 !hasEglImageArrayExt());
5933 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5934
5935 constexpr size_t kDepth = 2;
5936
5937 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
5938 1, 1, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage));
5939
5940 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
5941 AHardwareBuffer *source;
5942 EGLImageKHR image;
5943 createEGLImageAndroidHardwareBufferSource(1, 1, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5944 kDefaultAHBUsage, kDefaultAttribs, {}, &source,
5945 &image);
5946
5947 // Create a texture target to bind the egl image
5948 GLTexture target;
5949 createEGLImageTargetTexture2DArray(image, target);
5950
5951 // Upload texture data
5952 glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 1, 1, kDepth, GL_RGBA, GL_UNSIGNED_BYTE,
5953 kLinearColor3D);
5954
5955 // Use texture target bound to egl image as source and render to framebuffer
5956 for (size_t layer = 0; layer < kDepth; layer++)
5957 {
5958 // Expect that the target texture has the same color as the source texture
5959 verifyResults2DArray(target, &kLinearColor3D[layer * 4], layer);
5960 }
5961
5962 // Clean up
5963 eglDestroyImageKHR(window->getDisplay(), image);
5964 destroyAndroidHardwareBuffer(source);
5965 }
5966
5967 // Testing source cubemap AHB EGL image, target cubemap texture
TEST_P(ImageTestES3,SourceAHBCubeTargetCube)5968 TEST_P(ImageTestES3, SourceAHBCubeTargetCube)
5969 {
5970 EGLWindow *window = getEGLWindow();
5971
5972 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
5973 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
5974
5975 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
5976 1, 1, kCubeFaceCount, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5977 kDefaultAHBUsage | kAHBUsageGPUCubeMap));
5978
5979 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
5980 AHardwareBuffer *source;
5981 EGLImageKHR image;
5982 createEGLImageAndroidHardwareBufferSource(
5983 1, 1, kCubeFaceCount, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
5984 kDefaultAHBUsage | kAHBUsageGPUCubeMap, kDefaultAttribs, {}, &source, &image);
5985
5986 // Create a texture target to bind the egl image
5987 GLTexture target;
5988 createEGLImageTargetTextureStorage(image, GL_TEXTURE_CUBE_MAP, target, nullptr);
5989
5990 // Upload texture data
5991 for (size_t faceIdx = 0; faceIdx < kCubeFaceCount; faceIdx++)
5992 {
5993 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIdx, 0, 0, 0, 1, 1, GL_RGBA,
5994 GL_UNSIGNED_BYTE, &kLinearColorCube[faceIdx * 4]);
5995 ASSERT_GL_NO_ERROR();
5996 }
5997
5998 // Use texture target bound to egl image as source and render to framebuffer
5999 for (size_t faceIdx = 0; faceIdx < kCubeFaceCount; faceIdx++)
6000 {
6001 // Expect that the target texture has the same color as the source texture
6002 verifyResultsCube(target, &kLinearColorCube[faceIdx * 4], faceIdx);
6003 }
6004
6005 // Clean up
6006 eglDestroyImageKHR(window->getDisplay(), image);
6007 destroyAndroidHardwareBuffer(source);
6008 }
6009
6010 // Testing source cubemap array AHB EGL image, target cubemap array texture
TEST_P(ImageTestES31,SourceAHBCubeArrayTargetCubeArray)6011 TEST_P(ImageTestES31, SourceAHBCubeArrayTargetCubeArray)
6012 {
6013 EGLWindow *window = getEGLWindow();
6014
6015 ANGLE_SKIP_TEST_IF(!(getClientMajorVersion() >= 3 && getClientMinorVersion() >= 1));
6016 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt() ||
6017 !IsGLExtensionEnabled("GL_EXT_texture_cube_map_array"));
6018 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6019
6020 constexpr size_t kDepth = kCubeFaceCount * 2;
6021 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
6022 1, 1, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6023 kDefaultAHBUsage | kAHBUsageGPUCubeMap));
6024
6025 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
6026 AHardwareBuffer *source;
6027 EGLImageKHR image;
6028 createEGLImageAndroidHardwareBufferSource(1, 1, kDepth, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6029 kDefaultAHBUsage | kAHBUsageGPUCubeMap,
6030 kDefaultAttribs, {}, &source, &image);
6031
6032 // Create a texture target to bind the egl image
6033 GLTexture target;
6034 createEGLImageTargetTextureStorage(image, GL_TEXTURE_CUBE_MAP_ARRAY, target, nullptr);
6035
6036 // Upload texture data
6037 for (size_t faceIdx = 0; faceIdx < kCubeFaceCount; faceIdx++)
6038 {
6039 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, faceIdx, 1, 1, 1, GL_RGBA,
6040 GL_UNSIGNED_BYTE, &kLinearColorCube[faceIdx * 4]);
6041 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 11 - faceIdx, 1, 1, 1, GL_RGBA,
6042 GL_UNSIGNED_BYTE, &kLinearColorCube[faceIdx * 4]);
6043 ASSERT_GL_NO_ERROR();
6044 }
6045
6046 // Use texture target bound to egl image as source and render to framebuffer
6047 for (size_t faceIdx = 0; faceIdx < kCubeFaceCount; faceIdx++)
6048 {
6049 // Expect that the target texture has the same color as the source texture
6050 verifyResultsCubeArray(target, &kLinearColorCube[faceIdx * 4], faceIdx, 0);
6051 verifyResultsCubeArray(target, &kLinearColorCube[(5 - faceIdx) * 4], faceIdx, 1);
6052 }
6053
6054 // Clean up
6055 eglDestroyImageKHR(window->getDisplay(), image);
6056 destroyAndroidHardwareBuffer(source);
6057 }
6058
6059 // Testing source 2D AHB with mipmap EGL image, target 2D texture with mipmap
TEST_P(ImageTestES3,SourceAHBMipTarget2DMip)6060 TEST_P(ImageTestES3, SourceAHBMipTarget2DMip)
6061 {
6062 EGLWindow *window = getEGLWindow();
6063
6064 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
6065 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6066
6067 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
6068 2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6069 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete));
6070
6071 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
6072 AHardwareBuffer *source;
6073 EGLImageKHR image;
6074 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6075 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete,
6076 kDefaultAttribs, {}, &source, &image);
6077
6078 // Create a texture target to bind the egl image
6079 GLTexture target;
6080 createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, target, nullptr);
6081
6082 // Upload texture data
6083 // Set Mip level 0 to one color
6084 const std::vector<GLColor> kRedData(4, GLColor::red);
6085 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, kRedData.data());
6086
6087 // Set Mip level 1 to a different color
6088 const std::vector<GLColor> kGreenData(1, GLColor::green);
6089 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kGreenData.data());
6090
6091 // Use texture target bound to egl image as source and render to framebuffer
6092 // Expect that the target texture has the same color as the corresponding mip level in the
6093 // source texture
6094 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
6095 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
6096 verifyResults2D(target, GLColor::red.data());
6097
6098 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6099 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6100 verifyResults2D(target, GLColor::green.data());
6101
6102 // Clean up
6103 eglDestroyImageKHR(window->getDisplay(), image);
6104 destroyAndroidHardwareBuffer(source);
6105 }
6106
6107 // Test glGenerateMipmap and GL_EXT_EGL_image_storage interaction
TEST_P(ImageTestES3,SourceAHBMipTarget2DMipGenerateMipmap)6108 TEST_P(ImageTestES3, SourceAHBMipTarget2DMipGenerateMipmap)
6109 {
6110 EGLWindow *window = getEGLWindow();
6111
6112 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt());
6113 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6114
6115 ANGLE_SKIP_TEST_IF(!isAndroidHardwareBufferConfigurationSupported(
6116 2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6117 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete));
6118
6119 // Create the Image without data so we don't need ANGLE_AHARDWARE_BUFFER_LOCK_PLANES_SUPPORT
6120 AHardwareBuffer *source;
6121 EGLImageKHR image;
6122 createEGLImageAndroidHardwareBufferSource(2, 2, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
6123 kDefaultAHBUsage | kAHBUsageGPUMipMapComplete,
6124 kDefaultAttribs, {}, &source, &image);
6125
6126 // Create a texture target to bind the egl image
6127 GLTexture target;
6128 createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, target, nullptr);
6129
6130 // Upload texture data
6131 // Set Mip level 0 to one color
6132 const std::vector<GLColor> kRedData(4, GLColor::red);
6133 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, kRedData.data());
6134
6135 // Set Mip level 1 to a different color
6136 const std::vector<GLColor> kGreenData(1, GLColor::green);
6137 glTexSubImage2D(GL_TEXTURE_2D, 1, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kGreenData.data());
6138
6139 // Generate mipmap level 1
6140 glGenerateMipmap(GL_TEXTURE_2D);
6141
6142 // Use mipmap level 1 of texture target bound to egl image as source and render to framebuffer
6143 // Expect that the target texture has the same color as the mip level 0 in the source texture
6144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 1);
6145 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1);
6146 verifyResults2D(target, GLColor::red.data());
6147
6148 // Clean up
6149 eglDestroyImageKHR(window->getDisplay(), image);
6150 destroyAndroidHardwareBuffer(source);
6151 }
6152
6153 // Create a depth format AHB backed EGL image and verify that the image's aspect is honored
TEST_P(ImageTest,SourceAHBTarget2DDepth)6154 TEST_P(ImageTest, SourceAHBTarget2DDepth)
6155 {
6156 // TODO - Support for depth formats in AHB is missing (http://anglebug.com/42263405)
6157 ANGLE_SKIP_TEST_IF(true);
6158
6159 EGLWindow *window = getEGLWindow();
6160
6161 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6162 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
6163 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6164 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
6165
6166 GLint level = 0;
6167 GLsizei width = 1;
6168 GLsizei height = 1;
6169 GLsizei depth = 1;
6170 GLint depthStencilValue = 0;
6171
6172 // Create the Image
6173 AHardwareBuffer *source;
6174 EGLImageKHR image;
6175 createEGLImageAndroidHardwareBufferSource(
6176 width, height, depth, AHARDWAREBUFFER_FORMAT_D24_UNORM, kDefaultAHBUsage, kDefaultAttribs,
6177 {{reinterpret_cast<GLubyte *>(&depthStencilValue), 3}}, &source, &image);
6178
6179 // Create a texture target to bind the egl image
6180 GLTexture depthTextureTarget;
6181 createEGLImageTargetTexture2D(image, depthTextureTarget);
6182
6183 // Create a color texture and fill it with red
6184 GLTexture colorTexture;
6185 glBindTexture(GL_TEXTURE_2D, colorTexture);
6186 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
6187 GLColor::red.data());
6188 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6189 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6190 glBindTexture(GL_TEXTURE_2D, 0);
6191 EXPECT_GL_NO_ERROR();
6192
6193 GLFramebuffer fbo;
6194 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6195 EXPECT_GL_NO_ERROR();
6196
6197 // Attach the color and depth texture to the FBO
6198 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
6199 EXPECT_GL_NO_ERROR();
6200 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureTarget,
6201 0);
6202 EXPECT_GL_NO_ERROR();
6203
6204 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
6205
6206 // Clear the color texture to red
6207 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
6208 glClear(GL_COLOR_BUFFER_BIT);
6209 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
6210
6211 // Enable Depth test but disable depth writes. The depth function is set to ">".
6212 glEnable(GL_DEPTH_TEST);
6213 glDepthMask(GL_FALSE);
6214 glDepthFunc(GL_GREATER);
6215
6216 // Fill any fragment of the color attachment with blue if it passes the depth test.
6217 ANGLE_GL_PROGRAM(colorFillProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
6218 drawQuad(colorFillProgram, essl1_shaders::PositionAttrib(), 1.0f, 1.0f);
6219
6220 // Since 1.0f > 0.0f, all fragments of the color attachment should be blue.
6221 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
6222
6223 // Clean up
6224 glBindFramebuffer(GL_FRAMEBUFFER, 0);
6225 eglDestroyImageKHR(window->getDisplay(), image);
6226 destroyAndroidHardwareBuffer(source);
6227 }
6228
TEST_P(ImageTest,Source2DTargetRenderbuffer)6229 TEST_P(ImageTest, Source2DTargetRenderbuffer)
6230 {
6231 Source2DTargetRenderbuffer_helper(kDefaultAttribs);
6232 }
6233
TEST_P(ImageTest,Source2DTargetRenderbuffer_Colorspace)6234 TEST_P(ImageTest, Source2DTargetRenderbuffer_Colorspace)
6235 {
6236 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6237 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6238 Source2DTargetRenderbuffer_helper(kColorspaceAttribs);
6239 }
6240
Source2DTargetRenderbuffer_helper(const EGLint * attribs)6241 void ImageTest::Source2DTargetRenderbuffer_helper(const EGLint *attribs)
6242 {
6243
6244 EGLWindow *window = getEGLWindow();
6245 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
6246
6247 // Create sampling texture
6248 GLTexture sampleTexture;
6249 glBindTexture(GL_TEXTURE_2D, sampleTexture);
6250 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, kLinearColor);
6251 // Disable mipmapping
6252 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6253 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6254 ASSERT_GL_NO_ERROR();
6255
6256 // Create the attachment texture and image
6257 GLTexture attachmentTexture;
6258 EGLImageKHR image;
6259 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, nullptr,
6260 attachmentTexture, &image);
6261
6262 // Create the renderbuffer
6263 GLRenderbuffer renderbuffer;
6264 createEGLImageTargetRenderbuffer(image, renderbuffer);
6265
6266 // Verify that the render buffer has the expected color
6267 verifyResultsRenderbufferWithClearAndDraw(
6268 sampleTexture, renderbuffer, kLinearColor,
6269 getExpected2DColorForAttribList(attribs, EglImageUsage::Rendering));
6270
6271 // Clean up
6272 eglDestroyImageKHR(window->getDisplay(), image);
6273 }
6274
6275 // Testing source native client buffer EGL image, target external texture
6276 // where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest,SourceNativeClientBufferTargetExternal)6277 TEST_P(ImageTest, SourceNativeClientBufferTargetExternal)
6278 {
6279 SourceNativeClientBufferTargetExternal_helper(kDefaultAttribs);
6280 }
6281
6282 // Testing source native client buffer EGL image with colorspace, target external texture
6283 // where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest,SourceNativeClientBufferTargetExternal_Colorspace)6284 TEST_P(ImageTest, SourceNativeClientBufferTargetExternal_Colorspace)
6285 {
6286 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6287 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6288 SourceNativeClientBufferTargetExternal_helper(kColorspaceAttribs);
6289 }
6290
SourceNativeClientBufferTargetExternal_helper(const EGLint * attribs)6291 void ImageTest::SourceNativeClientBufferTargetExternal_helper(const EGLint *attribs)
6292 {
6293
6294 EGLWindow *window = getEGLWindow();
6295 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
6296 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6297 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
6298
6299 // Create an Image backed by a native client buffer allocated using
6300 // EGL_ANDROID_create_native_client_buffer API
6301 EGLImageKHR image;
6302 createEGLImageANWBClientBufferSource(1, 1, 1, kNativeClientBufferAttribs_RGBA8_Texture, attribs,
6303 {{kSrgbColor, 4}}, &image);
6304
6305 // Create the target
6306 GLTexture target;
6307 createEGLImageTargetTextureExternal(image, target);
6308
6309 // Verify that the target texture has the expected color
6310 verifyResultsExternal(target, getExpected2DColorForAttribList(attribs));
6311
6312 // Clean up
6313 eglDestroyImageKHR(window->getDisplay(), image);
6314 }
6315
6316 // Testing source native client buffer EGL image, target Renderbuffer
6317 // where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest,SourceNativeClientBufferTargetRenderbuffer)6318 TEST_P(ImageTest, SourceNativeClientBufferTargetRenderbuffer)
6319 {
6320 SourceNativeClientBufferTargetRenderbuffer_helper(kDefaultAttribs);
6321 }
6322
6323 // Testing source native client buffer EGL image with colorspace, target Renderbuffer
6324 // where source native client buffer is created using EGL_ANDROID_create_native_client_buffer API
TEST_P(ImageTest,SourceNativeClientBufferTargetRenderbuffer_Colorspace)6325 TEST_P(ImageTest, SourceNativeClientBufferTargetRenderbuffer_Colorspace)
6326 {
6327 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6328 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6329 SourceNativeClientBufferTargetRenderbuffer_helper(kColorspaceAttribs);
6330 }
6331
SourceNativeClientBufferTargetRenderbuffer_helper(const EGLint * attribs)6332 void ImageTest::SourceNativeClientBufferTargetRenderbuffer_helper(const EGLint *attribs)
6333 {
6334
6335 EGLWindow *window = getEGLWindow();
6336 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
6337 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
6338 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
6339
6340 // Create an Image backed by a native client buffer allocated using
6341 // EGL_ANDROID_create_native_client_buffer API
6342 EGLImageKHR image = EGL_NO_IMAGE_KHR;
6343 createEGLImageANWBClientBufferSource(1, 1, 1, kNativeClientBufferAttribs_RGBA8_Renderbuffer,
6344 attribs, {{kSrgbColor, 4}}, &image);
6345 // We are locking AHB to initialize AHB with data. The lock is allowed to fail, and may fail if
6346 // driver decided to allocate with framebuffer compression enabled.
6347 ANGLE_SKIP_TEST_IF(image == EGL_NO_IMAGE_KHR);
6348
6349 // Create the target
6350 GLRenderbuffer target;
6351 createEGLImageTargetRenderbuffer(image, target);
6352
6353 // Create a framebuffer with renderbuffer attachment and clear it
6354 GLFramebuffer framebuffer;
6355 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6356 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, target);
6357 glClearColor(kLinearColor[0] / 255.0f, kLinearColor[1] / 255.0f, kLinearColor[2] / 255.0f,
6358 kLinearColor[3] / 255.0f);
6359 glClear(GL_COLOR_BUFFER_BIT);
6360 ASSERT_GL_NO_ERROR();
6361
6362 // Verify that the render buffer has the expected color
6363 verifyResultsRenderbuffer(target,
6364 getExpected2DColorForAttribList(attribs, EglImageUsage::Rendering));
6365
6366 // Clean up
6367 eglDestroyImageKHR(window->getDisplay(), image);
6368 }
6369
TEST_P(ImageTest,Source2DTargetExternal)6370 TEST_P(ImageTest, Source2DTargetExternal)
6371 {
6372 Source2DTargetExternal_helper(kDefaultAttribs);
6373 }
6374
TEST_P(ImageTest,Source2DTargetExternal_Colorspace)6375 TEST_P(ImageTest, Source2DTargetExternal_Colorspace)
6376 {
6377 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6378 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6379 Source2DTargetExternal_helper(kColorspaceAttribs);
6380 }
6381
Source2DTargetExternal_helper(const EGLint * attribs)6382 void ImageTest::Source2DTargetExternal_helper(const EGLint *attribs)
6383 {
6384 EGLWindow *window = getEGLWindow();
6385 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
6386
6387 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
6388 ANGLE_SKIP_TEST_IF(IsOzone());
6389
6390 // Create the Image
6391 GLTexture source;
6392 EGLImageKHR image;
6393 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor, source,
6394 &image);
6395
6396 // Create the target
6397 GLTexture target;
6398 createEGLImageTargetTextureExternal(image, target);
6399
6400 // Verify that the target texture has the expected color
6401 verifyResultsExternal(target, getExpected2DColorForAttribList(attribs));
6402
6403 // Clean up
6404 eglDestroyImageKHR(window->getDisplay(), image);
6405 }
6406
TEST_P(ImageTestES3,Source2DTargetExternalESSL3)6407 TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
6408 {
6409 Source2DTargetExternalESSL3_helper(kDefaultAttribs);
6410 }
6411
TEST_P(ImageTestES3,Source2DTargetExternalESSL3_Colorspace)6412 TEST_P(ImageTestES3, Source2DTargetExternalESSL3_Colorspace)
6413 {
6414 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6415 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6416 Source2DTargetExternalESSL3_helper(kColorspaceAttribs);
6417 }
6418
Source2DTargetExternalESSL3_helper(const EGLint * attribs)6419 void ImageTest::Source2DTargetExternalESSL3_helper(const EGLint *attribs)
6420 {
6421 EGLWindow *window = getEGLWindow();
6422 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
6423 !hasExternalESSL3Ext());
6424
6425 // Create the Image
6426 GLTexture source;
6427 EGLImageKHR image;
6428 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor, source,
6429 &image);
6430
6431 // Create the target
6432 GLTexture target;
6433 createEGLImageTargetTextureExternal(image, target);
6434
6435 // Verify that the target texture has the expected color
6436 verifyResultsExternalESSL3(target, getExpected2DColorForAttribList(attribs));
6437
6438 // Clean up
6439 eglDestroyImageKHR(window->getDisplay(), image);
6440 }
6441
TEST_P(ImageTest,SourceCubeTarget2D)6442 TEST_P(ImageTest, SourceCubeTarget2D)
6443 {
6444 SourceCubeTarget2D_helper(kDefaultAttribs);
6445 }
6446
TEST_P(ImageTest,SourceCubeTarget2D_Colorspace)6447 TEST_P(ImageTest, SourceCubeTarget2D_Colorspace)
6448 {
6449 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6450 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6451 SourceCubeTarget2D_helper(kColorspaceAttribs);
6452 }
6453
SourceCubeTarget2D_helper(const EGLint * attribs)6454 void ImageTest::SourceCubeTarget2D_helper(const EGLint *attribs)
6455 {
6456 EGLWindow *window = getEGLWindow();
6457 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
6458
6459 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
6460 {
6461 // Create the Image
6462 GLTexture source;
6463 EGLImageKHR image;
6464 createEGLImageCubemapTextureSource(
6465 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(kSrgbColorCube),
6466 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, source, &image);
6467
6468 // Create the target
6469 GLTexture target;
6470 createEGLImageTargetTexture2D(image, target);
6471
6472 // Verify that the target texture has the expected color
6473 verifyResults2D(target, &getExpectedCubeColorForAttribList(attribs)[faceIdx * 4]);
6474
6475 // Clean up
6476 eglDestroyImageKHR(window->getDisplay(), image);
6477 }
6478 }
6479
TEST_P(ImageTest,SourceCubeTargetRenderbuffer)6480 TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
6481 {
6482 SourceCubeTargetRenderbuffer_helper(kDefaultAttribs);
6483 }
6484
TEST_P(ImageTest,SourceCubeTargetRenderbuffer_Colorspace)6485 TEST_P(ImageTest, SourceCubeTargetRenderbuffer_Colorspace)
6486 {
6487 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6488 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6489 SourceCubeTargetRenderbuffer_helper(kColorspaceAttribs);
6490 }
6491
SourceCubeTargetRenderbuffer_helper(const EGLint * attribs)6492 void ImageTest::SourceCubeTargetRenderbuffer_helper(const EGLint *attribs)
6493 {
6494 EGLWindow *window = getEGLWindow();
6495 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
6496
6497 // http://anglebug.com/42261821
6498 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsFuchsia());
6499
6500 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
6501 {
6502 // Create the Image
6503 GLTexture source;
6504 EGLImageKHR image;
6505 createEGLImageCubemapTextureSource(
6506 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(kSrgbColorCube),
6507 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, source, &image);
6508
6509 // Create the target
6510 GLRenderbuffer target;
6511 createEGLImageTargetRenderbuffer(image, target);
6512
6513 // Create a framebuffer with renderbuffer attachment and clear it
6514 GLFramebuffer framebuffer;
6515 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6516 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, target);
6517 glClearColor(
6518 kLinearColorCube[faceIdx * 4 + 0] / 255.0f, kLinearColorCube[faceIdx * 4 + 1] / 255.0f,
6519 kLinearColorCube[faceIdx * 4 + 2] / 255.0f, kLinearColorCube[faceIdx * 4 + 3] / 255.0f);
6520 glClear(GL_COLOR_BUFFER_BIT);
6521 ASSERT_GL_NO_ERROR();
6522
6523 // Verify that the render buffer has the expected color
6524 verifyResultsRenderbuffer(target, &getExpectedCubeColorForAttribList(
6525 attribs, EglImageUsage::Rendering)[faceIdx * 4]);
6526
6527 // Clean up
6528 eglDestroyImageKHR(window->getDisplay(), image);
6529 }
6530 }
6531
6532 // Test cubemap -> external texture EGL images.
TEST_P(ImageTest,SourceCubeTargetExternal)6533 TEST_P(ImageTest, SourceCubeTargetExternal)
6534 {
6535 SourceCubeTargetExternal_helper(kDefaultAttribs);
6536 }
6537
TEST_P(ImageTest,SourceCubeTargetExternal_Colorspace)6538 TEST_P(ImageTest, SourceCubeTargetExternal_Colorspace)
6539 {
6540 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6541 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6542 SourceCubeTargetExternal_helper(kColorspaceAttribs);
6543 }
6544
SourceCubeTargetExternal_helper(const EGLint * attribs)6545 void ImageTest::SourceCubeTargetExternal_helper(const EGLint *attribs)
6546 {
6547 EGLWindow *window = getEGLWindow();
6548 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt() || !hasExternalExt());
6549
6550 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
6551 ANGLE_SKIP_TEST_IF(IsOzone());
6552
6553 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
6554 {
6555 // Create the Image
6556 GLTexture source;
6557 EGLImageKHR image;
6558 // Upload sRGB color so that it is converted to linear when sampling.
6559 createEGLImageCubemapTextureSource(
6560 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(kSrgbColorCube),
6561 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, source, &image);
6562
6563 // Create the target
6564 GLTexture target;
6565 createEGLImageTargetTextureExternal(image, target);
6566
6567 // Verify that the target texture has the expected color
6568 verifyResultsExternal(target, &getExpectedCubeColorForAttribList(attribs)[faceIdx * 4]);
6569
6570 // Clean up
6571 eglDestroyImageKHR(window->getDisplay(), image);
6572 }
6573 }
6574
6575 // Test cubemap -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,SourceCubeTargetExternalESSL3)6576 TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
6577 {
6578 SourceCubeTargetExternalESSL3_helper(kDefaultAttribs);
6579 }
6580
TEST_P(ImageTestES3,SourceCubeTargetExternalESSL3_Colorspace)6581 TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3_Colorspace)
6582 {
6583 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6584 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6585 SourceCubeTargetExternalESSL3_helper(kColorspaceAttribs);
6586 }
6587
SourceCubeTargetExternalESSL3_helper(const EGLint * attribs)6588 void ImageTest::SourceCubeTargetExternalESSL3_helper(const EGLint *attribs)
6589 {
6590 EGLWindow *window = getEGLWindow();
6591 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() || !hasCubemapExt());
6592
6593 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
6594 {
6595 // Create the Image
6596 GLTexture source;
6597 EGLImageKHR image;
6598 // Upload sRGB color so that it is converted to linear when sampling.
6599 createEGLImageCubemapTextureSource(
6600 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(kSrgbColorCube),
6601 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, source, &image);
6602
6603 // Create the target
6604 GLTexture target;
6605 createEGLImageTargetTextureExternal(image, target);
6606
6607 // Verify that the target texture has the expected color
6608 verifyResultsExternalESSL3(target,
6609 &getExpectedCubeColorForAttribList(attribs)[faceIdx * 4]);
6610
6611 // Clean up
6612 eglDestroyImageKHR(window->getDisplay(), image);
6613 }
6614 }
6615
TEST_P(ImageTest,Source3DTargetTexture)6616 TEST_P(ImageTest, Source3DTargetTexture)
6617 {
6618 Source3DTargetTexture_helper(default3DAttribs);
6619 }
6620
TEST_P(ImageTest,Source3DTargetTexture_Colorspace)6621 TEST_P(ImageTest, Source3DTargetTexture_Colorspace)
6622 {
6623 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6624 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6625 Source3DTargetTexture_helper(colorspace3DAttribs);
6626 }
6627
Source3DTargetTexture_helper(EGLint * attribs)6628 void ImageTest::Source3DTargetTexture_helper(EGLint *attribs)
6629 {
6630 EGLWindow *window = getEGLWindow();
6631 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
6632
6633 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
6634
6635 constexpr size_t depth = 2;
6636
6637 for (size_t layer = 0; layer < depth; layer++)
6638 {
6639 // Create the Image
6640 GLTexture source;
6641 EGLImageKHR image;
6642 // Upload sRGB color so that it is converted to linear when sampling.
6643 attribs[kTextureZOffsetAttributeIndex] = static_cast<EGLint>(layer);
6644 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor3D,
6645 source, &image);
6646
6647 // Create the target
6648 GLTexture target;
6649 createEGLImageTargetTexture2D(image, target);
6650
6651 // Verify that the target texture has the expected color
6652 verifyResults2D(target, &getExpected3DColorForAttribList(attribs)[layer * 4]);
6653
6654 // Clean up
6655 eglDestroyImageKHR(window->getDisplay(), image);
6656 }
6657 }
6658
TEST_P(ImageTest,Source3DTargetRenderbuffer)6659 TEST_P(ImageTest, Source3DTargetRenderbuffer)
6660 {
6661 Source3DTargetRenderbuffer_helper(default3DAttribs);
6662 }
6663
TEST_P(ImageTest,Source3DTargetRenderbuffer_Colorspace)6664 TEST_P(ImageTest, Source3DTargetRenderbuffer_Colorspace)
6665 {
6666 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
6667 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6668 Source3DTargetRenderbuffer_helper(colorspace3DAttribs);
6669 }
6670
Source3DTargetRenderbuffer_helper(EGLint * attribs)6671 void ImageTest::Source3DTargetRenderbuffer_helper(EGLint *attribs)
6672 {
6673 // Qualcom drivers appear to always bind the 0 layer of the source 3D texture when the
6674 // target is a renderbuffer. They work correctly when the target is a 2D texture.
6675 // http://anglebug.com/42261453
6676 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
6677
6678 EGLWindow *window = getEGLWindow();
6679 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
6680
6681 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
6682
6683 constexpr size_t depth = 2;
6684
6685 for (size_t layer = 0; layer < depth; layer++)
6686 {
6687 // Create the Image
6688 GLTexture source;
6689 EGLImageKHR image;
6690
6691 attribs[kTextureZOffsetAttributeIndex] = static_cast<EGLint>(layer);
6692 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor3D,
6693 source, &image);
6694
6695 // Create the target
6696 GLRenderbuffer target;
6697 createEGLImageTargetRenderbuffer(image, target);
6698
6699 // Create a framebuffer with renderbuffer attachment and clear it
6700 GLFramebuffer framebuffer;
6701 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6702 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, target);
6703 glClearColor(kLinearColor3D[layer * 4 + 0] / 255.0f, kLinearColor3D[layer * 4 + 1] / 255.0f,
6704 kLinearColor3D[layer * 4 + 2] / 255.0f,
6705 kLinearColor3D[layer * 4 + 3] / 255.0f);
6706 glClear(GL_COLOR_BUFFER_BIT);
6707 ASSERT_GL_NO_ERROR();
6708
6709 // Verify that the render buffer has the expected color
6710 verifyResultsRenderbuffer(
6711 target, &getExpected3DColorForAttribList(attribs, EglImageUsage::Rendering)[layer * 4]);
6712
6713 // Clean up
6714 eglDestroyImageKHR(window->getDisplay(), image);
6715 }
6716 }
6717
6718 // Test 3D -> external texture EGL images.
TEST_P(ImageTest,Source3DTargetExternal)6719 TEST_P(ImageTest, Source3DTargetExternal)
6720 {
6721 Source3DTargetExternal_helper(default3DAttribs);
6722 }
6723
TEST_P(ImageTest,Source3DTargetExternal_Colorspace)6724 TEST_P(ImageTest, Source3DTargetExternal_Colorspace)
6725 {
6726 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6727 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6728 Source3DTargetExternal_helper(colorspace3DAttribs);
6729 }
6730
Source3DTargetExternal_helper(EGLint * attribs)6731 void ImageTest::Source3DTargetExternal_helper(EGLint *attribs)
6732 {
6733 EGLWindow *window = getEGLWindow();
6734 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !has3DTextureExt());
6735
6736 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
6737
6738 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
6739 ANGLE_SKIP_TEST_IF(IsOzone());
6740
6741 constexpr size_t depth = 2;
6742
6743 for (size_t layer = 0; layer < depth; layer++)
6744 {
6745 // Create the Image
6746 GLTexture source;
6747 EGLImageKHR image;
6748 // Upload sRGB color so that it is converted to linear when sampling.
6749 attribs[kTextureZOffsetAttributeIndex] = static_cast<EGLint>(layer);
6750 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor3D,
6751 source, &image);
6752
6753 // Create the target
6754 GLTexture target;
6755 createEGLImageTargetTextureExternal(image, target);
6756
6757 // Verify that the target texture has the expected color
6758 verifyResultsExternal(target, &getExpected3DColorForAttribList(attribs)[layer * 4]);
6759
6760 // Clean up
6761 eglDestroyImageKHR(window->getDisplay(), image);
6762 }
6763 }
6764
6765 // Test 3D -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,Source3DTargetExternalESSL3)6766 TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
6767 {
6768 Source3DTargetExternalESSL3_helper(default3DAttribs);
6769 }
6770
TEST_P(ImageTestES3,Source3DTargetExternalESSL3_Colorspace)6771 TEST_P(ImageTestES3, Source3DTargetExternalESSL3_Colorspace)
6772 {
6773 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6774 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6775 Source3DTargetExternalESSL3_helper(colorspace3DAttribs);
6776 }
6777
Source3DTargetExternalESSL3_helper(EGLint * attribs)6778 void ImageTest::Source3DTargetExternalESSL3_helper(EGLint *attribs)
6779 {
6780 EGLWindow *window = getEGLWindow();
6781 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
6782 !has3DTextureExt());
6783
6784 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
6785
6786 constexpr size_t depth = 2;
6787
6788 for (size_t layer = 0; layer < depth; layer++)
6789 {
6790 // Create the Image
6791 GLTexture source;
6792 EGLImageKHR image;
6793 // Upload sRGB color so that it is converted to linear when sampling.
6794 attribs[kTextureZOffsetAttributeIndex] = static_cast<EGLint>(layer);
6795 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, attribs, kSrgbColor3D,
6796 source, &image);
6797
6798 // Create the target
6799 GLTexture target;
6800 createEGLImageTargetTextureExternal(image, target);
6801
6802 // Verify that the target texture has the expected color
6803 verifyResultsExternalESSL3(target, &getExpected3DColorForAttribList(attribs)[layer * 4]);
6804
6805 // Clean up
6806 eglDestroyImageKHR(window->getDisplay(), image);
6807 }
6808 }
6809
TEST_P(ImageTest,SourceRenderbufferTargetTexture)6810 TEST_P(ImageTest, SourceRenderbufferTargetTexture)
6811 {
6812 SourceRenderbufferTargetTexture_helper(kDefaultAttribs);
6813 }
6814
TEST_P(ImageTest,SourceRenderbufferTargetTexture_Colorspace)6815 TEST_P(ImageTest, SourceRenderbufferTargetTexture_Colorspace)
6816 {
6817 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6818 SourceRenderbufferTargetTexture_helper(kColorspaceAttribs);
6819 }
6820
SourceRenderbufferTargetTexture_helper(const EGLint * attribs)6821 void ImageTest::SourceRenderbufferTargetTexture_helper(const EGLint *attribs)
6822 {
6823 EGLWindow *window = getEGLWindow();
6824 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
6825
6826 // Create the Image
6827 GLRenderbuffer source;
6828 EGLImageKHR image;
6829 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, source, &image);
6830
6831 // Create a framebuffer with renderbuffer attachment and clear it
6832 GLFramebuffer framebuffer;
6833 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6834 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
6835 glClearColor(kSrgbColor[0] / 255.0f, kSrgbColor[1] / 255.0f, kSrgbColor[2] / 255.0f,
6836 kSrgbColor[3] / 255.0f);
6837 glClear(GL_COLOR_BUFFER_BIT);
6838 ASSERT_GL_NO_ERROR();
6839
6840 // Create the target
6841 GLTexture target;
6842 createEGLImageTargetTexture2D(image, target);
6843
6844 // Verify that the target texture has the expected color
6845 verifyResults2D(target, getExpected2DColorForAttribList(attribs));
6846
6847 // Clean up
6848 eglDestroyImageKHR(window->getDisplay(), image);
6849 }
6850
6851 // Test renderbuffer -> external texture EGL images.
TEST_P(ImageTest,SourceRenderbufferTargetTextureExternal)6852 TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
6853 {
6854 SourceRenderbufferTargetTextureExternal_helper(kDefaultAttribs);
6855 }
6856
TEST_P(ImageTest,SourceRenderbufferTargetTextureExternal_Colorspace)6857 TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal_Colorspace)
6858 {
6859 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6860 SourceRenderbufferTargetTextureExternal_helper(kColorspaceAttribs);
6861 }
6862
SourceRenderbufferTargetTextureExternal_helper(const EGLint * attribs)6863 void ImageTest::SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs)
6864 {
6865 EGLWindow *window = getEGLWindow();
6866 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !hasRenderbufferExt());
6867
6868 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
6869 ANGLE_SKIP_TEST_IF(IsOzone());
6870
6871 // Create the Image
6872 GLRenderbuffer source;
6873 EGLImageKHR image;
6874 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, source, &image);
6875
6876 // Create a framebuffer with renderbuffer attachment and clear it
6877 GLFramebuffer framebuffer;
6878 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6879 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
6880 glClearColor(kSrgbColor[0] / 255.0f, kSrgbColor[1] / 255.0f, kSrgbColor[2] / 255.0f,
6881 kSrgbColor[3] / 255.0f);
6882 glClear(GL_COLOR_BUFFER_BIT);
6883 ASSERT_GL_NO_ERROR();
6884
6885 // Create the target
6886 GLTexture target;
6887 createEGLImageTargetTextureExternal(image, target);
6888
6889 // Verify that the target texture has the expected color
6890 verifyResultsExternal(target, getExpected2DColorForAttribList(attribs));
6891
6892 // Clean up
6893 eglDestroyImageKHR(window->getDisplay(), image);
6894 }
6895
6896 // Test renderbuffer -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,SourceRenderbufferTargetTextureExternalESSL3)6897 TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
6898 {
6899 SourceRenderbufferTargetTextureExternalESSL3_helper(kDefaultAttribs);
6900 }
6901
TEST_P(ImageTestES3,SourceRenderbufferTargetTextureExternalESSL3_Colorspace)6902 TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3_Colorspace)
6903 {
6904 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6905 SourceRenderbufferTargetTextureExternalESSL3_helper(kColorspaceAttribs);
6906 }
6907
SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint * attribs)6908 void ImageTest::SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs)
6909 {
6910 EGLWindow *window = getEGLWindow();
6911 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
6912 !hasRenderbufferExt());
6913
6914 // Create the Image
6915 GLRenderbuffer source;
6916 EGLImageKHR image;
6917 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, source, &image);
6918
6919 // Create a framebuffer with renderbuffer attachment and clear it
6920 GLFramebuffer framebuffer;
6921 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6922 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
6923 glClearColor(kSrgbColor[0] / 255.0f, kSrgbColor[1] / 255.0f, kSrgbColor[2] / 255.0f,
6924 kSrgbColor[3] / 255.0f);
6925 glClear(GL_COLOR_BUFFER_BIT);
6926 ASSERT_GL_NO_ERROR();
6927
6928 // Create the target
6929 GLTexture target;
6930 createEGLImageTargetTextureExternal(image, target);
6931
6932 // Verify that the target texture has the expected color
6933 verifyResultsExternalESSL3(target, getExpected2DColorForAttribList(attribs));
6934
6935 // Clean up
6936 eglDestroyImageKHR(window->getDisplay(), image);
6937 }
6938
TEST_P(ImageTest,SourceRenderbufferTargetRenderbuffer)6939 TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
6940 {
6941 SourceRenderbufferTargetRenderbuffer_helper(kDefaultAttribs);
6942 }
6943
TEST_P(ImageTest,SourceRenderbufferTargetRenderbuffer_Colorspace)6944 TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer_Colorspace)
6945 {
6946 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
6947 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
6948 SourceRenderbufferTargetRenderbuffer_helper(kColorspaceAttribs);
6949 }
6950
SourceRenderbufferTargetRenderbuffer_helper(const EGLint * attribs)6951 void ImageTest::SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs)
6952 {
6953 EGLWindow *window = getEGLWindow();
6954 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
6955
6956 // Create the Image
6957 GLRenderbuffer source;
6958 EGLImageKHR image;
6959 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, source, &image);
6960
6961 // Create the target
6962 GLRenderbuffer target;
6963 createEGLImageTargetRenderbuffer(image, target);
6964
6965 // Create a framebuffer with renderbuffer attachment and clear it
6966 GLFramebuffer framebuffer;
6967 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
6968 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, target);
6969 glClearColor(kLinearColor[0] / 255.0f, kLinearColor[1] / 255.0f, kLinearColor[2] / 255.0f,
6970 kLinearColor[3] / 255.0f);
6971 glClear(GL_COLOR_BUFFER_BIT);
6972 ASSERT_GL_NO_ERROR();
6973
6974 // Verify that the render buffer has the expected color
6975 verifyResultsRenderbuffer(target,
6976 getExpected2DColorForAttribList(attribs, EglImageUsage::Rendering));
6977
6978 // Clean up
6979 eglDestroyImageKHR(window->getDisplay(), image);
6980 }
6981
FixedRatedCompressionBasicHelper(const GLint * attribs)6982 void ImageTest::FixedRatedCompressionBasicHelper(const GLint *attribs)
6983 {
6984 constexpr size_t width = 16;
6985 constexpr size_t height = 16;
6986 GLTexture textureSource;
6987 EGLImageKHR image;
6988 EGLWindow *window = getEGLWindow();
6989 createEGLImage2DTextureStorage(width, height, GL_RGBA8, attribs, textureSource, &image);
6990
6991 GLTexture textureAttachment;
6992 createEGLImageTargetTextureStorage(image, GL_TEXTURE_2D, textureAttachment, attribs);
6993
6994 GLFramebuffer fbo;
6995 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
6996 ASSERT_GL_NO_ERROR();
6997 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureAttachment,
6998 0);
6999 ASSERT_GL_NO_ERROR();
7000 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7001
7002 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7003 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
7004 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::red);
7005 ASSERT_GL_NO_ERROR();
7006 eglDestroyImageKHR(window->getDisplay(), image);
7007 }
7008
7009 // Test basic usage of extension GL_EXT_EGL_image_storage_compression
TEST_P(ImageTest,FixedRatedCompressionBasic)7010 TEST_P(ImageTest, FixedRatedCompressionBasic)
7011 {
7012 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt() || !hasEglImageStorageCompressionExt());
7013 ANGLE_SKIP_TEST_IF(!hasTextureStorageCompressionExt());
7014 constexpr GLint kAttribList[3][3] = {
7015 {GL_NONE, GL_NONE, GL_NONE},
7016 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT, GL_NONE},
7017 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT, GL_NONE},
7018 };
7019 for (const GLint *attribs : kAttribList)
7020 {
7021 FixedRatedCompressionBasicHelper(attribs);
7022 }
7023 }
7024
FixedRatedCompressionImageAttribCheck(EGLImageKHR image,const GLint * attribs,const GLint expectResult)7025 void ImageTest::FixedRatedCompressionImageAttribCheck(EGLImageKHR image,
7026 const GLint *attribs,
7027 const GLint expectResult)
7028 {
7029 GLTexture textureAttachment;
7030 // Create a target texture from the image
7031 glBindTexture(GL_TEXTURE_2D, textureAttachment);
7032 glEGLImageTargetTexStorageEXT(GL_TEXTURE_2D, image, attribs);
7033 ASSERT_GL_ERROR(expectResult);
7034 }
7035
7036 // Test whether the result is expected when the attributes mismatched with source
TEST_P(ImageTest,FixedRatedCompressionMixedAttrib)7037 TEST_P(ImageTest, FixedRatedCompressionMixedAttrib)
7038 {
7039 ANGLE_SKIP_TEST_IF(!hasEglImageStorageExt() || !hasEglImageStorageCompressionExt());
7040 ANGLE_SKIP_TEST_IF(!hasTextureStorageCompressionExt());
7041 constexpr size_t width = 16;
7042 constexpr size_t height = 16;
7043 EGLWindow *window = getEGLWindow();
7044 constexpr GLint textureAttribList[][3] = {
7045 {GL_NONE, GL_NONE, GL_NONE},
7046 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT, GL_NONE},
7047 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT, GL_NONE},
7048 };
7049 constexpr GLint imageAttribList[][3] = {
7050 {GL_NONE, GL_NONE, GL_NONE},
7051 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT, GL_NONE},
7052 };
7053
7054 constexpr GLint invalidImageAttribList[][3] = {
7055 {GL_SURFACE_COMPRESSION_EXT, GL_SURFACE_COMPRESSION_EXT, GL_NONE},
7056 {GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT, GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT,
7057 GL_NONE},
7058 };
7059
7060 for (const GLint *textureAttribs : textureAttribList)
7061 {
7062 GLTexture textureSource;
7063 EGLImageKHR image;
7064 bool isFixRatedCompressed;
7065 createEGLImage2DTextureStorage(width, height, GL_RGBA8, textureAttribs, textureSource,
7066 &image);
7067 /* Query compression rate */
7068 GLint compressRate = GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT;
7069 glGetTexParameteriv(GL_TEXTURE_2D, GL_SURFACE_COMPRESSION_EXT, &compressRate);
7070 ASSERT_GL_NO_ERROR();
7071 isFixRatedCompressed = (compressRate == GL_SURFACE_COMPRESSION_FIXED_RATE_DEFAULT_EXT ||
7072 (compressRate >= GL_SURFACE_COMPRESSION_FIXED_RATE_1BPC_EXT &&
7073 compressRate <= GL_SURFACE_COMPRESSION_FIXED_RATE_12BPC_EXT));
7074
7075 for (const GLint *attribs : imageAttribList)
7076 {
7077 if (isFixRatedCompressed && attribs[0] == GL_SURFACE_COMPRESSION_EXT &&
7078 attribs[1] == GL_SURFACE_COMPRESSION_FIXED_RATE_NONE_EXT)
7079 {
7080 FixedRatedCompressionImageAttribCheck(image, attribs, GL_INVALID_OPERATION);
7081 }
7082 else
7083 {
7084 FixedRatedCompressionImageAttribCheck(image, attribs, GL_NO_ERROR);
7085 }
7086 }
7087
7088 for (const GLint *attribs : invalidImageAttribList)
7089 {
7090 FixedRatedCompressionImageAttribCheck(image, attribs, GL_INVALID_VALUE);
7091 }
7092
7093 eglDestroyImageKHR(window->getDisplay(), image);
7094 }
7095 }
7096
7097 // Delete the source texture and EGL image. The image targets should still have the same data
7098 // because
7099 // they hold refs to the image.
TEST_P(ImageTest,Deletion)7100 TEST_P(ImageTest, Deletion)
7101 {
7102 EGLWindow *window = getEGLWindow();
7103 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7104
7105 GLubyte originalData[4] = {255, 0, 255, 255};
7106 GLubyte updateData[4] = {0, 255, 0, 255};
7107
7108 // Create the Image
7109 GLTexture source;
7110 EGLImageKHR image;
7111 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7112 source, &image);
7113
7114 // Create multiple targets
7115 GLTexture targetTexture;
7116 createEGLImageTargetTexture2D(image, targetTexture);
7117
7118 GLRenderbuffer targetRenderbuffer;
7119 createEGLImageTargetRenderbuffer(image, targetRenderbuffer);
7120
7121 // Delete the source texture
7122 source.reset();
7123
7124 // Expect that both the targets have the original data
7125 verifyResults2D(targetTexture, originalData);
7126 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
7127
7128 // Update the data of the target
7129 glBindTexture(GL_TEXTURE_2D, targetTexture);
7130 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7131
7132 // Expect that both targets have the updated data
7133 verifyResults2D(targetTexture, updateData);
7134 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
7135
7136 // Delete the EGL image
7137 eglDestroyImageKHR(window->getDisplay(), image);
7138 image = EGL_NO_IMAGE_KHR;
7139
7140 // Update the data of the target back to the original data
7141 glBindTexture(GL_TEXTURE_2D, targetTexture);
7142 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
7143
7144 // Expect that both targets have the original data again
7145 verifyResults2D(targetTexture, originalData);
7146 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
7147 }
7148
TEST_P(ImageTest,MipLevels)7149 TEST_P(ImageTest, MipLevels)
7150 {
7151 // Driver returns OOM in read pixels, some internal error.
7152 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
7153 // Also fails on NVIDIA Shield TV bot.
7154 // http://anglebug.com/42262494
7155 ANGLE_SKIP_TEST_IF(IsNVIDIAShield() && IsOpenGLES());
7156 // On Vulkan, the clear operation in the loop is optimized with a render pass loadOp=Clear. On
7157 // Linux/Intel, that operation is mistakenly clearing the rest of the mips to 0.
7158 // http://anglebug.com/42261962
7159 ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && IsIntel());
7160
7161 EGLWindow *window = getEGLWindow();
7162 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7163
7164 const size_t mipLevels = 3;
7165 const size_t textureSize = 4;
7166 std::vector<GLColor> mip0Data(textureSize * textureSize, GLColor::red);
7167 std::vector<GLColor> mip1Data(mip0Data.size() << 1, GLColor::green);
7168 std::vector<GLColor> mip2Data(mip0Data.size() << 2, GLColor::blue);
7169 GLubyte *data[mipLevels] = {
7170 reinterpret_cast<GLubyte *>(&mip0Data[0]),
7171 reinterpret_cast<GLubyte *>(&mip1Data[0]),
7172 reinterpret_cast<GLubyte *>(&mip2Data[0]),
7173 };
7174
7175 GLTexture source;
7176 glBindTexture(GL_TEXTURE_2D, source);
7177
7178 for (size_t level = 0; level < mipLevels; level++)
7179 {
7180 glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA, textureSize >> level,
7181 textureSize >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[level]);
7182 }
7183
7184 ASSERT_GL_NO_ERROR();
7185
7186 for (size_t level = 0; level < mipLevels; level++)
7187 {
7188 // Create the Image
7189 EGLint attribs[] = {
7190 EGL_GL_TEXTURE_LEVEL_KHR,
7191 static_cast<EGLint>(level),
7192 EGL_NONE,
7193 };
7194 EGLImageKHR image =
7195 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
7196 reinterpretHelper<EGLClientBuffer>(source), attribs);
7197 ASSERT_EGL_SUCCESS();
7198
7199 // Create a texture and renderbuffer target
7200 GLTexture textureTarget;
7201 createEGLImageTargetTexture2D(image, textureTarget);
7202
7203 // Disable mipmapping
7204 glBindTexture(GL_TEXTURE_2D, textureTarget);
7205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7206 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7207
7208 GLRenderbuffer renderbufferTarget;
7209 createEGLImageTargetRenderbuffer(image, renderbufferTarget);
7210
7211 // Expect that the targets have the same color as the source texture
7212 verifyResults2D(textureTarget, data[level]);
7213 verifyResultsRenderbuffer(renderbufferTarget, data[level]);
7214
7215 // Update the data by uploading data to the texture
7216 std::vector<GLuint> textureUpdateData(textureSize * textureSize, level);
7217 glBindTexture(GL_TEXTURE_2D, textureTarget);
7218 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureSize >> level, textureSize >> level, GL_RGBA,
7219 GL_UNSIGNED_BYTE, textureUpdateData.data());
7220 ASSERT_GL_NO_ERROR();
7221
7222 // Expect that both the texture and renderbuffer see the updated texture data
7223 verifyResults2D(textureTarget, reinterpret_cast<GLubyte *>(textureUpdateData.data()));
7224 verifyResultsRenderbuffer(renderbufferTarget,
7225 reinterpret_cast<GLubyte *>(textureUpdateData.data()));
7226
7227 // Update the renderbuffer by clearing it
7228 GLFramebuffer fbo;
7229 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7230 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
7231 renderbufferTarget);
7232
7233 GLubyte clearValue = static_cast<GLubyte>(level);
7234 GLubyte renderbufferClearData[4]{clearValue, clearValue, clearValue, clearValue};
7235 glClearColor(renderbufferClearData[0] / 255.0f, renderbufferClearData[1] / 255.0f,
7236 renderbufferClearData[2] / 255.0f, renderbufferClearData[3] / 255.0f);
7237 glClear(GL_COLOR_BUFFER_BIT);
7238 glBindFramebuffer(GL_FRAMEBUFFER, 0);
7239 ASSERT_GL_NO_ERROR();
7240
7241 // Expect that both the texture and renderbuffer see the cleared renderbuffer data
7242 verifyResults2D(textureTarget, renderbufferClearData);
7243 verifyResultsRenderbuffer(renderbufferTarget, renderbufferClearData);
7244
7245 // Clean up
7246 eglDestroyImageKHR(window->getDisplay(), image);
7247 }
7248 }
7249
7250 // Respecify the source texture, orphaning it. The target texture should not have updated data.
TEST_P(ImageTest,Respecification)7251 TEST_P(ImageTest, Respecification)
7252 {
7253 // Respecification of textures that does not change the size of the level attached to the EGL
7254 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/42261452
7255 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
7256 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
7257
7258 EGLWindow *window = getEGLWindow();
7259 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7260
7261 GLubyte originalData[4] = {255, 0, 255, 255};
7262 GLubyte updateData[4] = {0, 255, 0, 255};
7263
7264 // Create the Image
7265 GLTexture source;
7266 EGLImageKHR image;
7267 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7268 source, &image);
7269
7270 // Create the target
7271 GLTexture target;
7272 createEGLImageTargetTexture2D(image, target);
7273
7274 // Respecify source
7275 glBindTexture(GL_TEXTURE_2D, source);
7276 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7277
7278 // Expect that the target texture has the original data
7279 verifyResults2D(target, originalData);
7280
7281 // Expect that the source texture has the updated data
7282 verifyResults2D(source, updateData);
7283
7284 // Clean up
7285 eglDestroyImageKHR(window->getDisplay(), image);
7286 }
7287
7288 // Respecify the source texture with a different size, orphaning it. The target texture should not
7289 // have updated data.
TEST_P(ImageTest,RespecificationDifferentSize)7290 TEST_P(ImageTest, RespecificationDifferentSize)
7291 {
7292 EGLWindow *window = getEGLWindow();
7293 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7294
7295 GLubyte originalData[4] = {255, 0, 255, 255};
7296 GLubyte updateData[16] = {0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
7297
7298 // Create the Image
7299 GLTexture source;
7300 EGLImageKHR image;
7301 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7302 source, &image);
7303
7304 // Create the target
7305 GLTexture target;
7306 createEGLImageTargetTexture2D(image, target);
7307
7308 // Respecify source
7309 glBindTexture(GL_TEXTURE_2D, source);
7310 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7311
7312 // Expect that the target texture has the original data
7313 verifyResults2D(target, originalData);
7314
7315 // Expect that the source texture has the updated data
7316 verifyResults2D(source, updateData);
7317
7318 // Clean up
7319 eglDestroyImageKHR(window->getDisplay(), image);
7320 }
7321
7322 // First render to a target texture, then respecify the source texture, orphaning it.
7323 // The target texture's FBO should be notified of the target texture's orphaning.
TEST_P(ImageTest,RespecificationWithFBO)7324 TEST_P(ImageTest, RespecificationWithFBO)
7325 {
7326 EGLWindow *window = getEGLWindow();
7327 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7328
7329 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
7330
7331 GLubyte originalData[4] = {255, 0, 255, 255};
7332 GLubyte updateData[4] = {0, 255, 0, 255};
7333
7334 // Create the Image
7335 GLTexture source;
7336 EGLImageKHR image;
7337 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7338 source, &image);
7339
7340 // Create the target
7341 GLTexture target;
7342 createEGLImageTargetTexture2D(image, target);
7343
7344 // Render to the target texture
7345 GLFramebuffer fbo;
7346 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7347 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
7348 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7349 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7350
7351 // Respecify source with same parameters. This should not change the texture storage in D3D11.
7352 glBindTexture(GL_TEXTURE_2D, source);
7353 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7354
7355 // Expect that the source texture has the updated data
7356 verifyResults2D(source, updateData);
7357
7358 // Render to the target texture again and verify it gets the rendered pixels.
7359 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
7360 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
7361
7362 // Clean up
7363 eglDestroyImageKHR(window->getDisplay(), image);
7364 }
7365
7366 // Test that respecifying a level of the target texture orphans it and keeps a copy of the EGLimage
7367 // data
TEST_P(ImageTest,RespecificationOfOtherLevel)7368 TEST_P(ImageTest, RespecificationOfOtherLevel)
7369 {
7370 // Respecification of textures that does not change the size of the level attached to the EGL
7371 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/42261452
7372 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
7373
7374 // It is undefined what happens to the mip 0 of the dest texture after it is orphaned. Some
7375 // backends explicitly copy the data but Vulkan does not.
7376 ANGLE_SKIP_TEST_IF(IsVulkan());
7377
7378 EGLWindow *window = getEGLWindow();
7379 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7380
7381 GLubyte originalData[2 * 2 * 4] = {
7382 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
7383 };
7384
7385 GLubyte updateData[2 * 2 * 4] = {
7386 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
7387 };
7388
7389 // Create the Image
7390 GLTexture source;
7391 EGLImageKHR image;
7392 createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7393 source, &image);
7394
7395 // Create the target
7396 GLTexture target;
7397 createEGLImageTargetTexture2D(image, target);
7398
7399 // Expect that the target and source textures have the original data
7400 verifyResults2D(source, originalData);
7401 verifyResults2D(target, originalData);
7402
7403 // Add a new mipLevel to the target, orphaning it
7404 glBindTexture(GL_TEXTURE_2D, target);
7405 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
7406 EXPECT_GL_NO_ERROR();
7407
7408 // Expect that the target and source textures still have the original data
7409 verifyResults2D(source, originalData);
7410 verifyResults2D(target, originalData);
7411
7412 // Update the source's data
7413 glBindTexture(GL_TEXTURE_2D, source);
7414 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7415
7416 // Expect that the target still has the original data and source has the updated data
7417 verifyResults2D(source, updateData);
7418 verifyResults2D(target, originalData);
7419
7420 // Clean up
7421 eglDestroyImageKHR(window->getDisplay(), image);
7422 }
7423
7424 // Update the data of the source and target textures. All image siblings should have the new data.
TEST_P(ImageTest,UpdatedData)7425 TEST_P(ImageTest, UpdatedData)
7426 {
7427 EGLWindow *window = getEGLWindow();
7428 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7429
7430 GLubyte originalData[4] = {255, 0, 255, 255};
7431 GLubyte updateData[4] = {0, 255, 0, 255};
7432
7433 // Create the Image
7434 GLTexture source;
7435 EGLImageKHR image;
7436 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7437 source, &image);
7438
7439 // Create multiple targets
7440 GLTexture targetTexture;
7441 createEGLImageTargetTexture2D(image, targetTexture);
7442
7443 GLRenderbuffer targetRenderbuffer;
7444 createEGLImageTargetRenderbuffer(image, targetRenderbuffer);
7445
7446 // Expect that both the source and targets have the original data
7447 verifyResults2D(source, originalData);
7448 verifyResults2D(targetTexture, originalData);
7449 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
7450
7451 // Update the data of the source
7452 glBindTexture(GL_TEXTURE_2D, source);
7453 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7454
7455 // Expect that both the source and targets have the updated data
7456 verifyResults2D(source, updateData);
7457 verifyResults2D(targetTexture, updateData);
7458 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
7459
7460 // Update the data of the target back to the original data
7461 glBindTexture(GL_TEXTURE_2D, targetTexture);
7462 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
7463
7464 // Expect that both the source and targets have the original data again
7465 verifyResults2D(source, originalData);
7466 verifyResults2D(targetTexture, originalData);
7467 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
7468
7469 // Clean up
7470 eglDestroyImageKHR(window->getDisplay(), image);
7471 }
7472
7473 // Check that the external texture is successfully updated when only glTexSubImage2D is called.
TEST_P(ImageTest,AHBUpdatedExternalTexture)7474 TEST_P(ImageTest, AHBUpdatedExternalTexture)
7475 {
7476 EGLWindow *window = getEGLWindow();
7477
7478 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7479 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
7480 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
7481
7482 GLubyte originalData[4] = {255, 0, 255, 255};
7483 GLubyte updateData[4] = {0, 255, 0, 255};
7484 const uint32_t bytesPerPixel = 4;
7485
7486 // Create the Image
7487 AHardwareBuffer *source;
7488 EGLImageKHR image;
7489 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
7490 kDefaultAHBUsage, kDefaultAttribs,
7491 {{originalData, bytesPerPixel}}, &source, &image);
7492
7493 // Create target
7494 GLTexture targetTexture;
7495 createEGLImageTargetTexture2D(image, targetTexture);
7496
7497 // Expect that both the target have the original data
7498 verifyResults2D(targetTexture, originalData);
7499
7500 // Update the data of the source
7501 glBindTexture(GL_TEXTURE_2D, targetTexture);
7502 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7503
7504 // Set sync object and flush the GL commands
7505 EGLSyncKHR fence = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, NULL);
7506 ASSERT_NE(fence, EGL_NO_SYNC_KHR);
7507 glFlush();
7508
7509 // Delete the target texture
7510 targetTexture.reset();
7511
7512 // Wait that the flush command is finished
7513 EGLint result = eglClientWaitSyncKHR(window->getDisplay(), fence, 0, 1000000000);
7514 ASSERT_EQ(result, EGL_CONDITION_SATISFIED_KHR);
7515 ASSERT_EGL_TRUE(eglDestroySyncKHR(window->getDisplay(), fence));
7516
7517 // Delete the EGL image
7518 eglDestroyImageKHR(window->getDisplay(), image);
7519
7520 // Access the android hardware buffer directly to check the data is updated
7521 verifyResultAHB(source, {{updateData, bytesPerPixel}});
7522
7523 // Create the EGL image again
7524 image =
7525 eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
7526 angle::android::AHardwareBufferToClientBuffer(source), kDefaultAttribs);
7527 ASSERT_EGL_SUCCESS();
7528
7529 // Create the target texture again
7530 GLTexture targetTexture2;
7531 createEGLImageTargetTexture2D(image, targetTexture2);
7532
7533 // Expect that the target have the update data
7534 verifyResults2D(targetTexture2, updateData);
7535
7536 // Clean up
7537 eglDestroyImageKHR(window->getDisplay(), image);
7538 destroyAndroidHardwareBuffer(source);
7539 }
7540
7541 // Check that the texture successfully updates when an image is deleted
TEST_P(ImageTest,DeletedImageWithSameSizeAndFormat)7542 TEST_P(ImageTest, DeletedImageWithSameSizeAndFormat)
7543 {
7544 EGLWindow *window = getEGLWindow();
7545
7546 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7547
7548 GLubyte originalData[4] = {255, 0, 255, 255};
7549 GLubyte updateData[4] = {0, 255, 0, 255};
7550
7551 // Create the Image
7552 GLTexture source;
7553 EGLImageKHR image;
7554 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
7555 source, &image);
7556
7557 // Create texture & bind to Image
7558 GLTexture texture;
7559 createEGLImageTargetTexture2D(image, texture);
7560
7561 // Delete Image
7562 eglDestroyImageKHR(window->getDisplay(), image);
7563
7564 ASSERT_EGL_SUCCESS();
7565
7566 // Redefine Texture
7567 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
7568
7569 ASSERT_GL_NO_ERROR();
7570 }
7571
7572 // Check that create a source cube texture and then redefine the same target texture with each face
7573 // of source cube texture renders correctly
TEST_P(ImageTest,SourceCubeAndSameTargetTextureWithEachCubeFace)7574 TEST_P(ImageTest, SourceCubeAndSameTargetTextureWithEachCubeFace)
7575 {
7576 EGLWindow *window = getEGLWindow();
7577
7578 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7579
7580 // Create a source cube map texture
7581 GLTexture sourceTexture;
7582 glBindTexture(GL_TEXTURE_CUBE_MAP, sourceTexture);
7583 uint8_t *data = reinterpret_cast<uint8_t *>(kLinearColorCube);
7584 size_t dataStride = sizeof(GLubyte) * 4;
7585 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
7586 {
7587 glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
7588 GL_UNSIGNED_BYTE, data + (faceIdx * dataStride));
7589 }
7590 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7591 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7592 ASSERT_GL_NO_ERROR();
7593
7594 EGLImageKHR images[6];
7595 GLTexture targetTexture;
7596 glBindTexture(GL_TEXTURE_2D, targetTexture);
7597
7598 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
7599 {
7600 // Create the Image with EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR
7601 images[faceIdx] =
7602 eglCreateImageKHR(window->getDisplay(), window->getContext(),
7603 EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx,
7604 reinterpretHelper<EGLClientBuffer>(sourceTexture), kDefaultAttribs);
7605
7606 // Create a target texture from the image
7607 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, images[faceIdx]);
7608 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
7609 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
7610 ASSERT_GL_NO_ERROR();
7611 // Expect that the target texture has the same color as the source texture
7612 verifyResults2D(targetTexture, &kLinearColorCube[faceIdx * 4]);
7613 }
7614
7615 // Clean up
7616 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
7617 {
7618 eglDestroyImageKHR(window->getDisplay(), images[faceIdx]);
7619 }
7620 }
7621
7622 // Case for testing External Texture support in MEC.
7623 // To run this test with the right capture setting, make sure to set these environment variables:
7624 //
7625 // For Linux:
7626 // export ANGLE_CAPTURE_FRAME_START=2
7627 // export ANGLE_CAPTURE_FRAME_END=2
7628 // export ANGLE_CAPTURE_LABEL=external_textures
7629 // export ANGLE_CAPTURE_OUT_DIR=[PATH_TO_ANGLE]/src/tests/restricted_traces/external_textures/
7630 //
7631 // For Android:
7632 // adb shell setprop debug.angle.capture.frame_start 2
7633 // adb shell setprop debug.angle.capture.frame_end 2
7634 // adb shell setprop debug.angle.capture.label external_textures
7635 // adb shell setprop debug.angle.capture.out_dir /data/data/externaltextures/angle_capture/
TEST_P(ImageTest,AppTraceExternalTextureDefaultAttribs)7636 TEST_P(ImageTest, AppTraceExternalTextureDefaultAttribs)
7637 {
7638 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
7639 !hasExternalESSL3Ext());
7640
7641 constexpr EGLint attribs[] = {
7642 EGL_IMAGE_PRESERVED,
7643 EGL_TRUE,
7644 EGL_NONE,
7645 };
7646
7647 externalTextureTracerTestHelper(attribs);
7648 }
7649
7650 // Same as AppTraceExternalTextureUseCase, except we will pass additional attrib_list values in
7651 // EGLAttrib* for eglCreateImageKHR calls
TEST_P(ImageTest,AppTraceExternalTextureOtherAttribs)7652 TEST_P(ImageTest, AppTraceExternalTextureOtherAttribs)
7653 {
7654 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
7655 !hasExternalESSL3Ext());
7656
7657 constexpr EGLint attribs[] = {
7658 EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_GL_TEXTURE_LEVEL, 0, EGL_NONE,
7659 };
7660
7661 externalTextureTracerTestHelper(attribs);
7662 }
7663
7664 // Same as AppTraceExternalTextureUseCase, except we will pass nullptr as EGLAttrib* for
7665 // eglCreateImageKHR calls
TEST_P(ImageTest,AppTraceExternalTextureNullAttribs)7666 TEST_P(ImageTest, AppTraceExternalTextureNullAttribs)
7667 {
7668 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
7669 !hasExternalESSL3Ext());
7670
7671 externalTextureTracerTestHelper(nullptr);
7672 }
7673
7674 // Alternate case for testing External Texture (created with AHB) support in MEC.
7675 // Make sure to use the following environment variables for the right capture setting on Android:
7676 //
7677 // adb shell setprop debug.angle.capture.frame_start 2
7678 // adb shell setprop debug.angle.capture.frame_end 2
7679 // adb shell setprop debug.angle.capture.label AHB_textures
7680 // adb shell setprop debug.angle.capture.out_dir /data/data/AHBtextures/angle_capture/
TEST_P(ImageTest,AppTraceExternalTextureWithAHBUseCase)7681 TEST_P(ImageTest, AppTraceExternalTextureWithAHBUseCase)
7682 {
7683 EGLWindow *window = getEGLWindow();
7684
7685 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7686 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
7687 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
7688
7689 GLubyte data[4] = {7, 51, 197, 231};
7690
7691 // Create the Image
7692 AHardwareBuffer *source;
7693 EGLImageKHR image;
7694 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
7695 kDefaultAHBUsage, kDefaultAttribs, {{data, 4}},
7696 &source, &image);
7697
7698 // Create a texture target to bind the egl image & disable mipmapping
7699 GLTexture target;
7700 createEGLImageTargetTextureExternal(image, target);
7701
7702 // Calls On EndFrame(), with MidExecutionSetup to restore external target texture above
7703 EGLDisplay display = getEGLWindow()->getDisplay();
7704 EGLSurface surface = getEGLWindow()->getSurface();
7705 eglSwapBuffers(display, surface);
7706
7707 // Create another eglImage with another associated texture
7708 // Draw using the eglImage target texture created in frame 1
7709 AHardwareBuffer *source2;
7710 EGLImageKHR image2;
7711 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
7712 kDefaultAHBUsage, kDefaultAttribs, {{data, 4}},
7713 &source2, &image2);
7714
7715 // Create another texture target to bind the egl image & disable mipmapping
7716 GLTexture target2;
7717 createEGLImageTargetTextureExternal(image, target2);
7718
7719 glUseProgram(mTextureExternalProgram);
7720 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
7721 glUniform1i(mTextureExternalUniformLocation, 0);
7722
7723 drawQuad(mTextureExternalProgram, "position", 0.5f);
7724
7725 // Calls On EndFrame() to save the gl calls creating external texture target2;
7726 // We use this as a reference to check the gl calls we restore for GLTexture target
7727 // in MidExecutionSetup
7728 eglSwapBuffers(display, surface);
7729
7730 // Draw a quad with the GLTexture target2
7731 glUseProgram(mTextureExternalProgram);
7732 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target2);
7733 glUniform1i(mTextureExternalUniformLocation, 0);
7734
7735 drawQuad(mTextureExternalProgram, "position", 0.5f);
7736
7737 eglSwapBuffers(display, surface);
7738
7739 // Clean up
7740 eglDestroyImageKHR(window->getDisplay(), image);
7741 eglDestroyImageKHR(window->getDisplay(), image2);
7742 }
7743
7744 // Thread 0 creates the AHB and binds it to a texture, thread 1 uses it without synchronization.
TEST_P(ImageTest,MultithreadedAHBImportAndUseAsTexture)7745 TEST_P(ImageTest, MultithreadedAHBImportAndUseAsTexture)
7746 {
7747 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
7748 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
7749 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
7750 ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
7751
7752 EGLWindow *window = getEGLWindow();
7753
7754 GLuint sharedTexture = 0;
7755
7756 // Create the Image
7757 AHardwareBuffer *source;
7758 EGLImageKHR image;
7759
7760 constexpr GLubyte kInitialData[4] = {127, 63, 191, 255};
7761
7762 std::mutex mutex;
7763 std::condition_variable condVar;
7764
7765 enum class Step
7766 {
7767 Start,
7768 Thread0CreatedTexture,
7769 Thread1UsedTexture,
7770 Finish,
7771 Abort,
7772 };
7773 Step currentStep = Step::Start;
7774
7775 auto thread0 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
7776 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
7777
7778 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
7779
7780 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
7781 kDefaultAHBUsage, kDefaultAttribs,
7782 {{kInitialData, 4}}, &source, &image);
7783 ASSERT_GL_NO_ERROR();
7784
7785 GLTexture texture;
7786 sharedTexture = texture;
7787
7788 createEGLImageTargetTextureExternal(image, sharedTexture);
7789 ASSERT_GL_NO_ERROR();
7790
7791 // Wait for the other thread to use it.
7792 threadSynchronization.nextStep(Step::Thread0CreatedTexture);
7793 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1UsedTexture));
7794
7795 eglDestroyImageKHR(window->getDisplay(), image);
7796 texture.reset();
7797
7798 threadSynchronization.nextStep(Step::Finish);
7799
7800 // Clean up
7801 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
7802 };
7803
7804 auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
7805 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
7806
7807 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
7808
7809 // Wait for thread 0 to set up
7810 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0CreatedTexture));
7811
7812 // Sample from the texture
7813 ANGLE_GL_PROGRAM(drawTexture, getVS(), getTextureExternalFS());
7814 glUseProgram(drawTexture);
7815 glBindTexture(GL_TEXTURE_EXTERNAL_OES, sharedTexture);
7816 glUniform1i(mTextureExternalUniformLocation, 0);
7817 ASSERT_GL_NO_ERROR();
7818
7819 drawQuad(drawTexture, "position", 0.5f);
7820 ASSERT_GL_NO_ERROR();
7821
7822 // Make a submission
7823 EXPECT_PIXEL_COLOR_NEAR(
7824 0, 0, GLColor(kInitialData[0], kInitialData[1], kInitialData[2], kInitialData[3]), 1);
7825
7826 // Notify the other thread that it's finished using the texture.
7827 threadSynchronization.nextStep(Step::Thread1UsedTexture);
7828 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish));
7829
7830 // Clean up
7831 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
7832 };
7833
7834 std::array<LockStepThreadFunc, 2> threadFuncs = {
7835 std::move(thread0),
7836 std::move(thread1),
7837 };
7838
7839 RunLockStepThreads(getEGLWindow(), threadFuncs.size(), threadFuncs.data());
7840
7841 ASSERT_NE(currentStep, Step::Abort);
7842 }
7843
7844 // Thread 0 creates the AHB and binds it to a renderbuffer, thread 1 uses it without
7845 // synchronization.
TEST_P(ImageTest,MultithreadedAHBImportAndUseAsRenderbuffer)7846 TEST_P(ImageTest, MultithreadedAHBImportAndUseAsRenderbuffer)
7847 {
7848 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
7849 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
7850 ANGLE_SKIP_TEST_IF(!hasAhbLockPlanesSupport());
7851 ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
7852
7853 EGLWindow *window = getEGLWindow();
7854
7855 GLuint sharedRenderbuffer = 0;
7856
7857 // Create the Image
7858 AHardwareBuffer *source;
7859 EGLImageKHR image;
7860
7861 constexpr GLubyte kInitialData[4] = {127, 63, 191, 255};
7862
7863 std::mutex mutex;
7864 std::condition_variable condVar;
7865
7866 enum class Step
7867 {
7868 Start,
7869 Thread0CreatedRenderbuffer,
7870 Thread1UsedRenderbuffer,
7871 Finish,
7872 Abort,
7873 };
7874 Step currentStep = Step::Start;
7875
7876 auto thread0 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
7877 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
7878
7879 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
7880
7881 createEGLImageAndroidHardwareBufferSource(1, 1, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM,
7882 kDefaultAHBUsage, kDefaultAttribs,
7883 {{kInitialData, 4}}, &source, &image);
7884 ASSERT_GL_NO_ERROR();
7885
7886 GLRenderbuffer renderbuffer;
7887 sharedRenderbuffer = renderbuffer;
7888
7889 createEGLImageTargetRenderbuffer(image, sharedRenderbuffer);
7890 ASSERT_GL_NO_ERROR();
7891
7892 // Wait for the other thread to use it.
7893 threadSynchronization.nextStep(Step::Thread0CreatedRenderbuffer);
7894 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1UsedRenderbuffer));
7895
7896 eglDestroyImageKHR(window->getDisplay(), image);
7897 renderbuffer.reset();
7898
7899 threadSynchronization.nextStep(Step::Finish);
7900
7901 // Clean up
7902 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
7903 };
7904
7905 auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
7906 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
7907
7908 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
7909
7910 // Wait for thread 0 to set up
7911 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0CreatedRenderbuffer));
7912
7913 // Blend into the renderbuffer
7914 GLFramebuffer fbo;
7915 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
7916 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
7917 sharedRenderbuffer);
7918 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
7919 ASSERT_GL_NO_ERROR();
7920
7921 glEnable(GL_BLEND);
7922 glBlendFunc(GL_ONE, GL_ONE);
7923
7924 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
7925 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.5f);
7926 ASSERT_GL_NO_ERROR();
7927
7928 // Make a submission
7929 EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(255, kInitialData[1], kInitialData[2], 255), 1);
7930
7931 // Notify the other thread that it's finished using the renderbuffer.
7932 threadSynchronization.nextStep(Step::Thread1UsedRenderbuffer);
7933 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish));
7934
7935 // Clean up
7936 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
7937 };
7938
7939 std::array<LockStepThreadFunc, 2> threadFuncs = {
7940 std::move(thread0),
7941 std::move(thread1),
7942 };
7943
7944 RunLockStepThreads(getEGLWindow(), threadFuncs.size(), threadFuncs.data());
7945
7946 ASSERT_NE(currentStep, Step::Abort);
7947 }
7948
framebufferAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,bool deleteSourceTextureLast)7949 void ImageTest::framebufferAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,
7950 bool deleteSourceTextureLast)
7951 {
7952 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt());
7953 ANGLE_SKIP_TEST_IF(useTextureAttachment && !has2DTextureExt());
7954 ANGLE_SKIP_TEST_IF(!useTextureAttachment && !hasRenderbufferExt());
7955 ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
7956
7957 EGLWindow *window = getEGLWindow();
7958 EGLImageKHR image = EGL_NO_IMAGE_KHR;
7959
7960 std::mutex mutex;
7961 std::condition_variable condVar;
7962 EGLSyncKHR sync;
7963
7964 enum class Step
7965 {
7966 Start,
7967 Thread0CreatedImage,
7968 Thread1UsedImage,
7969 Finish,
7970 Abort,
7971 };
7972 Step currentStep = Step::Start;
7973
7974 EXPECT_EGL_TRUE(window->makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
7975
7976 // This thread will use window context
7977 std::thread thread0([&]() {
7978 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
7979
7980 window->makeCurrent();
7981
7982 // Create the Image
7983 GLTexture source;
7984 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
7985 kLinearColor, source, &image);
7986
7987 sync = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, nullptr);
7988 ASSERT_GL_NO_ERROR();
7989
7990 // Wait thread 1 finish using the Image
7991 threadSynchronization.nextStep(Step::Thread0CreatedImage);
7992 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1UsedImage));
7993
7994 if (!deleteSourceTextureLast)
7995 {
7996 // Delete "source" texture first - image buffer will be deleted with the "image"
7997 source.reset();
7998 }
7999
8000 // Destroy Image
8001 eglDestroyImageKHR(window->getDisplay(), image);
8002
8003 if (deleteSourceTextureLast)
8004 {
8005 // Delete "source" texture last - this will delete image buffer
8006 source.reset();
8007 }
8008
8009 threadSynchronization.nextStep(Step::Finish);
8010
8011 EXPECT_EGL_TRUE(window->makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8012 });
8013
8014 // This thread will use non Shared context
8015 auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
8016 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
8017
8018 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0CreatedImage));
8019
8020 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
8021 eglWaitSyncKHR(dpy, sync, 0);
8022
8023 // Create the target and set up a framebuffer to render into the Image
8024 GLFramebuffer fbo;
8025 GLTexture targetTexture;
8026 GLRenderbuffer targetRenderbuffer;
8027 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8028 if (useTextureAttachment)
8029 {
8030 createEGLImageTargetTexture2D(image, targetTexture);
8031 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
8032 targetTexture, 0);
8033 }
8034 else
8035 {
8036 createEGLImageTargetRenderbuffer(image, targetRenderbuffer);
8037 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
8038 targetRenderbuffer);
8039 }
8040 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8041
8042 // Test that framebuffer has source content
8043 EXPECT_PIXEL_EQ(0, 0, kLinearColor[0], kLinearColor[1], kLinearColor[2], kLinearColor[3]);
8044
8045 // Create additional target texture
8046 GLTexture targetTexture2;
8047 createEGLImageTargetTexture2D(image, targetTexture2);
8048
8049 // Enable additive blend
8050 glEnable(GL_BLEND);
8051 glBlendFunc(GL_ONE, GL_ONE);
8052
8053 // Draw Red quad into the framebuffer
8054 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8055 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
8056 ASSERT_GL_NO_ERROR();
8057
8058 // Delete "targetTexture2" that may affect RenderPass because it uses same Image
8059 targetTexture2.reset();
8060
8061 // Clear previous draw
8062 glClearColor(128 / 255.0f, 128 / 255.0f, 128 / 255.0f, 1.0f);
8063 glClear(GL_COLOR_BUFFER_BIT);
8064
8065 // Draw Green quad into the framebuffer
8066 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8067 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
8068 ASSERT_GL_NO_ERROR();
8069
8070 // Test that clear and second draw worked as expected
8071 EXPECT_PIXEL_EQ(0, 0, 128, 255, 128, 255);
8072
8073 // Draw again to open RenderPass after the read pixels
8074 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
8075 ASSERT_GL_NO_ERROR();
8076
8077 // Delete resources
8078 fbo.reset();
8079 targetTexture.reset();
8080 targetRenderbuffer.reset();
8081 ASSERT_GL_NO_ERROR();
8082
8083 // Wait thread 0 destroys the Image and source
8084 threadSynchronization.nextStep(Step::Thread1UsedImage);
8085 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish));
8086
8087 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8088 };
8089
8090 std::array<LockStepThreadFunc, 1> threadFuncs = {
8091 std::move(thread1),
8092 };
8093
8094 RunLockStepThreads(getEGLWindow(), threadFuncs.size(), threadFuncs.data());
8095 thread0.join();
8096
8097 window->makeCurrent();
8098
8099 ASSERT_NE(currentStep, Step::Abort);
8100 }
8101
8102 // Testing Target 2D Texture deleted while still used in the RenderPass (Image destroyed last).
TEST_P(ImageTest,TargetTexture2DDeletedWhileInUse)8103 TEST_P(ImageTest, TargetTexture2DDeletedWhileInUse)
8104 {
8105 framebufferAttachmentDeletedWhileInUseHelper(true, false);
8106 }
8107
8108 // Testing Target 2D Texture deleted while still used in the RenderPass (Source deleted last).
TEST_P(ImageTest,TargetTexture2DDeletedWhileInUse2)8109 TEST_P(ImageTest, TargetTexture2DDeletedWhileInUse2)
8110 {
8111 framebufferAttachmentDeletedWhileInUseHelper(true, true);
8112 }
8113
8114 // Testing Target Renderbuffer deleted while still used in the RenderPass (Image destroyed last).
TEST_P(ImageTest,TargetRenderbufferDeletedWhileInUse)8115 TEST_P(ImageTest, TargetRenderbufferDeletedWhileInUse)
8116 {
8117 framebufferAttachmentDeletedWhileInUseHelper(false, false);
8118 }
8119
8120 // Testing Target Renderbuffer deleted while still used in the RenderPass (Source deleted last).
TEST_P(ImageTest,TargetRenderbufferDeletedWhileInUse2)8121 TEST_P(ImageTest, TargetRenderbufferDeletedWhileInUse2)
8122 {
8123 framebufferAttachmentDeletedWhileInUseHelper(false, true);
8124 }
8125
framebufferResolveAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,bool deleteSourceTextureLast)8126 void ImageTest::framebufferResolveAttachmentDeletedWhileInUseHelper(bool useTextureAttachment,
8127 bool deleteSourceTextureLast)
8128 {
8129 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt());
8130 ANGLE_SKIP_TEST_IF(useTextureAttachment && !has2DTextureExt());
8131 ANGLE_SKIP_TEST_IF(!useTextureAttachment && !hasRenderbufferExt());
8132 ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
8133
8134 EGLWindow *window = getEGLWindow();
8135 EGLImageKHR image = EGL_NO_IMAGE_KHR;
8136
8137 std::mutex mutex;
8138 std::condition_variable condVar;
8139 EGLSyncKHR sync;
8140
8141 enum class Step
8142 {
8143 Start,
8144 Thread0CreatedImage,
8145 Thread1UsedImage,
8146 Finish,
8147 Abort,
8148 };
8149 Step currentStep = Step::Start;
8150
8151 EXPECT_EGL_TRUE(window->makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8152
8153 // This thread will use window context
8154 std::thread thread0([&]() {
8155 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
8156
8157 window->makeCurrent();
8158
8159 // Create the Image
8160 GLTexture source;
8161 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
8162 kLinearColor, source, &image);
8163
8164 sync = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, nullptr);
8165 ASSERT_GL_NO_ERROR();
8166
8167 // Wait thread 1 finish using the Image
8168 threadSynchronization.nextStep(Step::Thread0CreatedImage);
8169 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1UsedImage));
8170
8171 if (!deleteSourceTextureLast)
8172 {
8173 // Delete "source" texture first - image buffer will be deleted with the "image"
8174 source.reset();
8175 }
8176
8177 // Destroy Image
8178 eglDestroyImageKHR(window->getDisplay(), image);
8179
8180 if (deleteSourceTextureLast)
8181 {
8182 // Delete "source" texture last - this will delete image buffer
8183 source.reset();
8184 }
8185
8186 threadSynchronization.nextStep(Step::Finish);
8187
8188 EXPECT_EGL_TRUE(window->makeCurrent(EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8189 });
8190
8191 // This thread will use non Shared context
8192 auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
8193 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
8194
8195 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0CreatedImage));
8196
8197 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
8198 eglWaitSyncKHR(dpy, sync, 0);
8199
8200 // Create the target and set up a framebuffer to render into the Image
8201 GLFramebuffer fbo;
8202 GLTexture targetTexture;
8203 GLRenderbuffer targetRenderbuffer;
8204 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8205 if (useTextureAttachment)
8206 {
8207 createEGLImageTargetTexture2D(image, targetTexture);
8208 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
8209 targetTexture, 0);
8210 }
8211 else
8212 {
8213 createEGLImageTargetRenderbuffer(image, targetRenderbuffer);
8214 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
8215 targetRenderbuffer);
8216 }
8217 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8218
8219 // Test that framebuffer has source content
8220 EXPECT_PIXEL_EQ(0, 0, kLinearColor[0], kLinearColor[1], kLinearColor[2], kLinearColor[3]);
8221
8222 // Create additional target texture
8223 GLTexture targetTexture2;
8224 createEGLImageTargetTexture2D(image, targetTexture2);
8225
8226 // Create MSAA framebuffer
8227 GLTexture msaaColor;
8228 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msaaColor);
8229 glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, 1, 1, false);
8230
8231 GLFramebuffer msaaFBO;
8232 glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO);
8233 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
8234 msaaColor, 0);
8235 ASSERT_GL_NO_ERROR();
8236 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8237
8238 // Draw Red quad into the MSAA framebuffer
8239 ANGLE_GL_PROGRAM(drawRed, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8240 drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f);
8241 ASSERT_GL_NO_ERROR();
8242
8243 // Resolve into image
8244 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8245 glBlitFramebuffer(0, 0, 1, 1, 0, 0, 1, 1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
8246 ASSERT_GL_NO_ERROR();
8247
8248 // Delete "targetTexture2" that may affect RenderPass because it uses same Image
8249 targetTexture2.reset();
8250
8251 // Start another render pass and blend into the image.
8252 glEnable(GL_BLEND);
8253 glBlendFunc(GL_ONE, GL_ONE);
8254
8255 ANGLE_GL_PROGRAM(drawGreen, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8256 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
8257 ASSERT_GL_NO_ERROR();
8258
8259 // Test that resolve and draw worked
8260 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8261 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::yellow);
8262
8263 // Draw again to open RenderPass after the read pixels
8264 glDisable(GL_BLEND);
8265 drawQuad(drawGreen, essl1_shaders::PositionAttrib(), 0.0f);
8266 ASSERT_GL_NO_ERROR();
8267
8268 // Delete resources
8269 fbo.reset();
8270 targetTexture.reset();
8271 targetRenderbuffer.reset();
8272 ASSERT_GL_NO_ERROR();
8273
8274 // Wait thread 0 destroys the Image and source
8275 threadSynchronization.nextStep(Step::Thread1UsedImage);
8276 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish));
8277
8278 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8279 };
8280
8281 std::array<LockStepThreadFunc, 1> threadFuncs = {
8282 std::move(thread1),
8283 };
8284
8285 RunLockStepThreads(getEGLWindow(), threadFuncs.size(), threadFuncs.data());
8286 thread0.join();
8287
8288 window->makeCurrent();
8289
8290 ASSERT_NE(currentStep, Step::Abort);
8291 }
8292
8293 // Test whether the dimension size of the target GL_TEXTURE_EXTERNAL_OES is as expected.
TEST_P(ImageTestES31,QueryDimFromExternalTex)8294 TEST_P(ImageTestES31, QueryDimFromExternalTex)
8295 {
8296 EGLWindow *window = getEGLWindow();
8297 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
8298
8299 // Create the Image
8300 GLTexture source;
8301 GLsizei src_w = 1, src_h = 1, qw = 0, qh = 0;
8302 EGLImageKHR image;
8303 createEGLImage2DTextureSource(src_w, src_h, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs,
8304 kSrgbColor, source, &image);
8305
8306 // Create the target
8307 GLTexture target;
8308 createEGLImageTargetTextureExternal(image, target);
8309
8310 // Querying the dimensions should work
8311 glGetTexLevelParameteriv(GL_TEXTURE_EXTERNAL_OES, 0, GL_TEXTURE_WIDTH, &qw);
8312 EXPECT_EQ(qw, src_w);
8313 glGetTexLevelParameteriv(GL_TEXTURE_EXTERNAL_OES, 0, GL_TEXTURE_HEIGHT, &qh);
8314 EXPECT_EQ(qh, src_h);
8315
8316 // Clean up
8317 eglDestroyImageKHR(window->getDisplay(), image);
8318 }
8319
8320 // Testing Target 2D Texture deleted while still used in the RenderPass as resolve attachment (Image
8321 // destroyed last).
TEST_P(ImageTestES31,TargetTexture2DDeletedWhileInUseAsResolve)8322 TEST_P(ImageTestES31, TargetTexture2DDeletedWhileInUseAsResolve)
8323 {
8324 framebufferResolveAttachmentDeletedWhileInUseHelper(true, false);
8325 }
8326
8327 // Testing Target 2D Texture deleted while still used in the RenderPass as resolve attachment
8328 // (Source deleted last).
TEST_P(ImageTestES31,TargetTexture2DDeletedWhileInUseAsResolve2)8329 TEST_P(ImageTestES31, TargetTexture2DDeletedWhileInUseAsResolve2)
8330 {
8331 framebufferResolveAttachmentDeletedWhileInUseHelper(true, true);
8332 }
8333
8334 // Testing Target Renderbuffer deleted while still used in the RenderPass as resolve attachment
8335 // (Image destroyed last).
TEST_P(ImageTestES31,TargetRenderbufferDeletedWhileInUseAsResolve)8336 TEST_P(ImageTestES31, TargetRenderbufferDeletedWhileInUseAsResolve)
8337 {
8338 framebufferResolveAttachmentDeletedWhileInUseHelper(false, false);
8339 }
8340
8341 // Testing Target Renderbuffer deleted while still used in the RenderPass as resolve attachment
8342 // (Source deleted last).
TEST_P(ImageTestES31,TargetRenderbufferDeletedWhileInUseAsResolve2)8343 TEST_P(ImageTestES31, TargetRenderbufferDeletedWhileInUseAsResolve2)
8344 {
8345 framebufferResolveAttachmentDeletedWhileInUseHelper(false, true);
8346 }
8347
8348 // Test that the AHB can be used in some way in GL, then accessed by foreign entity, then used again
8349 // by GL. This makes sure transitions in and out of the FOREIGN Vulkan queue are correctly
8350 // implemented.
useAHBByGLThenForeignThenGLHelper(std::function<void (const GLTexture &,uint32_t,uint32_t)> firstUse,std::function<void (const GLTexture &,uint32_t,uint32_t)> secondUse)8351 void ImageTest::useAHBByGLThenForeignThenGLHelper(
8352 std::function<void(const GLTexture &, uint32_t, uint32_t)> firstUse,
8353 std::function<void(const GLTexture &, uint32_t, uint32_t)> secondUse)
8354 {
8355 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
8356 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
8357
8358 constexpr uint32_t kWidth = 53;
8359 constexpr uint32_t kHeight = 37;
8360
8361 // Create the Image
8362 AHardwareBuffer *source;
8363 EGLImageKHR image;
8364 createEGLImageAndroidHardwareBufferSource(
8365 kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage,
8366 kDefaultAttribs, {}, &source, &image);
8367
8368 // Create a texture target to bind the egl image
8369 GLTexture target;
8370 createEGLImageTargetTexture2D(image, target);
8371
8372 glViewport(0, 0, kWidth, kHeight);
8373
8374 // Use the image in GL once.
8375 firstUse(target, kWidth, kHeight);
8376
8377 // In between uses, overwrite parts of the image.
8378 // First, wait for first use to finish.
8379 EGLWindow *window = getEGLWindow();
8380 EGLSyncKHR fence = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, NULL);
8381 glFlush();
8382 EGLint result = eglClientWaitSyncKHR(window->getDisplay(), fence, 0, 1'000'000'000);
8383 ASSERT_EQ(result, EGL_CONDITION_SATISFIED_KHR);
8384 ASSERT_EGL_TRUE(eglDestroySyncKHR(window->getDisplay(), fence));
8385
8386 // Then overwrite a quarter of the image with some color
8387 std::vector<GLubyte> data((kWidth / 2) * (kHeight / 2) * 4, 99);
8388 writeAHBData(source, kWidth / 2, kHeight / 2, 1, false, {{data.data(), 4}});
8389
8390 // And use the image again in GL.
8391 secondUse(target, kWidth, kHeight);
8392
8393 ASSERT_GL_NO_ERROR();
8394 }
8395
8396 // Test draw, use in foreign, then draw again
TEST_P(ImageTest,DrawForeignDraw)8397 TEST_P(ImageTest, DrawForeignDraw)
8398 {
8399 GLFramebuffer fbo;
8400 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8401
8402 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8403 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8404 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8405
8406 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8407 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8408 };
8409 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8410 glBindTexture(GL_TEXTURE_2D, texture);
8411
8412 glEnable(GL_BLEND);
8413 glBlendFunc(GL_ONE, GL_ONE);
8414
8415 glEnable(GL_SCISSOR_TEST);
8416 glScissor(width / 4, 0, width / 2, height);
8417
8418 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8419 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8420
8421 // Expect the following:
8422 //
8423 // +-----+-----+-----+-----+
8424 // | | | | |
8425 // | 99 | 99 | G | G |
8426 // | | + | + | |
8427 // | | R | R | |
8428 // | | | | |
8429 // +-----+-----+-----+ |
8430 // | | | |
8431 // | G | G + R | G |
8432 // | | | |
8433 // | | | |
8434 // | | | |
8435 // +-----+-----------+-----+
8436 //
8437 EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height / 2, GLColor(99, 99, 99, 99));
8438 EXPECT_PIXEL_RECT_EQ(0, height / 2, width / 4, height - height / 2, GLColor::green);
8439 EXPECT_PIXEL_RECT_EQ(width / 4, 0, width / 2 - width / 4, height / 2,
8440 GLColor(255, 99, 99, 255));
8441 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 2, height - height / 2,
8442 GLColor::yellow);
8443 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2 - width / 4, height / 2, GLColor::yellow);
8444 EXPECT_PIXEL_RECT_EQ(width / 4 + width / 2, 0, width - width / 2 - width / 4, height,
8445 GLColor::green);
8446 };
8447
8448 useAHBByGLThenForeignThenGLHelper(first, second);
8449 }
8450
8451 // Test draw, use in foreign, then blit
TEST_P(ImageTestES3,DrawForeignBlit)8452 TEST_P(ImageTestES3, DrawForeignBlit)
8453 {
8454 GLFramebuffer fbo;
8455 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8456
8457 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8458 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8459 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8460
8461 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8462 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8463 };
8464 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8465 GLFramebuffer otherFbo;
8466 glBindFramebuffer(GL_FRAMEBUFFER, otherFbo);
8467
8468 GLTexture color;
8469 glBindTexture(GL_TEXTURE_2D, color);
8470 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8471 nullptr);
8472 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
8473 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8474
8475 glClearColor(0, 0, 1, 1);
8476 glClear(GL_COLOR_BUFFER_BIT);
8477
8478 glBindTexture(GL_TEXTURE_2D, texture);
8479 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8480
8481 glBlitFramebuffer(width / 4, 0, width / 2 + width / 4, height, width / 4, 0,
8482 width / 2 + width / 4, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
8483 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8484
8485 // Expect the following:
8486 //
8487 // +-----+-----------+-----+
8488 // | | | |
8489 // | 99 | B | G |
8490 // | | | |
8491 // | | | |
8492 // | | | |
8493 // +-----+ | |
8494 // | | | |
8495 // | G | | |
8496 // | | | |
8497 // | | | |
8498 // | | | |
8499 // +-----+-----------+-----+
8500 //
8501 EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height / 2, GLColor(99, 99, 99, 99));
8502 EXPECT_PIXEL_RECT_EQ(0, height / 2, width / 4, height - height / 2, GLColor::green);
8503 EXPECT_PIXEL_RECT_EQ(width / 4, 0, width / 2 - width / 4, height, GLColor::blue);
8504 EXPECT_PIXEL_RECT_EQ(width / 4 + width / 2, 0, width - width / 2 - width / 4, height,
8505 GLColor::green);
8506 };
8507
8508 useAHBByGLThenForeignThenGLHelper(first, second);
8509 }
8510
8511 // Test draw, readback, use in foreign, then draw again
TEST_P(ImageTest,DrawReadbackForeignDraw)8512 TEST_P(ImageTest, DrawReadbackForeignDraw)
8513 {
8514 GLFramebuffer fbo;
8515 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8516
8517 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8518 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8519 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8520
8521 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8522 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8523
8524 // A second usage of the same image
8525 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::green);
8526 };
8527 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8528 glBindTexture(GL_TEXTURE_2D, texture);
8529
8530 glEnable(GL_BLEND);
8531 glBlendFunc(GL_ONE, GL_ONE);
8532
8533 glEnable(GL_SCISSOR_TEST);
8534 glScissor(width / 4, 0, width / 2, height);
8535
8536 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8537 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8538
8539 // Expect the following:
8540 //
8541 // +-----+-----+-----+-----+
8542 // | | | | |
8543 // | 99 | 99 | G | G |
8544 // | | + | + | |
8545 // | | R | R | |
8546 // | | | | |
8547 // +-----+-----+-----+ |
8548 // | | | |
8549 // | G | G + R | G |
8550 // | | | |
8551 // | | | |
8552 // | | | |
8553 // +-----+-----------+-----+
8554 //
8555 EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height / 2, GLColor(99, 99, 99, 99));
8556 EXPECT_PIXEL_RECT_EQ(0, height / 2, width / 4, height - height / 2, GLColor::green);
8557 EXPECT_PIXEL_RECT_EQ(width / 4, 0, width / 2 - width / 4, height / 2,
8558 GLColor(255, 99, 99, 255));
8559 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 2, height - height / 2,
8560 GLColor::yellow);
8561 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2 - width / 4, height / 2, GLColor::yellow);
8562 EXPECT_PIXEL_RECT_EQ(width / 4 + width / 2, 0, width - width / 2 - width / 4, height,
8563 GLColor::green);
8564 };
8565
8566 useAHBByGLThenForeignThenGLHelper(first, second);
8567 }
8568
8569 // Test draw, use in foreign, then readback
TEST_P(ImageTest,DrawForeignReadback)8570 TEST_P(ImageTest, DrawForeignReadback)
8571 {
8572 GLFramebuffer fbo;
8573 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8574
8575 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8576 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8577 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8578
8579 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8580 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8581 };
8582 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8583 glBindTexture(GL_TEXTURE_2D, texture);
8584
8585 // Expect the following:
8586 //
8587 // +-----------+-----------+
8588 // | | |
8589 // | 99 | |
8590 // | | |
8591 // | | |
8592 // | | |
8593 // +-----------+ |
8594 // | |
8595 // | G |
8596 // | |
8597 // | |
8598 // | |
8599 // +-----------------------+
8600 //
8601 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2, height / 2, GLColor(99, 99, 99, 99));
8602 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width - width / 2, height / 2, GLColor::green);
8603 EXPECT_PIXEL_RECT_EQ(0, height / 2, width, height - height / 2, GLColor::green);
8604 };
8605
8606 useAHBByGLThenForeignThenGLHelper(first, second);
8607 }
8608
8609 // Test use as resolve attachment, use in foreign, then draw again
TEST_P(ImageTestES3,ResolveForeignDraw)8610 TEST_P(ImageTestES3, ResolveForeignDraw)
8611 {
8612 GLFramebuffer fbo;
8613
8614 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8615 GLRenderbuffer color;
8616 glBindRenderbuffer(GL_RENDERBUFFER, color);
8617 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, width, height);
8618
8619 GLFramebuffer msaaFbo;
8620 glBindFramebuffer(GL_FRAMEBUFFER, msaaFbo);
8621 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
8622 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8623
8624 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8625 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8626
8627 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
8628 glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,
8629 0);
8630 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_DRAW_FRAMEBUFFER);
8631
8632 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT,
8633 GL_NEAREST);
8634 glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
8635 };
8636 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8637 glBindTexture(GL_TEXTURE_2D, texture);
8638
8639 glEnable(GL_BLEND);
8640 glBlendFunc(GL_ONE, GL_ONE);
8641
8642 glEnable(GL_SCISSOR_TEST);
8643 glScissor(width / 4, 0, width / 2, height);
8644
8645 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8646 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8647
8648 // Expect the following:
8649 //
8650 // +-----+-----+-----+-----+
8651 // | | | | |
8652 // | 99 | 99 | G | G |
8653 // | | + | + | |
8654 // | | R | R | |
8655 // | | | | |
8656 // +-----+-----+-----+ |
8657 // | | | |
8658 // | G | G + R | G |
8659 // | | | |
8660 // | | | |
8661 // | | | |
8662 // +-----+-----------+-----+
8663 //
8664 EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height / 2, GLColor(99, 99, 99, 99));
8665 EXPECT_PIXEL_RECT_EQ(0, height / 2, width / 4, height - height / 2, GLColor::green);
8666 EXPECT_PIXEL_RECT_EQ(width / 4, 0, width / 2 - width / 4, height / 2,
8667 GLColor(255, 99, 99, 255));
8668 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 2, height - height / 2,
8669 GLColor::yellow);
8670 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2 - width / 4, height / 2, GLColor::yellow);
8671 EXPECT_PIXEL_RECT_EQ(width / 4 + width / 2, 0, width - width / 2 - width / 4, height,
8672 GLColor::green);
8673 };
8674
8675 useAHBByGLThenForeignThenGLHelper(first, second);
8676 }
8677
8678 // Test upload, use in foreign, then draw
TEST_P(ImageTest,UploadForeignDraw)8679 TEST_P(ImageTest, UploadForeignDraw)
8680 {
8681 GLFramebuffer fbo;
8682 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8683
8684 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8685 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8686 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8687
8688 std::vector<GLColor> data(width * height, GLColor::blue);
8689 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
8690 data.data());
8691
8692 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::blue);
8693 };
8694 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8695 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
8696 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8697
8698 glEnable(GL_BLEND);
8699 glBlendFunc(GL_ONE, GL_ONE);
8700
8701 glEnable(GL_SCISSOR_TEST);
8702 glScissor(width / 4, 0, width / 2, height);
8703
8704 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
8705 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8706
8707 // Expect the following:
8708 //
8709 // +-----+-----+-----+-----+
8710 // | | | | |
8711 // | 99 | 99 | B | B |
8712 // | | + | + | |
8713 // | | R | R | |
8714 // | | | | |
8715 // +-----+-----+-----+ |
8716 // | | | |
8717 // | B | B + R | B |
8718 // | | | |
8719 // | | | |
8720 // | | | |
8721 // +-----+-----------+-----+
8722 //
8723 EXPECT_PIXEL_RECT_EQ(0, 0, width / 4, height / 2, GLColor(99, 99, 99, 99));
8724 EXPECT_PIXEL_RECT_EQ(0, height / 2, width / 4, height - height / 2, GLColor::blue);
8725 EXPECT_PIXEL_RECT_EQ(width / 4, 0, width / 2 - width / 4, height / 2,
8726 GLColor(255, 99, 99, 255));
8727 EXPECT_PIXEL_RECT_EQ(width / 4, height / 2, width / 2, height - height / 2,
8728 GLColor::magenta);
8729 EXPECT_PIXEL_RECT_EQ(width / 2, 0, width / 2 - width / 4, height / 2, GLColor::magenta);
8730 EXPECT_PIXEL_RECT_EQ(width / 4 + width / 2, 0, width - width / 2 - width / 4, height,
8731 GLColor::blue);
8732 };
8733
8734 useAHBByGLThenForeignThenGLHelper(first, second);
8735 }
8736
8737 // Test sample in FS, use in foreign, then sample again in VS
TEST_P(ImageTestES3,SampleForeignSample)8738 TEST_P(ImageTestES3, SampleForeignSample)
8739 {
8740 GLTexture color;
8741
8742 GLFramebuffer fbo;
8743 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8744
8745 auto first = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8746 glBindTexture(GL_TEXTURE_2D, color);
8747 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8748 nullptr);
8749 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
8750 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8751
8752 glBindTexture(GL_TEXTURE_2D, texture);
8753 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8754 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8755 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
8756 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
8757
8758 std::vector<GLColor> data(width * height, GLColor::blue);
8759 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
8760 data.data());
8761
8762 ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(),
8763 essl1_shaders::fs::Texture2D());
8764 glUseProgram(drawTexture);
8765 GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform());
8766 ASSERT_NE(-1, texLocation);
8767 glUniform1i(texLocation, 0);
8768 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
8769
8770 EXPECT_PIXEL_RECT_EQ(0, 0, width, height, GLColor::blue);
8771 };
8772 auto second = [&](const GLTexture &texture, uint32_t width, uint32_t height) {
8773 glBindTexture(GL_TEXTURE_2D, texture);
8774
8775 constexpr char kVS[] = R"(precision highp float;
8776 uniform highp sampler2D tex;
8777 attribute vec2 position;
8778 varying vec4 color;
8779 void main()
8780 {
8781 color = texture2D(tex, position * 0.5 + 0.5);
8782 gl_Position = vec4(position, 0, 1);
8783 })";
8784
8785 constexpr char kFS[] = R"(precision highp float;
8786 varying vec4 color;
8787 void main()
8788 {
8789 gl_FragColor = color;
8790 })";
8791
8792 ANGLE_GL_PROGRAM(program, kVS, kFS);
8793 glUseProgram(program);
8794 GLint texLocation = glGetUniformLocation(program, "tex");
8795 ASSERT_NE(-1, texLocation);
8796 glUniform1i(texLocation, 0);
8797
8798 const std::array<Vector3, 12> kVertices = {{
8799 Vector3(-1.0f, -1.0f, 0.5f),
8800 Vector3(-1.0f, -0.1f, 0.5f),
8801 Vector3(-0.1f, -0.1f, 0.5f),
8802
8803 Vector3(-1.0f, -1.0f, 0.5f),
8804 Vector3(-0.1f, -0.1f, 0.5f),
8805 Vector3(-0.1f, -1.0f, 0.5f),
8806
8807 Vector3(0.1f, -1.0f, 0.5f),
8808 Vector3(0.1f, -0.1f, 0.5f),
8809 Vector3(1.0f, -0.1f, 0.5f),
8810
8811 Vector3(0.1f, -1.0f, 0.5f),
8812 Vector3(1.0f, -0.1f, 0.5f),
8813 Vector3(1.0f, -1.0f, 0.5f),
8814 }};
8815
8816 GLint positionLocation = glGetAttribLocation(program, "position");
8817 ASSERT_NE(-1, positionLocation);
8818 glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, kVertices.data());
8819 glEnableVertexAttribArray(positionLocation);
8820
8821 glClearColor(0, 255, 0, 255);
8822 glClear(GL_COLOR_BUFFER_BIT);
8823 glDrawArrays(GL_TRIANGLES, 0, 12);
8824
8825 // Expect the following:
8826 //
8827 // +---------+---+---------+
8828 // | | | |
8829 // | 99 | | B |
8830 // | | | |
8831 // | | | |
8832 // |---------+ +---------|
8833 // | |
8834 // | |
8835 // | G |
8836 // | |
8837 // | |
8838 // | |
8839 // +-----------------------+
8840 //
8841 EXPECT_PIXEL_RECT_EQ(0, 0, width / 2 - width / 10 - 1, height / 2 - height / 10 - 1,
8842 GLColor(99, 99, 99, 99));
8843 EXPECT_PIXEL_RECT_EQ(width / 2 + width / 10 + 1, 0, width - width / 2 - width / 10 - 1,
8844 height / 2 - 1, GLColor::blue);
8845 EXPECT_PIXEL_RECT_EQ(0, height / 2, width, height - height / 2, GLColor::green);
8846 };
8847
8848 useAHBByGLThenForeignThenGLHelper(first, second);
8849 }
8850
8851 // Test draw, use in foreign, readback in another context, use in foreign, then sample in the
8852 // original context.
TEST_P(ImageTestES3,MultithreadedDrawForeignReadbackForeignSample)8853 TEST_P(ImageTestES3, MultithreadedDrawForeignReadbackForeignSample)
8854 {
8855 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
8856 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
8857 ANGLE_SKIP_TEST_IF(!platformSupportsMultithreading());
8858
8859 EGLWindow *window = getEGLWindow();
8860
8861 constexpr uint32_t kWidth = 53;
8862 constexpr uint32_t kHeight = 37;
8863
8864 // Create the Image
8865 AHardwareBuffer *source;
8866 EGLImageKHR image;
8867 createEGLImageAndroidHardwareBufferSource(
8868 kWidth, kHeight, 1, AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM, kDefaultAHBUsage,
8869 kDefaultAttribs, {}, &source, &image);
8870
8871 std::mutex mutex;
8872 std::condition_variable condVar;
8873
8874 enum class Step
8875 {
8876 Start,
8877 Thread0DrawDone,
8878 Thread1ReadbackDone,
8879 Finish,
8880 Abort,
8881 };
8882 Step currentStep = Step::Start;
8883
8884 auto thread0 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
8885 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
8886
8887 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
8888
8889 // Create a texture target to bind the egl image
8890 GLTexture target;
8891 createEGLImageTargetTexture2D(image, target);
8892 ASSERT_GL_NO_ERROR();
8893
8894 // Draw into the image in this context.
8895 GLFramebuffer fbo;
8896 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
8897 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
8898 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8899
8900 glViewport(0, 0, kWidth, kHeight);
8901 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
8902 drawQuad(program, essl1_shaders::PositionAttrib(), 0.0f);
8903 ASSERT_GL_NO_ERROR();
8904
8905 EGLSyncKHR fence = eglCreateSyncKHR(window->getDisplay(), EGL_SYNC_FENCE_KHR, NULL);
8906 glFlush();
8907 EGLint result = eglClientWaitSyncKHR(window->getDisplay(), fence, 0, 1'000'000'000);
8908 ASSERT_EQ(result, EGL_CONDITION_SATISFIED_KHR);
8909 ASSERT_EGL_TRUE(eglDestroySyncKHR(window->getDisplay(), fence));
8910
8911 // Then overwrite a quarter of the image with some color
8912 std::vector<GLubyte> data((kWidth / 2) * (kHeight / 2) * 4, 99);
8913 writeAHBData(source, kWidth / 2, kHeight / 2, 1, false, {{data.data(), 4}});
8914
8915 // Wait for the other thread to read back from it.
8916 threadSynchronization.nextStep(Step::Thread0DrawDone);
8917 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread1ReadbackDone));
8918
8919 // Create a different framebuffer to render to.
8920 GLTexture color;
8921 glBindTexture(GL_TEXTURE_2D, color);
8922 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
8923 nullptr);
8924 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
8925 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
8926
8927 // Sample from the image.
8928 glBindTexture(GL_TEXTURE_2D, target);
8929 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
8930 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
8931 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
8932 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
8933
8934 ANGLE_GL_PROGRAM(drawTexture, essl1_shaders::vs::Texture2D(),
8935 essl1_shaders::fs::Texture2D());
8936 glUseProgram(drawTexture);
8937 GLint texLocation = glGetUniformLocation(drawTexture, essl1_shaders::Texture2DUniform());
8938 ASSERT_NE(-1, texLocation);
8939 glUniform1i(texLocation, 0);
8940 drawQuad(drawTexture, essl1_shaders::PositionAttrib(), 0.5f);
8941
8942 // Expect the following:
8943 //
8944 // +-----+-----+-----+-----+
8945 // | | | |
8946 // | 123 | 99 | G |
8947 // | | | |
8948 // | | | |
8949 // | | | |
8950 // | +-----+ |
8951 // | | |
8952 // | 123 | |
8953 // | | |
8954 // | | |
8955 // | | |
8956 // +-----+-----------+-----+
8957 //
8958 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 4, kHeight, GLColor(123, 123, 123, 123));
8959 EXPECT_PIXEL_RECT_EQ(kWidth / 4, 0, kWidth / 2 - kWidth / 4, kHeight / 2,
8960 GLColor(99, 99, 99, 99));
8961 EXPECT_PIXEL_RECT_EQ(kWidth / 4, kHeight / 2, kWidth / 2 - kWidth / 4,
8962 kHeight - kHeight / 2, GLColor::green);
8963 EXPECT_PIXEL_RECT_EQ(kWidth / 2, 0, kWidth - kWidth / 2, kHeight, GLColor::green);
8964
8965 eglDestroyImageKHR(window->getDisplay(), image);
8966
8967 threadSynchronization.nextStep(Step::Finish);
8968
8969 // Clean up
8970 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
8971 };
8972
8973 auto thread1 = [&](EGLDisplay dpy, EGLSurface surface, EGLContext context) {
8974 ThreadSynchronization<Step> threadSynchronization(¤tStep, &mutex, &condVar);
8975
8976 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, surface, surface, context));
8977
8978 // Create a texture target to bind the egl image
8979 GLTexture target;
8980 createEGLImageTargetTexture2D(image, target);
8981
8982 // Wait for thread 0 to set up, and rebind the texture.
8983 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Thread0DrawDone));
8984 glBindTexture(GL_TEXTURE_2D, target);
8985
8986 // Expect the following:
8987 //
8988 // +-----------+-----------+
8989 // | | |
8990 // | 99 | |
8991 // | | |
8992 // | | |
8993 // | | |
8994 // +-----------+ |
8995 // | |
8996 // | G |
8997 // | |
8998 // | |
8999 // | |
9000 // +-----------------------+
9001 //
9002 GLFramebuffer fbo;
9003 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
9004 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
9005 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
9006
9007 EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kHeight / 2, GLColor(99, 99, 99, 99));
9008 EXPECT_PIXEL_RECT_EQ(kWidth / 2, 0, kWidth - kWidth / 2, kHeight / 2, GLColor::green);
9009 EXPECT_PIXEL_RECT_EQ(0, kHeight / 2, kWidth, kHeight - kHeight / 2, GLColor::green);
9010
9011 // Then overwrite parts of the image with another color
9012 std::vector<GLubyte> data((kWidth / 4) * kHeight * 4, 123);
9013 writeAHBData(source, kWidth / 4, kHeight, 1, false, {{data.data(), 4}});
9014
9015 // Notify the other thread that it's finished reading back the texture.
9016 threadSynchronization.nextStep(Step::Thread1ReadbackDone);
9017 ASSERT_TRUE(threadSynchronization.waitForStep(Step::Finish));
9018
9019 // Clean up
9020 EXPECT_EGL_TRUE(eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
9021 };
9022
9023 std::array<LockStepThreadFunc, 2> threadFuncs = {
9024 std::move(thread0),
9025 std::move(thread1),
9026 };
9027
9028 RunLockStepThreads(getEGLWindow(), threadFuncs.size(), threadFuncs.data());
9029
9030 ASSERT_NE(currentStep, Step::Abort);
9031 }
9032
9033 // Test redefining the same GL texture with different EGLImages
TEST_P(ImageTest,RedefineWithMultipleImages)9034 TEST_P(ImageTest, RedefineWithMultipleImages)
9035 {
9036 EGLWindow *window = getEGLWindow();
9037
9038 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
9039
9040 GLubyte originalData[4] = {255, 0, 255, 255};
9041 GLubyte updateData[4] = {0, 255, 0, 255};
9042
9043 // Create the Images
9044 GLTexture source1, source2;
9045 EGLImageKHR image1, image2;
9046 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
9047 source1, &image1);
9048 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
9049 source2, &image2);
9050
9051 // Create texture & bind to Image
9052 GLTexture texture;
9053 createEGLImageTargetTexture2D(image1, texture);
9054
9055 // Upload some data between the redefinition
9056 glBindTexture(GL_TEXTURE_2D, texture);
9057 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
9058
9059 GLFramebuffer fbo;
9060 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
9061 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
9062 EXPECT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
9063 ASSERT_GL_NO_ERROR();
9064
9065 glClear(GL_COLOR_BUFFER_BIT);
9066
9067 // Bind the second image to this texture
9068 createEGLImageTargetTexture2D(image2, texture);
9069
9070 // Delete Image
9071 eglDestroyImageKHR(window->getDisplay(), image1);
9072 eglDestroyImageKHR(window->getDisplay(), image2);
9073
9074 ASSERT_EGL_SUCCESS();
9075
9076 ASSERT_GL_NO_ERROR();
9077 }
9078
9079 // Regression test to check that sRGB texture can be used to create image in sRGB colorspace.
9080 // Also check that creating image using sRGB texture in linear colorspace wouldn't fail.
TEST_P(ImageTestES3,CreatesRGBImages)9081 TEST_P(ImageTestES3, CreatesRGBImages)
9082 {
9083 EGLWindow *window = getEGLWindow();
9084 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
9085 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_sRGB"));
9086 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
9087 ANGLE_SKIP_TEST_IF(
9088 !IsEGLDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_colorspace"));
9089
9090 std::vector<EGLint> colorSpaces = {EGL_GL_COLORSPACE_SRGB_KHR, EGL_GL_COLORSPACE_LINEAR_KHR};
9091 constexpr GLsizei kWidth = 2;
9092 constexpr GLsizei kHeight = 2;
9093
9094 for (size_t i = 0; i < colorSpaces.size(); i++)
9095 {
9096 // Create sRGB texture
9097 GLTexture sRGBTexture;
9098 glBindTexture(GL_TEXTURE_2D, sRGBTexture);
9099 glTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB8_ALPHA8, kWidth, kHeight, 0, GL_RGBA,
9100 GL_UNSIGNED_BYTE, nullptr);
9101 ASSERT_GL_NO_ERROR();
9102
9103 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
9104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
9105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
9106 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
9107 ASSERT_GL_NO_ERROR();
9108
9109 EGLint createImageAttribs[] = {
9110 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_GL_COLORSPACE_KHR, colorSpaces[i], EGL_NONE,
9111 };
9112
9113 // Create the Image using sRGB texture
9114 EGLImageKHR image =
9115 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
9116 reinterpretHelper<EGLClientBuffer>(sRGBTexture), createImageAttribs);
9117 ASSERT_EGL_SUCCESS();
9118 ASSERT_NE(image, EGL_NO_IMAGE_KHR);
9119
9120 // Clean up
9121 eglDestroyImageKHR(window->getDisplay(), image);
9122 }
9123 }
9124
9125 // Regression test to check that sRGB texture can be used to create image in sRGB colorspace.
9126 // Also check that creating image using sRGB texture in linear colorspace wouldn't fail.
TEST_P(ImageTestES3,DmaBufNegativeValidation)9127 TEST_P(ImageTestES3, DmaBufNegativeValidation)
9128 {
9129 EGLWindow *window = getEGLWindow();
9130 ANGLE_SKIP_TEST_IF(!hasBaseExt());
9131 ANGLE_SKIP_TEST_IF(!IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
9132 "EGL_EXT_image_dma_buf_import"));
9133
9134 const EGLint invalidImageAttributeList[][3] = {
9135 {EGL_YUV_COLOR_SPACE_HINT_EXT, EGL_NONE, EGL_NONE},
9136 {EGL_SAMPLE_RANGE_HINT_EXT, EGL_NONE, EGL_NONE},
9137 {EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT, EGL_NONE, EGL_NONE},
9138 {EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT, EGL_NONE, EGL_NONE},
9139 };
9140
9141 EGLImageKHR image;
9142
9143 for (size_t i = 0; i < 4; i++)
9144 {
9145 image = eglCreateImageKHR(window->getDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL,
9146 invalidImageAttributeList[i]);
9147 ASSERT_EGL_ERROR(EGL_BAD_ATTRIBUTE);
9148 ASSERT_EQ(image, EGL_NO_IMAGE_KHR);
9149 }
9150 }
9151
9152 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND(ImageTest,
9153 ES3_VULKAN().enable(Feature::AllocateNonZeroMemory));
9154
9155 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageTestES3);
9156 ANGLE_INSTANTIATE_TEST_ES3_AND(ImageTestES3, ES3_VULKAN().enable(Feature::AllocateNonZeroMemory));
9157
9158 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ImageTestES31);
9159 ANGLE_INSTANTIATE_TEST_ES31_AND(ImageTestES31,
9160 ES31_VULKAN().enable(Feature::AllocateNonZeroMemory));
9161 } // namespace angle
9162