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