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