xref: /aosp_15_r20/external/angle/src/tests/gl_tests/ImageTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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(&currentStep, &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(&currentStep, &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(&currentStep, &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(&currentStep, &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(&currentStep, &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(&currentStep, &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(&currentStep, &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(&currentStep, &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