blob: 9adb1c69f319076f402d17593101fd6181adb100 [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
14namespace angle
15{
Jamie Madill0be37b42018-07-19 10:03:52 -040016namespace
17{
18constexpr char kOESExt[] = "GL_OES_EGL_image";
19constexpr char kExternalExt[] = "GL_OES_EGL_image_external";
20constexpr char kExternalESSL3Ext[] = "GL_OES_EGL_image_external_essl3";
21constexpr char kBaseExt[] = "EGL_KHR_image_base";
22constexpr char k2DTextureExt[] = "EGL_KHR_gl_texture_2D_image";
23constexpr char k3DTextureExt[] = "EGL_KHR_gl_texture_3D_image";
24constexpr char kPixmapExt[] = "EGL_KHR_image_pixmap";
25constexpr char kRenderbufferExt[] = "EGL_KHR_gl_renderbuffer_image";
26constexpr char kCubemapExt[] = "EGL_KHR_gl_texture_cubemap_image";
27} // anonymous namespace
28
Geoff Langa8406172015-07-21 16:53:39 -040029class ImageTest : public ANGLETest
30{
31 protected:
32 ImageTest()
33 {
34 setWindowWidth(128);
35 setWindowHeight(128);
36 setConfigRedBits(8);
37 setConfigGreenBits(8);
38 setConfigBlueBits(8);
39 setConfigAlphaBits(8);
40 setConfigDepthBits(24);
41 }
42
43 void SetUp() override
44 {
45 ANGLETest::SetUp();
46
Jamie Madill35cd7332018-12-02 12:03:33 -050047 constexpr char kVS[] =
Geoff Langa8406172015-07-21 16:53:39 -040048 "precision highp float;\n"
49 "attribute vec4 position;\n"
50 "varying vec2 texcoord;\n"
51 "\n"
52 "void main()\n"
53 "{\n"
54 " gl_Position = position;\n"
55 " texcoord = (position.xy * 0.5) + 0.5;\n"
56 " texcoord.y = 1.0 - texcoord.y;\n"
57 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -050058 constexpr char kVSESSL3[] =
Geoff Langb66a9092016-05-16 15:59:14 -040059 "#version 300 es\n"
60 "precision highp float;\n"
61 "in vec4 position;\n"
62 "out vec2 texcoord;\n"
63 "\n"
64 "void main()\n"
65 "{\n"
66 " gl_Position = position;\n"
67 " texcoord = (position.xy * 0.5) + 0.5;\n"
68 " texcoord.y = 1.0 - texcoord.y;\n"
69 "}\n";
Geoff Langa8406172015-07-21 16:53:39 -040070
Jamie Madill35cd7332018-12-02 12:03:33 -050071 constexpr char kTextureFS[] =
Geoff Langa8406172015-07-21 16:53:39 -040072 "precision highp float;\n"
73 "uniform sampler2D tex;\n"
74 "varying vec2 texcoord;\n"
75 "\n"
76 "void main()\n"
77 "{\n"
78 " gl_FragColor = texture2D(tex, texcoord);\n"
79 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -050080 constexpr char kTextureExternalFS[] =
Geoff Langb66a9092016-05-16 15:59:14 -040081 "#extension GL_OES_EGL_image_external : require\n"
82 "precision highp float;\n"
83 "uniform samplerExternalOES tex;\n"
84 "varying vec2 texcoord;\n"
85 "\n"
86 "void main()\n"
87 "{\n"
88 " gl_FragColor = texture2D(tex, texcoord);\n"
89 "}\n";
Jamie Madill35cd7332018-12-02 12:03:33 -050090 constexpr char kTextureExternalESSL3FS[] =
Geoff Langb66a9092016-05-16 15:59:14 -040091 "#version 300 es\n"
92 "#extension GL_OES_EGL_image_external_essl3 : require\n"
93 "precision highp float;\n"
94 "uniform samplerExternalOES tex;\n"
95 "in vec2 texcoord;\n"
96 "out vec4 color;"
97 "\n"
98 "void main()\n"
99 "{\n"
100 " color = texture(tex, texcoord);\n"
101 "}\n";
Geoff Langa8406172015-07-21 16:53:39 -0400102
Jamie Madill35cd7332018-12-02 12:03:33 -0500103 mTextureProgram = CompileProgram(kVS, kTextureFS);
Geoff Langa8406172015-07-21 16:53:39 -0400104 if (mTextureProgram == 0)
105 {
106 FAIL() << "shader compilation failed.";
107 }
108
109 mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
110
Geoff Langb66a9092016-05-16 15:59:14 -0400111 if (extensionEnabled("GL_OES_EGL_image_external"))
112 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500113 mTextureExternalProgram = CompileProgram(kVS, kTextureExternalFS);
Geoff Langb66a9092016-05-16 15:59:14 -0400114 ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
115
116 mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
117 }
118
119 if (extensionEnabled("GL_OES_EGL_image_external_essl3"))
120 {
Jamie Madill35cd7332018-12-02 12:03:33 -0500121 mTextureExternalESSL3Program = CompileProgram(kVSESSL3, kTextureExternalESSL3FS);
Geoff Langb66a9092016-05-16 15:59:14 -0400122 ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
123
124 mTextureExternalESSL3UniformLocation =
125 glGetUniformLocation(mTextureExternalESSL3Program, "tex");
126 }
127
Geoff Langa8406172015-07-21 16:53:39 -0400128 eglCreateImageKHR =
129 reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
130 eglDestroyImageKHR =
131 reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
132
133 ASSERT_GL_NO_ERROR();
134 }
135
136 void TearDown() override
137 {
Geoff Langa8406172015-07-21 16:53:39 -0400138 glDeleteProgram(mTextureProgram);
Geoff Langb66a9092016-05-16 15:59:14 -0400139 glDeleteProgram(mTextureExternalProgram);
140 glDeleteProgram(mTextureExternalESSL3Program);
141
142 ANGLETest::TearDown();
Geoff Langa8406172015-07-21 16:53:39 -0400143 }
144
145 void createEGLImage2DTextureSource(size_t width,
146 size_t height,
147 GLenum format,
148 GLenum type,
149 void *data,
150 GLuint *outSourceTexture,
151 EGLImageKHR *outSourceImage)
152 {
153 // Create a source 2D texture
154 GLuint source;
155 glGenTextures(1, &source);
156 glBindTexture(GL_TEXTURE_2D, source);
157
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700158 glTexImage2D(GL_TEXTURE_2D, 0, format, static_cast<GLsizei>(width),
159 static_cast<GLsizei>(height), 0, format, type, data);
Geoff Langa8406172015-07-21 16:53:39 -0400160
161 // Disable mipmapping
162 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
163 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
164
165 ASSERT_GL_NO_ERROR();
166
167 // Create an image from the source texture
168 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400169
170 EGLint attribs[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500171 EGL_IMAGE_PRESERVED,
172 EGL_TRUE,
173 EGL_NONE,
Geoff Langc0b61502018-07-27 15:59:32 -0400174 };
175
Geoff Langa8406172015-07-21 16:53:39 -0400176 EGLImageKHR image =
177 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
Geoff Langc0b61502018-07-27 15:59:32 -0400178 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400179
180 ASSERT_EGL_SUCCESS();
181
182 *outSourceTexture = source;
183 *outSourceImage = image;
184 }
185
186 void createEGLImageCubemapTextureSource(size_t width,
187 size_t height,
188 GLenum format,
189 GLenum type,
190 uint8_t *data,
191 size_t dataStride,
192 EGLenum imageTarget,
193 GLuint *outSourceTexture,
194 EGLImageKHR *outSourceImage)
195 {
196 // Create a source cube map texture
197 GLuint source;
198 glGenTextures(1, &source);
199 glBindTexture(GL_TEXTURE_CUBE_MAP, source);
200
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700201 for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -0400202 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700203 glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format,
204 static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, format, type,
205 data + (faceIdx * dataStride));
Geoff Langa8406172015-07-21 16:53:39 -0400206 }
207
208 // Disable mipmapping
209 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
210 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
211
212 ASSERT_GL_NO_ERROR();
213
214 // Create an image from the source texture
215 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400216
217 EGLint attribs[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500218 EGL_IMAGE_PRESERVED,
219 EGL_TRUE,
220 EGL_NONE,
Geoff Langc0b61502018-07-27 15:59:32 -0400221 };
222
Geoff Langa8406172015-07-21 16:53:39 -0400223 EGLImageKHR image =
224 eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
Geoff Langc0b61502018-07-27 15:59:32 -0400225 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400226
227 ASSERT_EGL_SUCCESS();
228
229 *outSourceTexture = source;
230 *outSourceImage = image;
231 }
232
233 void createEGLImage3DTextureSource(size_t width,
234 size_t height,
235 size_t depth,
236 GLenum format,
237 GLenum type,
238 void *data,
239 size_t imageLayer,
240 GLuint *outSourceTexture,
241 EGLImageKHR *outSourceImage)
242 {
243 // Create a source 3D texture
244 GLuint source;
245 glGenTextures(1, &source);
246 glBindTexture(GL_TEXTURE_3D, source);
247
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700248 glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast<GLsizei>(width),
249 static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type,
250 data);
Geoff Langa8406172015-07-21 16:53:39 -0400251
252 // Disable mipmapping
253 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
254 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
255
256 ASSERT_GL_NO_ERROR();
257
258 // Create an image from the source texture
259 EGLWindow *window = getEGLWindow();
260
261 EGLint attribs[] = {
Geoff Langc0b61502018-07-27 15:59:32 -0400262 EGL_GL_TEXTURE_ZOFFSET_KHR,
263 static_cast<EGLint>(imageLayer),
264 EGL_IMAGE_PRESERVED,
265 EGL_TRUE,
266 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400267 };
268 EGLImageKHR image =
269 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700270 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400271
272 ASSERT_EGL_SUCCESS();
273
274 *outSourceTexture = source;
275 *outSourceImage = image;
276 }
277
278 void createEGLImageRenderbufferSource(size_t width,
279 size_t height,
280 GLenum internalFormat,
281 GLubyte data[4],
282 GLuint *outSourceRenderbuffer,
283 EGLImageKHR *outSourceImage)
284 {
285 // Create a source renderbuffer
286 GLuint source;
287 glGenRenderbuffers(1, &source);
288 glBindRenderbuffer(GL_RENDERBUFFER, source);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700289 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, static_cast<GLsizei>(width),
290 static_cast<GLsizei>(height));
Geoff Langa8406172015-07-21 16:53:39 -0400291
292 // Create a framebuffer and clear it to set the data
293 GLuint framebuffer;
294 glGenFramebuffers(1, &framebuffer);
295 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
296 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
297
298 glClearColor(data[0] / 255.0f, data[1] / 255.0f, data[2] / 255.0f, data[3] / 255.0f);
299 glClear(GL_COLOR_BUFFER_BIT);
300
301 glDeleteFramebuffers(1, &framebuffer);
302
303 ASSERT_GL_NO_ERROR();
304
305 // Create an image from the source renderbuffer
306 EGLWindow *window = getEGLWindow();
Geoff Langc0b61502018-07-27 15:59:32 -0400307
308 EGLint attribs[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500309 EGL_IMAGE_PRESERVED,
310 EGL_TRUE,
311 EGL_NONE,
Geoff Langc0b61502018-07-27 15:59:32 -0400312 };
313
Geoff Langa8406172015-07-21 16:53:39 -0400314 EGLImageKHR image =
315 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
Geoff Langc0b61502018-07-27 15:59:32 -0400316 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -0400317
318 ASSERT_EGL_SUCCESS();
319
320 *outSourceRenderbuffer = source;
321 *outSourceImage = image;
322 }
323
324 void createEGLImageTargetTexture2D(EGLImageKHR image, GLuint *outTargetTexture)
325 {
326 // Create a target texture from the image
327 GLuint target;
328 glGenTextures(1, &target);
329 glBindTexture(GL_TEXTURE_2D, target);
330 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
331
332 // Disable mipmapping
333 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
334 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
335
336 ASSERT_GL_NO_ERROR();
337
338 *outTargetTexture = target;
339 }
340
Geoff Langb66a9092016-05-16 15:59:14 -0400341 void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint *outTargetTexture)
342 {
343 // Create a target texture from the image
344 GLuint target;
345 glGenTextures(1, &target);
346 glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
347 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
348
349 // Disable mipmapping
350 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
351 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
352
353 ASSERT_GL_NO_ERROR();
354
355 *outTargetTexture = target;
356 }
357
Geoff Langa8406172015-07-21 16:53:39 -0400358 void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
359 {
360 // Create a target texture from the image
361 GLuint target;
362 glGenRenderbuffers(1, &target);
363 glBindRenderbuffer(GL_RENDERBUFFER, target);
364 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
365
366 ASSERT_GL_NO_ERROR();
367
368 *outTargetRenderbuffer = target;
369 }
370
Geoff Langb66a9092016-05-16 15:59:14 -0400371 void verifyResultsTexture(GLuint texture,
372 GLubyte data[4],
373 GLenum textureTarget,
374 GLuint program,
375 GLuint textureUniform)
Geoff Langa8406172015-07-21 16:53:39 -0400376 {
377 // Draw a quad with the target texture
Geoff Langb66a9092016-05-16 15:59:14 -0400378 glUseProgram(program);
379 glBindTexture(textureTarget, texture);
380 glUniform1i(textureUniform, 0);
Geoff Langa8406172015-07-21 16:53:39 -0400381
Geoff Langb66a9092016-05-16 15:59:14 -0400382 drawQuad(program, "position", 0.5f);
Geoff Langa8406172015-07-21 16:53:39 -0400383
384 // Expect that the rendered quad has the same color as the source texture
385 EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
386 }
387
Geoff Langb66a9092016-05-16 15:59:14 -0400388 void verifyResults2D(GLuint texture, GLubyte data[4])
389 {
390 verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
391 mTextureUniformLocation);
392 }
393
394 void verifyResultsExternal(GLuint texture, GLubyte data[4])
395 {
396 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
397 mTextureExternalUniformLocation);
398 }
399
400 void verifyResultsExternalESSL3(GLuint texture, GLubyte data[4])
401 {
402 verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
403 mTextureExternalESSL3UniformLocation);
404 }
405
Geoff Langa8406172015-07-21 16:53:39 -0400406 void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
407 {
408 // Bind the renderbuffer to a framebuffer
409 GLuint framebuffer;
410 glGenFramebuffers(1, &framebuffer);
411 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
412 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
413 renderbuffer);
414
415 // Expect that the rendered quad has the same color as the source texture
416 EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
417
418 glDeleteFramebuffers(1, &framebuffer);
419 }
420
Austin Kinrossa8187762015-08-12 10:54:37 -0700421 template <typename destType, typename sourcetype>
422 destType reinterpretHelper(sourcetype source)
423 {
424 static_assert(sizeof(destType) == sizeof(size_t),
425 "destType should be the same size as a size_t");
426 size_t sourceSizeT = static_cast<size_t>(source);
427 return reinterpret_cast<destType>(sourceSizeT);
428 }
429
Jamie Madill0be37b42018-07-19 10:03:52 -0400430 bool hasOESExt() const { return extensionEnabled(kOESExt); }
431
432 bool hasExternalExt() const { return extensionEnabled(kExternalExt); }
433
434 bool hasExternalESSL3Ext() const { return extensionEnabled(kExternalESSL3Ext); }
435
436 bool hasBaseExt() const
437 {
438 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kBaseExt);
439 }
440
441 bool has2DTextureExt() const
442 {
443 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k2DTextureExt);
444 }
445
446 bool has3DTextureExt() const
447 {
448 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), k3DTextureExt);
449 }
450
451 bool hasPixmapExt() const
452 {
453 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kPixmapExt);
454 }
455
456 bool hasRenderbufferExt() const
457 {
458 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kRenderbufferExt);
459 }
460
461 bool hasCubemapExt() const
462 {
463 return eglDisplayExtensionEnabled(getEGLWindow()->getDisplay(), kCubemapExt);
464 }
465
Geoff Langa8406172015-07-21 16:53:39 -0400466 GLuint mTextureProgram;
467 GLint mTextureUniformLocation;
468
Geoff Langb66a9092016-05-16 15:59:14 -0400469 GLuint mTextureExternalProgram = 0;
470 GLint mTextureExternalUniformLocation = -1;
471
472 GLuint mTextureExternalESSL3Program = 0;
473 GLint mTextureExternalESSL3UniformLocation = -1;
474
Geoff Langa8406172015-07-21 16:53:39 -0400475 PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
476 PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
477};
478
Geoff Langb66a9092016-05-16 15:59:14 -0400479class ImageTestES3 : public ImageTest
Jamie Madillb980c562018-11-27 11:34:27 -0500480{};
Geoff Langb66a9092016-05-16 15:59:14 -0400481
Jamie Madill0be37b42018-07-19 10:03:52 -0400482// Tests that the extension is exposed on the platforms we think it should be. Please modify this as
483// you change extension availability.
484TEST_P(ImageTest, ANGLEExtensionAvailability)
485{
Geoff Langc0b61502018-07-27 15:59:32 -0400486 // EGL support is based on driver extension availability.
Geoff Langdbd16122018-07-19 11:30:21 -0400487 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsAndroid());
Geoff Langc0b61502018-07-27 15:59:32 -0400488 ANGLE_SKIP_TEST_IF(IsOpenGLES() && IsOzone());
Geoff Langdbd16122018-07-19 11:30:21 -0400489
Jamie Madill0be37b42018-07-19 10:03:52 -0400490 if (IsD3D11() || IsD3D9())
491 {
492 EXPECT_TRUE(hasOESExt());
493 EXPECT_TRUE(hasExternalExt());
494 EXPECT_TRUE(hasBaseExt());
495 EXPECT_TRUE(has2DTextureExt());
496 EXPECT_TRUE(hasRenderbufferExt());
497
498 if (IsD3D11())
499 {
500 EXPECT_TRUE(hasCubemapExt());
501
502 if (getClientMajorVersion() >= 3)
503 {
504 EXPECT_TRUE(hasExternalESSL3Ext());
505 }
506 else
507 {
508 EXPECT_FALSE(hasExternalESSL3Ext());
509 }
510 }
511 else
512 {
513 EXPECT_FALSE(hasCubemapExt());
514 EXPECT_FALSE(hasExternalESSL3Ext());
515 }
516 }
Geoff Langfe59f6b2019-01-16 09:34:30 -0500517 else if (IsVulkan())
518 {
519 EXPECT_TRUE(hasOESExt());
Geoff Lang366df2b2019-01-18 15:40:34 -0500520 EXPECT_TRUE(hasExternalExt());
Geoff Langfe59f6b2019-01-16 09:34:30 -0500521 EXPECT_TRUE(hasBaseExt());
522 EXPECT_TRUE(has2DTextureExt());
Geoff Langeca36cb2019-01-18 14:03:52 -0500523 EXPECT_TRUE(hasCubemapExt());
Geoff Langfe59f6b2019-01-16 09:34:30 -0500524 EXPECT_TRUE(hasRenderbufferExt());
525 // TODO(geofflang): Support GL_OES_EGL_image_external_essl3. http://anglebug.com/2668
526 EXPECT_FALSE(hasExternalESSL3Ext());
527 }
Jamie Madill0be37b42018-07-19 10:03:52 -0400528 else
529 {
530 EXPECT_FALSE(hasOESExt());
531 EXPECT_FALSE(hasExternalExt());
532 EXPECT_FALSE(hasExternalESSL3Ext());
533 EXPECT_FALSE(hasBaseExt());
534 EXPECT_FALSE(has2DTextureExt());
535 EXPECT_FALSE(has3DTextureExt());
536 EXPECT_FALSE(hasRenderbufferExt());
537 }
538
539 // These extensions are not yet available on any platform.
540 EXPECT_FALSE(hasPixmapExt());
541 EXPECT_FALSE(has3DTextureExt());
542}
543
Geoff Langa8406172015-07-21 16:53:39 -0400544// Check validation from the EGL_KHR_image_base extension
545TEST_P(ImageTest, ValidationImageBase)
546{
547 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -0400548 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -0400549
550 GLuint glTexture2D;
551 glGenTextures(1, &glTexture2D);
552 glBindTexture(GL_TEXTURE_2D, glTexture2D);
553 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
554
555 EGLDisplay display = window->getDisplay();
556 EGLContext context = window->getContext();
557 EGLConfig config = window->getConfig();
558 EGLImageKHR image = EGL_NO_IMAGE_KHR;
Austin Kinrossa8187762015-08-12 10:54:37 -0700559 EGLClientBuffer texture2D = reinterpretHelper<EGLClientBuffer>(glTexture2D);
Geoff Langa8406172015-07-21 16:53:39 -0400560
561 // Test validation of eglCreateImageKHR
562
563 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
564 // generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700565 image = eglCreateImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), context,
Geoff Langa8406172015-07-21 16:53:39 -0400566 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
567 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
568 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
569
570 // If <ctx> is neither the handle of a valid EGLContext object on <dpy> nor EGL_NO_CONTEXT, the
571 // error EGL_BAD_CONTEXT is generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700572 image = eglCreateImageKHR(display, reinterpretHelper<EGLContext>(0xBAADF00D),
Geoff Langa8406172015-07-21 16:53:39 -0400573 EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
574 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
575 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
576
577 // Test EGL_NO_CONTEXT with a 2D texture target which does require a context.
578 image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
579 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
580 EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
581
582 // If an attribute specified in <attrib_list> is not one of the attributes listed in Table bbb,
583 // the error EGL_BAD_PARAMETER is generated.
584 EGLint badAttributes[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500585 static_cast<EGLint>(0xDEADBEEF),
586 0,
587 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400588 };
589
590 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, badAttributes);
591 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
592 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
593
594 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> has an off -
595 // screen buffer bound to it(e.g., by a
596 // previous call to eglBindTexImage), the error EGL_BAD_ACCESS is generated.
597 EGLint surfaceType = 0;
598 eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
599
600 EGLint bindToTextureRGBA = 0;
601 eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
602 if ((surfaceType & EGL_PBUFFER_BIT) != 0 && bindToTextureRGBA == EGL_TRUE)
603 {
604 EGLint pbufferAttributes[] = {
605 EGL_WIDTH, 1,
606 EGL_HEIGHT, 1,
607 EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
608 EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
609 EGL_NONE, EGL_NONE,
610 };
611 EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbufferAttributes);
612 ASSERT_NE(pbuffer, EGL_NO_SURFACE);
613 EXPECT_EGL_SUCCESS();
614
615 eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
616 EXPECT_EGL_SUCCESS();
617
618 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
619 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
620 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
621
622 eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
623 eglDestroySurface(display, pbuffer);
624 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
625 EXPECT_EGL_SUCCESS();
626 EXPECT_GL_NO_ERROR();
627 }
628
629 // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and
630 // <attrib_list> is itself an EGLImage sibling, the error EGL_BAD_ACCESS is generated.
631 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
632 EXPECT_NE(image, EGL_NO_IMAGE_KHR);
633 EXPECT_EGL_SUCCESS();
634
635 /* TODO(geofflang): Enable this validation when it passes.
636 EGLImageKHR image2 = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
637 reinterpret_cast<EGLClientBuffer>(texture2D), nullptr);
638 EXPECT_EQ(image2, EGL_NO_IMAGE_KHR);
639 EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
640 */
641
642 // Test validation of eglDestroyImageKHR
643 // Note: image is now a valid EGL image
644 EGLBoolean result = EGL_FALSE;
645
646 // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
647 // generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700648 result = eglDestroyImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), image);
Geoff Langa8406172015-07-21 16:53:39 -0400649 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
650 EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
651
652 // If <image> is not a valid EGLImageKHR object created with respect to <dpy>, the error
653 // EGL_BAD_PARAMETER is generated.
Austin Kinrossa8187762015-08-12 10:54:37 -0700654 result = eglDestroyImageKHR(display, reinterpretHelper<EGLImageKHR>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -0400655 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
656 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
657
658 // Clean up and validate image is destroyed
659 result = eglDestroyImageKHR(display, image);
660 EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_TRUE));
661 EXPECT_EGL_SUCCESS();
662
663 glDeleteTextures(1, &glTexture2D);
664 EXPECT_GL_NO_ERROR();
665}
666
Geoff Langa8406172015-07-21 16:53:39 -0400667// Check validation from the EGL_KHR_gl_texture_2D_image, EGL_KHR_gl_texture_cubemap_image,
668// EGL_KHR_gl_texture_3D_image and EGL_KHR_gl_renderbuffer_image extensions
669TEST_P(ImageTest, ValidationGLImage)
670{
671 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -0400672 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt());
Geoff Langa8406172015-07-21 16:53:39 -0400673
674 EGLDisplay display = window->getDisplay();
675 EGLContext context = window->getContext();
676 EGLImageKHR image = EGL_NO_IMAGE_KHR;
677
Jamie Madill0be37b42018-07-19 10:03:52 -0400678 if (has2DTextureExt())
Geoff Langa8406172015-07-21 16:53:39 -0400679 {
680 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR or
681 // EGL_GL_TEXTURE_3D_KHR and <buffer> is not the name of a texture object of type <target>,
682 // the error EGL_BAD_PARAMETER is generated.
683 GLuint textureCube;
684 glGenTextures(1, &textureCube);
685 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
686 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
687 face++)
688 {
689 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
690 }
691
692 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700693 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400694 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
695 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
696
697 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR,
698 // EGL_GL_TEXTURE_CUBE_MAP_*_KHR or EGL_GL_TEXTURE_3D_KHR, <buffer> is the name of an
699 // incomplete GL texture object, and any mipmap levels other than mipmap level 0 are
700 // specified, the error EGL_BAD_PARAMETER is generated.
701 GLuint incompleteTexture;
702 glGenTextures(1, &incompleteTexture);
703 glBindTexture(GL_TEXTURE_2D, incompleteTexture);
704 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
705 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
706
707 EGLint level0Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500708 EGL_GL_TEXTURE_LEVEL_KHR,
709 0,
710 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400711 };
712 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700713 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
Geoff Langa8406172015-07-21 16:53:39 -0400714 level0Attribute);
715 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
716 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
717
718 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR or
719 // EGL_GL_TEXTURE_3D_KHR, <buffer> is not the name of a complete GL texture object, and
720 // mipmap level 0 is not specified, the error EGL_BAD_PARAMETER is generated.
721 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
722 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700723 reinterpretHelper<EGLClientBuffer>(incompleteTexture), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400724 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
725 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
726
727 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR,
728 // EGL_GL_RENDERBUFFER_KHR or EGL_GL_TEXTURE_3D_KHR and <buffer> refers to the default GL
729 // texture object(0) for the corresponding GL target, the error EGL_BAD_PARAMETER is
730 // generated.
731 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, 0, nullptr);
732 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
733 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
734
735 // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR, or
736 // EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
737 // EGL_GL_TEXTURE_LEVEL_KHR is not a valid mipmap level for the specified GL texture object
738 // <buffer>, the error EGL_BAD_MATCH is generated.
739 EGLint level2Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500740 EGL_GL_TEXTURE_LEVEL_KHR,
741 2,
742 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400743 };
744 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700745 reinterpretHelper<EGLClientBuffer>(incompleteTexture),
Geoff Langa8406172015-07-21 16:53:39 -0400746 level2Attribute);
747 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
748 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
749 }
750 else
751 {
752 GLuint texture2D;
753 glGenTextures(1, &texture2D);
754 glBindTexture(GL_TEXTURE_2D, texture2D);
755 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
756
757 // From EGL_KHR_image_base:
758 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
759 // generated.
760 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700761 reinterpretHelper<EGLClientBuffer>(texture2D), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400762 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
763 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
764 }
765
Jamie Madill0be37b42018-07-19 10:03:52 -0400766 if (hasCubemapExt())
Geoff Langa8406172015-07-21 16:53:39 -0400767 {
768 // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_CUBE_MAP_*_KHR, <buffer> is
769 // not the name of a complete GL texture object, and one or more faces do not have mipmap
770 // level 0 specified, the error EGL_BAD_PARAMETER is generated.
771 GLuint incompleteTextureCube;
772 glGenTextures(1, &incompleteTextureCube);
773 glBindTexture(GL_TEXTURE_CUBE_MAP, incompleteTextureCube);
774 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
775 nullptr);
776 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
777 nullptr);
778 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
779 nullptr);
780 glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
781 nullptr);
782 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
783 nullptr);
784
785 EGLint level0Attribute[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500786 EGL_GL_TEXTURE_LEVEL_KHR,
787 0,
788 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400789 };
790 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700791 reinterpretHelper<EGLClientBuffer>(incompleteTextureCube),
Geoff Langa8406172015-07-21 16:53:39 -0400792 level0Attribute);
793 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
794 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
795 }
796 else
797 {
798 GLuint textureCube;
799 glGenTextures(1, &textureCube);
800 glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
801 for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
802 face++)
803 {
804 glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
805 }
806
807 // From EGL_KHR_image_base:
808 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
809 // generated.
810 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700811 reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400812 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
813 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
814 }
815
Jamie Madill0be37b42018-07-19 10:03:52 -0400816 if (has3DTextureExt() && getClientMajorVersion() >= 3)
Geoff Langa8406172015-07-21 16:53:39 -0400817 {
818 // If <target> is EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
819 // EGL_GL_TEXTURE_ZOFFSET_KHR exceeds the depth of the specified mipmap level - of - detail
820 // in <buffer>, the error EGL_BAD_PARAMETER is generated.
821 GLuint texture3D;
822 glGenTextures(1, &texture3D);
823 glBindTexture(GL_TEXTURE_3D, texture3D);
824 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
825
826 EGLint zOffset3Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500827 EGL_GL_TEXTURE_ZOFFSET_KHR,
828 3,
829 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400830 };
831 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700832 reinterpretHelper<EGLClientBuffer>(texture3D), zOffset3Parameter);
Geoff Langa8406172015-07-21 16:53:39 -0400833 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
834 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
835
836 EGLint zOffsetNegative1Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500837 EGL_GL_TEXTURE_ZOFFSET_KHR,
838 -1,
839 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400840 };
841 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700842 reinterpretHelper<EGLClientBuffer>(texture3D),
Geoff Langa8406172015-07-21 16:53:39 -0400843 zOffsetNegative1Parameter);
844 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
845 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
846 }
847 else
848 {
Jamie Madill0be37b42018-07-19 10:03:52 -0400849 if (has2DTextureExt())
Geoff Langa8406172015-07-21 16:53:39 -0400850 {
851 GLuint texture2D;
852 glGenTextures(1, &texture2D);
853 glBindTexture(GL_TEXTURE_2D, texture2D);
854 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
855
856 // Verify EGL_GL_TEXTURE_ZOFFSET_KHR is not a valid parameter
857 EGLint zOffset0Parameter[] = {
Jamie Madillb980c562018-11-27 11:34:27 -0500858 EGL_GL_TEXTURE_ZOFFSET_KHR,
859 0,
860 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -0400861 };
862
863 image =
864 eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700865 reinterpretHelper<EGLClientBuffer>(texture2D), zOffset0Parameter);
Geoff Langa8406172015-07-21 16:53:39 -0400866 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
867 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
868 }
869
Martin Radev1be913c2016-07-11 17:59:16 +0300870 if (getClientMajorVersion() >= 3)
Geoff Langa8406172015-07-21 16:53:39 -0400871 {
872 GLuint texture3D;
873 glGenTextures(1, &texture3D);
874 glBindTexture(GL_TEXTURE_3D, texture3D);
875 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
876
877 // From EGL_KHR_image_base:
878 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
879 // generated.
880 image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700881 reinterpretHelper<EGLClientBuffer>(texture3D), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400882 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
883 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
884 }
885 }
886
Jamie Madill0be37b42018-07-19 10:03:52 -0400887 if (hasRenderbufferExt())
Geoff Langa8406172015-07-21 16:53:39 -0400888 {
889 // If <target> is EGL_GL_RENDERBUFFER_KHR and <buffer> is not the name of a renderbuffer
890 // object, or if <buffer> is the name of a multisampled renderbuffer object, the error
891 // EGL_BAD_PARAMETER is generated.
892 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
893 reinterpret_cast<EGLClientBuffer>(0), nullptr);
894 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
895 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
896
897 if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
898 {
899 GLuint renderbuffer;
900 glGenRenderbuffers(1, &renderbuffer);
901 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
902 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
903 EXPECT_GL_NO_ERROR();
904
905 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
906 reinterpret_cast<EGLClientBuffer>(0), nullptr);
907 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
908 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
909 }
910 }
911 else
912 {
913 GLuint renderbuffer;
914 glGenRenderbuffers(1, &renderbuffer);
915 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
916 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
917
918 // From EGL_KHR_image_base:
919 // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
920 // generated.
921 image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -0700922 reinterpretHelper<EGLClientBuffer>(renderbuffer), nullptr);
Geoff Langa8406172015-07-21 16:53:39 -0400923 EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
924 EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
925 }
926}
927
928// Check validation from the GL_OES_EGL_image extension
929TEST_P(ImageTest, ValidationGLEGLImage)
930{
Jamie Madill0be37b42018-07-19 10:03:52 -0400931 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -0400932
933 GLubyte data[4] = {255, 0, 255, 255};
934
935 // Create the Image
936 GLuint source;
937 EGLImageKHR image;
938 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
939
940 // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
941 glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
942 EXPECT_GL_ERROR(GL_INVALID_ENUM);
943
944 // If <image> does not refer to a valid eglImageOES object, the error INVALID_VALUE is
945 // generated.
946 GLuint texture;
947 glGenTextures(1, &texture);
948 glBindTexture(GL_TEXTURE_2D, texture);
Austin Kinrossa8187762015-08-12 10:54:37 -0700949 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, reinterpretHelper<GLeglImageOES>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -0400950 EXPECT_GL_ERROR(GL_INVALID_VALUE);
951
952 // <target> must be RENDERBUFFER_OES, and <image> must be the handle of a valid EGLImage
953 // resource, cast into the type
954 // eglImageOES.
955 glEGLImageTargetRenderbufferStorageOES(GL_TEXTURE_2D, image);
956 EXPECT_GL_ERROR(GL_INVALID_ENUM);
957
958 // If the GL is unable to create a renderbuffer using the specified eglImageOES, the error
959 // INVALID_OPERATION is generated.If <image>
960 // does not refer to a valid eglImageOES object, the error INVALID_VALUE is generated.
961 GLuint renderbuffer;
962 glGenRenderbuffers(1, &renderbuffer);
963 glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
964 glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
Austin Kinrossa8187762015-08-12 10:54:37 -0700965 reinterpretHelper<GLeglImageOES>(0xBAADF00D));
Geoff Langa8406172015-07-21 16:53:39 -0400966 EXPECT_GL_ERROR(GL_INVALID_VALUE);
967
968 // Clean up
969 glDeleteTextures(1, &source);
Jamie Madill0be37b42018-07-19 10:03:52 -0400970 eglDestroyImageKHR(getEGLWindow()->getDisplay(), image);
Geoff Langa8406172015-07-21 16:53:39 -0400971 glDeleteTextures(1, &texture);
972 glDeleteRenderbuffers(1, &renderbuffer);
973}
974
975// Check validation from the GL_OES_EGL_image_external extension
976TEST_P(ImageTest, ValidationGLEGLImageExternal)
977{
Jamie Madill0be37b42018-07-19 10:03:52 -0400978 ANGLE_SKIP_TEST_IF(!hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -0400979
980 GLuint texture;
981 glGenTextures(1, &texture);
982 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
983
984 // In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
985 // TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
986 // to CLAMP_TO_EDGE
Jamie Madillb980c562018-11-27 11:34:27 -0500987 auto getTexParam = [](GLenum target, GLenum pname) {
Geoff Langb66a9092016-05-16 15:59:14 -0400988 GLint value = 0;
989 glGetTexParameteriv(target, pname, &value);
990 EXPECT_GL_NO_ERROR();
991 return value;
992 };
993 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
994 EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
995 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
996 EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
997
998 // "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
999 // TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
1000 // only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
1001 // TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
1002 // INVALID_ENUM error.
1003 GLenum validMinFilters[]{
Jamie Madillb980c562018-11-27 11:34:27 -05001004 GL_NEAREST,
1005 GL_LINEAR,
Geoff Langb66a9092016-05-16 15:59:14 -04001006 };
1007 for (auto minFilter : validMinFilters)
1008 {
1009 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
1010 EXPECT_GL_NO_ERROR();
1011 }
1012
1013 GLenum invalidMinFilters[]{
Jamie Madillb980c562018-11-27 11:34:27 -05001014 GL_NEAREST_MIPMAP_LINEAR,
1015 GL_NEAREST_MIPMAP_NEAREST,
1016 GL_LINEAR_MIPMAP_LINEAR,
Geoff Langb66a9092016-05-16 15:59:14 -04001017 GL_LINEAR_MIPMAP_NEAREST,
1018 };
1019 for (auto minFilter : invalidMinFilters)
1020 {
1021 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
1022 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1023 }
1024
1025 GLenum validWrapModes[]{
1026 GL_CLAMP_TO_EDGE,
1027 };
1028 for (auto minFilter : validWrapModes)
1029 {
1030 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
1031 EXPECT_GL_NO_ERROR();
1032 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
1033 EXPECT_GL_NO_ERROR();
1034 }
1035
1036 GLenum invalidWrapModes[]{
Jamie Madillb980c562018-11-27 11:34:27 -05001037 GL_REPEAT,
1038 GL_MIRRORED_REPEAT,
Geoff Langb66a9092016-05-16 15:59:14 -04001039 };
1040 for (auto minFilter : invalidWrapModes)
1041 {
1042 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
1043 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1044 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
1045 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1046 }
1047
1048 // When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
1049 // INVALID_ENUM error.
1050 glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
1051 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1052
1053 glDeleteTextures(1, &texture);
Geoff Langa8406172015-07-21 16:53:39 -04001054}
1055
1056// Check validation from the GL_OES_EGL_image_external_essl3 extension
1057TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
1058{
Jamie Madill0be37b42018-07-19 10:03:52 -04001059 ANGLE_SKIP_TEST_IF(!hasExternalESSL3Ext());
Geoff Langb66a9092016-05-16 15:59:14 -04001060
1061 // Make sure this extension is not exposed without ES3.
Martin Radev1be913c2016-07-11 17:59:16 +03001062 ASSERT_GE(getClientMajorVersion(), 3);
Geoff Langb66a9092016-05-16 15:59:14 -04001063
1064 GLuint texture;
1065 glGenTextures(1, &texture);
1066 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
1067
1068 // It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
1069 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
1070 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1071
1072 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
1073 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1074
1075 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
1076 EXPECT_GL_NO_ERROR();
1077
1078 glDeleteTextures(1, &texture);
Geoff Langa8406172015-07-21 16:53:39 -04001079}
1080
1081TEST_P(ImageTest, Source2DTarget2D)
1082{
1083 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001084 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001085
1086 GLubyte data[4] = {255, 0, 255, 255};
1087
1088 // Create the Image
1089 GLuint source;
1090 EGLImageKHR image;
1091 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1092
1093 // Create the target
1094 GLuint target;
1095 createEGLImageTargetTexture2D(image, &target);
1096
1097 // Expect that the target texture has the same color as the source texture
1098 verifyResults2D(target, data);
1099
1100 // Clean up
1101 glDeleteTextures(1, &source);
1102 eglDestroyImageKHR(window->getDisplay(), image);
1103 glDeleteTextures(1, &target);
1104}
1105
1106TEST_P(ImageTest, Source2DTargetRenderbuffer)
1107{
1108 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001109 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001110
1111 GLubyte data[4] = {255, 0, 255, 255};
1112
1113 // Create the Image
1114 GLuint source;
1115 EGLImageKHR image;
1116 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1117
1118 // Create the target
1119 GLuint target;
1120 createEGLImageTargetRenderbuffer(image, &target);
1121
1122 // Expect that the target renderbuffer has the same color as the source texture
1123 verifyResultsRenderbuffer(target, data);
1124
1125 // Clean up
1126 glDeleteTextures(1, &source);
1127 eglDestroyImageKHR(window->getDisplay(), image);
1128 glDeleteRenderbuffers(1, &target);
1129}
1130
Geoff Langb66a9092016-05-16 15:59:14 -04001131TEST_P(ImageTest, Source2DTargetExternal)
1132{
1133 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001134 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() || !hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001135
Yuly Novikov64f62f42018-12-12 11:57:35 -05001136 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1137 ANGLE_SKIP_TEST_IF(IsOzone());
1138
Geoff Langb66a9092016-05-16 15:59:14 -04001139 GLubyte data[4] = {255, 0, 255, 255};
1140
1141 // Create the Image
1142 GLuint source;
1143 EGLImageKHR image;
1144 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1145
1146 // Create the target
1147 GLuint target;
1148 createEGLImageTargetTextureExternal(image, &target);
1149
1150 // Expect that the target renderbuffer has the same color as the source texture
1151 verifyResultsExternal(target, data);
1152
1153 // Clean up
1154 glDeleteTextures(1, &source);
1155 eglDestroyImageKHR(window->getDisplay(), image);
1156 glDeleteRenderbuffers(1, &target);
1157}
1158
1159TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
1160{
1161 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001162 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt() ||
1163 !hasExternalESSL3Ext());
Geoff Langb66a9092016-05-16 15:59:14 -04001164
1165 GLubyte data[4] = {255, 0, 255, 255};
1166
1167 // Create the Image
1168 GLuint source;
1169 EGLImageKHR image;
1170 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1171
1172 // Create the target
1173 GLuint target;
1174 createEGLImageTargetTextureExternal(image, &target);
1175
1176 // Expect that the target renderbuffer has the same color as the source texture
1177 verifyResultsExternalESSL3(target, data);
1178
1179 // Clean up
1180 glDeleteTextures(1, &source);
1181 eglDestroyImageKHR(window->getDisplay(), image);
1182 glDeleteRenderbuffers(1, &target);
1183}
1184
Geoff Langa8406172015-07-21 16:53:39 -04001185TEST_P(ImageTest, SourceCubeTarget2D)
1186{
1187 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001188 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
Geoff Langa8406172015-07-21 16:53:39 -04001189
1190 GLubyte data[24] = {
1191 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1192 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1193 };
1194
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001195 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -04001196 {
1197 // Create the Image
1198 GLuint source;
1199 EGLImageKHR image;
1200 createEGLImageCubemapTextureSource(
1201 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1202 EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1203
1204 // Create the target
1205 GLuint target;
1206 createEGLImageTargetTexture2D(image, &target);
1207
1208 // Expect that the target texture has the same color as the source texture
1209 verifyResults2D(target, &data[faceIdx * 4]);
1210
1211 // Clean up
1212 glDeleteTextures(1, &source);
1213 eglDestroyImageKHR(window->getDisplay(), image);
1214 glDeleteTextures(1, &target);
1215 }
1216}
1217
1218TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
1219{
1220 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001221 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt());
Geoff Langa8406172015-07-21 16:53:39 -04001222
Kevin Schoedeleef531f2019-02-20 16:33:21 -05001223 // http://anglebug.com/3145
1224 ANGLE_SKIP_TEST_IF(IsVulkan() && IsIntel() && IsFuchsia());
1225
Geoff Langa8406172015-07-21 16:53:39 -04001226 GLubyte data[24] = {
1227 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1228 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1229 };
1230
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001231 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
Geoff Langa8406172015-07-21 16:53:39 -04001232 {
1233 // Create the Image
1234 GLuint source;
1235 EGLImageKHR image;
1236 createEGLImageCubemapTextureSource(
1237 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1238 EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1239
1240 // Create the target
1241 GLuint target;
1242 createEGLImageTargetRenderbuffer(image, &target);
1243
1244 // Expect that the target texture has the same color as the source texture
1245 verifyResultsRenderbuffer(target, &data[faceIdx * 4]);
1246
1247 // Clean up
1248 glDeleteTextures(1, &source);
1249 eglDestroyImageKHR(window->getDisplay(), image);
1250 glDeleteRenderbuffers(1, &target);
1251 }
1252}
1253
Geoff Langb66a9092016-05-16 15:59:14 -04001254// Test cubemap -> external texture EGL images.
1255TEST_P(ImageTest, SourceCubeTargetExternal)
1256{
1257 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001258 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasCubemapExt() || !hasExternalExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001259
Yuly Novikov64f62f42018-12-12 11:57:35 -05001260 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1261 ANGLE_SKIP_TEST_IF(IsOzone());
1262
Geoff Langb66a9092016-05-16 15:59:14 -04001263 GLubyte data[24] = {
1264 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1265 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1266 };
1267
1268 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1269 {
1270 // Create the Image
1271 GLuint source;
1272 EGLImageKHR image;
1273 createEGLImageCubemapTextureSource(
1274 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1275 EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1276
1277 // Create the target
1278 GLuint target;
1279 createEGLImageTargetTextureExternal(image, &target);
1280
1281 // Expect that the target texture has the same color as the source texture
1282 verifyResultsExternal(target, &data[faceIdx * 4]);
1283
1284 // Clean up
1285 glDeleteTextures(1, &source);
1286 eglDestroyImageKHR(window->getDisplay(), image);
1287 glDeleteRenderbuffers(1, &target);
1288 }
1289}
1290
1291// Test cubemap -> external texture EGL images using ESSL3 shaders.
1292TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
1293{
1294 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001295 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() || !hasCubemapExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001296
1297 GLubyte data[24] = {
1298 255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1299 0, 0, 255, 255, 0, 255, 0, 255, 0, 0, 0, 255,
1300 };
1301
1302 for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1303 {
1304 // Create the Image
1305 GLuint source;
1306 EGLImageKHR image;
1307 createEGLImageCubemapTextureSource(
1308 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1309 EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1310
1311 // Create the target
1312 GLuint target;
1313 createEGLImageTargetTextureExternal(image, &target);
1314
1315 // Expect that the target texture has the same color as the source texture
1316 verifyResultsExternalESSL3(target, &data[faceIdx * 4]);
1317
1318 // Clean up
1319 glDeleteTextures(1, &source);
1320 eglDestroyImageKHR(window->getDisplay(), image);
1321 glDeleteRenderbuffers(1, &target);
1322 }
1323}
1324
Geoff Langa8406172015-07-21 16:53:39 -04001325TEST_P(ImageTest, Source3DTargetTexture)
1326{
1327 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001328 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001329
Yunchao He9550c602018-02-13 14:47:05 +08001330 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"));
Geoff Langa8406172015-07-21 16:53:39 -04001331
1332 const size_t depth = 2;
1333 GLubyte data[4 * depth] = {
1334 255, 0, 255, 255, 255, 255, 0, 255,
1335 };
1336
1337 for (size_t layer = 0; layer < depth; layer++)
1338 {
1339 // Create the Image
1340 GLuint source;
1341 EGLImageKHR image;
1342 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1343 &image);
1344
1345 // Create the target
1346 GLuint target;
1347 createEGLImageTargetTexture2D(image, &target);
1348
1349 // Expect that the target renderbuffer has the same color as the source texture
1350 verifyResults2D(target, &data[layer * 4]);
1351
1352 // Clean up
1353 glDeleteTextures(1, &source);
1354 eglDestroyImageKHR(window->getDisplay(), image);
1355 glDeleteTextures(1, &target);
1356 }
1357}
1358
1359TEST_P(ImageTest, Source3DTargetRenderbuffer)
1360{
Geoff Langdbd16122018-07-19 11:30:21 -04001361 // Qualcom drivers appear to always bind the 0 layer of the source 3D texture when the target is
1362 // a renderbuffer. They work correctly when the target is a 2D texture. http://anglebug.com/2745
1363 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1364
Geoff Langa8406172015-07-21 16:53:39 -04001365 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001366 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001367
Yunchao He9550c602018-02-13 14:47:05 +08001368 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"));
Geoff Langa8406172015-07-21 16:53:39 -04001369
1370 const size_t depth = 2;
1371 GLubyte data[4 * depth] = {
1372 255, 0, 255, 255, 255, 255, 0, 255,
1373 };
1374
1375 for (size_t layer = 0; layer < depth; layer++)
1376 {
1377 // Create the Image
1378 GLuint source;
1379 EGLImageKHR image;
1380 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1381 &image);
1382
1383 // Create the target
1384 GLuint target;
1385 createEGLImageTargetRenderbuffer(image, &target);
1386
1387 // Expect that the target renderbuffer has the same color as the source texture
1388 verifyResultsRenderbuffer(target, &data[layer * 4]);
1389
1390 // Clean up
1391 glDeleteTextures(1, &source);
1392 eglDestroyImageKHR(window->getDisplay(), image);
1393 glDeleteTextures(1, &target);
1394 }
1395}
1396
Geoff Langb66a9092016-05-16 15:59:14 -04001397// Test 3D -> external texture EGL images.
1398TEST_P(ImageTest, Source3DTargetExternal)
1399{
1400 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001401 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !has3DTextureExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001402
Yunchao He9550c602018-02-13 14:47:05 +08001403 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"));
Geoff Langb66a9092016-05-16 15:59:14 -04001404
1405 const size_t depth = 2;
1406 GLubyte data[4 * depth] = {
1407 255, 0, 255, 255, 255, 255, 0, 255,
1408 };
1409
1410 for (size_t layer = 0; layer < depth; layer++)
1411 {
1412 // Create the Image
1413 GLuint source;
1414 EGLImageKHR image;
1415 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1416 &image);
1417
1418 // Create the target
1419 GLuint target;
1420 createEGLImageTargetTextureExternal(image, &target);
1421
1422 // Expect that the target renderbuffer has the same color as the source texture
1423 verifyResultsExternal(target, &data[layer * 4]);
1424
1425 // Clean up
1426 glDeleteTextures(1, &source);
1427 eglDestroyImageKHR(window->getDisplay(), image);
1428 glDeleteTextures(1, &target);
1429 }
1430}
1431
1432// Test 3D -> external texture EGL images using ESSL3 shaders.
1433TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
1434{
1435 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001436 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
1437 !has3DTextureExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001438
Yunchao He9550c602018-02-13 14:47:05 +08001439 ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"));
Geoff Langb66a9092016-05-16 15:59:14 -04001440
1441 const size_t depth = 2;
1442 GLubyte data[4 * depth] = {
1443 255, 0, 255, 255, 255, 255, 0, 255,
1444 };
1445
1446 for (size_t layer = 0; layer < depth; layer++)
1447 {
1448 // Create the Image
1449 GLuint source;
1450 EGLImageKHR image;
1451 createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1452 &image);
1453
1454 // Create the target
1455 GLuint target;
1456 createEGLImageTargetTextureExternal(image, &target);
1457
1458 // Expect that the target renderbuffer has the same color as the source texture
1459 verifyResultsExternalESSL3(target, &data[layer * 4]);
1460
1461 // Clean up
1462 glDeleteTextures(1, &source);
1463 eglDestroyImageKHR(window->getDisplay(), image);
1464 glDeleteTextures(1, &target);
1465 }
1466}
1467
Geoff Langa8406172015-07-21 16:53:39 -04001468TEST_P(ImageTest, SourceRenderbufferTargetTexture)
1469{
1470 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001471 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langa8406172015-07-21 16:53:39 -04001472
1473 GLubyte data[4] = {255, 0, 255, 255};
1474
1475 // Create the Image
1476 GLuint source;
1477 EGLImageKHR image;
1478 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1479
1480 // Create the target
1481 GLuint target;
1482 createEGLImageTargetTexture2D(image, &target);
1483
1484 // Expect that the target texture has the same color as the source texture
1485 verifyResults2D(target, data);
1486
1487 // Clean up
1488 glDeleteRenderbuffers(1, &source);
1489 eglDestroyImageKHR(window->getDisplay(), image);
1490 glDeleteTextures(1, &target);
1491}
1492
Geoff Langb66a9092016-05-16 15:59:14 -04001493// Test renderbuffer -> external texture EGL images.
1494TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
1495{
1496 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001497 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001498
Yuly Novikov64f62f42018-12-12 11:57:35 -05001499 // Ozone only supports external target for images created with EGL_EXT_image_dma_buf_import
1500 ANGLE_SKIP_TEST_IF(IsOzone());
1501
Geoff Langb66a9092016-05-16 15:59:14 -04001502 GLubyte data[4] = {255, 0, 255, 255};
1503
1504 // Create the Image
1505 GLuint source;
1506 EGLImageKHR image;
1507 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1508
1509 // Create the target
1510 GLuint target;
1511 createEGLImageTargetTextureExternal(image, &target);
1512
1513 // Expect that the target texture has the same color as the source texture
1514 verifyResultsExternal(target, data);
1515
1516 // Clean up
1517 glDeleteRenderbuffers(1, &source);
1518 eglDestroyImageKHR(window->getDisplay(), image);
1519 glDeleteTextures(1, &target);
1520}
1521
1522// Test renderbuffer -> external texture EGL images using ESSL3 shaders.
1523TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
1524{
1525 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001526 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasExternalESSL3Ext() || !hasBaseExt() ||
1527 !hasRenderbufferExt());
Geoff Langb66a9092016-05-16 15:59:14 -04001528
1529 GLubyte data[4] = {255, 0, 255, 255};
1530
1531 // Create the Image
1532 GLuint source;
1533 EGLImageKHR image;
1534 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1535
1536 // Create the target
1537 GLuint target;
1538 createEGLImageTargetTextureExternal(image, &target);
1539
1540 // Expect that the target texture has the same color as the source texture
1541 verifyResultsExternalESSL3(target, data);
1542
1543 // Clean up
1544 glDeleteRenderbuffers(1, &source);
1545 eglDestroyImageKHR(window->getDisplay(), image);
1546 glDeleteTextures(1, &target);
1547}
1548
Geoff Langa8406172015-07-21 16:53:39 -04001549TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
1550{
1551 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001552 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !hasRenderbufferExt());
Geoff Langa8406172015-07-21 16:53:39 -04001553
1554 GLubyte data[4] = {255, 0, 255, 255};
1555
1556 // Create the Image
1557 GLuint source;
1558 EGLImageKHR image;
1559 createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1560
1561 // Create the target
1562 GLuint target;
1563 createEGLImageTargetRenderbuffer(image, &target);
1564
1565 // Expect that the target renderbuffer has the same color as the source texture
1566 verifyResultsRenderbuffer(target, data);
1567
1568 // Clean up
1569 glDeleteRenderbuffers(1, &source);
1570 eglDestroyImageKHR(window->getDisplay(), image);
1571 glDeleteRenderbuffers(1, &target);
1572}
1573
1574// Delete the source texture and EGL image. The image targets should still have the same data
1575// because
1576// they hold refs to the image.
1577TEST_P(ImageTest, Deletion)
1578{
1579 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001580 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001581
1582 GLubyte originalData[4] = {255, 0, 255, 255};
1583 GLubyte updateData[4] = {0, 255, 0, 255};
1584
1585 // Create the Image
1586 GLuint source;
1587 EGLImageKHR image;
1588 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1589
1590 // Create multiple targets
1591 GLuint targetTexture;
1592 createEGLImageTargetTexture2D(image, &targetTexture);
1593
1594 GLuint targetRenderbuffer;
1595 createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
1596
1597 // Delete the source texture
1598 glDeleteTextures(1, &source);
1599 source = 0;
1600
1601 // Expect that both the targets have the original data
1602 verifyResults2D(targetTexture, originalData);
1603 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1604
1605 // Update the data of the target
1606 glBindTexture(GL_TEXTURE_2D, targetTexture);
1607 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1608
1609 // Expect that both targets have the updated data
1610 verifyResults2D(targetTexture, updateData);
1611 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
1612
1613 // Delete the EGL image
1614 eglDestroyImageKHR(window->getDisplay(), image);
1615 image = EGL_NO_IMAGE_KHR;
1616
1617 // Update the data of the target back to the original data
1618 glBindTexture(GL_TEXTURE_2D, targetTexture);
1619 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1620
1621 // Expect that both targets have the original data again
1622 verifyResults2D(targetTexture, originalData);
1623 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1624
1625 // Clean up
1626 glDeleteTextures(1, &targetTexture);
1627 glDeleteRenderbuffers(1, &targetRenderbuffer);
1628}
1629
1630TEST_P(ImageTest, MipLevels)
1631{
Geoff Langc0b61502018-07-27 15:59:32 -04001632 // Driver returns OOM in read pixels, some internal error.
1633 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
Zhenyao Mo5b3b5cc2018-07-27 16:49:57 -07001634 // Also fails on NVIDIA Shield TV bot.
Jonah Ryan-Davis9078c6a2019-03-19 11:10:15 -04001635 ANGLE_SKIP_TEST_IF(IsNVIDIAShield() && IsOpenGLES());
Shahbaz Youssefi0c128e12019-03-25 23:50:14 -04001636 // On Vulkan, the clear operation in the loop is optimized with a render pass loadOp=Clear. On
1637 // Linux/Intel, that operation is mistakenly clearing the rest of the mips to 0.
1638 // http://anglebug.com/3284
1639 ANGLE_SKIP_TEST_IF(IsVulkan() && IsLinux() && IsIntel());
Geoff Langc0b61502018-07-27 15:59:32 -04001640
Geoff Langa8406172015-07-21 16:53:39 -04001641 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001642 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001643
1644 const size_t mipLevels = 3;
1645 const size_t textureSize = 4;
Geoff Lang48d040e2019-01-18 10:43:45 -05001646 std::vector<GLColor> mip0Data(textureSize * textureSize, GLColor::red);
1647 std::vector<GLColor> mip1Data(mip0Data.size() << 1, GLColor::green);
1648 std::vector<GLColor> mip2Data(mip0Data.size() << 2, GLColor::blue);
Geoff Langa8406172015-07-21 16:53:39 -04001649 GLubyte *data[mipLevels] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001650 reinterpret_cast<GLubyte *>(&mip0Data[0]),
1651 reinterpret_cast<GLubyte *>(&mip1Data[0]),
Geoff Langa8406172015-07-21 16:53:39 -04001652 reinterpret_cast<GLubyte *>(&mip2Data[0]),
1653 };
1654
1655 GLuint source;
1656 glGenTextures(1, &source);
1657 glBindTexture(GL_TEXTURE_2D, source);
1658
1659 for (size_t level = 0; level < mipLevels; level++)
1660 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -07001661 glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA, textureSize >> level,
1662 textureSize >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[level]);
Geoff Langa8406172015-07-21 16:53:39 -04001663 }
1664
1665 ASSERT_GL_NO_ERROR();
1666
1667 for (size_t level = 0; level < mipLevels; level++)
1668 {
1669 // Create the Image
1670 EGLint attribs[] = {
Jamie Madillb980c562018-11-27 11:34:27 -05001671 EGL_GL_TEXTURE_LEVEL_KHR,
1672 static_cast<EGLint>(level),
1673 EGL_NONE,
Geoff Langa8406172015-07-21 16:53:39 -04001674 };
1675 EGLImageKHR image =
1676 eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
Austin Kinrossa8187762015-08-12 10:54:37 -07001677 reinterpretHelper<EGLClientBuffer>(source), attribs);
Geoff Langa8406172015-07-21 16:53:39 -04001678 ASSERT_EGL_SUCCESS();
1679
1680 // Create a texture and renderbuffer target
1681 GLuint textureTarget;
1682 createEGLImageTargetTexture2D(image, &textureTarget);
1683
1684 // Disable mipmapping
1685 glBindTexture(GL_TEXTURE_2D, textureTarget);
1686 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1687 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1688
1689 GLuint renderbufferTarget;
1690 createEGLImageTargetRenderbuffer(image, &renderbufferTarget);
1691
1692 // Expect that the targets have the same color as the source texture
1693 verifyResults2D(textureTarget, data[level]);
1694 verifyResultsRenderbuffer(renderbufferTarget, data[level]);
1695
Geoff Lang48d040e2019-01-18 10:43:45 -05001696 // Update the data by uploading data to the texture
1697 std::vector<GLuint> textureUpdateData(textureSize * textureSize, level);
1698 glBindTexture(GL_TEXTURE_2D, textureTarget);
1699 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, textureSize >> level, textureSize >> level, GL_RGBA,
1700 GL_UNSIGNED_BYTE, textureUpdateData.data());
1701 ASSERT_GL_NO_ERROR();
1702
1703 // Expect that both the texture and renderbuffer see the updated texture data
1704 verifyResults2D(textureTarget, reinterpret_cast<GLubyte *>(textureUpdateData.data()));
1705 verifyResultsRenderbuffer(renderbufferTarget,
1706 reinterpret_cast<GLubyte *>(textureUpdateData.data()));
1707
1708 // Update the renderbuffer by clearing it
1709 GLFramebuffer fbo;
1710 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1711 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
1712 renderbufferTarget);
1713
1714 GLubyte clearValue = static_cast<GLubyte>(level);
1715 GLubyte renderbufferClearData[4]{clearValue, clearValue, clearValue, clearValue};
1716 glClearColor(renderbufferClearData[0] / 255.0f, renderbufferClearData[1] / 255.0f,
1717 renderbufferClearData[2] / 255.0f, renderbufferClearData[3] / 255.0f);
1718 glClear(GL_COLOR_BUFFER_BIT);
1719 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1720 ASSERT_GL_NO_ERROR();
1721
1722 // Expect that both the texture and renderbuffer see the cleared renderbuffer data
1723 verifyResults2D(textureTarget, renderbufferClearData);
1724 verifyResultsRenderbuffer(renderbufferTarget, renderbufferClearData);
1725
Geoff Langa8406172015-07-21 16:53:39 -04001726 // Clean up
1727 eglDestroyImageKHR(window->getDisplay(), image);
1728 glDeleteTextures(1, &textureTarget);
1729 glDeleteRenderbuffers(1, &renderbufferTarget);
1730 }
1731
1732 // Clean up
1733 glDeleteTextures(1, &source);
1734}
1735
1736// Respecify the source texture, orphaning it. The target texture should not have updated data.
1737TEST_P(ImageTest, Respecification)
1738{
Geoff Langdbd16122018-07-19 11:30:21 -04001739 // Respecification of textures that does not change the size of the level attached to the EGL
1740 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/2744
1741 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
Geoff Langc0b61502018-07-27 15:59:32 -04001742 ANGLE_SKIP_TEST_IF(IsOzone() && IsOpenGLES());
Geoff Langdbd16122018-07-19 11:30:21 -04001743
Geoff Langa8406172015-07-21 16:53:39 -04001744 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001745 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001746
1747 GLubyte originalData[4] = {255, 0, 255, 255};
1748 GLubyte updateData[4] = {0, 255, 0, 255};
1749
1750 // Create the Image
1751 GLuint source;
1752 EGLImageKHR image;
1753 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1754
1755 // Create the target
1756 GLuint target;
1757 createEGLImageTargetTexture2D(image, &target);
1758
1759 // Respecify source
1760 glBindTexture(GL_TEXTURE_2D, source);
1761 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1762
1763 // Expect that the target texture has the original data
1764 verifyResults2D(target, originalData);
1765
1766 // Expect that the source texture has the updated data
1767 verifyResults2D(source, updateData);
1768
1769 // Clean up
1770 glDeleteTextures(1, &source);
1771 eglDestroyImageKHR(window->getDisplay(), image);
1772 glDeleteTextures(1, &target);
1773}
1774
Geoff Langdbd16122018-07-19 11:30:21 -04001775// Respecify the source texture with a different size, orphaning it. The target texture should not
1776// have updated data.
1777TEST_P(ImageTest, RespecificationDifferentSize)
1778{
1779 EGLWindow *window = getEGLWindow();
1780 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
1781
1782 GLubyte originalData[4] = {255, 0, 255, 255};
1783 GLubyte updateData[16] = {0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255};
1784
1785 // Create the Image
1786 GLuint source;
1787 EGLImageKHR image;
1788 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1789
1790 // Create the target
1791 GLuint target;
1792 createEGLImageTargetTexture2D(image, &target);
1793
1794 // Respecify source
1795 glBindTexture(GL_TEXTURE_2D, source);
1796 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1797
1798 // Expect that the target texture has the original data
1799 verifyResults2D(target, originalData);
1800
1801 // Expect that the source texture has the updated data
1802 verifyResults2D(source, updateData);
1803
1804 // Clean up
1805 glDeleteTextures(1, &source);
1806 eglDestroyImageKHR(window->getDisplay(), image);
1807 glDeleteTextures(1, &target);
1808}
1809
Jamie Madill1fbc59f2016-02-24 15:25:51 -05001810// First render to a target texture, then respecify the source texture, orphaning it.
1811// The target texture's FBO should be notified of the target texture's orphaning.
1812TEST_P(ImageTest, RespecificationWithFBO)
1813{
1814 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001815 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Jamie Madill1fbc59f2016-02-24 15:25:51 -05001816
Olli Etuaho5804dc82018-04-13 14:11:46 +03001817 GLuint program = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
Jamie Madill1fbc59f2016-02-24 15:25:51 -05001818 ASSERT_NE(0u, program);
1819
1820 GLubyte originalData[4] = {255, 0, 255, 255};
1821 GLubyte updateData[4] = {0, 255, 0, 255};
1822
1823 // Create the Image
1824 GLuint source;
1825 EGLImageKHR image;
1826 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1827
1828 // Create the target
1829 GLuint target;
1830 createEGLImageTargetTexture2D(image, &target);
1831
1832 // Render to the target texture
1833 GLuint fbo;
1834 glGenFramebuffers(1, &fbo);
1835 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1836 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
Olli Etuaho5804dc82018-04-13 14:11:46 +03001837 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1838 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
Jamie Madill1fbc59f2016-02-24 15:25:51 -05001839
1840 // Respecify source with same parameters. This should not change the texture storage in D3D11.
1841 glBindTexture(GL_TEXTURE_2D, source);
1842 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1843
1844 // Expect that the source texture has the updated data
1845 verifyResults2D(source, updateData);
1846
1847 // Render to the target texture again and verify it gets the rendered pixels.
Olli Etuaho5804dc82018-04-13 14:11:46 +03001848 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
1849 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
Jamie Madill1fbc59f2016-02-24 15:25:51 -05001850
1851 // Clean up
1852 glDeleteTextures(1, &source);
1853 eglDestroyImageKHR(window->getDisplay(), image);
1854 glDeleteTextures(1, &target);
1855 glDeleteProgram(program);
1856 glDeleteFramebuffers(1, &fbo);
1857}
1858
Geoff Langa8406172015-07-21 16:53:39 -04001859// Test that respecifying a level of the target texture orphans it and keeps a copy of the EGLimage
1860// data
1861TEST_P(ImageTest, RespecificationOfOtherLevel)
1862{
Geoff Langdbd16122018-07-19 11:30:21 -04001863 // Respecification of textures that does not change the size of the level attached to the EGL
1864 // image does not cause orphaning on Qualcomm devices. http://anglebug.com/2744
1865 ANGLE_SKIP_TEST_IF(IsAndroid() && IsOpenGLES());
1866
Geoff Langfe59f6b2019-01-16 09:34:30 -05001867 // It is undefined what happens to the mip 0 of the dest texture after it is orphaned. Some
1868 // backends explicitly copy the data but Vulkan does not.
1869 ANGLE_SKIP_TEST_IF(IsVulkan());
1870
Geoff Langa8406172015-07-21 16:53:39 -04001871 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001872 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001873
1874 GLubyte originalData[2 * 2 * 4] = {
1875 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
1876 };
1877
1878 GLubyte updateData[2 * 2 * 4] = {
1879 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
1880 };
1881
1882 // Create the Image
1883 GLuint source;
1884 EGLImageKHR image;
1885 createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1886
1887 // Create the target
1888 GLuint target;
1889 createEGLImageTargetTexture2D(image, &target);
1890
1891 // Expect that the target and source textures have the original data
1892 verifyResults2D(source, originalData);
1893 verifyResults2D(target, originalData);
1894
1895 // Add a new mipLevel to the target, orphaning it
1896 glBindTexture(GL_TEXTURE_2D, target);
1897 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1898 EXPECT_GL_NO_ERROR();
1899
1900 // Expect that the target and source textures still have the original data
1901 verifyResults2D(source, originalData);
1902 verifyResults2D(target, originalData);
1903
1904 // Update the source's data
1905 glBindTexture(GL_TEXTURE_2D, source);
1906 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1907
1908 // Expect that the target still has the original data and source has the updated data
1909 verifyResults2D(source, updateData);
1910 verifyResults2D(target, originalData);
1911
1912 // Clean up
1913 glDeleteTextures(1, &source);
1914 eglDestroyImageKHR(window->getDisplay(), image);
1915 glDeleteTextures(1, &target);
1916}
1917
1918// Update the data of the source and target textures. All image siblings should have the new data.
1919TEST_P(ImageTest, UpdatedData)
1920{
1921 EGLWindow *window = getEGLWindow();
Jamie Madill0be37b42018-07-19 10:03:52 -04001922 ANGLE_SKIP_TEST_IF(!hasOESExt() || !hasBaseExt() || !has2DTextureExt());
Geoff Langa8406172015-07-21 16:53:39 -04001923
1924 GLubyte originalData[4] = {255, 0, 255, 255};
1925 GLubyte updateData[4] = {0, 255, 0, 255};
1926
1927 // Create the Image
1928 GLuint source;
1929 EGLImageKHR image;
1930 createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1931
1932 // Create multiple targets
1933 GLuint targetTexture;
1934 createEGLImageTargetTexture2D(image, &targetTexture);
1935
1936 GLuint targetRenderbuffer;
1937 createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
1938
1939 // Expect that both the source and targets have the original data
1940 verifyResults2D(source, originalData);
1941 verifyResults2D(targetTexture, originalData);
1942 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1943
1944 // Update the data of the source
1945 glBindTexture(GL_TEXTURE_2D, source);
1946 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1947
1948 // Expect that both the source and targets have the updated data
1949 verifyResults2D(source, updateData);
1950 verifyResults2D(targetTexture, updateData);
1951 verifyResultsRenderbuffer(targetRenderbuffer, updateData);
1952
1953 // Update the data of the target back to the original data
1954 glBindTexture(GL_TEXTURE_2D, targetTexture);
1955 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1956
1957 // Expect that both the source and targets have the original data again
1958 verifyResults2D(source, originalData);
1959 verifyResults2D(targetTexture, originalData);
1960 verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1961
1962 // Clean up
1963 glDeleteTextures(1, &source);
1964 eglDestroyImageKHR(window->getDisplay(), image);
1965 glDeleteTextures(1, &targetTexture);
1966 glDeleteRenderbuffers(1, &targetRenderbuffer);
1967}
1968
1969// Use this to select which configurations (e.g. which renderer, which GLES major version) these
1970// tests should be run against.
Geoff Lange0cc2a42016-01-20 10:58:17 -05001971ANGLE_INSTANTIATE_TEST(ImageTest,
1972 ES2_D3D9(),
1973 ES2_D3D11(),
1974 ES3_D3D11(),
1975 ES2_OPENGL(),
1976 ES3_OPENGL(),
1977 ES2_OPENGLES(),
Luc Ferronaf883622018-06-08 15:57:31 -04001978 ES3_OPENGLES(),
1979 ES2_VULKAN());
Geoff Langb66a9092016-05-16 15:59:14 -04001980ANGLE_INSTANTIATE_TEST(ImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
Jamie Madillb980c562018-11-27 11:34:27 -05001981} // namespace angle