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