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