blob: b846d8471bb3c34c64639485f6dc3ca99ef4f3b4 [file] [log] [blame]
Geoff Langa8406172015-07-21 16:53:39 -04001//
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"
Geoff Lang48d040e2019-01-18 10:43:45 -050011#include "test_utils/gl_raii.h"
Jamie Madillba319ba2018-12-29 10:29:33 -050012#include "util/EGLWindow.h"
Geoff Langa8406172015-07-21 16:53:39 -040013
Mohan Maiyadd2316d2020-07-02 14:20:05 -070014#include "common/android_util.h"
15
16#if defined(ANGLE_PLATFORM_ANDROID) && __ANDROID_API__ >= 26
17# define ANGLE_AHARDWARE_BUFFER_SUPPORT
18// NDK header file for access to Android Hardware Buffers
19# include <android/hardware_buffer.h>
20#endif
21
Geoff Langa8406172015-07-21 16:53:39 -040022namespace angle
23{
Jamie Madill0be37b42018-07-19 10:03:52 -040024namespace
25{
Mohan Maiyadd2316d2020-07-02 14:20:05 -070026constexpr char kOESExt[] = "GL_OES_EGL_image";
27constexpr char kExternalExt[] = "GL_OES_EGL_image_external";
28constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
29constexpr char kBaseExt[] = "EGL_KHR_image_base";
30constexpr char k2DTextureExt[] = "EGL_KHR_gl_texture_2D_image";
31constexpr char k3DTextureExt[] = "EGL_KHR_gl_texture_3D_image";
32constexpr char kPixmapExt[] = "EGL_KHR_image_pixmap";
33constexpr char kRenderbufferExt[] = "EGL_KHR_gl_renderbuffer_image";
34constexpr char kCubemapExt[] = "EGL_KHR_gl_texture_cubemap_image";
35constexpr char kImageGLColorspaceExt[] = "EGL_EXT_image_gl_colorspace";
36constexpr char kEGLImageArrayExt[] = "GL_EXT_EGL_image_array";
37constexpr char kEGLAndroidImageNativeBufferExt[] = "EGL_ANDROID_image_native_buffer";
38constexpr EGLint kDefaultAttribs[] = {
Mohan Maiyadac5cc32020-04-08 18:26:46 -070039 EGL_IMAGE_PRESERVED,
40 EGL_TRUE,
41 EGL_NONE,
42};
43constexpr EGLint kColorspaceAttribs[] = {
44 EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_SRGB_KHR, EGL_NONE,
45};
Jamie Madill0be37b42018-07-19 10:03:52 -040046} // anonymous namespace
47
Geoff Langa8406172015-07-21 16:53:39 -040048class ImageTest : public ANGLETest
49{
50 protected:
51 ImageTest()
52 {
53 setWindowWidth(128);
54 setWindowHeight(128);
55 setConfigRedBits(8);
56 setConfigGreenBits(8);
57 setConfigBlueBits(8);
58 setConfigAlphaBits(8);
59 setConfigDepthBits(24);
60 }
61
Jamie Madill5cbaa3f2019-05-07 15:49:22 -040062 void testSetUp() override
Geoff Langa8406172015-07-21 16:53:39 -040063 {
Jamie Madill35cd7332018-12-02 12:03:33 -050064 constexpr char kVS[] =
Geoff Langa8406172015-07-21 16:53:39 -040065 "precision highp float;\n"
66 "attribute vec4 position;\n"
67 "varying vec2 texcoord;\n"
68 "\n"
69 "void main()\n"
70 "{\n"
71 " gl_Position = position;\n"
72 " texcoord = (position.xy * 0.5) + 0.5;\n"
73 " texcoord.y = 1.0 - texcoord.y;\n"
74 "}\n";
Mohan Maiyadaed3692020-05-05 14:24:26 -070075 constexpr char kVS2DArray[] =
76 "#version 300 es\n"
77 "out vec2 texcoord;\n"
78 "in vec4 position;\n"
79 "void main()\n"
80 "{\n"
81 " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
82 " texcoord = (position.xy * 0.5) + 0.5;\n"
83 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -050084 constexpr char kVSESSL3[] =
Geoff Langb66a9092016-05-16 15:59:14 -040085 "#version 300 es\n"
86 "precision highp float;\n"
87 "in vec4 position;\n"
88 "out vec2 texcoord;\n"
89 "\n"
90 "void main()\n"
91 "{\n"
92 " gl_Position = position;\n"
93 " texcoord = (position.xy * 0.5) + 0.5;\n"
94 " texcoord.y = 1.0 - texcoord.y;\n"
95 "}\n";
Geoff Langa8406172015-07-21 16:53:39 -040096
Jamie Madill35cd7332018-12-02 12:03:33 -050097 constexpr char kTextureFS[] =
Geoff Langa8406172015-07-21 16:53:39 -040098 "precision highp float;\n"
99 "uniform sampler2D tex;\n"
100 "varying vec2 texcoord;\n"
101 "\n"
102 "void main()\n"
103 "{\n"
104 " gl_FragColor = texture2D(tex, texcoord);\n"
105 "}\n";
Mohan Maiyadaed3692020-05-05 14:24:26 -0700106 constexpr char kTexture2DArrayFS[] =
107 "#version 300 es\n"
108 "precision highp float;\n"
109 "uniform highp sampler2DArray tex2DArray;\n"
110 "in vec2 texcoord;\n"
111 "out vec4 fragColor;\n"
112 "void main()\n"
113 "{\n"
114 " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
115 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500116 constexpr char kTextureExternalFS[] =
Geoff Langb66a9092016-05-16 15:59:14 -0400117 "#extension GL_OES_EGL_image_external : require\n"
118 "precision highp float;\n"
119 "uniform samplerExternalOES tex;\n"
120 "varying vec2 texcoord;\n"
121 "\n"
122 "void main()\n"
123 "{\n"
124 " gl_FragColor = texture2D(tex, texcoord);\n"
125 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -0500126 constexpr char kTextureExternalESSL3FS[] =
Geoff Langb66a9092016-05-16 15:59:14 -0400127 "#version 300 es\n"
128 "#extension GL_OES_EGL_image_external_essl3 : require\n"
129 "precision highp float;\n"
130 "uniform samplerExternalOES tex;\n"
131 "in vec2 texcoord;\n"
132 "out vec4 color;"
133 "\n"
134 "void main()\n"
135 "{\n"
136 " color = texture(tex, texcoord);\n"
137 "}\n";
Geoff Langa8406172015-07-21 16:53:39 -0400138
Jamie Madill35cd7332018-12-02 12:03:33 -0500139 mTextureProgram = CompileProgram(kVS, kTextureFS);
Geoff Langa8406172015-07-21 16:53:39 -0400140 if (mTextureProgram == 0)
141 {
142 FAIL() << "shader compilation failed.";
143 }
144
145 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
146
Mohan Maiyadaed3692020-05-05 14:24:26 -0700147 if (getClientMajorVersion() >= 3)
148 {
149 m2DArrayTextureProgram = CompileProgram(kVS2DArray, kTexture2DArrayFS);
150 if (m2DArrayTextureProgram == 0)
151 {
152 FAIL() << "shader compilation failed.";
153 }
154
155 m2DArrayTextureUniformLocation =
156 glGetUniformLocation(m2DArrayTextureProgram, "tex2DArray");
157 }
158
Jamie Madillb8149072019-04-30 16:14:44 -0400159 if (IsGLExtensionEnabled("GL_OES_EGL_image_external"))
Geoff Langb66a9092016-05-16 15:59:14 -0400160 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500161 mTextureExternalProgram = CompileProgram(kVS, kTextureExternalFS);
Geoff Langb66a9092016-05-16 15:59:14 -0400162 ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
163
164 mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
165 }
166
Jamie Madillb8149072019-04-30 16:14:44 -0400167 if (IsGLExtensionEnabled("GL_OES_EGL_image_external_essl3"))
Geoff Langb66a9092016-05-16 15:59:14 -0400168 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500169 mTextureExternalESSL3Program = CompileProgram(kVSESSL3, kTextureExternalESSL3FS);
Geoff Langb66a9092016-05-16 15:59:14 -0400170 ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
171
172 mTextureExternalESSL3UniformLocation =
173 glGetUniformLocation(mTextureExternalESSL3Program, "tex");
174 }
175
Geoff Langa8406172015-07-21 16:53:39 -0400176 ASSERT_GL_NO_ERROR();
177 }
178
Jamie Madill5cbaa3f2019-05-07 15:49:22 -0400179 void testTearDown() override
Geoff Langa8406172015-07-21 16:53:39 -0400180 {
Geoff Langa8406172015-07-21 16:53:39 -0400181 glDeleteProgram(mTextureProgram);
Geoff Langb66a9092016-05-16 15:59:14 -0400182 glDeleteProgram(mTextureExternalProgram);
183 glDeleteProgram(mTextureExternalESSL3Program);
Geoff Langa8406172015-07-21 16:53:39 -0400184 }
185
186 void createEGLImage2DTextureSource(size_t width,
187 size_t height,
188 GLenum format,
189 GLenum type,
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700190 const EGLint *attribs,
Geoff Langa8406172015-07-21 16:53:39 -0400191 void *data,
192 GLuint *outSourceTexture,
193 EGLImageKHR *outSourceImage)
194 {
195 // Create a source 2D texture
196 GLuint source;
197 glGenTextures(1, &source);
198 glBindTexture(GL_TEXTURE_2D, source);
199
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700200 glTexImage2D(GL_TEXTURE_2D, 0, format, static_cast<GLsizei>(width),
201 static_cast<GLsizei>(height), 0, format, type, data);
Geoff Langa8406172015-07-21 16:53:39 -0400202
203 // Disable mipmapping
204 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
205 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
206
207 ASSERT_GL_NO_ERROR();
208
209 // Create an image from the source texture
210 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400211
Geoff Langa8406172015-07-21 16:53:39 -0400212 EGLImageKHR image =
213 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
Geoff Langc0b61502018-07-27 15:59:32 -0400214 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400215
216 ASSERT_EGL_SUCCESS();
217
218 *outSourceTexture = source;
219 *outSourceImage = image;
220 }
221
222 void createEGLImageCubemapTextureSource(size_t width,
223 size_t height,
224 GLenum format,
225 GLenum type,
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700226 const EGLint *attribs,
Geoff Langa8406172015-07-21 16:53:39 -0400227 uint8_t *data,
228 size_t dataStride,
229 EGLenum imageTarget,
230 GLuint *outSourceTexture,
231 EGLImageKHR *outSourceImage)
232 {
233 // Create a source cube map texture
234 GLuint source;
235 glGenTextures(1, &source);
236 glBindTexture(GL_TEXTURE_CUBE_MAP, source);
237
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700238 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -0400239 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700240 glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format,
241 static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, format, type,
242 data + (faceIdx * dataStride));
Geoff Langa8406172015-07-21 16:53:39 -0400243 }
244
245 // Disable mipmapping
246 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
247 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
248
249 ASSERT_GL_NO_ERROR();
250
251 // Create an image from the source texture
252 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400253
Geoff Langa8406172015-07-21 16:53:39 -0400254 EGLImageKHR image =
255 eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
Geoff Langc0b61502018-07-27 15:59:32 -0400256 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400257
258 ASSERT_EGL_SUCCESS();
259
260 *outSourceTexture = source;
261 *outSourceImage = image;
262 }
263
264 void createEGLImage3DTextureSource(size_t width,
265 size_t height,
266 size_t depth,
267 GLenum format,
268 GLenum type,
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700269 const EGLint *attribs,
Geoff Langa8406172015-07-21 16:53:39 -0400270 void *data,
Geoff Langa8406172015-07-21 16:53:39 -0400271 GLuint *outSourceTexture,
272 EGLImageKHR *outSourceImage)
273 {
274 // Create a source 3D texture
275 GLuint source;
276 glGenTextures(1, &source);
277 glBindTexture(GL_TEXTURE_3D, source);
278
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700279 glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast<GLsizei>(width),
280 static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type,
281 data);
Geoff Langa8406172015-07-21 16:53:39 -0400282
283 // Disable mipmapping
284 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
285 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
286
287 ASSERT_GL_NO_ERROR();
288
289 // Create an image from the source texture
290 EGLWindow *window = getEGLWindow();
291
Geoff Langa8406172015-07-21 16:53:39 -0400292 EGLImageKHR image =
293 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700294 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400295
296 ASSERT_EGL_SUCCESS();
297
298 *outSourceTexture = source;
299 *outSourceImage = image;
300 }
301
302 void createEGLImageRenderbufferSource(size_t width,
303 size_t height,
304 GLenum internalFormat,
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700305 const EGLint *attribs,
Geoff Langa8406172015-07-21 16:53:39 -0400306 GLubyte data[4],
307 GLuint *outSourceRenderbuffer,
308 EGLImageKHR *outSourceImage)
309 {
310 // Create a source renderbuffer
311 GLuint source;
312 glGenRenderbuffers(1, &source);
313 glBindRenderbuffer(GL_RENDERBUFFER, source);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700314 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, static_cast<GLsizei>(width),
315 static_cast<GLsizei>(height));
Geoff Langa8406172015-07-21 16:53:39 -0400316
317 // Create a framebuffer and clear it to set the data
318 GLuint framebuffer;
319 glGenFramebuffers(1, &framebuffer);
320 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
321 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
322
323 glClearColor(data[0] / 255.0f, data[1] / 255.0f, data[2] / 255.0f, data[3] / 255.0f);
324 glClear(GL_COLOR_BUFFER_BIT);
325
326 glDeleteFramebuffers(1, &framebuffer);
327
328 ASSERT_GL_NO_ERROR();
329
330 // Create an image from the source renderbuffer
331 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400332
Geoff Langa8406172015-07-21 16:53:39 -0400333 EGLImageKHR image =
334 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
Geoff Langc0b61502018-07-27 15:59:32 -0400335 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400336
337 ASSERT_EGL_SUCCESS();
338
339 *outSourceRenderbuffer = source;
340 *outSourceImage = image;
341 }
342
343 void createEGLImageTargetTexture2D(EGLImageKHR image, GLuint *outTargetTexture)
344 {
345 // Create a target texture from the image
346 GLuint target;
347 glGenTextures(1, &target);
348 glBindTexture(GL_TEXTURE_2D, target);
349 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
350
351 // Disable mipmapping
352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
354
355 ASSERT_GL_NO_ERROR();
356
357 *outTargetTexture = target;
358 }
359
Mohan Maiyadaed3692020-05-05 14:24:26 -0700360 void createEGLImageTargetTexture2DArray(EGLImageKHR image, GLuint *outTargetTexture)
361 {
362 // Create a target texture from the image
363 GLuint target;
364 glGenTextures(1, &target);
365 glBindTexture(GL_TEXTURE_2D_ARRAY, target);
366 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D_ARRAY, image);
367
368 // Disable mipmapping
369 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
370 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
371
372 ASSERT_GL_NO_ERROR();
373
374 *outTargetTexture = target;
375 }
376
Geoff Langb66a9092016-05-16 15:59:14 -0400377 void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint *outTargetTexture)
378 {
379 // Create a target texture from the image
380 GLuint target;
381 glGenTextures(1, &target);
382 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
383 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
384
385 // Disable mipmapping
386 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
387 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
388
389 ASSERT_GL_NO_ERROR();
390
391 *outTargetTexture = target;
392 }
393
Mohan Maiyadd2316d2020-07-02 14:20:05 -0700394 AHardwareBuffer *createAndroidHardwareBuffer(size_t width,
395 size_t height,
396 size_t depth,
397 int androidFormat,
398 const GLubyte *data,
399 size_t bytesPerPixel)
400 {
401#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
402 // The height and width are number of pixels of size format
403 AHardwareBuffer_Desc aHardwareBufferDescription = {};
404 aHardwareBufferDescription.width = width;
405 aHardwareBufferDescription.height = height;
406 aHardwareBufferDescription.layers = depth;
407 aHardwareBufferDescription.format = androidFormat;
408 aHardwareBufferDescription.usage =
409 AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY | AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
410 aHardwareBufferDescription.stride = 0;
411 aHardwareBufferDescription.rfu0 = 0;
412 aHardwareBufferDescription.rfu1 = 0;
413
414 // Allocate memory from Android Hardware Buffer
415 AHardwareBuffer *aHardwareBuffer = nullptr;
416 EXPECT_EQ(0, AHardwareBuffer_allocate(&aHardwareBufferDescription, &aHardwareBuffer));
417
418 void *mappedMemory = nullptr;
419 EXPECT_EQ(0, AHardwareBuffer_lock(aHardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_WRITE_RARELY,
420 -1, nullptr, &mappedMemory));
421
422 // Need to grab the stride the implementation might have enforced
423 AHardwareBuffer_describe(aHardwareBuffer, &aHardwareBufferDescription);
424 const uint32_t stride = aHardwareBufferDescription.stride;
425
426 const uint32_t rowSize = bytesPerPixel * width;
427 for (uint32_t i = 0; i < height; i++)
428 {
429 uint32_t dstPtrOffset = stride * i * bytesPerPixel;
430 uint32_t srcPtrOffset = width * i * bytesPerPixel;
431
432 void *dst = reinterpret_cast<uint8_t *>(mappedMemory) + dstPtrOffset;
433 memcpy(dst, data + srcPtrOffset, rowSize);
434 }
435
436 EXPECT_EQ(0, AHardwareBuffer_unlock(aHardwareBuffer, nullptr));
Mohan Maiyadd2316d2020-07-02 14:20:05 -0700437 return aHardwareBuffer;
438#else
439 return nullptr;
440#endif // ANGLE_PLATFORM_ANDROID
441 }
442
443 void destroyAndroidHardwareBuffer(AHardwareBuffer *aHardwarebuffer)
444 {
445#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
446 AHardwareBuffer_release(aHardwarebuffer);
447#endif
448 }
449
450 void createEGLImageAndroidHardwareBufferSource(size_t width,
451 size_t height,
452 size_t depth,
453 GLenum sizedInternalFormat,
454 const EGLint *attribs,
455 const GLubyte *data,
456 size_t bytesPerPixel,
457 AHardwareBuffer **outSourceAHB,
458 EGLImageKHR *outSourceImage)
459 {
460 // Set Android Memory
461 AHardwareBuffer *aHardwareBuffer = createAndroidHardwareBuffer(
462 width, height, depth,
463 angle::android::GLInternalFormatToNativePixelFormat(sizedInternalFormat), data,
464 bytesPerPixel);
465 EXPECT_NE(aHardwareBuffer, nullptr);
466
467 // Create an image from the source AHB
468 EGLWindow *window = getEGLWindow();
469
470 EGLImageKHR image = eglCreateImageKHR(
471 window->getDisplay(), EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
472 angle::android::AHardwareBufferToClientBuffer(aHardwareBuffer), attribs);
473 ASSERT_EGL_SUCCESS();
474
475 *outSourceAHB = aHardwareBuffer;
476 *outSourceImage = image;
477 }
Geoff Langa8406172015-07-21 16:53:39 -0400478 void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
479 {
480 // Create a target texture from the image
481 GLuint target;
482 glGenRenderbuffers(1, &target);
483 glBindRenderbuffer(GL_RENDERBUFFER, target);
484 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
485
486 ASSERT_GL_NO_ERROR();
487
488 *outTargetRenderbuffer = target;
489 }
490
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700491 void ValidationGLEGLImage_helper(const EGLint *attribs);
Mohan Maiyadd2316d2020-07-02 14:20:05 -0700492 void SourceAHBTarget2D_helper(const EGLint *attribs);
493 void SourceAHBTarget2DArray_helper(const EGLint *attribs);
494 void SourceAHBTargetExternal_helper(const EGLint *attribs);
495 void SourceAHBTargetExternalESSL3_helper(const EGLint *attribs);
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700496 void Source2DTarget2D_helper(const EGLint *attribs);
Mohan Maiyadaed3692020-05-05 14:24:26 -0700497 void Source2DTarget2DArray_helper(const EGLint *attribs);
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700498 void Source2DTargetRenderbuffer_helper(const EGLint *attribs);
499 void Source2DTargetExternal_helper(const EGLint *attribs);
500 void Source2DTargetExternalESSL3_helper(const EGLint *attribs);
501 void SourceCubeTarget2D_helper(const EGLint *attribs);
502 void SourceCubeTargetRenderbuffer_helper(const EGLint *attribs);
503 void SourceCubeTargetExternal_helper(const EGLint *attribs);
504 void SourceCubeTargetExternalESSL3_helper(const EGLint *attribs);
505 void Source3DTargetTexture_helper(const bool withColorspace);
506 void Source3DTargetRenderbuffer_helper(const bool withColorspace);
507 void Source3DTargetExternal_helper(const bool withColorspace);
508 void Source3DTargetExternalESSL3_helper(const bool withColorspace);
509 void SourceRenderbufferTargetTexture_helper(const EGLint *attribs);
510 void SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs);
511 void SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs);
512 void SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs);
513
Geoff Langb66a9092016-05-16 15:59:14 -0400514 void verifyResultsTexture(GLuint texture,
515 GLubyte data[4],
516 GLenum textureTarget,
517 GLuint program,
518 GLuint textureUniform)
Geoff Langa8406172015-07-21 16:53:39 -0400519 {
520 // Draw a quad with the target texture
Geoff Langb66a9092016-05-16 15:59:14 -0400521 glUseProgram(program);
522 glBindTexture(textureTarget, texture);
523 glUniform1i(textureUniform, 0);
Geoff Langa8406172015-07-21 16:53:39 -0400524
Geoff Langb66a9092016-05-16 15:59:14 -0400525 drawQuad(program, "position", 0.5f);
Geoff Langa8406172015-07-21 16:53:39 -0400526
527 // Expect that the rendered quad has the same color as the source texture
528 EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
529 }
530
Geoff Langb66a9092016-05-16 15:59:14 -0400531 void verifyResults2D(GLuint texture, GLubyte data[4])
532 {
533 verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
534 mTextureUniformLocation);
535 }
536
Mohan Maiyadaed3692020-05-05 14:24:26 -0700537 void verifyResults2DArray(GLuint texture, GLubyte data[4])
538 {
539 verifyResultsTexture(texture, data, GL_TEXTURE_2D_ARRAY, m2DArrayTextureProgram,
540 m2DArrayTextureUniformLocation);
541 }
542
Geoff Langb66a9092016-05-16 15:59:14 -0400543 void verifyResultsExternal(GLuint texture, GLubyte data[4])
544 {
545 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
546 mTextureExternalUniformLocation);
547 }
548
549 void verifyResultsExternalESSL3(GLuint texture, GLubyte data[4])
550 {
551 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
552 mTextureExternalESSL3UniformLocation);
553 }
554
Geoff Langa8406172015-07-21 16:53:39 -0400555 void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
556 {
557 // Bind the renderbuffer to a framebuffer
558 GLuint framebuffer;
559 glGenFramebuffers(1, &framebuffer);
560 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
561 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
562 renderbuffer);
563
564 // Expect that the rendered quad has the same color as the source texture
565 EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
566
567 glDeleteFramebuffers(1, &framebuffer);
568 }
569
Austin Kinrossa8187762015-08-12 10:54:37 -0700570 template <typename destType, typename sourcetype>
571 destType reinterpretHelper(sourcetype source)
572 {
573 static_assert(sizeof(destType) == sizeof(size_t),
574 "destType should be the same size as a size_t");
575 size_t sourceSizeT = static_cast<size_t>(source);
576 return reinterpret_cast<destType>(sourceSizeT);
577 }
578
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700579 bool hasImageGLColorspaceExt() const
580 {
581 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kImageGLColorspaceExt);
582 }
583
Mohan Maiyadd2316d2020-07-02 14:20:05 -0700584 bool hasAndroidImageNativeBufferExt() const
585 {
586 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(),
587 kEGLAndroidImageNativeBufferExt);
588 }
589
590 bool hasAndroidHardwareBufferSupport() const
591 {
592#if defined(ANGLE_AHARDWARE_BUFFER_SUPPORT)
593 return true;
594#else
595 return false;
596#endif
597 }
598
Mohan Maiyadaed3692020-05-05 14:24:26 -0700599 bool hasEglImageArrayExt() const { return IsGLExtensionEnabled(kEGLImageArrayExt); }
600
Jamie Madillb8149072019-04-30 16:14:44 -0400601 bool hasOESExt() const { return IsGLExtensionEnabled(kOESExt); }
Jamie Madill0be37b42018-07-19 10:03:52 -0400602
Jamie Madillb8149072019-04-30 16:14:44 -0400603 bool hasExternalExt() const { return IsGLExtensionEnabled(kExternalExt); }
Jamie Madill0be37b42018-07-19 10:03:52 -0400604
Jamie Madillb8149072019-04-30 16:14:44 -0400605 bool hasExternalESSL3Ext() const { return IsGLExtensionEnabled(kExternalESSL3Ext); }
Jamie Madill0be37b42018-07-19 10:03:52 -0400606
607 bool hasBaseExt() const
608 {
Jamie Madillb8149072019-04-30 16:14:44 -0400609 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kBaseExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400610 }
611
612 bool has2DTextureExt() const
613 {
Jamie Madillb8149072019-04-30 16:14:44 -0400614 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k2DTextureExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400615 }
616
617 bool has3DTextureExt() const
618 {
Jamie Madillb8149072019-04-30 16:14:44 -0400619 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k3DTextureExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400620 }
621
622 bool hasPixmapExt() const
623 {
Jamie Madillb8149072019-04-30 16:14:44 -0400624 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kPixmapExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400625 }
626
627 bool hasRenderbufferExt() const
628 {
Jamie Madillb8149072019-04-30 16:14:44 -0400629 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kRenderbufferExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400630 }
631
632 bool hasCubemapExt() const
633 {
Jamie Madillb8149072019-04-30 16:14:44 -0400634 return IsEGLDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kCubemapExt);
Jamie Madill0be37b42018-07-19 10:03:52 -0400635 }
636
Mohan Maiyadac5cc32020-04-08 18:26:46 -0700637 EGLint *get3DAttributes(const bool withColorspace = false, EGLint layer = 0)
638 {
639 if (!withColorspace)
640 {
641 default3DAttribs[1] = static_cast<EGLint>(layer);
642 return default3DAttribs;
643 }
644
645 colorspace3DAttribs[1] = static_cast<EGLint>(layer);
646 return colorspace3DAttribs;
647 }
648
649 EGLint default3DAttribs[5] = {
650 EGL_GL_TEXTURE_ZOFFSET_KHR, static_cast<EGLint>(0), EGL_IMAGE_PRESERVED, EGL_TRUE, EGL_NONE,
651 };
652 EGLint colorspace3DAttribs[7] = {
653 EGL_GL_TEXTURE_ZOFFSET_KHR,
654 static_cast<EGLint>(0),
655 EGL_IMAGE_PRESERVED,
656 EGL_TRUE,
657 EGL_GL_COLORSPACE,
658 EGL_GL_COLORSPACE_SRGB_KHR,
659 EGL_NONE,
660 };
Geoff Langa8406172015-07-21 16:53:39 -0400661 GLuint mTextureProgram;
Mohan Maiyadaed3692020-05-05 14:24:26 -0700662 GLuint m2DArrayTextureProgram;
Geoff Langa8406172015-07-21 16:53:39 -0400663 GLint mTextureUniformLocation;
Mohan Maiyadaed3692020-05-05 14:24:26 -0700664 GLuint m2DArrayTextureUniformLocation;
Geoff Langa8406172015-07-21 16:53:39 -0400665
Geoff Langb66a9092016-05-16 15:59:14 -0400666 GLuint mTextureExternalProgram = 0;
667 GLint mTextureExternalUniformLocation = -1;
668
669 GLuint mTextureExternalESSL3Program = 0;
670 GLint mTextureExternalESSL3UniformLocation = -1;
Geoff Langa8406172015-07-21 16:53:39 -0400671};
672
Geoff Langb66a9092016-05-16 15:59:14 -0400673class ImageTestES3 : public ImageTest
Jamie Madillb980c562018-11-27 11:34:27 -0500674{};
Geoff Langb66a9092016-05-16 15:59:14 -0400675
Jamie Madill0be37b42018-07-19 10:03:52 -0400676// Tests that the extension is exposed on the platforms we think it should be. Please modify this as
677// you change extension availability.
678TEST_P(ImageTest, ANGLEExtensionAvailability)
679{
Geoff Langc0b61502018-07-27 15:59:32 -0400680 // EGL support is based on driver extension availability.
Geoff Langdbd16122018-07-19 11:30:21 -0400681 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());
Geoff Langc0b61502018-07-27 15:59:32 -0400682 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsOzone());
Geoff Langdbd16122018-07-19 11:30:21 -0400683
Jamie Madill0be37b42018-07-19 10:03:52 -0400684 if (IsD3D11() || IsD3D9())
685 {
686 EXPECT_TRUE(hasOESExt());
687 EXPECT_TRUE(hasExternalExt());
688 EXPECT_TRUE(hasBaseExt());
689 EXPECT_TRUE(has2DTextureExt());
690 EXPECT_TRUE(hasRenderbufferExt());
691
692 if (IsD3D11())
693 {
694 EXPECT_TRUE(hasCubemapExt());
695
696 if (getClientMajorVersion() >= 3)
697 {
698 EXPECT_TRUE(hasExternalESSL3Ext());
699 }
700 else
701 {
702 EXPECT_FALSE(hasExternalESSL3Ext());
703 }
704 }
705 else
706 {
707 EXPECT_FALSE(hasCubemapExt());
708 EXPECT_FALSE(hasExternalESSL3Ext());
709 }
710 }
Geoff Langfe59f6b2019-01-16 09:34:30 -0500711 else if (IsVulkan())
712 {
713 EXPECT_TRUE(hasOESExt());
Geoff Lang366df2b2019-01-18 15:40:34 -0500714 EXPECT_TRUE(hasExternalExt());
Geoff Langfe59f6b2019-01-16 09:34:30 -0500715 EXPECT_TRUE(hasBaseExt());
716 EXPECT_TRUE(has2DTextureExt());
Geoff Langeca36cb2019-01-18 14:03:52 -0500717 EXPECT_TRUE(hasCubemapExt());
Geoff Langfe59f6b2019-01-16 09:34:30 -0500718 EXPECT_TRUE(hasRenderbufferExt());
Mohan Maiyaee08d922019-10-10 08:56:12 -0700719 if (getClientMajorVersion() >= 3)
720 {
721 EXPECT_TRUE(hasExternalESSL3Ext());
722 }
723 else
724 {
725 EXPECT_FALSE(hasExternalESSL3Ext());
726 }
Geoff Langfe59f6b2019-01-16 09:34:30 -0500727 }
Jamie Madill0be37b42018-07-19 10:03:52 -0400728 else
729 {
730 EXPECT_FALSE(hasOESExt());
731 EXPECT_FALSE(hasExternalExt());
732 EXPECT_FALSE(hasExternalESSL3Ext());
733 EXPECT_FALSE(hasBaseExt());
734 EXPECT_FALSE(has2DTextureExt());
735 EXPECT_FALSE(has3DTextureExt());
736 EXPECT_FALSE(hasRenderbufferExt());
737 }
738
739 // These extensions are not yet available on any platform.
740 EXPECT_FALSE(hasPixmapExt());
741 EXPECT_FALSE(has3DTextureExt());
742}
743
Geoff Langa8406172015-07-21 16:53:39 -0400744// Check validation from the EGL_KHR_image_base extension
745TEST_P(ImageTest, ValidationImageBase)
746{
747 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -0400748 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -0400749
750 GLuint glTexture2D;
751 glGenTextures(1, &glTexture2D);
752 glBindTexture(GL_TEXTURE_2D, glTexture2D);
753 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
754
755 EGLDisplay display = window->getDisplay();
756 EGLContext context = window->getContext();
757 EGLConfig config = window->getConfig();
758 EGLImageKHR image = EGL_NO_IMAGE_KHR;
Austin Kinrossa8187762015-08-12 10:54:37 -0700759 EGLClientBuffer texture2D = reinterpretHelper<EGLClientBuffer>(glTexture2D);
Geoff Langa8406172015-07-21 16:53:39 -0400760
761 // Test validation of eglCreateImageKHR
762
763 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
764 // generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700765 image = eglCreateImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), context,
Geoff Langa8406172015-07-21 16:53:39 -0400766 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
767 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
768 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
769
770 // If <ctx> is neither the handle of a valid EGLContext object on <dpy> nor EGL_NO_CONTEXT, the
771 // error EGL_BAD_CONTEXT is generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700772 image = eglCreateImageKHR(display, reinterpretHelper<EGLContext>(0xBAADF00D),
Geoff Langa8406172015-07-21 16:53:39 -0400773 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
774 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
775 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
776
777 // Test EGL_NO_CONTEXT with a 2D texture target which does require a context.
778 image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
779 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
780 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
781
782 // If an attribute specified in <attrib_list> is not one of the attributes listed in Table bbb,
783 // the error EGL_BAD_PARAMETER is generated.
784 EGLint badAttributes[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500785 static_cast<EGLint>(0xDEADBEEF),
786 0,
787 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400788 };
789
790 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, badAttributes);
791 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
792 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
793
794 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> has an off -
795 // screen buffer bound to it(e.g., by a
796 // previous call to eglBindTexImage), the error EGL_BAD_ACCESS is generated.
797 EGLint surfaceType = 0;
798 eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
799
800 EGLint bindToTextureRGBA = 0;
801 eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
802 if ((surfaceType & EGL_PBUFFER_BIT) != 0 && bindToTextureRGBA == EGL_TRUE)
803 {
804 EGLint pbufferAttributes[] = {
805 EGL_WIDTH, 1,
806 EGL_HEIGHT, 1,
807 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
808 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
809 EGL_NONE, EGL_NONE,
810 };
811 EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbufferAttributes);
812 ASSERT_NE(pbuffer, EGL_NO_SURFACE);
813 EXPECT_EGL_SUCCESS();
814
815 eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
816 EXPECT_EGL_SUCCESS();
817
818 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
819 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
820 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
821
822 eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
823 eglDestroySurface(display, pbuffer);
824 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
825 EXPECT_EGL_SUCCESS();
826 EXPECT_GL_NO_ERROR();
827 }
828
829 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and
830 // <attrib_list> is itself an EGLImage sibling, the error EGL_BAD_ACCESS is generated.
831 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
832 EXPECT_NE(image, EGL_NO_IMAGE_KHR);
833 EXPECT_EGL_SUCCESS();
834
835 /* TODO(geofflang): Enable this validation when it passes.
836 EGLImageKHR image2 = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
837 reinterpret_cast<EGLClientBuffer>(texture2D), nullptr);
838 EXPECT_EQ(image2, EGL_NO_IMAGE_KHR);
839 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
840 */
841
842 // Test validation of eglDestroyImageKHR
843 // Note: image is now a valid EGL image
844 EGLBoolean result = EGL_FALSE;
845
846 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
847 // generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700848 result = eglDestroyImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), image);
Geoff Langa8406172015-07-21 16:53:39 -0400849 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
850 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
851
852 // If <image> is not a valid EGLImageKHR object created with respect to <dpy>, the error
853 // EGL_BAD_PARAMETER is generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700854 result = eglDestroyImageKHR(display, reinterpretHelper<EGLImageKHR>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -0400855 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
856 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
857
858 // Clean up and validate image is destroyed
859 result = eglDestroyImageKHR(display, image);
860 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_TRUE));
861 EXPECT_EGL_SUCCESS();
862
863 glDeleteTextures(1, &glTexture2D);
864 EXPECT_GL_NO_ERROR();
865}
866
Geoff Langa8406172015-07-21 16:53:39 -0400867// Check validation from the EGL_KHR_gl_texture_2D_image, EGL_KHR_gl_texture_cubemap_image,
868// EGL_KHR_gl_texture_3D_image and EGL_KHR_gl_renderbuffer_image extensions
869TEST_P(ImageTest, ValidationGLImage)
870{
871 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -0400872 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt());
Geoff Langa8406172015-07-21 16:53:39 -0400873
874 EGLDisplay display = window->getDisplay();
875 EGLContext context = window->getContext();
876 EGLImageKHR image = EGL_NO_IMAGE_KHR;
877
Jamie Madill0be37b42018-07-19 10:03:52 -0400878 if (has2DTextureExt())
Geoff Langa8406172015-07-21 16:53:39 -0400879 {
880 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR or
881 // EGL_GL_TEXTURE_3D_KHR and <buffer> is not the name of a texture object of type <target>,
882 // the error EGL_BAD_PARAMETER is generated.
883 GLuint textureCube;
884 glGenTextures(1, &textureCube);
885 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
886 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
887 face++)
888 {
889 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
890 }
891
892 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700893 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400894 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
895 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
896
897 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR,
898 // EGL_GL_TEXTURE_CUBE_MAP_*_KHR or EGL_GL_TEXTURE_3D_KHR, <buffer> is the name of an
899 // incomplete GL texture object, and any mipmap levels other than mipmap level 0 are
900 // specified, the error EGL_BAD_PARAMETER is generated.
901 GLuint incompleteTexture;
902 glGenTextures(1, &incompleteTexture);
903 glBindTexture(GL_TEXTURE_2D, incompleteTexture);
904 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
905 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
906
907 EGLint level0Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500908 EGL_GL_TEXTURE_LEVEL_KHR,
909 0,
910 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400911 };
912 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700913 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
Geoff Langa8406172015-07-21 16:53:39 -0400914 level0Attribute);
915 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
916 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
917
918 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR or
919 // EGL_GL_TEXTURE_3D_KHR, <buffer> is not the name of a complete GL texture object, and
920 // mipmap level 0 is not specified, the error EGL_BAD_PARAMETER is generated.
921 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
922 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700923 reinterpretHelper<EGLClientBuffer>(incompleteTexture), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400924 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
925 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
926
927 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR,
928 // EGL_GL_RENDERBUFFER_KHR or EGL_GL_TEXTURE_3D_KHR and <buffer> refers to the default GL
929 // texture object(0) for the corresponding GL target, the error EGL_BAD_PARAMETER is
930 // generated.
931 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, 0, nullptr);
932 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
933 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
934
935 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR, or
936 // EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
937 // EGL_GL_TEXTURE_LEVEL_KHR is not a valid mipmap level for the specified GL texture object
938 // <buffer>, the error EGL_BAD_MATCH is generated.
939 EGLint level2Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500940 EGL_GL_TEXTURE_LEVEL_KHR,
941 2,
942 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400943 };
944 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700945 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
Geoff Langa8406172015-07-21 16:53:39 -0400946 level2Attribute);
947 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
948 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
949 }
950 else
951 {
952 GLuint texture2D;
953 glGenTextures(1, &texture2D);
954 glBindTexture(GL_TEXTURE_2D, texture2D);
955 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
956
957 // From EGL_KHR_image_base:
958 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
959 // generated.
960 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700961 reinterpretHelper<EGLClientBuffer>(texture2D), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400962 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
963 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
964 }
965
Jamie Madill0be37b42018-07-19 10:03:52 -0400966 if (hasCubemapExt())
Geoff Langa8406172015-07-21 16:53:39 -0400967 {
968 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_CUBE_MAP_*_KHR, <buffer> is
969 // not the name of a complete GL texture object, and one or more faces do not have mipmap
970 // level 0 specified, the error EGL_BAD_PARAMETER is generated.
971 GLuint incompleteTextureCube;
972 glGenTextures(1, &incompleteTextureCube);
973 glBindTexture(GL_TEXTURE_CUBE_MAP, incompleteTextureCube);
974 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
975 nullptr);
976 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
977 nullptr);
978 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
979 nullptr);
980 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
981 nullptr);
982 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
983 nullptr);
984
985 EGLint level0Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500986 EGL_GL_TEXTURE_LEVEL_KHR,
987 0,
988 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400989 };
990 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700991 reinterpretHelper<EGLClientBuffer>(incompleteTextureCube),
Geoff Langa8406172015-07-21 16:53:39 -0400992 level0Attribute);
993 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
994 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
995 }
996 else
997 {
998 GLuint textureCube;
999 glGenTextures(1, &textureCube);
1000 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
1001 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
1002 face++)
1003 {
1004 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1005 }
1006
1007 // From EGL_KHR_image_base:
1008 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
1009 // generated.
1010 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001011 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -04001012 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1013 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1014 }
1015
Jamie Madill0be37b42018-07-19 10:03:52 -04001016 if (has3DTextureExt() && getClientMajorVersion() >= 3)
Geoff Langa8406172015-07-21 16:53:39 -04001017 {
1018 // If <target> is EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
1019 // EGL_GL_TEXTURE_ZOFFSET_KHR exceeds the depth of the specified mipmap level - of - detail
1020 // in <buffer>, the error EGL_BAD_PARAMETER is generated.
1021 GLuint texture3D;
1022 glGenTextures(1, &texture3D);
1023 glBindTexture(GL_TEXTURE_3D, texture3D);
1024 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1025
1026 EGLint zOffset3Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001027 EGL_GL_TEXTURE_ZOFFSET_KHR,
1028 3,
1029 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -04001030 };
1031 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001032 reinterpretHelper<EGLClientBuffer>(texture3D), zOffset3Parameter);
Geoff Langa8406172015-07-21 16:53:39 -04001033 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1034 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1035
1036 EGLint zOffsetNegative1Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001037 EGL_GL_TEXTURE_ZOFFSET_KHR,
1038 -1,
1039 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -04001040 };
1041 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001042 reinterpretHelper<EGLClientBuffer>(texture3D),
Geoff Langa8406172015-07-21 16:53:39 -04001043 zOffsetNegative1Parameter);
1044 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1045 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1046 }
1047 else
1048 {
Jamie Madill0be37b42018-07-19 10:03:52 -04001049 if (has2DTextureExt())
Geoff Langa8406172015-07-21 16:53:39 -04001050 {
1051 GLuint texture2D;
1052 glGenTextures(1, &texture2D);
1053 glBindTexture(GL_TEXTURE_2D, texture2D);
1054 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1055
1056 // Verify EGL_GL_TEXTURE_ZOFFSET_KHR is not a valid parameter
1057 EGLint zOffset0Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001058 EGL_GL_TEXTURE_ZOFFSET_KHR,
1059 0,
1060 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -04001061 };
1062
1063 image =
1064 eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001065 reinterpretHelper<EGLClientBuffer>(texture2D), zOffset0Parameter);
Geoff Langa8406172015-07-21 16:53:39 -04001066 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1067 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1068 }
1069
Martin Radev1be913c2016-07-11 17:59:16 +03001070 if (getClientMajorVersion() >= 3)
Geoff Langa8406172015-07-21 16:53:39 -04001071 {
1072 GLuint texture3D;
1073 glGenTextures(1, &texture3D);
1074 glBindTexture(GL_TEXTURE_3D, texture3D);
1075 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
1076
1077 // From EGL_KHR_image_base:
1078 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
1079 // generated.
1080 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001081 reinterpretHelper<EGLClientBuffer>(texture3D), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -04001082 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1083 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1084 }
1085 }
1086
Jamie Madill0be37b42018-07-19 10:03:52 -04001087 if (hasRenderbufferExt())
Geoff Langa8406172015-07-21 16:53:39 -04001088 {
1089 // If <target> is EGL_GL_RENDERBUFFER_KHR and <buffer> is not the name of a renderbuffer
1090 // object, or if <buffer> is the name of a multisampled renderbuffer object, the error
1091 // EGL_BAD_PARAMETER is generated.
1092 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
1093 reinterpret_cast<EGLClientBuffer>(0), nullptr);
1094 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1095 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1096
Jamie Madillb8149072019-04-30 16:14:44 -04001097 if (IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample"))
Geoff Langa8406172015-07-21 16:53:39 -04001098 {
1099 GLuint renderbuffer;
1100 glGenRenderbuffers(1, &renderbuffer);
1101 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1102 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
1103 EXPECT_GL_NO_ERROR();
1104
1105 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
1106 reinterpret_cast<EGLClientBuffer>(0), nullptr);
1107 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1108 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1109 }
1110 }
1111 else
1112 {
1113 GLuint renderbuffer;
1114 glGenRenderbuffers(1, &renderbuffer);
1115 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1116 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
1117
1118 // From EGL_KHR_image_base:
1119 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
1120 // generated.
1121 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001122 reinterpretHelper<EGLClientBuffer>(renderbuffer), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -04001123 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
1124 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
1125 }
1126}
1127
1128// Check validation from the GL_OES_EGL_image extension
1129TEST_P(ImageTest, ValidationGLEGLImage)
1130{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001131 ValidationGLEGLImage_helper(kDefaultAttribs);
1132}
1133
1134TEST_P(ImageTest, ValidationGLEGLImage_Colorspace)
1135{
1136 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1137 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1138 ValidationGLEGLImage_helper(kColorspaceAttribs);
1139}
1140
1141void ImageTest::ValidationGLEGLImage_helper(const EGLint *attribs)
1142{
Jamie Madill0be37b42018-07-19 10:03:52 -04001143 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001144
1145 GLubyte data[4] = {255, 0, 255, 255};
1146
1147 // Create the Image
1148 GLuint source;
1149 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001150 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04001151
1152 // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
1153 glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
1154 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1155
1156 // If <image> does not refer to a valid eglImageOES object, the error INVALID_VALUE is
1157 // generated.
1158 GLuint texture;
1159 glGenTextures(1, &texture);
1160 glBindTexture(GL_TEXTURE_2D, texture);
Austin Kinrossa8187762015-08-12 10:54:37 -07001161 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, reinterpretHelper<GLeglImageOES>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -04001162 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1163
1164 // <target> must be RENDERBUFFER_OES, and <image> must be the handle of a valid EGLImage
1165 // resource, cast into the type
1166 // eglImageOES.
1167 glEGLImageTargetRenderbufferStorageOES(GL_TEXTURE_2D, image);
1168 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1169
1170 // If the GL is unable to create a renderbuffer using the specified eglImageOES, the error
1171 // INVALID_OPERATION is generated.If <image>
1172 // does not refer to a valid eglImageOES object, the error INVALID_VALUE is generated.
1173 GLuint renderbuffer;
1174 glGenRenderbuffers(1, &renderbuffer);
1175 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
1176 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
Austin Kinrossa8187762015-08-12 10:54:37 -07001177 reinterpretHelper<GLeglImageOES>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -04001178 EXPECT_GL_ERROR(GL_INVALID_VALUE);
1179
1180 // Clean up
1181 glDeleteTextures(1, &source);
Jamie Madill0be37b42018-07-19 10:03:52 -04001182 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image);
Geoff Langa8406172015-07-21 16:53:39 -04001183 glDeleteTextures(1, &texture);
1184 glDeleteRenderbuffers(1, &renderbuffer);
1185}
1186
1187// Check validation from the GL_OES_EGL_image_external extension
1188TEST_P(ImageTest, ValidationGLEGLImageExternal)
1189{
Jamie Madill0be37b42018-07-19 10:03:52 -04001190 ANGLE_SKIP_TEST_IF(!hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001191
1192 GLuint texture;
1193 glGenTextures(1, &texture);
1194 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
1195
1196 // In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
1197 // TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
1198 // to CLAMP_TO_EDGE
Jamie Madillb980c562018-11-27 11:34:27 -05001199 auto getTexParam = [](GLenum target, GLenum pname) {
Geoff Langb66a9092016-05-16 15:59:14 -04001200 GLint value = 0;
1201 glGetTexParameteriv(target, pname, &value);
1202 EXPECT_GL_NO_ERROR();
1203 return value;
1204 };
1205 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
1206 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
1207 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
1208 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
1209
1210 // "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
1211 // TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
1212 // only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
1213 // TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
1214 // INVALID_ENUM error.
1215 GLenum validMinFilters[]{
Jamie Madillb980c562018-11-27 11:34:27 -05001216 GL_NEAREST,
1217 GL_LINEAR,
Geoff Langb66a9092016-05-16 15:59:14 -04001218 };
1219 for (auto minFilter : validMinFilters)
1220 {
1221 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
1222 EXPECT_GL_NO_ERROR();
1223 }
1224
1225 GLenum invalidMinFilters[]{
Jamie Madillb980c562018-11-27 11:34:27 -05001226 GL_NEAREST_MIPMAP_LINEAR,
1227 GL_NEAREST_MIPMAP_NEAREST,
1228 GL_LINEAR_MIPMAP_LINEAR,
Geoff Langb66a9092016-05-16 15:59:14 -04001229 GL_LINEAR_MIPMAP_NEAREST,
1230 };
1231 for (auto minFilter : invalidMinFilters)
1232 {
1233 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
1234 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1235 }
1236
1237 GLenum validWrapModes[]{
1238 GL_CLAMP_TO_EDGE,
1239 };
Mohan Maiya62b72552020-03-20 07:51:26 -07001240 for (auto wrapMode : validWrapModes)
Geoff Langb66a9092016-05-16 15:59:14 -04001241 {
Mohan Maiya62b72552020-03-20 07:51:26 -07001242 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
Geoff Langb66a9092016-05-16 15:59:14 -04001243 EXPECT_GL_NO_ERROR();
Mohan Maiya62b72552020-03-20 07:51:26 -07001244 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
Geoff Langb66a9092016-05-16 15:59:14 -04001245 EXPECT_GL_NO_ERROR();
1246 }
1247
Mohan Maiya62b72552020-03-20 07:51:26 -07001248 if (IsGLExtensionEnabled("GL_EXT_EGL_image_external_wrap_modes"))
Geoff Langb66a9092016-05-16 15:59:14 -04001249 {
Mohan Maiya62b72552020-03-20 07:51:26 -07001250 GLenum validWrapModesEXT[]{GL_REPEAT, GL_MIRRORED_REPEAT};
1251 for (auto wrapMode : validWrapModesEXT)
1252 {
1253 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
1254 EXPECT_GL_NO_ERROR();
1255 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
1256 EXPECT_GL_NO_ERROR();
1257 }
1258 }
1259 else
1260 {
1261 GLenum invalidWrapModes[]{
1262 GL_REPEAT,
1263 GL_MIRRORED_REPEAT,
1264 };
1265 for (auto wrapMode : invalidWrapModes)
1266 {
1267 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, wrapMode);
1268 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1269 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, wrapMode);
1270 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1271 }
Geoff Langb66a9092016-05-16 15:59:14 -04001272 }
1273
1274 // When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
1275 // INVALID_ENUM error.
1276 glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
1277 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1278
1279 glDeleteTextures(1, &texture);
Geoff Langa8406172015-07-21 16:53:39 -04001280}
1281
1282// Check validation from the GL_OES_EGL_image_external_essl3 extension
1283TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
1284{
Jamie Madill0be37b42018-07-19 10:03:52 -04001285 ANGLE_SKIP_TEST_IF(!hasExternalESSL3Ext());
Geoff Langb66a9092016-05-16 15:59:14 -04001286
1287 // Make sure this extension is not exposed without ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001288 ASSERT_GE(getClientMajorVersion(), 3);
Geoff Langb66a9092016-05-16 15:59:14 -04001289
1290 GLuint texture;
1291 glGenTextures(1, &texture);
1292 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
1293
1294 // It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
1295 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
1296 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1297
1298 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
1299 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1300
1301 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
1302 EXPECT_GL_NO_ERROR();
1303
1304 glDeleteTextures(1, &texture);
Geoff Langa8406172015-07-21 16:53:39 -04001305}
1306
1307TEST_P(ImageTest, Source2DTarget2D)
1308{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001309 Source2DTarget2D_helper(kDefaultAttribs);
1310}
1311
1312TEST_P(ImageTest, Source2DTarget2D_Colorspace)
1313{
1314 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1315 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1316 Source2DTarget2D_helper(kColorspaceAttribs);
1317}
1318
1319void ImageTest::Source2DTarget2D_helper(const EGLint *attribs)
1320{
Geoff Langa8406172015-07-21 16:53:39 -04001321 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001322 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001323
1324 GLubyte data[4] = {255, 0, 255, 255};
1325
1326 // Create the Image
1327 GLuint source;
1328 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001329 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04001330
1331 // Create the target
1332 GLuint target;
1333 createEGLImageTargetTexture2D(image, &target);
1334
1335 // Expect that the target texture has the same color as the source texture
1336 verifyResults2D(target, data);
1337
1338 // Clean up
1339 glDeleteTextures(1, &source);
1340 eglDestroyImageKHR(window->getDisplay(), image);
1341 glDeleteTextures(1, &target);
1342}
1343
Mohan Maiyadaed3692020-05-05 14:24:26 -07001344// Testing source 2D texture, target 2D array texture
1345TEST_P(ImageTest, Source2DTarget2DArray)
1346{
1347 Source2DTarget2DArray_helper(kDefaultAttribs);
1348}
1349
1350// Testing source 2D texture with colorspace, target 2D array texture
1351TEST_P(ImageTest, Source2DTarget2DArray_Colorspace)
1352{
1353 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1354 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1355 Source2DTarget2DArray_helper(kColorspaceAttribs);
1356}
Mohan Maiyadd2316d2020-07-02 14:20:05 -07001357
Mohan Maiyadaed3692020-05-05 14:24:26 -07001358void ImageTest::Source2DTarget2DArray_helper(const EGLint *attribs)
1359{
1360 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1361 EGLWindow *window = getEGLWindow();
1362 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1363 !hasEglImageArrayExt());
1364
1365 GLubyte data[4] = {255, 0, 255, 255};
1366
1367 // Create the Image
1368 GLuint source;
1369 EGLImageKHR image;
1370 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
1371
1372 // Create the target
1373 GLuint target;
1374 createEGLImageTargetTexture2DArray(image, &target);
1375
1376 // Expect that the target texture has the same color as the source texture
1377 verifyResults2DArray(target, data);
1378
1379 // Clean up
1380 glDeleteTextures(1, &source);
1381 eglDestroyImageKHR(window->getDisplay(), image);
1382 glDeleteTextures(1, &target);
1383}
1384
Mohan Maiyadd2316d2020-07-02 14:20:05 -07001385// Testing source AHB EGL image, target 2D texture
1386TEST_P(ImageTest, SourceAHBTarget2D)
1387{
1388 ANGLE_SKIP_TEST_IF(!IsAndroid());
1389 SourceAHBTarget2D_helper(kDefaultAttribs);
1390}
1391
1392// Testing source AHB EGL image with colorspace, target 2D texture
1393TEST_P(ImageTest, SourceAHBTarget2D_Colorspace)
1394{
1395 ANGLE_SKIP_TEST_IF(!IsAndroid());
1396 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1397 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1398 SourceAHBTarget2D_helper(kColorspaceAttribs);
1399}
1400
1401void ImageTest::SourceAHBTarget2D_helper(const EGLint *attribs)
1402{
1403 EGLWindow *window = getEGLWindow();
1404
1405 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
1406 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1407
1408 GLubyte data[4] = {7, 51, 197, 231};
1409
1410 // Create the Image
1411 AHardwareBuffer *source;
1412 EGLImageKHR image;
1413 createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1414
1415 // Create a texture target to bind the egl image
1416 GLuint target;
1417 createEGLImageTargetTexture2D(image, &target);
1418
1419 // Use texture target bound to egl image as source and render to framebuffer
1420 // Verify that data in framebuffer matches that in the egl image
1421 verifyResults2D(target, data);
1422
1423 // Clean up
1424 eglDestroyImageKHR(window->getDisplay(), image);
1425 destroyAndroidHardwareBuffer(source);
1426 glDeleteTextures(1, &target);
1427}
1428
1429// Testing source AHB EGL image, target 2D array texture
1430TEST_P(ImageTest, SourceAHBTarget2DArray)
1431{
1432 ANGLE_SKIP_TEST_IF(!IsAndroid());
1433 SourceAHBTarget2DArray_helper(kDefaultAttribs);
1434}
1435
1436// Testing source AHB EGL image with colorspace, target 2D array texture
1437TEST_P(ImageTest, SourceAHBTarget2DArray_Colorspace)
1438{
1439 ANGLE_SKIP_TEST_IF(!IsAndroid());
1440 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1441 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1442 SourceAHBTarget2DArray_helper(kColorspaceAttribs);
1443}
1444
1445void ImageTest::SourceAHBTarget2DArray_helper(const EGLint *attribs)
1446{
1447 EGLWindow *window = getEGLWindow();
1448
1449 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1450 !hasEglImageArrayExt());
1451 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1452
1453 GLubyte data[4] = {7, 51, 197, 231};
1454
1455 // Create the Image
1456 AHardwareBuffer *source;
1457 EGLImageKHR image;
1458 createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1459
1460 // Create a texture target to bind the egl image
1461 GLuint target;
1462 createEGLImageTargetTexture2DArray(image, &target);
1463
1464 // Use texture target bound to egl image as source and render to framebuffer
1465 // Verify that data in framebuffer matches that in the egl image
1466 verifyResults2DArray(target, data);
1467
1468 // Clean up
1469 eglDestroyImageKHR(window->getDisplay(), image);
1470 destroyAndroidHardwareBuffer(source);
1471 glDeleteTextures(1, &target);
1472}
1473
1474// Testing source AHB EGL image, target external texture
1475TEST_P(ImageTest, SourceAHBTargetExternal)
1476{
1477 ANGLE_SKIP_TEST_IF(!IsAndroid());
1478 SourceAHBTargetExternal_helper(kDefaultAttribs);
1479}
1480
1481// Testing source AHB EGL image with colorspace, target external texture
1482TEST_P(ImageTest, SourceAHBTargetExternal_Colorspace)
1483{
1484 ANGLE_SKIP_TEST_IF(!IsAndroid());
1485 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1486 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1487 SourceAHBTargetExternal_helper(kColorspaceAttribs);
1488}
1489
1490void ImageTest::SourceAHBTargetExternal_helper(const EGLint *attribs)
1491{
1492 EGLWindow *window = getEGLWindow();
1493 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
1494 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1495
1496 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1497 ANGLE_SKIP_TEST_IF(IsOzone());
1498
1499 GLubyte data[4] = {7, 51, 197, 231};
1500
1501 // Create the Image
1502 AHardwareBuffer *source;
1503 EGLImageKHR image;
1504 createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1505
1506 // Create a texture target to bind the egl image
1507 GLuint target;
1508 createEGLImageTargetTextureExternal(image, &target);
1509
1510 // Use texture target bound to egl image as source and render to framebuffer
1511 // Verify that data in framebuffer matches that in the egl image
1512 verifyResultsExternal(target, data);
1513
1514 // Clean up
1515 eglDestroyImageKHR(window->getDisplay(), image);
1516 destroyAndroidHardwareBuffer(source);
1517 glDeleteTextures(1, &target);
1518}
1519
1520// Testing source AHB EGL image, target external ESSL3 texture
1521TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3)
1522{
1523 ANGLE_SKIP_TEST_IF(!IsAndroid());
1524 SourceAHBTargetExternalESSL3_helper(kDefaultAttribs);
1525}
1526
1527// Testing source AHB EGL image with colorspace, target external ESSL3 texture
1528TEST_P(ImageTestES3, SourceAHBTargetExternalESSL3_Colorspace)
1529{
1530 ANGLE_SKIP_TEST_IF(!IsAndroid());
1531 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1532 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1533 SourceAHBTargetExternalESSL3_helper(kColorspaceAttribs);
1534}
1535
1536void ImageTest::SourceAHBTargetExternalESSL3_helper(const EGLint *attribs)
1537{
1538 EGLWindow *window = getEGLWindow();
1539 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1540 !hasExternalESSL3Ext());
1541 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1542
1543 GLubyte data[4] = {7, 51, 197, 231};
1544
1545 // Create the Image
1546 AHardwareBuffer *source;
1547 EGLImageKHR image;
1548 createEGLImageAndroidHardwareBufferSource(1, 1, 1, GL_RGBA8, attribs, data, 4, &source, &image);
1549
1550 // Create a texture target to bind the egl image
1551 GLuint target;
1552 createEGLImageTargetTextureExternal(image, &target);
1553
1554 // Use texture target bound to egl image as source and render to framebuffer
1555 // Verify that data in framebuffer matches that in the egl image
1556 verifyResultsExternalESSL3(target, data);
1557
1558 // Clean up
1559 eglDestroyImageKHR(window->getDisplay(), image);
1560 destroyAndroidHardwareBuffer(source);
1561 glDeleteTextures(1, &target);
1562}
1563
Mohan Maiya69fa4d22020-06-30 09:06:33 -07001564// Create a depth format AHB backed EGL image and verify that the image's aspect is honored
1565TEST_P(ImageTest, SourceAHBTarget2DDepth)
1566{
1567 // TODO - Support for depth formats in AHB is missing (http://anglebug.com/4818)
1568 ANGLE_SKIP_TEST_IF(true);
1569
1570 EGLWindow *window = getEGLWindow();
1571
1572 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1573 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
1574 ANGLE_SKIP_TEST_IF(!hasAndroidImageNativeBufferExt() || !hasAndroidHardwareBufferSupport());
1575
1576 GLint level = 0;
1577 GLsizei width = 1;
1578 GLsizei height = 1;
1579 GLsizei depth = 1;
1580 GLint depthStencilValue = 0;
1581
1582 // Create the Image
1583 AHardwareBuffer *source;
1584 EGLImageKHR image;
1585 createEGLImageAndroidHardwareBufferSource(
1586 width, height, depth, GL_DEPTH_COMPONENT24, kDefaultAttribs,
1587 reinterpret_cast<GLubyte *>(&depthStencilValue), 3, &source, &image);
1588
1589 // Create a texture target to bind the egl image
1590 GLuint depthTextureTarget;
1591 createEGLImageTargetTexture2D(image, &depthTextureTarget);
1592
1593 // Create a color texture and fill it with red
1594 GLTexture colorTexture;
1595 glBindTexture(GL_TEXTURE_2D, colorTexture);
1596 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
1597 GLColor::red.data());
1598 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1599 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1600 glBindTexture(GL_TEXTURE_2D, 0);
1601 EXPECT_GL_NO_ERROR();
1602
1603 GLFramebuffer fbo;
1604 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1605 EXPECT_GL_NO_ERROR();
1606
1607 // Attach the color and depth texture to the FBO
1608 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorTexture, 0);
1609 EXPECT_GL_NO_ERROR();
1610 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthTextureTarget,
1611 0);
1612 EXPECT_GL_NO_ERROR();
1613
1614 ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
1615
1616 // Clear the color texture to red
1617 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
1618 glClear(GL_COLOR_BUFFER_BIT);
1619 EXPECT_PIXEL_EQ(0, 0, 255, 0, 0, 255);
1620
1621 // Enable Depth test but disable depth writes. The depth function is set to ">".
1622 glEnable(GL_DEPTH_TEST);
1623 glDepthMask(GL_FALSE);
1624 glDepthFunc(GL_GREATER);
1625
1626 // Fill any fragment of the color attachment with blue if it passes the depth test.
1627 ANGLE_GL_PROGRAM(colorFillProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
1628 drawQuad(colorFillProgram, essl1_shaders::PositionAttrib(), 1.0f, 1.0f);
1629
1630 // Since 1.0f > 0.0f, all fragments of the color attachment should be blue.
1631 EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
1632
1633 // Clean up
1634 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1635 eglDestroyImageKHR(window->getDisplay(), image);
1636 destroyAndroidHardwareBuffer(source);
1637}
1638
Geoff Langa8406172015-07-21 16:53:39 -04001639TEST_P(ImageTest, Source2DTargetRenderbuffer)
1640{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001641 Source2DTargetRenderbuffer_helper(kDefaultAttribs);
1642}
1643
1644TEST_P(ImageTest, Source2DTargetRenderbuffer_Colorspace)
1645{
1646 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1647 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1648 Source2DTargetRenderbuffer_helper(kColorspaceAttribs);
1649}
1650
1651void ImageTest::Source2DTargetRenderbuffer_helper(const EGLint *attribs)
1652{
1653
Geoff Langa8406172015-07-21 16:53:39 -04001654 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001655 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001656
1657 GLubyte data[4] = {255, 0, 255, 255};
1658
1659 // Create the Image
1660 GLuint source;
1661 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001662 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04001663
1664 // Create the target
1665 GLuint target;
1666 createEGLImageTargetRenderbuffer(image, &target);
1667
1668 // Expect that the target renderbuffer has the same color as the source texture
1669 verifyResultsRenderbuffer(target, data);
1670
1671 // Clean up
1672 glDeleteTextures(1, &source);
1673 eglDestroyImageKHR(window->getDisplay(), image);
1674 glDeleteRenderbuffers(1, &target);
1675}
1676
Geoff Langb66a9092016-05-16 15:59:14 -04001677TEST_P(ImageTest, Source2DTargetExternal)
1678{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001679 Source2DTargetExternal_helper(kDefaultAttribs);
1680}
1681
1682TEST_P(ImageTest, Source2DTargetExternal_Colorspace)
1683{
1684 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1685 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1686 Source2DTargetExternal_helper(kColorspaceAttribs);
1687}
1688
1689void ImageTest::Source2DTargetExternal_helper(const EGLint *attribs)
1690{
Geoff Langb66a9092016-05-16 15:59:14 -04001691 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001692 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001693
Yuly Novikov64f62f42018-12-12 11:57:35 -05001694 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1695 ANGLE_SKIP_TEST_IF(IsOzone());
1696
Geoff Langb66a9092016-05-16 15:59:14 -04001697 GLubyte data[4] = {255, 0, 255, 255};
1698
1699 // Create the Image
1700 GLuint source;
1701 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001702 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04001703
1704 // Create the target
1705 GLuint target;
1706 createEGLImageTargetTextureExternal(image, &target);
1707
1708 // Expect that the target renderbuffer has the same color as the source texture
1709 verifyResultsExternal(target, data);
1710
1711 // Clean up
1712 glDeleteTextures(1, &source);
1713 eglDestroyImageKHR(window->getDisplay(), image);
1714 glDeleteRenderbuffers(1, &target);
1715}
1716
1717TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
1718{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001719 Source2DTargetExternalESSL3_helper(kDefaultAttribs);
1720}
1721
1722TEST_P(ImageTestES3, Source2DTargetExternalESSL3_Colorspace)
1723{
1724 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1725 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1726 Source2DTargetExternalESSL3_helper(kColorspaceAttribs);
1727}
1728
1729void ImageTest::Source2DTargetExternalESSL3_helper(const EGLint *attribs)
1730{
Geoff Langb66a9092016-05-16 15:59:14 -04001731 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001732 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1733 !hasExternalESSL3Ext());
Geoff Langb66a9092016-05-16 15:59:14 -04001734
1735 GLubyte data[4] = {255, 0, 255, 255};
1736
1737 // Create the Image
1738 GLuint source;
1739 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001740 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, data, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04001741
1742 // Create the target
1743 GLuint target;
1744 createEGLImageTargetTextureExternal(image, &target);
1745
1746 // Expect that the target renderbuffer has the same color as the source texture
1747 verifyResultsExternalESSL3(target, data);
1748
1749 // Clean up
1750 glDeleteTextures(1, &source);
1751 eglDestroyImageKHR(window->getDisplay(), image);
1752 glDeleteRenderbuffers(1, &target);
1753}
1754
Geoff Langa8406172015-07-21 16:53:39 -04001755TEST_P(ImageTest, SourceCubeTarget2D)
1756{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001757 SourceCubeTarget2D_helper(kDefaultAttribs);
1758}
1759
1760TEST_P(ImageTest, SourceCubeTarget2D_Colorspace)
1761{
1762 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1763 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1764 SourceCubeTarget2D_helper(kColorspaceAttribs);
1765}
1766
1767void ImageTest::SourceCubeTarget2D_helper(const EGLint *attribs)
1768{
Geoff Langa8406172015-07-21 16:53:39 -04001769 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001770 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
Geoff Langa8406172015-07-21 16:53:39 -04001771
1772 GLubyte data[24] = {
1773 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1774 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1775 };
1776
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001777 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -04001778 {
1779 // Create the Image
1780 GLuint source;
1781 EGLImageKHR image;
1782 createEGLImageCubemapTextureSource(
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001783 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
1784 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04001785
1786 // Create the target
1787 GLuint target;
1788 createEGLImageTargetTexture2D(image, &target);
1789
1790 // Expect that the target texture has the same color as the source texture
1791 verifyResults2D(target, &data[faceIdx * 4]);
1792
1793 // Clean up
1794 glDeleteTextures(1, &source);
1795 eglDestroyImageKHR(window->getDisplay(), image);
1796 glDeleteTextures(1, &target);
1797 }
1798}
1799
1800TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
1801{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001802 SourceCubeTargetRenderbuffer_helper(kDefaultAttribs);
1803}
1804
1805TEST_P(ImageTest, SourceCubeTargetRenderbuffer_Colorspace)
1806{
1807 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1808 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1809 SourceCubeTargetRenderbuffer_helper(kColorspaceAttribs);
1810}
1811
1812void ImageTest::SourceCubeTargetRenderbuffer_helper(const EGLint *attribs)
1813{
Geoff Langa8406172015-07-21 16:53:39 -04001814 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001815 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
Geoff Langa8406172015-07-21 16:53:39 -04001816
Kevin Schoedeleef531f2019-02-20 16:33:21 -05001817 // http://anglebug.com/3145
1818 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsFuchsia());
1819
Geoff Langa8406172015-07-21 16:53:39 -04001820 GLubyte data[24] = {
1821 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1822 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1823 };
1824
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001825 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -04001826 {
1827 // Create the Image
1828 GLuint source;
1829 EGLImageKHR image;
1830 createEGLImageCubemapTextureSource(
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001831 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
1832 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04001833
1834 // Create the target
1835 GLuint target;
1836 createEGLImageTargetRenderbuffer(image, &target);
1837
1838 // Expect that the target texture has the same color as the source texture
1839 verifyResultsRenderbuffer(target, &data[faceIdx * 4]);
1840
1841 // Clean up
1842 glDeleteTextures(1, &source);
1843 eglDestroyImageKHR(window->getDisplay(), image);
1844 glDeleteRenderbuffers(1, &target);
1845 }
1846}
1847
Geoff Langb66a9092016-05-16 15:59:14 -04001848// Test cubemap -> external texture EGL images.
1849TEST_P(ImageTest, SourceCubeTargetExternal)
1850{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001851 SourceCubeTargetExternal_helper(kDefaultAttribs);
1852}
1853
1854TEST_P(ImageTest, SourceCubeTargetExternal_Colorspace)
1855{
1856 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1857 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1858 SourceCubeTargetExternal_helper(kColorspaceAttribs);
1859}
1860
1861void ImageTest::SourceCubeTargetExternal_helper(const EGLint *attribs)
1862{
Geoff Langb66a9092016-05-16 15:59:14 -04001863 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001864 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt() || !hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001865
Yuly Novikov64f62f42018-12-12 11:57:35 -05001866 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1867 ANGLE_SKIP_TEST_IF(IsOzone());
1868
Geoff Langb66a9092016-05-16 15:59:14 -04001869 GLubyte data[24] = {
1870 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1871 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1872 };
1873
1874 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1875 {
1876 // Create the Image
1877 GLuint source;
1878 EGLImageKHR image;
1879 createEGLImageCubemapTextureSource(
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001880 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
1881 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04001882
1883 // Create the target
1884 GLuint target;
1885 createEGLImageTargetTextureExternal(image, &target);
1886
1887 // Expect that the target texture has the same color as the source texture
1888 verifyResultsExternal(target, &data[faceIdx * 4]);
1889
1890 // Clean up
1891 glDeleteTextures(1, &source);
1892 eglDestroyImageKHR(window->getDisplay(), image);
1893 glDeleteRenderbuffers(1, &target);
1894 }
1895}
1896
1897// Test cubemap -> external texture EGL images using ESSL3 shaders.
1898TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
1899{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001900 SourceCubeTargetExternalESSL3_helper(kDefaultAttribs);
1901}
1902
1903TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3_Colorspace)
1904{
1905 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1906 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1907 SourceCubeTargetExternalESSL3_helper(kColorspaceAttribs);
1908}
1909
1910void ImageTest::SourceCubeTargetExternalESSL3_helper(const EGLint *attribs)
1911{
Geoff Langb66a9092016-05-16 15:59:14 -04001912 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001913 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() || !hasCubemapExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001914
1915 GLubyte data[24] = {
1916 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1917 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1918 };
1919
1920 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1921 {
1922 // Create the Image
1923 GLuint source;
1924 EGLImageKHR image;
1925 createEGLImageCubemapTextureSource(
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001926 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, attribs, reinterpret_cast<uint8_t *>(data),
1927 sizeof(GLubyte) * 4, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04001928
1929 // Create the target
1930 GLuint target;
1931 createEGLImageTargetTextureExternal(image, &target);
1932
1933 // Expect that the target texture has the same color as the source texture
1934 verifyResultsExternalESSL3(target, &data[faceIdx * 4]);
1935
1936 // Clean up
1937 glDeleteTextures(1, &source);
1938 eglDestroyImageKHR(window->getDisplay(), image);
1939 glDeleteRenderbuffers(1, &target);
1940 }
1941}
1942
Geoff Langa8406172015-07-21 16:53:39 -04001943TEST_P(ImageTest, Source3DTargetTexture)
1944{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001945 Source3DTargetTexture_helper(false);
1946}
1947
1948TEST_P(ImageTest, Source3DTargetTexture_Colorspace)
1949{
1950 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
1951 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1952 Source3DTargetTexture_helper(true);
1953}
1954
1955void ImageTest::Source3DTargetTexture_helper(const bool withColorspace)
1956{
Geoff Langa8406172015-07-21 16:53:39 -04001957 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001958 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001959
Jamie Madillb8149072019-04-30 16:14:44 -04001960 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
Geoff Langa8406172015-07-21 16:53:39 -04001961
1962 const size_t depth = 2;
1963 GLubyte data[4 * depth] = {
1964 255, 0, 255, 255, 255, 255, 0, 255,
1965 };
1966
1967 for (size_t layer = 0; layer < depth; layer++)
1968 {
1969 // Create the Image
1970 GLuint source;
1971 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001972 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
1973 get3DAttributes(withColorspace, layer), data, &source,
Geoff Langa8406172015-07-21 16:53:39 -04001974 &image);
1975
1976 // Create the target
1977 GLuint target;
1978 createEGLImageTargetTexture2D(image, &target);
1979
1980 // Expect that the target renderbuffer has the same color as the source texture
1981 verifyResults2D(target, &data[layer * 4]);
1982
1983 // Clean up
1984 glDeleteTextures(1, &source);
1985 eglDestroyImageKHR(window->getDisplay(), image);
1986 glDeleteTextures(1, &target);
1987 }
1988}
1989
1990TEST_P(ImageTest, Source3DTargetRenderbuffer)
1991{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07001992 Source3DTargetRenderbuffer_helper(false);
1993}
1994
1995TEST_P(ImageTest, Source3DTargetRenderbuffer_Colorspace)
1996{
1997 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3);
1998 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
1999 Source3DTargetRenderbuffer_helper(true);
2000}
2001
2002void ImageTest::Source3DTargetRenderbuffer_helper(const bool withColorspace)
2003{
2004 // Qualcom drivers appear to always bind the 0 layer of the source 3D texture when the
2005 // target is a renderbuffer. They work correctly when the target is a 2D texture.
2006 // http://anglebug.com/2745
Geoff Langdbd16122018-07-19 11:30:21 -04002007 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2008
Geoff Langa8406172015-07-21 16:53:39 -04002009 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002010 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002011
Jamie Madillb8149072019-04-30 16:14:44 -04002012 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
Geoff Langa8406172015-07-21 16:53:39 -04002013
2014 const size_t depth = 2;
2015 GLubyte data[4 * depth] = {
2016 255, 0, 255, 255, 255, 255, 0, 255,
2017 };
2018
2019 for (size_t layer = 0; layer < depth; layer++)
2020 {
2021 // Create the Image
2022 GLuint source;
2023 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002024
2025 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
2026 get3DAttributes(withColorspace, layer), data, &source,
Geoff Langa8406172015-07-21 16:53:39 -04002027 &image);
2028
2029 // Create the target
2030 GLuint target;
2031 createEGLImageTargetRenderbuffer(image, &target);
2032
2033 // Expect that the target renderbuffer has the same color as the source texture
2034 verifyResultsRenderbuffer(target, &data[layer * 4]);
2035
2036 // Clean up
2037 glDeleteTextures(1, &source);
2038 eglDestroyImageKHR(window->getDisplay(), image);
2039 glDeleteTextures(1, &target);
2040 }
2041}
2042
Geoff Langb66a9092016-05-16 15:59:14 -04002043// Test 3D -> external texture EGL images.
2044TEST_P(ImageTest, Source3DTargetExternal)
2045{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002046 Source3DTargetExternal_helper(false);
2047}
2048
2049TEST_P(ImageTest, Source3DTargetExternal_Colorspace)
2050{
2051 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2052 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2053 Source3DTargetExternal_helper(true);
2054}
2055
2056void ImageTest::Source3DTargetExternal_helper(const bool withColorspace)
2057{
Geoff Langb66a9092016-05-16 15:59:14 -04002058 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002059 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langb66a9092016-05-16 15:59:14 -04002060
Jamie Madillb8149072019-04-30 16:14:44 -04002061 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
Geoff Langb66a9092016-05-16 15:59:14 -04002062
Yuly Novikov994938c2019-07-03 13:44:46 -04002063 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
2064 ANGLE_SKIP_TEST_IF(IsOzone());
2065
Geoff Langb66a9092016-05-16 15:59:14 -04002066 const size_t depth = 2;
2067 GLubyte data[4 * depth] = {
2068 255, 0, 255, 255, 255, 255, 0, 255,
2069 };
2070
2071 for (size_t layer = 0; layer < depth; layer++)
2072 {
2073 // Create the Image
2074 GLuint source;
2075 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002076 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
2077 get3DAttributes(withColorspace, layer), data, &source,
Geoff Langb66a9092016-05-16 15:59:14 -04002078 &image);
2079
2080 // Create the target
2081 GLuint target;
2082 createEGLImageTargetTextureExternal(image, &target);
2083
2084 // Expect that the target renderbuffer has the same color as the source texture
2085 verifyResultsExternal(target, &data[layer * 4]);
2086
2087 // Clean up
2088 glDeleteTextures(1, &source);
2089 eglDestroyImageKHR(window->getDisplay(), image);
2090 glDeleteTextures(1, &target);
2091 }
2092}
2093
2094// Test 3D -> external texture EGL images using ESSL3 shaders.
2095TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
2096{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002097 Source3DTargetExternalESSL3_helper(false);
2098}
2099
2100TEST_P(ImageTestES3, Source3DTargetExternalESSL3_Colorspace)
2101{
2102 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2103 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2104 Source3DTargetExternalESSL3_helper(true);
2105}
2106
2107void ImageTest::Source3DTargetExternalESSL3_helper(const bool withColorspace)
2108{
Geoff Langb66a9092016-05-16 15:59:14 -04002109 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002110 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
2111 !has3DTextureExt());
Geoff Langb66a9092016-05-16 15:59:14 -04002112
Jamie Madillb8149072019-04-30 16:14:44 -04002113 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_OES_texture_3D"));
Geoff Langb66a9092016-05-16 15:59:14 -04002114
2115 const size_t depth = 2;
2116 GLubyte data[4 * depth] = {
2117 255, 0, 255, 255, 255, 255, 0, 255,
2118 };
2119
2120 for (size_t layer = 0; layer < depth; layer++)
2121 {
2122 // Create the Image
2123 GLuint source;
2124 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002125
2126 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE,
2127 get3DAttributes(withColorspace, layer), data, &source,
Geoff Langb66a9092016-05-16 15:59:14 -04002128 &image);
2129
2130 // Create the target
2131 GLuint target;
2132 createEGLImageTargetTextureExternal(image, &target);
2133
2134 // Expect that the target renderbuffer has the same color as the source texture
2135 verifyResultsExternalESSL3(target, &data[layer * 4]);
2136
2137 // Clean up
2138 glDeleteTextures(1, &source);
2139 eglDestroyImageKHR(window->getDisplay(), image);
2140 glDeleteTextures(1, &target);
2141 }
2142}
2143
Geoff Langa8406172015-07-21 16:53:39 -04002144TEST_P(ImageTest, SourceRenderbufferTargetTexture)
2145{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002146 SourceRenderbufferTargetTexture_helper(kDefaultAttribs);
2147}
2148
2149TEST_P(ImageTest, SourceRenderbufferTargetTexture_Colorspace)
2150{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002151 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2152 SourceRenderbufferTargetTexture_helper(kColorspaceAttribs);
2153}
2154
2155void ImageTest::SourceRenderbufferTargetTexture_helper(const EGLint *attribs)
2156{
Geoff Langa8406172015-07-21 16:53:39 -04002157 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002158 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langa8406172015-07-21 16:53:39 -04002159
2160 GLubyte data[4] = {255, 0, 255, 255};
2161
2162 // Create the Image
2163 GLuint source;
2164 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002165 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002166
2167 // Create the target
2168 GLuint target;
2169 createEGLImageTargetTexture2D(image, &target);
2170
2171 // Expect that the target texture has the same color as the source texture
2172 verifyResults2D(target, data);
2173
2174 // Clean up
2175 glDeleteRenderbuffers(1, &source);
2176 eglDestroyImageKHR(window->getDisplay(), image);
2177 glDeleteTextures(1, &target);
2178}
2179
Geoff Langb66a9092016-05-16 15:59:14 -04002180// Test renderbuffer -> external texture EGL images.
2181TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
2182{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002183 SourceRenderbufferTargetTextureExternal_helper(kDefaultAttribs);
2184}
2185
2186TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal_Colorspace)
2187{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002188 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2189 SourceRenderbufferTargetTextureExternal_helper(kColorspaceAttribs);
2190}
2191
2192void ImageTest::SourceRenderbufferTargetTextureExternal_helper(const EGLint *attribs)
2193{
Geoff Langb66a9092016-05-16 15:59:14 -04002194 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002195 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langb66a9092016-05-16 15:59:14 -04002196
Yuly Novikov64f62f42018-12-12 11:57:35 -05002197 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
2198 ANGLE_SKIP_TEST_IF(IsOzone());
2199
Geoff Langb66a9092016-05-16 15:59:14 -04002200 GLubyte data[4] = {255, 0, 255, 255};
2201
2202 // Create the Image
2203 GLuint source;
2204 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002205 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04002206
2207 // Create the target
2208 GLuint target;
2209 createEGLImageTargetTextureExternal(image, &target);
2210
2211 // Expect that the target texture has the same color as the source texture
2212 verifyResultsExternal(target, data);
2213
2214 // Clean up
2215 glDeleteRenderbuffers(1, &source);
2216 eglDestroyImageKHR(window->getDisplay(), image);
2217 glDeleteTextures(1, &target);
2218}
2219
2220// Test renderbuffer -> external texture EGL images using ESSL3 shaders.
2221TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
2222{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002223 SourceRenderbufferTargetTextureExternalESSL3_helper(kDefaultAttribs);
2224}
2225
2226TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3_Colorspace)
2227{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002228 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2229 SourceRenderbufferTargetTextureExternalESSL3_helper(kColorspaceAttribs);
2230}
2231
2232void ImageTest::SourceRenderbufferTargetTextureExternalESSL3_helper(const EGLint *attribs)
2233{
Geoff Langb66a9092016-05-16 15:59:14 -04002234 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002235 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
2236 !hasRenderbufferExt());
Geoff Langb66a9092016-05-16 15:59:14 -04002237
2238 GLubyte data[4] = {255, 0, 255, 255};
2239
2240 // Create the Image
2241 GLuint source;
2242 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002243 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
Geoff Langb66a9092016-05-16 15:59:14 -04002244
2245 // Create the target
2246 GLuint target;
2247 createEGLImageTargetTextureExternal(image, &target);
2248
2249 // Expect that the target texture has the same color as the source texture
2250 verifyResultsExternalESSL3(target, data);
2251
2252 // Clean up
2253 glDeleteRenderbuffers(1, &source);
2254 eglDestroyImageKHR(window->getDisplay(), image);
2255 glDeleteTextures(1, &target);
2256}
2257
Geoff Langa8406172015-07-21 16:53:39 -04002258TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
2259{
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002260 SourceRenderbufferTargetRenderbuffer_helper(kDefaultAttribs);
2261}
2262
2263TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer_Colorspace)
2264{
2265 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_EXT_sRGB"));
2266 ANGLE_SKIP_TEST_IF(!hasImageGLColorspaceExt());
2267 SourceRenderbufferTargetRenderbuffer_helper(kColorspaceAttribs);
2268}
2269
2270void ImageTest::SourceRenderbufferTargetRenderbuffer_helper(const EGLint *attribs)
2271{
Geoff Langa8406172015-07-21 16:53:39 -04002272 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002273 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langa8406172015-07-21 16:53:39 -04002274
2275 GLubyte data[4] = {255, 0, 255, 255};
2276
2277 // Create the Image
2278 GLuint source;
2279 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002280 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, attribs, data, &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002281
2282 // Create the target
2283 GLuint target;
2284 createEGLImageTargetRenderbuffer(image, &target);
2285
2286 // Expect that the target renderbuffer has the same color as the source texture
2287 verifyResultsRenderbuffer(target, data);
2288
2289 // Clean up
2290 glDeleteRenderbuffers(1, &source);
2291 eglDestroyImageKHR(window->getDisplay(), image);
2292 glDeleteRenderbuffers(1, &target);
2293}
2294
2295// Delete the source texture and EGL image. The image targets should still have the same data
2296// because
2297// they hold refs to the image.
2298TEST_P(ImageTest, Deletion)
2299{
2300 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002301 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002302
2303 GLubyte originalData[4] = {255, 0, 255, 255};
2304 GLubyte updateData[4] = {0, 255, 0, 255};
2305
2306 // Create the Image
2307 GLuint source;
2308 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002309 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2310 &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002311
2312 // Create multiple targets
2313 GLuint targetTexture;
2314 createEGLImageTargetTexture2D(image, &targetTexture);
2315
2316 GLuint targetRenderbuffer;
2317 createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
2318
2319 // Delete the source texture
2320 glDeleteTextures(1, &source);
2321 source = 0;
2322
2323 // Expect that both the targets have the original data
2324 verifyResults2D(targetTexture, originalData);
2325 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
2326
2327 // Update the data of the target
2328 glBindTexture(GL_TEXTURE_2D, targetTexture);
2329 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2330
2331 // Expect that both targets have the updated data
2332 verifyResults2D(targetTexture, updateData);
2333 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
2334
2335 // Delete the EGL image
2336 eglDestroyImageKHR(window->getDisplay(), image);
2337 image = EGL_NO_IMAGE_KHR;
2338
2339 // Update the data of the target back to the original data
2340 glBindTexture(GL_TEXTURE_2D, targetTexture);
2341 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
2342
2343 // Expect that both targets have the original data again
2344 verifyResults2D(targetTexture, originalData);
2345 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
2346
2347 // Clean up
2348 glDeleteTextures(1, &targetTexture);
2349 glDeleteRenderbuffers(1, &targetRenderbuffer);
2350}
2351
2352TEST_P(ImageTest, MipLevels)
2353{
Geoff Langc0b61502018-07-27 15:59:32 -04002354 // Driver returns OOM in read pixels, some internal error.
2355 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
Zhenyao Mo5b3b5cc2018-07-27 16:49:57 -07002356 // Also fails on NVIDIA Shield TV bot.
Sami Väisänen5f454322019-08-22 15:34:57 +02002357 // http://anglebug.com/3850
Jonah Ryan-Davis9078c6a2019-03-19 11:10:15 -04002358 ANGLE_SKIP_TEST_IF(IsNVIDIAShield() && IsOpenGLES());
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04002359 // On Vulkan, the clear operation in the loop is optimized with a render pass loadOp=Clear. On
2360 // Linux/Intel, that operation is mistakenly clearing the rest of the mips to 0.
2361 // http://anglebug.com/3284
2362 ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && IsIntel());
Geoff Langc0b61502018-07-27 15:59:32 -04002363
Geoff Langa8406172015-07-21 16:53:39 -04002364 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002365 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002366
2367 const size_t mipLevels = 3;
2368 const size_t textureSize = 4;
Geoff Lang48d040e2019-01-18 10:43:45 -05002369 std::vector<GLColor> mip0Data(textureSize * textureSize, GLColor::red);
2370 std::vector<GLColor> mip1Data(mip0Data.size() << 1, GLColor::green);
2371 std::vector<GLColor> mip2Data(mip0Data.size() << 2, GLColor::blue);
Geoff Langa8406172015-07-21 16:53:39 -04002372 GLubyte *data[mipLevels] = {
Jamie Madillb980c562018-11-27 11:34:27 -05002373 reinterpret_cast<GLubyte *>(&mip0Data[0]),
2374 reinterpret_cast<GLubyte *>(&mip1Data[0]),
Geoff Langa8406172015-07-21 16:53:39 -04002375 reinterpret_cast<GLubyte *>(&mip2Data[0]),
2376 };
2377
2378 GLuint source;
2379 glGenTextures(1, &source);
2380 glBindTexture(GL_TEXTURE_2D, source);
2381
2382 for (size_t level = 0; level < mipLevels; level++)
2383 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -07002384 glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA, textureSize >> level,
2385 textureSize >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[level]);
Geoff Langa8406172015-07-21 16:53:39 -04002386 }
2387
2388 ASSERT_GL_NO_ERROR();
2389
2390 for (size_t level = 0; level < mipLevels; level++)
2391 {
2392 // Create the Image
2393 EGLint attribs[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05002394 EGL_GL_TEXTURE_LEVEL_KHR,
2395 static_cast<EGLint>(level),
2396 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -04002397 };
2398 EGLImageKHR image =
2399 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07002400 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -04002401 ASSERT_EGL_SUCCESS();
2402
2403 // Create a texture and renderbuffer target
2404 GLuint textureTarget;
2405 createEGLImageTargetTexture2D(image, &textureTarget);
2406
2407 // Disable mipmapping
2408 glBindTexture(GL_TEXTURE_2D, textureTarget);
2409 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2410 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2411
2412 GLuint renderbufferTarget;
2413 createEGLImageTargetRenderbuffer(image, &renderbufferTarget);
2414
2415 // Expect that the targets have the same color as the source texture
2416 verifyResults2D(textureTarget, data[level]);
2417 verifyResultsRenderbuffer(renderbufferTarget, data[level]);
2418
Geoff Lang48d040e2019-01-18 10:43:45 -05002419 // Update the data by uploading data to the texture
2420 std::vector<GLuint> textureUpdateData(textureSize * textureSize, level);
2421 glBindTexture(GL_TEXTURE_2D, textureTarget);
2422 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureSize >> level, textureSize >> level, GL_RGBA,
2423 GL_UNSIGNED_BYTE, textureUpdateData.data());
2424 ASSERT_GL_NO_ERROR();
2425
2426 // Expect that both the texture and renderbuffer see the updated texture data
2427 verifyResults2D(textureTarget, reinterpret_cast<GLubyte *>(textureUpdateData.data()));
2428 verifyResultsRenderbuffer(renderbufferTarget,
2429 reinterpret_cast<GLubyte *>(textureUpdateData.data()));
2430
2431 // Update the renderbuffer by clearing it
2432 GLFramebuffer fbo;
2433 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2434 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
2435 renderbufferTarget);
2436
2437 GLubyte clearValue = static_cast<GLubyte>(level);
2438 GLubyte renderbufferClearData[4]{clearValue, clearValue, clearValue, clearValue};
2439 glClearColor(renderbufferClearData[0] / 255.0f, renderbufferClearData[1] / 255.0f,
2440 renderbufferClearData[2] / 255.0f, renderbufferClearData[3] / 255.0f);
2441 glClear(GL_COLOR_BUFFER_BIT);
2442 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2443 ASSERT_GL_NO_ERROR();
2444
2445 // Expect that both the texture and renderbuffer see the cleared renderbuffer data
2446 verifyResults2D(textureTarget, renderbufferClearData);
2447 verifyResultsRenderbuffer(renderbufferTarget, renderbufferClearData);
2448
Geoff Langa8406172015-07-21 16:53:39 -04002449 // Clean up
2450 eglDestroyImageKHR(window->getDisplay(), image);
2451 glDeleteTextures(1, &textureTarget);
2452 glDeleteRenderbuffers(1, &renderbufferTarget);
2453 }
2454
2455 // Clean up
2456 glDeleteTextures(1, &source);
2457}
2458
2459// Respecify the source texture, orphaning it. The target texture should not have updated data.
2460TEST_P(ImageTest, Respecification)
2461{
Geoff Langdbd16122018-07-19 11:30:21 -04002462 // Respecification of textures that does not change the size of the level attached to the EGL
2463 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/2744
2464 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Geoff Langc0b61502018-07-27 15:59:32 -04002465 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
Geoff Langdbd16122018-07-19 11:30:21 -04002466
Geoff Langa8406172015-07-21 16:53:39 -04002467 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002468 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002469
2470 GLubyte originalData[4] = {255, 0, 255, 255};
2471 GLubyte updateData[4] = {0, 255, 0, 255};
2472
2473 // Create the Image
2474 GLuint source;
2475 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002476 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2477 &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002478
2479 // Create the target
2480 GLuint target;
2481 createEGLImageTargetTexture2D(image, &target);
2482
2483 // Respecify source
2484 glBindTexture(GL_TEXTURE_2D, source);
2485 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2486
2487 // Expect that the target texture has the original data
2488 verifyResults2D(target, originalData);
2489
2490 // Expect that the source texture has the updated data
2491 verifyResults2D(source, updateData);
2492
2493 // Clean up
2494 glDeleteTextures(1, &source);
2495 eglDestroyImageKHR(window->getDisplay(), image);
2496 glDeleteTextures(1, &target);
2497}
2498
Geoff Langdbd16122018-07-19 11:30:21 -04002499// Respecify the source texture with a different size, orphaning it. The target texture should not
2500// have updated data.
2501TEST_P(ImageTest, RespecificationDifferentSize)
2502{
2503 EGLWindow *window = getEGLWindow();
2504 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
2505
2506 GLubyte originalData[4] = {255, 0, 255, 255};
2507 GLubyte updateData[16] = {0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
2508
2509 // Create the Image
2510 GLuint source;
2511 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002512 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2513 &source, &image);
Geoff Langdbd16122018-07-19 11:30:21 -04002514
2515 // Create the target
2516 GLuint target;
2517 createEGLImageTargetTexture2D(image, &target);
2518
2519 // Respecify source
2520 glBindTexture(GL_TEXTURE_2D, source);
2521 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2522
2523 // Expect that the target texture has the original data
2524 verifyResults2D(target, originalData);
2525
2526 // Expect that the source texture has the updated data
2527 verifyResults2D(source, updateData);
2528
2529 // Clean up
2530 glDeleteTextures(1, &source);
2531 eglDestroyImageKHR(window->getDisplay(), image);
2532 glDeleteTextures(1, &target);
2533}
2534
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002535// First render to a target texture, then respecify the source texture, orphaning it.
2536// The target texture's FBO should be notified of the target texture's orphaning.
2537TEST_P(ImageTest, RespecificationWithFBO)
2538{
2539 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002540 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002541
Olli Etuaho5804dc82018-04-13 14:11:46 +03002542 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002543 ASSERT_NE(0u, program);
2544
2545 GLubyte originalData[4] = {255, 0, 255, 255};
2546 GLubyte updateData[4] = {0, 255, 0, 255};
2547
2548 // Create the Image
2549 GLuint source;
2550 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002551 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2552 &source, &image);
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002553
2554 // Create the target
2555 GLuint target;
2556 createEGLImageTargetTexture2D(image, &target);
2557
2558 // Render to the target texture
2559 GLuint fbo;
2560 glGenFramebuffers(1, &fbo);
2561 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2562 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
Olli Etuaho5804dc82018-04-13 14:11:46 +03002563 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2564 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002565
2566 // Respecify source with same parameters. This should not change the texture storage in D3D11.
2567 glBindTexture(GL_TEXTURE_2D, source);
2568 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2569
2570 // Expect that the source texture has the updated data
2571 verifyResults2D(source, updateData);
2572
2573 // Render to the target texture again and verify it gets the rendered pixels.
Olli Etuaho5804dc82018-04-13 14:11:46 +03002574 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
2575 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
Jamie Madill1fbc59f2016-02-24 15:25:51 -05002576
2577 // Clean up
2578 glDeleteTextures(1, &source);
2579 eglDestroyImageKHR(window->getDisplay(), image);
2580 glDeleteTextures(1, &target);
2581 glDeleteProgram(program);
2582 glDeleteFramebuffers(1, &fbo);
2583}
2584
Geoff Langa8406172015-07-21 16:53:39 -04002585// Test that respecifying a level of the target texture orphans it and keeps a copy of the EGLimage
2586// data
2587TEST_P(ImageTest, RespecificationOfOtherLevel)
2588{
Geoff Langdbd16122018-07-19 11:30:21 -04002589 // Respecification of textures that does not change the size of the level attached to the EGL
2590 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/2744
2591 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
2592
Geoff Langfe59f6b2019-01-16 09:34:30 -05002593 // It is undefined what happens to the mip 0 of the dest texture after it is orphaned. Some
2594 // backends explicitly copy the data but Vulkan does not.
2595 ANGLE_SKIP_TEST_IF(IsVulkan());
2596
Geoff Langa8406172015-07-21 16:53:39 -04002597 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002598 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002599
2600 GLubyte originalData[2 * 2 * 4] = {
2601 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
2602 };
2603
2604 GLubyte updateData[2 * 2 * 4] = {
2605 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
2606 };
2607
2608 // Create the Image
2609 GLuint source;
2610 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002611 createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2612 &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002613
2614 // Create the target
2615 GLuint target;
2616 createEGLImageTargetTexture2D(image, &target);
2617
2618 // Expect that the target and source textures have the original data
2619 verifyResults2D(source, originalData);
2620 verifyResults2D(target, originalData);
2621
2622 // Add a new mipLevel to the target, orphaning it
2623 glBindTexture(GL_TEXTURE_2D, target);
2624 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
2625 EXPECT_GL_NO_ERROR();
2626
2627 // Expect that the target and source textures still have the original data
2628 verifyResults2D(source, originalData);
2629 verifyResults2D(target, originalData);
2630
2631 // Update the source's data
2632 glBindTexture(GL_TEXTURE_2D, source);
2633 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2634
2635 // Expect that the target still has the original data and source has the updated data
2636 verifyResults2D(source, updateData);
2637 verifyResults2D(target, originalData);
2638
2639 // Clean up
2640 glDeleteTextures(1, &source);
2641 eglDestroyImageKHR(window->getDisplay(), image);
2642 glDeleteTextures(1, &target);
2643}
2644
2645// Update the data of the source and target textures. All image siblings should have the new data.
2646TEST_P(ImageTest, UpdatedData)
2647{
2648 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04002649 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04002650
2651 GLubyte originalData[4] = {255, 0, 255, 255};
2652 GLubyte updateData[4] = {0, 255, 0, 255};
2653
2654 // Create the Image
2655 GLuint source;
2656 EGLImageKHR image;
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002657 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, kDefaultAttribs, originalData,
2658 &source, &image);
Geoff Langa8406172015-07-21 16:53:39 -04002659
2660 // Create multiple targets
2661 GLuint targetTexture;
2662 createEGLImageTargetTexture2D(image, &targetTexture);
2663
2664 GLuint targetRenderbuffer;
2665 createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
2666
2667 // Expect that both the source and targets have the original data
2668 verifyResults2D(source, originalData);
2669 verifyResults2D(targetTexture, originalData);
2670 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
2671
2672 // Update the data of the source
2673 glBindTexture(GL_TEXTURE_2D, source);
2674 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
2675
2676 // Expect that both the source and targets have the updated data
2677 verifyResults2D(source, updateData);
2678 verifyResults2D(targetTexture, updateData);
2679 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
2680
2681 // Update the data of the target back to the original data
2682 glBindTexture(GL_TEXTURE_2D, targetTexture);
2683 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
2684
2685 // Expect that both the source and targets have the original data again
2686 verifyResults2D(source, originalData);
2687 verifyResults2D(targetTexture, originalData);
2688 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
2689
2690 // Clean up
2691 glDeleteTextures(1, &source);
2692 eglDestroyImageKHR(window->getDisplay(), image);
2693 glDeleteTextures(1, &targetTexture);
2694 glDeleteRenderbuffers(1, &targetRenderbuffer);
2695}
2696
2697// Use this to select which configurations (e.g. which renderer, which GLES major version) these
2698// tests should be run against.
Tobin Ehlis1a01b4b2019-11-11 16:41:07 -07002699ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ImageTest);
2700ANGLE_INSTANTIATE_TEST_ES3(ImageTestES3);
Mohan Maiyadac5cc32020-04-08 18:26:46 -07002701} // namespace angle