1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // ImageTest:
7 //   Tests the correctness of eglImage.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 
12 namespace angle
13 {
14 class ImageTest : public ANGLETest
15 {
16   protected:
ImageTest()17     ImageTest()
18     {
19         setWindowWidth(128);
20         setWindowHeight(128);
21         setConfigRedBits(8);
22         setConfigGreenBits(8);
23         setConfigBlueBits(8);
24         setConfigAlphaBits(8);
25         setConfigDepthBits(24);
26     }
27 
SetUp()28     void SetUp() override
29     {
30         ANGLETest::SetUp();
31 
32         const std::string vsSource =
33             "precision highp float;\n"
34             "attribute vec4 position;\n"
35             "varying vec2 texcoord;\n"
36             "\n"
37             "void main()\n"
38             "{\n"
39             "    gl_Position = position;\n"
40             "    texcoord = (position.xy * 0.5) + 0.5;\n"
41             "    texcoord.y = 1.0 - texcoord.y;\n"
42             "}\n";
43         const std::string vsESSL3Source =
44             "#version 300 es\n"
45             "precision highp float;\n"
46             "in vec4 position;\n"
47             "out vec2 texcoord;\n"
48             "\n"
49             "void main()\n"
50             "{\n"
51             "    gl_Position = position;\n"
52             "    texcoord = (position.xy * 0.5) + 0.5;\n"
53             "    texcoord.y = 1.0 - texcoord.y;\n"
54             "}\n";
55 
56         const std::string textureFSSource =
57             "precision highp float;\n"
58             "uniform sampler2D tex;\n"
59             "varying vec2 texcoord;\n"
60             "\n"
61             "void main()\n"
62             "{\n"
63             "    gl_FragColor = texture2D(tex, texcoord);\n"
64             "}\n";
65         const std::string textureExternalFSSource =
66             "#extension GL_OES_EGL_image_external : require\n"
67             "precision highp float;\n"
68             "uniform samplerExternalOES tex;\n"
69             "varying vec2 texcoord;\n"
70             "\n"
71             "void main()\n"
72             "{\n"
73             "    gl_FragColor = texture2D(tex, texcoord);\n"
74             "}\n";
75         const std::string textureExternalESSL3FSSource =
76             "#version 300 es\n"
77             "#extension GL_OES_EGL_image_external_essl3 : require\n"
78             "precision highp float;\n"
79             "uniform samplerExternalOES tex;\n"
80             "in vec2 texcoord;\n"
81             "out vec4 color;"
82             "\n"
83             "void main()\n"
84             "{\n"
85             "    color = texture(tex, texcoord);\n"
86             "}\n";
87 
88         mTextureProgram = CompileProgram(vsSource, textureFSSource);
89         if (mTextureProgram == 0)
90         {
91             FAIL() << "shader compilation failed.";
92         }
93 
94         mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
95 
96         if (extensionEnabled("GL_OES_EGL_image_external"))
97         {
98             mTextureExternalProgram = CompileProgram(vsSource, textureExternalFSSource);
99             ASSERT_NE(0u, mTextureExternalProgram) << "shader compilation failed.";
100 
101             mTextureExternalUniformLocation = glGetUniformLocation(mTextureExternalProgram, "tex");
102         }
103 
104         if (extensionEnabled("GL_OES_EGL_image_external_essl3"))
105         {
106             mTextureExternalESSL3Program =
107                 CompileProgram(vsESSL3Source, textureExternalESSL3FSSource);
108             ASSERT_NE(0u, mTextureExternalESSL3Program) << "shader compilation failed.";
109 
110             mTextureExternalESSL3UniformLocation =
111                 glGetUniformLocation(mTextureExternalESSL3Program, "tex");
112         }
113 
114         eglCreateImageKHR =
115             reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
116         eglDestroyImageKHR =
117             reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
118 
119         ASSERT_GL_NO_ERROR();
120     }
121 
TearDown()122     void TearDown() override
123     {
124         glDeleteProgram(mTextureProgram);
125         glDeleteProgram(mTextureExternalProgram);
126         glDeleteProgram(mTextureExternalESSL3Program);
127 
128         ANGLETest::TearDown();
129     }
130 
createEGLImage2DTextureSource(size_t width,size_t height,GLenum format,GLenum type,void * data,GLuint * outSourceTexture,EGLImageKHR * outSourceImage)131     void createEGLImage2DTextureSource(size_t width,
132                                        size_t height,
133                                        GLenum format,
134                                        GLenum type,
135                                        void *data,
136                                        GLuint *outSourceTexture,
137                                        EGLImageKHR *outSourceImage)
138     {
139         // Create a source 2D texture
140         GLuint source;
141         glGenTextures(1, &source);
142         glBindTexture(GL_TEXTURE_2D, source);
143 
144         glTexImage2D(GL_TEXTURE_2D, 0, format, static_cast<GLsizei>(width),
145                      static_cast<GLsizei>(height), 0, format, type, data);
146 
147         // Disable mipmapping
148         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
149         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
150 
151         ASSERT_GL_NO_ERROR();
152 
153         // Create an image from the source texture
154         EGLWindow *window = getEGLWindow();
155         EGLImageKHR image =
156             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
157                               reinterpretHelper<EGLClientBuffer>(source), nullptr);
158 
159         ASSERT_EGL_SUCCESS();
160 
161         *outSourceTexture = source;
162         *outSourceImage   = image;
163     }
164 
createEGLImageCubemapTextureSource(size_t width,size_t height,GLenum format,GLenum type,uint8_t * data,size_t dataStride,EGLenum imageTarget,GLuint * outSourceTexture,EGLImageKHR * outSourceImage)165     void createEGLImageCubemapTextureSource(size_t width,
166                                             size_t height,
167                                             GLenum format,
168                                             GLenum type,
169                                             uint8_t *data,
170                                             size_t dataStride,
171                                             EGLenum imageTarget,
172                                             GLuint *outSourceTexture,
173                                             EGLImageKHR *outSourceImage)
174     {
175         // Create a source cube map texture
176         GLuint source;
177         glGenTextures(1, &source);
178         glBindTexture(GL_TEXTURE_CUBE_MAP, source);
179 
180         for (GLenum faceIdx = 0; faceIdx < 6; faceIdx++)
181         {
182             glTexImage2D(faceIdx + GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, format,
183                          static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0, format, type,
184                          data + (faceIdx * dataStride));
185         }
186 
187         // Disable mipmapping
188         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
189         glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
190 
191         ASSERT_GL_NO_ERROR();
192 
193         // Create an image from the source texture
194         EGLWindow *window = getEGLWindow();
195         EGLImageKHR image =
196             eglCreateImageKHR(window->getDisplay(), window->getContext(), imageTarget,
197                               reinterpretHelper<EGLClientBuffer>(source), nullptr);
198 
199         ASSERT_EGL_SUCCESS();
200 
201         *outSourceTexture = source;
202         *outSourceImage   = image;
203     }
204 
createEGLImage3DTextureSource(size_t width,size_t height,size_t depth,GLenum format,GLenum type,void * data,size_t imageLayer,GLuint * outSourceTexture,EGLImageKHR * outSourceImage)205     void createEGLImage3DTextureSource(size_t width,
206                                        size_t height,
207                                        size_t depth,
208                                        GLenum format,
209                                        GLenum type,
210                                        void *data,
211                                        size_t imageLayer,
212                                        GLuint *outSourceTexture,
213                                        EGLImageKHR *outSourceImage)
214     {
215         // Create a source 3D texture
216         GLuint source;
217         glGenTextures(1, &source);
218         glBindTexture(GL_TEXTURE_3D, source);
219 
220         glTexImage3D(GL_TEXTURE_3D, 0, format, static_cast<GLsizei>(width),
221                      static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type,
222                      data);
223 
224         // Disable mipmapping
225         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
226         glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
227 
228         ASSERT_GL_NO_ERROR();
229 
230         // Create an image from the source texture
231         EGLWindow *window = getEGLWindow();
232 
233         EGLint attribs[] = {
234             EGL_GL_TEXTURE_ZOFFSET_KHR, static_cast<EGLint>(imageLayer), EGL_NONE,
235         };
236         EGLImageKHR image =
237             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_3D_KHR,
238                               reinterpretHelper<EGLClientBuffer>(source), attribs);
239 
240         ASSERT_EGL_SUCCESS();
241 
242         *outSourceTexture = source;
243         *outSourceImage   = image;
244     }
245 
createEGLImageRenderbufferSource(size_t width,size_t height,GLenum internalFormat,GLubyte data[4],GLuint * outSourceRenderbuffer,EGLImageKHR * outSourceImage)246     void createEGLImageRenderbufferSource(size_t width,
247                                           size_t height,
248                                           GLenum internalFormat,
249                                           GLubyte data[4],
250                                           GLuint *outSourceRenderbuffer,
251                                           EGLImageKHR *outSourceImage)
252     {
253         // Create a source renderbuffer
254         GLuint source;
255         glGenRenderbuffers(1, &source);
256         glBindRenderbuffer(GL_RENDERBUFFER, source);
257         glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, static_cast<GLsizei>(width),
258                               static_cast<GLsizei>(height));
259 
260         // Create a framebuffer and clear it to set the data
261         GLuint framebuffer;
262         glGenFramebuffers(1, &framebuffer);
263         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
264         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, source);
265 
266         glClearColor(data[0] / 255.0f, data[1] / 255.0f, data[2] / 255.0f, data[3] / 255.0f);
267         glClear(GL_COLOR_BUFFER_BIT);
268 
269         glDeleteFramebuffers(1, &framebuffer);
270 
271         ASSERT_GL_NO_ERROR();
272 
273         // Create an image from the source renderbuffer
274         EGLWindow *window = getEGLWindow();
275         EGLImageKHR image =
276             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_RENDERBUFFER_KHR,
277                               reinterpretHelper<EGLClientBuffer>(source), nullptr);
278 
279         ASSERT_EGL_SUCCESS();
280 
281         *outSourceRenderbuffer = source;
282         *outSourceImage        = image;
283     }
284 
createEGLImageTargetTexture2D(EGLImageKHR image,GLuint * outTargetTexture)285     void createEGLImageTargetTexture2D(EGLImageKHR image, GLuint *outTargetTexture)
286     {
287         // Create a target texture from the image
288         GLuint target;
289         glGenTextures(1, &target);
290         glBindTexture(GL_TEXTURE_2D, target);
291         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
292 
293         // Disable mipmapping
294         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
295         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
296 
297         ASSERT_GL_NO_ERROR();
298 
299         *outTargetTexture = target;
300     }
301 
createEGLImageTargetTextureExternal(EGLImageKHR image,GLuint * outTargetTexture)302     void createEGLImageTargetTextureExternal(EGLImageKHR image, GLuint *outTargetTexture)
303     {
304         // Create a target texture from the image
305         GLuint target;
306         glGenTextures(1, &target);
307         glBindTexture(GL_TEXTURE_EXTERNAL_OES, target);
308         glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image);
309 
310         // Disable mipmapping
311         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
312         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
313 
314         ASSERT_GL_NO_ERROR();
315 
316         *outTargetTexture = target;
317     }
318 
createEGLImageTargetRenderbuffer(EGLImageKHR image,GLuint * outTargetRenderbuffer)319     void createEGLImageTargetRenderbuffer(EGLImageKHR image, GLuint *outTargetRenderbuffer)
320     {
321         // Create a target texture from the image
322         GLuint target;
323         glGenRenderbuffers(1, &target);
324         glBindRenderbuffer(GL_RENDERBUFFER, target);
325         glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, image);
326 
327         ASSERT_GL_NO_ERROR();
328 
329         *outTargetRenderbuffer = target;
330     }
331 
verifyResultsTexture(GLuint texture,GLubyte data[4],GLenum textureTarget,GLuint program,GLuint textureUniform)332     void verifyResultsTexture(GLuint texture,
333                               GLubyte data[4],
334                               GLenum textureTarget,
335                               GLuint program,
336                               GLuint textureUniform)
337     {
338         // Draw a quad with the target texture
339         glUseProgram(program);
340         glBindTexture(textureTarget, texture);
341         glUniform1i(textureUniform, 0);
342 
343         drawQuad(program, "position", 0.5f);
344 
345         // Expect that the rendered quad has the same color as the source texture
346         EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
347     }
348 
verifyResults2D(GLuint texture,GLubyte data[4])349     void verifyResults2D(GLuint texture, GLubyte data[4])
350     {
351         verifyResultsTexture(texture, data, GL_TEXTURE_2D, mTextureProgram,
352                              mTextureUniformLocation);
353     }
354 
verifyResultsExternal(GLuint texture,GLubyte data[4])355     void verifyResultsExternal(GLuint texture, GLubyte data[4])
356     {
357         verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalProgram,
358                              mTextureExternalUniformLocation);
359     }
360 
verifyResultsExternalESSL3(GLuint texture,GLubyte data[4])361     void verifyResultsExternalESSL3(GLuint texture, GLubyte data[4])
362     {
363         verifyResultsTexture(texture, data, GL_TEXTURE_EXTERNAL_OES, mTextureExternalESSL3Program,
364                              mTextureExternalESSL3UniformLocation);
365     }
366 
verifyResultsRenderbuffer(GLuint renderbuffer,GLubyte data[4])367     void verifyResultsRenderbuffer(GLuint renderbuffer, GLubyte data[4])
368     {
369         // Bind the renderbuffer to a framebuffer
370         GLuint framebuffer;
371         glGenFramebuffers(1, &framebuffer);
372         glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
373         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
374                                   renderbuffer);
375 
376         // Expect that the rendered quad has the same color as the source texture
377         EXPECT_PIXEL_EQ(0, 0, data[0], data[1], data[2], data[3]);
378 
379         glDeleteFramebuffers(1, &framebuffer);
380     }
381 
382     template <typename destType, typename sourcetype>
383     destType reinterpretHelper(sourcetype source)
384     {
385         static_assert(sizeof(destType) == sizeof(size_t),
386                       "destType should be the same size as a size_t");
387         size_t sourceSizeT = static_cast<size_t>(source);
388         return reinterpret_cast<destType>(sourceSizeT);
389     }
390 
391     GLuint mTextureProgram;
392     GLint mTextureUniformLocation;
393 
394     GLuint mTextureExternalProgram        = 0;
395     GLint mTextureExternalUniformLocation = -1;
396 
397     GLuint mTextureExternalESSL3Program        = 0;
398     GLint mTextureExternalESSL3UniformLocation = -1;
399 
400     PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR;
401     PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR;
402 };
403 
404 class ImageTestES3 : public ImageTest
405 {
406 };
407 
408 // Check validation from the EGL_KHR_image_base extension
TEST_P(ImageTest,ValidationImageBase)409 TEST_P(ImageTest, ValidationImageBase)
410 {
411     EGLWindow *window = getEGLWindow();
412     if (!extensionEnabled("OES_EGL_image") ||
413         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
414         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
415     {
416         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
417                      "EGL_KHR_gl_texture_2D_image is not available."
418                   << std::endl;
419         return;
420     }
421 
422     GLuint glTexture2D;
423     glGenTextures(1, &glTexture2D);
424     glBindTexture(GL_TEXTURE_2D, glTexture2D);
425     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
426 
427     EGLDisplay display        = window->getDisplay();
428     EGLContext context        = window->getContext();
429     EGLConfig config          = window->getConfig();
430     EGLImageKHR image         = EGL_NO_IMAGE_KHR;
431     EGLClientBuffer texture2D = reinterpretHelper<EGLClientBuffer>(glTexture2D);
432 
433     // Test validation of eglCreateImageKHR
434 
435     // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
436     // generated.
437     image = eglCreateImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), context,
438                               EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
439     EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
440     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
441 
442     // If <ctx> is neither the handle of a valid EGLContext object on <dpy> nor EGL_NO_CONTEXT, the
443     // error EGL_BAD_CONTEXT is generated.
444     image = eglCreateImageKHR(display, reinterpretHelper<EGLContext>(0xBAADF00D),
445                               EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
446     EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
447     EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
448 
449     // Test EGL_NO_CONTEXT with a 2D texture target which does require a context.
450     image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
451     EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
452     EXPECT_EGL_ERROR(EGL_BAD_CONTEXT);
453 
454     // If an attribute specified in <attrib_list> is not one of the attributes listed in Table bbb,
455     // the error EGL_BAD_PARAMETER is generated.
456     EGLint badAttributes[] = {
457         static_cast<EGLint>(0xDEADBEEF), 0, EGL_NONE,
458     };
459 
460     image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, badAttributes);
461     EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
462     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
463 
464     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> has an off -
465     // screen buffer bound to it(e.g., by a
466     // previous call to eglBindTexImage), the error EGL_BAD_ACCESS is generated.
467     EGLint surfaceType = 0;
468     eglGetConfigAttrib(display, config, EGL_SURFACE_TYPE, &surfaceType);
469 
470     EGLint bindToTextureRGBA = 0;
471     eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_RGBA, &bindToTextureRGBA);
472     if ((surfaceType & EGL_PBUFFER_BIT) != 0 && bindToTextureRGBA == EGL_TRUE)
473     {
474         EGLint pbufferAttributes[] = {
475             EGL_WIDTH,          1,
476             EGL_HEIGHT,         1,
477             EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
478             EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
479             EGL_NONE,           EGL_NONE,
480         };
481         EGLSurface pbuffer = eglCreatePbufferSurface(display, config, pbufferAttributes);
482         ASSERT_NE(pbuffer, EGL_NO_SURFACE);
483         EXPECT_EGL_SUCCESS();
484 
485         eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
486         EXPECT_EGL_SUCCESS();
487 
488         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
489         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
490         EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
491 
492         eglReleaseTexImage(display, pbuffer, EGL_BACK_BUFFER);
493         eglDestroySurface(display, pbuffer);
494         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
495         EXPECT_EGL_SUCCESS();
496         EXPECT_GL_NO_ERROR();
497     }
498 
499     // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and
500     // <attrib_list> is itself an EGLImage sibling, the error EGL_BAD_ACCESS is generated.
501     image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, texture2D, nullptr);
502     EXPECT_NE(image, EGL_NO_IMAGE_KHR);
503     EXPECT_EGL_SUCCESS();
504 
505     /* TODO(geofflang): Enable this validation when it passes.
506     EGLImageKHR image2 = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
507     reinterpret_cast<EGLClientBuffer>(texture2D), nullptr);
508     EXPECT_EQ(image2, EGL_NO_IMAGE_KHR);
509     EXPECT_EGL_ERROR(EGL_BAD_ACCESS);
510     */
511 
512     // Test validation of eglDestroyImageKHR
513     // Note: image is now a valid EGL image
514     EGLBoolean result = EGL_FALSE;
515 
516     // If <dpy> is not the handle of a valid EGLDisplay object, the error EGL_BAD_DISPLAY is
517     // generated.
518     result = eglDestroyImageKHR(reinterpretHelper<EGLDisplay>(0xBAADF00D), image);
519     EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
520     EXPECT_EGL_ERROR(EGL_BAD_DISPLAY);
521 
522     // If <image> is not a valid EGLImageKHR object created with respect to <dpy>, the error
523     // EGL_BAD_PARAMETER is generated.
524     result = eglDestroyImageKHR(display, reinterpretHelper<EGLImageKHR>(0xBAADF00D));
525     EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_FALSE));
526     EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
527 
528     // Clean up and validate image is destroyed
529     result = eglDestroyImageKHR(display, image);
530     EXPECT_EQ(result, static_cast<EGLBoolean>(EGL_TRUE));
531     EXPECT_EGL_SUCCESS();
532 
533     glDeleteTextures(1, &glTexture2D);
534     EXPECT_GL_NO_ERROR();
535 }
536 
537 // Check validation from the EGL_KHR_gl_texture_2D_image extension
TEST_P(ImageTest,ValidationImagePixmap)538 TEST_P(ImageTest, ValidationImagePixmap)
539 {
540     // This extension is not implemented anywhere yet.  This makes sure that it is tested once it is
541     // added.
542     EGLWindow *window = getEGLWindow();
543     EXPECT_FALSE(eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_pixmap"));
544 }
545 
546 // Check validation from the EGL_KHR_gl_texture_2D_image, EGL_KHR_gl_texture_cubemap_image,
547 // EGL_KHR_gl_texture_3D_image and EGL_KHR_gl_renderbuffer_image extensions
TEST_P(ImageTest,ValidationGLImage)548 TEST_P(ImageTest, ValidationGLImage)
549 {
550     EGLWindow *window = getEGLWindow();
551     if (!extensionEnabled("OES_EGL_image") ||
552         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base"))
553     {
554         std::cout << "Test skipped because OES_EGL_image or EGL_KHR_image_base is not available."
555                   << std::endl;
556         return;
557     }
558 
559     EGLDisplay display = window->getDisplay();
560     EGLContext context = window->getContext();
561     EGLImageKHR image  = EGL_NO_IMAGE_KHR;
562 
563     if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
564     {
565         // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR or
566         // EGL_GL_TEXTURE_3D_KHR and <buffer> is not the name of a texture object of type <target>,
567         // the error EGL_BAD_PARAMETER is generated.
568         GLuint textureCube;
569         glGenTextures(1, &textureCube);
570         glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
571         for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
572              face++)
573         {
574             glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
575         }
576 
577         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
578                                   reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
579         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
580         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
581 
582         // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR,
583         // EGL_GL_TEXTURE_CUBE_MAP_*_KHR or EGL_GL_TEXTURE_3D_KHR, <buffer> is the name of an
584         // incomplete GL texture object, and any mipmap levels other than mipmap level 0 are
585         // specified, the error EGL_BAD_PARAMETER is generated.
586         GLuint incompleteTexture;
587         glGenTextures(1, &incompleteTexture);
588         glBindTexture(GL_TEXTURE_2D, incompleteTexture);
589         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
590         glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
591 
592         EGLint level0Attribute[] = {
593             EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE,
594         };
595         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
596                                   reinterpretHelper<EGLClientBuffer>(incompleteTexture),
597                                   level0Attribute);
598         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
599         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
600 
601         // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_2D_KHR or
602         // EGL_GL_TEXTURE_3D_KHR, <buffer> is not the name of a complete GL texture object, and
603         // mipmap level 0 is not specified, the error EGL_BAD_PARAMETER is generated.
604         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
605         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
606                                   reinterpretHelper<EGLClientBuffer>(incompleteTexture), nullptr);
607         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
608         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
609 
610         // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR,
611         // EGL_GL_RENDERBUFFER_KHR or EGL_GL_TEXTURE_3D_KHR and <buffer> refers to the default GL
612         // texture object(0) for the corresponding GL target, the error EGL_BAD_PARAMETER is
613         // generated.
614         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR, 0, nullptr);
615         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
616         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
617 
618         // If <target> is EGL_GL_TEXTURE_2D_KHR, EGL_GL_TEXTURE_CUBE_MAP_*_KHR, or
619         // EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
620         // EGL_GL_TEXTURE_LEVEL_KHR is not a valid mipmap level for the specified GL texture object
621         // <buffer>, the error EGL_BAD_MATCH is generated.
622         EGLint level2Attribute[] = {
623             EGL_GL_TEXTURE_LEVEL_KHR, 2, EGL_NONE,
624         };
625         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
626                                   reinterpretHelper<EGLClientBuffer>(incompleteTexture),
627                                   level2Attribute);
628         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
629         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
630     }
631     else
632     {
633         GLuint texture2D;
634         glGenTextures(1, &texture2D);
635         glBindTexture(GL_TEXTURE_2D, texture2D);
636         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
637 
638         // From EGL_KHR_image_base:
639         // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
640         // generated.
641         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
642                                   reinterpretHelper<EGLClientBuffer>(texture2D), nullptr);
643         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
644         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
645     }
646 
647     if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
648     {
649         // If EGL_GL_TEXTURE_LEVEL_KHR is 0, <target> is EGL_GL_TEXTURE_CUBE_MAP_*_KHR, <buffer> is
650         // not the name of a complete GL texture object, and one or more faces do not have mipmap
651         // level 0 specified, the error EGL_BAD_PARAMETER is generated.
652         GLuint incompleteTextureCube;
653         glGenTextures(1, &incompleteTextureCube);
654         glBindTexture(GL_TEXTURE_CUBE_MAP, incompleteTextureCube);
655         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
656                      nullptr);
657         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
658                      nullptr);
659         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
660                      nullptr);
661         glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
662                      nullptr);
663         glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE,
664                      nullptr);
665 
666         EGLint level0Attribute[] = {
667             EGL_GL_TEXTURE_LEVEL_KHR, 0, EGL_NONE,
668         };
669         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
670                                   reinterpretHelper<EGLClientBuffer>(incompleteTextureCube),
671                                   level0Attribute);
672         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
673         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
674     }
675     else
676     {
677         GLuint textureCube;
678         glGenTextures(1, &textureCube);
679         glBindTexture(GL_TEXTURE_CUBE_MAP, textureCube);
680         for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
681              face++)
682         {
683             glTexImage2D(face, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
684         }
685 
686         // From EGL_KHR_image_base:
687         // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
688         // generated.
689         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR,
690                                   reinterpretHelper<EGLClientBuffer>(textureCube), nullptr);
691         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
692         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
693     }
694 
695     if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image") &&
696         getClientMajorVersion() >= 3)
697     {
698         // If <target> is EGL_GL_TEXTURE_3D_KHR, and the value specified in <attr_list> for
699         // EGL_GL_TEXTURE_ZOFFSET_KHR exceeds the depth of the specified mipmap level - of - detail
700         // in <buffer>, the error EGL_BAD_PARAMETER is generated.
701         GLuint texture3D;
702         glGenTextures(1, &texture3D);
703         glBindTexture(GL_TEXTURE_3D, texture3D);
704         glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
705 
706         EGLint zOffset3Parameter[] = {
707             EGL_GL_TEXTURE_ZOFFSET_KHR, 3, EGL_NONE,
708         };
709         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
710                                   reinterpretHelper<EGLClientBuffer>(texture3D), zOffset3Parameter);
711         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
712         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
713 
714         EGLint zOffsetNegative1Parameter[] = {
715             EGL_GL_TEXTURE_ZOFFSET_KHR, -1, EGL_NONE,
716         };
717         image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
718                                   reinterpretHelper<EGLClientBuffer>(texture3D),
719                                   zOffsetNegative1Parameter);
720         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
721         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
722     }
723     else
724     {
725         if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
726         {
727             GLuint texture2D;
728             glGenTextures(1, &texture2D);
729             glBindTexture(GL_TEXTURE_2D, texture2D);
730             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
731 
732             // Verify EGL_GL_TEXTURE_ZOFFSET_KHR is not a valid parameter
733             EGLint zOffset0Parameter[] = {
734                 EGL_GL_TEXTURE_ZOFFSET_KHR, 0, EGL_NONE,
735             };
736 
737             image =
738                 eglCreateImageKHR(display, context, EGL_GL_TEXTURE_2D_KHR,
739                                   reinterpretHelper<EGLClientBuffer>(texture2D), zOffset0Parameter);
740             EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
741             EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
742         }
743 
744         if (getClientMajorVersion() >= 3)
745         {
746             GLuint texture3D;
747             glGenTextures(1, &texture3D);
748             glBindTexture(GL_TEXTURE_3D, texture3D);
749             glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
750 
751             // From EGL_KHR_image_base:
752             // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
753             // generated.
754             image = eglCreateImageKHR(display, context, EGL_GL_TEXTURE_3D_KHR,
755                                       reinterpretHelper<EGLClientBuffer>(texture3D), nullptr);
756             EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
757             EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
758         }
759     }
760 
761     if (eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
762     {
763         // If <target> is EGL_GL_RENDERBUFFER_KHR and <buffer> is not the name of a renderbuffer
764         // object, or if <buffer> is the name of a multisampled renderbuffer object, the error
765         // EGL_BAD_PARAMETER is generated.
766         image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
767                                   reinterpret_cast<EGLClientBuffer>(0), nullptr);
768         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
769         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
770 
771         if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
772         {
773             GLuint renderbuffer;
774             glGenRenderbuffers(1, &renderbuffer);
775             glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
776             glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1);
777             EXPECT_GL_NO_ERROR();
778 
779             image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
780                                       reinterpret_cast<EGLClientBuffer>(0), nullptr);
781             EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
782             EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
783         }
784     }
785     else
786     {
787         GLuint renderbuffer;
788         glGenRenderbuffers(1, &renderbuffer);
789         glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
790         glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, 1, 1);
791 
792         // From EGL_KHR_image_base:
793         // If <target> is not one of the values in Table aaa, the error EGL_BAD_PARAMETER is
794         // generated.
795         image = eglCreateImageKHR(display, context, EGL_GL_RENDERBUFFER_KHR,
796                                   reinterpretHelper<EGLClientBuffer>(renderbuffer), nullptr);
797         EXPECT_EQ(image, EGL_NO_IMAGE_KHR);
798         EXPECT_EGL_ERROR(EGL_BAD_PARAMETER);
799     }
800 }
801 
802 // Check validation from the GL_OES_EGL_image extension
TEST_P(ImageTest,ValidationGLEGLImage)803 TEST_P(ImageTest, ValidationGLEGLImage)
804 {
805     EGLWindow *window = getEGLWindow();
806     if (!extensionEnabled("OES_EGL_image") ||
807         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
808         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
809     {
810         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
811                      "EGL_KHR_gl_texture_2D_image is not available."
812                   << std::endl;
813         return;
814     }
815 
816     GLubyte data[4] = {255, 0, 255, 255};
817 
818     // Create the Image
819     GLuint source;
820     EGLImageKHR image;
821     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
822 
823     // If <target> is not TEXTURE_2D, the error INVALID_ENUM is generated.
824     glEGLImageTargetTexture2DOES(GL_TEXTURE_CUBE_MAP_POSITIVE_X, image);
825     EXPECT_GL_ERROR(GL_INVALID_ENUM);
826 
827     // If <image> does not refer to a valid eglImageOES object, the error INVALID_VALUE is
828     // generated.
829     GLuint texture;
830     glGenTextures(1, &texture);
831     glBindTexture(GL_TEXTURE_2D, texture);
832     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, reinterpretHelper<GLeglImageOES>(0xBAADF00D));
833     EXPECT_GL_ERROR(GL_INVALID_VALUE);
834 
835     // <target> must be RENDERBUFFER_OES, and <image> must be the handle of a valid EGLImage
836     // resource, cast into the type
837     // eglImageOES.
838     glEGLImageTargetRenderbufferStorageOES(GL_TEXTURE_2D, image);
839     EXPECT_GL_ERROR(GL_INVALID_ENUM);
840 
841     // If the GL is unable to create a renderbuffer using the specified eglImageOES, the error
842     // INVALID_OPERATION is generated.If <image>
843     // does not refer to a valid eglImageOES object, the error INVALID_VALUE is generated.
844     GLuint renderbuffer;
845     glGenRenderbuffers(1, &renderbuffer);
846     glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
847     glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER,
848                                            reinterpretHelper<GLeglImageOES>(0xBAADF00D));
849     EXPECT_GL_ERROR(GL_INVALID_VALUE);
850 
851     // Clean up
852     glDeleteTextures(1, &source);
853     eglDestroyImageKHR(window->getDisplay(), image);
854     glDeleteTextures(1, &texture);
855     glDeleteRenderbuffers(1, &renderbuffer);
856 }
857 
858 // Check validation from the GL_OES_EGL_image_external extension
TEST_P(ImageTest,ValidationGLEGLImageExternal)859 TEST_P(ImageTest, ValidationGLEGLImageExternal)
860 {
861     if (!extensionEnabled("GL_OES_EGL_image_external"))
862     {
863         std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
864                   << std::endl;
865         return;
866     }
867 
868     GLuint texture;
869     glGenTextures(1, &texture);
870     glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
871 
872     // In the initial state of a TEXTURE_EXTERNAL_OES texture object, the value assigned to
873     // TEXTURE_MIN_FILTER and TEXTURE_MAG_FILTER is LINEAR, and the s and t wrap modes are both set
874     // to CLAMP_TO_EDGE
875     auto getTexParam = [](GLenum target, GLenum pname)
876     {
877         GLint value = 0;
878         glGetTexParameteriv(target, pname, &value);
879         EXPECT_GL_NO_ERROR();
880         return value;
881     };
882     EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER));
883     EXPECT_GLENUM_EQ(GL_LINEAR, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER));
884     EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S));
885     EXPECT_GLENUM_EQ(GL_CLAMP_TO_EDGE, getTexParam(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T));
886 
887     // "When <target> is TEXTURE_EXTERNAL_OES only NEAREST and LINEAR are accepted as
888     // TEXTURE_MIN_FILTER, only CLAMP_TO_EDGE is accepted as TEXTURE_WRAP_S and TEXTURE_WRAP_T, and
889     // only FALSE is accepted as GENERATE_MIPMAP. Attempting to set other values for
890     // TEXTURE_MIN_FILTER, TEXTURE_WRAP_S, TEXTURE_WRAP_T, or GENERATE_MIPMAP will result in an
891     // INVALID_ENUM error.
892     GLenum validMinFilters[]{
893         GL_NEAREST, GL_LINEAR,
894     };
895     for (auto minFilter : validMinFilters)
896     {
897         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
898         EXPECT_GL_NO_ERROR();
899     }
900 
901     GLenum invalidMinFilters[]{
902         GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR,
903         GL_LINEAR_MIPMAP_NEAREST,
904     };
905     for (auto minFilter : invalidMinFilters)
906     {
907         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, minFilter);
908         EXPECT_GL_ERROR(GL_INVALID_ENUM);
909     }
910 
911     GLenum validWrapModes[]{
912         GL_CLAMP_TO_EDGE,
913     };
914     for (auto minFilter : validWrapModes)
915     {
916         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
917         EXPECT_GL_NO_ERROR();
918         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
919         EXPECT_GL_NO_ERROR();
920     }
921 
922     GLenum invalidWrapModes[]{
923         GL_REPEAT, GL_MIRRORED_REPEAT,
924     };
925     for (auto minFilter : invalidWrapModes)
926     {
927         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, minFilter);
928         EXPECT_GL_ERROR(GL_INVALID_ENUM);
929         glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, minFilter);
930         EXPECT_GL_ERROR(GL_INVALID_ENUM);
931     }
932 
933     // When <target> is set to TEXTURE_EXTERNAL_OES, GenerateMipmap always fails and generates an
934     // INVALID_ENUM error.
935     glGenerateMipmap(GL_TEXTURE_EXTERNAL_OES);
936     EXPECT_GL_ERROR(GL_INVALID_ENUM);
937 
938     glDeleteTextures(1, &texture);
939 }
940 
941 // Check validation from the GL_OES_EGL_image_external_essl3 extension
TEST_P(ImageTest,ValidationGLEGLImageExternalESSL3)942 TEST_P(ImageTest, ValidationGLEGLImageExternalESSL3)
943 {
944     if (!extensionEnabled("GL_OES_EGL_image_external_essl3"))
945     {
946         std::cout << "Test skipped because GL_OES_EGL_image_external is not available."
947                   << std::endl;
948         return;
949     }
950 
951     // Make sure this extension is not exposed without ES3.
952     ASSERT_GE(getClientMajorVersion(), 3);
953 
954     GLuint texture;
955     glGenTextures(1, &texture);
956     glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture);
957 
958     // It is an INVALID_OPERATION error to set the TEXTURE_BASE_LEVEL to a value other than zero.
959     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 1);
960     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
961 
962     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 10);
963     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
964 
965     glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_BASE_LEVEL, 0);
966     EXPECT_GL_NO_ERROR();
967 
968     glDeleteTextures(1, &texture);
969 }
970 
TEST_P(ImageTest,Source2DTarget2D)971 TEST_P(ImageTest, Source2DTarget2D)
972 {
973     EGLWindow *window = getEGLWindow();
974     if (!extensionEnabled("OES_EGL_image") ||
975         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
976         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
977     {
978         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
979                      "EGL_KHR_gl_texture_2D_image is not available."
980                   << std::endl;
981         return;
982     }
983 
984     GLubyte data[4] = {255, 0, 255, 255};
985 
986     // Create the Image
987     GLuint source;
988     EGLImageKHR image;
989     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
990 
991     // Create the target
992     GLuint target;
993     createEGLImageTargetTexture2D(image, &target);
994 
995     // Expect that the target texture has the same color as the source texture
996     verifyResults2D(target, data);
997 
998     // Clean up
999     glDeleteTextures(1, &source);
1000     eglDestroyImageKHR(window->getDisplay(), image);
1001     glDeleteTextures(1, &target);
1002 }
1003 
TEST_P(ImageTest,Source2DTargetRenderbuffer)1004 TEST_P(ImageTest, Source2DTargetRenderbuffer)
1005 {
1006     EGLWindow *window = getEGLWindow();
1007     if (!extensionEnabled("OES_EGL_image") ||
1008         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1009         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1010     {
1011         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1012                      "EGL_KHR_gl_texture_2D_image is not available."
1013                   << std::endl;
1014         return;
1015     }
1016 
1017     GLubyte data[4] = {255, 0, 255, 255};
1018 
1019     // Create the Image
1020     GLuint source;
1021     EGLImageKHR image;
1022     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1023 
1024     // Create the target
1025     GLuint target;
1026     createEGLImageTargetRenderbuffer(image, &target);
1027 
1028     // Expect that the target renderbuffer has the same color as the source texture
1029     verifyResultsRenderbuffer(target, data);
1030 
1031     // Clean up
1032     glDeleteTextures(1, &source);
1033     eglDestroyImageKHR(window->getDisplay(), image);
1034     glDeleteRenderbuffers(1, &target);
1035 }
1036 
TEST_P(ImageTest,Source2DTargetExternal)1037 TEST_P(ImageTest, Source2DTargetExternal)
1038 {
1039     EGLWindow *window = getEGLWindow();
1040     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
1041         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1042         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1043     {
1044         std::cout
1045             << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
1046                "EGL_KHR_gl_texture_2D_image is not available."
1047             << std::endl;
1048         return;
1049     }
1050 
1051     GLubyte data[4] = {255, 0, 255, 255};
1052 
1053     // Create the Image
1054     GLuint source;
1055     EGLImageKHR image;
1056     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1057 
1058     // Create the target
1059     GLuint target;
1060     createEGLImageTargetTextureExternal(image, &target);
1061 
1062     // Expect that the target renderbuffer has the same color as the source texture
1063     verifyResultsExternal(target, data);
1064 
1065     // Clean up
1066     glDeleteTextures(1, &source);
1067     eglDestroyImageKHR(window->getDisplay(), image);
1068     glDeleteRenderbuffers(1, &target);
1069 }
1070 
TEST_P(ImageTestES3,Source2DTargetExternalESSL3)1071 TEST_P(ImageTestES3, Source2DTargetExternalESSL3)
1072 {
1073     EGLWindow *window = getEGLWindow();
1074     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
1075         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1076         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1077     {
1078         std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
1079                      "EGL_KHR_image_base or "
1080                      "EGL_KHR_gl_texture_2D_image is not available."
1081                   << std::endl;
1082         return;
1083     }
1084 
1085     GLubyte data[4] = {255, 0, 255, 255};
1086 
1087     // Create the Image
1088     GLuint source;
1089     EGLImageKHR image;
1090     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data, &source, &image);
1091 
1092     // Create the target
1093     GLuint target;
1094     createEGLImageTargetTextureExternal(image, &target);
1095 
1096     // Expect that the target renderbuffer has the same color as the source texture
1097     verifyResultsExternalESSL3(target, data);
1098 
1099     // Clean up
1100     glDeleteTextures(1, &source);
1101     eglDestroyImageKHR(window->getDisplay(), image);
1102     glDeleteRenderbuffers(1, &target);
1103 }
1104 
TEST_P(ImageTest,SourceCubeTarget2D)1105 TEST_P(ImageTest, SourceCubeTarget2D)
1106 {
1107     EGLWindow *window = getEGLWindow();
1108     if (!extensionEnabled("OES_EGL_image") ||
1109         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1110         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
1111     {
1112         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1113                      "EGL_KHR_gl_texture_cubemap_image is not available."
1114                   << std::endl;
1115         return;
1116     }
1117 
1118     GLubyte data[24] = {
1119         255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1120         0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
1121     };
1122 
1123     for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1124     {
1125         // Create the Image
1126         GLuint source;
1127         EGLImageKHR image;
1128         createEGLImageCubemapTextureSource(
1129             1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1130             EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1131 
1132         // Create the target
1133         GLuint target;
1134         createEGLImageTargetTexture2D(image, &target);
1135 
1136         // Expect that the target texture has the same color as the source texture
1137         verifyResults2D(target, &data[faceIdx * 4]);
1138 
1139         // Clean up
1140         glDeleteTextures(1, &source);
1141         eglDestroyImageKHR(window->getDisplay(), image);
1142         glDeleteTextures(1, &target);
1143     }
1144 }
1145 
TEST_P(ImageTest,SourceCubeTargetRenderbuffer)1146 TEST_P(ImageTest, SourceCubeTargetRenderbuffer)
1147 {
1148     EGLWindow *window = getEGLWindow();
1149     if (!extensionEnabled("OES_EGL_image") ||
1150         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1151         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
1152     {
1153         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1154                      "EGL_KHR_gl_texture_cubemap_image is not available."
1155                   << std::endl;
1156         return;
1157     }
1158 
1159     GLubyte data[24] = {
1160         255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1161         0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
1162     };
1163 
1164     for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1165     {
1166         // Create the Image
1167         GLuint source;
1168         EGLImageKHR image;
1169         createEGLImageCubemapTextureSource(
1170             1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1171             EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1172 
1173         // Create the target
1174         GLuint target;
1175         createEGLImageTargetRenderbuffer(image, &target);
1176 
1177         // Expect that the target texture has the same color as the source texture
1178         verifyResultsRenderbuffer(target, &data[faceIdx * 4]);
1179 
1180         // Clean up
1181         glDeleteTextures(1, &source);
1182         eglDestroyImageKHR(window->getDisplay(), image);
1183         glDeleteRenderbuffers(1, &target);
1184     }
1185 }
1186 
1187 // Test cubemap -> external texture EGL images.
TEST_P(ImageTest,SourceCubeTargetExternal)1188 TEST_P(ImageTest, SourceCubeTargetExternal)
1189 {
1190     EGLWindow *window = getEGLWindow();
1191     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
1192         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1193         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
1194     {
1195         std::cout
1196             << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
1197                "EGL_KHR_gl_texture_cubemap_image is not available."
1198             << std::endl;
1199         return;
1200     }
1201 
1202     GLubyte data[24] = {
1203         255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1204         0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
1205     };
1206 
1207     for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1208     {
1209         // Create the Image
1210         GLuint source;
1211         EGLImageKHR image;
1212         createEGLImageCubemapTextureSource(
1213             1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1214             EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1215 
1216         // Create the target
1217         GLuint target;
1218         createEGLImageTargetTextureExternal(image, &target);
1219 
1220         // Expect that the target texture has the same color as the source texture
1221         verifyResultsExternal(target, &data[faceIdx * 4]);
1222 
1223         // Clean up
1224         glDeleteTextures(1, &source);
1225         eglDestroyImageKHR(window->getDisplay(), image);
1226         glDeleteRenderbuffers(1, &target);
1227     }
1228 }
1229 
1230 // Test cubemap -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,SourceCubeTargetExternalESSL3)1231 TEST_P(ImageTestES3, SourceCubeTargetExternalESSL3)
1232 {
1233     EGLWindow *window = getEGLWindow();
1234     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
1235         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1236         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_cubemap_image"))
1237     {
1238         std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
1239                      "EGL_KHR_image_base or "
1240                      "EGL_KHR_gl_texture_cubemap_image is not available."
1241                   << std::endl;
1242         return;
1243     }
1244 
1245     GLubyte data[24] = {
1246         255, 0, 255, 255, 255, 255, 255, 255, 255, 0, 0, 255,
1247         0,   0, 255, 255, 0,   255, 0,   255, 0,   0, 0, 255,
1248     };
1249 
1250     for (EGLenum faceIdx = 0; faceIdx < 6; faceIdx++)
1251     {
1252         // Create the Image
1253         GLuint source;
1254         EGLImageKHR image;
1255         createEGLImageCubemapTextureSource(
1256             1, 1, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<uint8_t *>(data), sizeof(GLubyte) * 4,
1257             EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR + faceIdx, &source, &image);
1258 
1259         // Create the target
1260         GLuint target;
1261         createEGLImageTargetTextureExternal(image, &target);
1262 
1263         // Expect that the target texture has the same color as the source texture
1264         verifyResultsExternalESSL3(target, &data[faceIdx * 4]);
1265 
1266         // Clean up
1267         glDeleteTextures(1, &source);
1268         eglDestroyImageKHR(window->getDisplay(), image);
1269         glDeleteRenderbuffers(1, &target);
1270     }
1271 }
1272 
TEST_P(ImageTest,Source3DTargetTexture)1273 TEST_P(ImageTest, Source3DTargetTexture)
1274 {
1275     EGLWindow *window = getEGLWindow();
1276     if (!extensionEnabled("OES_EGL_image") ||
1277         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1278         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
1279     {
1280         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1281                      "EGL_KHR_gl_texture_3D_image is not available."
1282                   << std::endl;
1283         return;
1284     }
1285 
1286     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
1287     {
1288         std::cout << "Test skipped because 3D textures are not available." << std::endl;
1289         return;
1290     }
1291 
1292     const size_t depth      = 2;
1293     GLubyte data[4 * depth] = {
1294         255, 0, 255, 255, 255, 255, 0, 255,
1295     };
1296 
1297     for (size_t layer = 0; layer < depth; layer++)
1298     {
1299         // Create the Image
1300         GLuint source;
1301         EGLImageKHR image;
1302         createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1303                                       &image);
1304 
1305         // Create the target
1306         GLuint target;
1307         createEGLImageTargetTexture2D(image, &target);
1308 
1309         // Expect that the target renderbuffer has the same color as the source texture
1310         verifyResults2D(target, &data[layer * 4]);
1311 
1312         // Clean up
1313         glDeleteTextures(1, &source);
1314         eglDestroyImageKHR(window->getDisplay(), image);
1315         glDeleteTextures(1, &target);
1316     }
1317 }
1318 
TEST_P(ImageTest,Source3DTargetRenderbuffer)1319 TEST_P(ImageTest, Source3DTargetRenderbuffer)
1320 {
1321     EGLWindow *window = getEGLWindow();
1322     if (!extensionEnabled("OES_EGL_image") ||
1323         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1324         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
1325     {
1326         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1327                      "EGL_KHR_gl_texture_3D_image is not available."
1328                   << std::endl;
1329         return;
1330     }
1331 
1332     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
1333     {
1334         std::cout << "Test skipped because 3D textures are not available." << std::endl;
1335         return;
1336     }
1337 
1338     const size_t depth      = 2;
1339     GLubyte data[4 * depth] = {
1340         255, 0, 255, 255, 255, 255, 0, 255,
1341     };
1342 
1343     for (size_t layer = 0; layer < depth; layer++)
1344     {
1345         // Create the Image
1346         GLuint source;
1347         EGLImageKHR image;
1348         createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1349                                       &image);
1350 
1351         // Create the target
1352         GLuint target;
1353         createEGLImageTargetRenderbuffer(image, &target);
1354 
1355         // Expect that the target renderbuffer has the same color as the source texture
1356         verifyResultsRenderbuffer(target, &data[layer * 4]);
1357 
1358         // Clean up
1359         glDeleteTextures(1, &source);
1360         eglDestroyImageKHR(window->getDisplay(), image);
1361         glDeleteTextures(1, &target);
1362     }
1363 }
1364 
1365 // Test 3D -> external texture EGL images.
TEST_P(ImageTest,Source3DTargetExternal)1366 TEST_P(ImageTest, Source3DTargetExternal)
1367 {
1368     EGLWindow *window = getEGLWindow();
1369     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
1370         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1371         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
1372     {
1373         std::cout
1374             << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
1375                "EGL_KHR_gl_texture_3D_image is not available."
1376             << std::endl;
1377         return;
1378     }
1379 
1380     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
1381     {
1382         std::cout << "Test skipped because 3D textures are not available." << std::endl;
1383         return;
1384     }
1385 
1386     const size_t depth      = 2;
1387     GLubyte data[4 * depth] = {
1388         255, 0, 255, 255, 255, 255, 0, 255,
1389     };
1390 
1391     for (size_t layer = 0; layer < depth; layer++)
1392     {
1393         // Create the Image
1394         GLuint source;
1395         EGLImageKHR image;
1396         createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1397                                       &image);
1398 
1399         // Create the target
1400         GLuint target;
1401         createEGLImageTargetTextureExternal(image, &target);
1402 
1403         // Expect that the target renderbuffer has the same color as the source texture
1404         verifyResultsExternal(target, &data[layer * 4]);
1405 
1406         // Clean up
1407         glDeleteTextures(1, &source);
1408         eglDestroyImageKHR(window->getDisplay(), image);
1409         glDeleteTextures(1, &target);
1410     }
1411 }
1412 
1413 // Test 3D -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,Source3DTargetExternalESSL3)1414 TEST_P(ImageTestES3, Source3DTargetExternalESSL3)
1415 {
1416     EGLWindow *window = getEGLWindow();
1417     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
1418         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1419         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_3D_image"))
1420     {
1421         std::cout << "Test skipped because OES_EGL_image, OES_EGL_image_external_essl3, "
1422                      "EGL_KHR_image_base or "
1423                      "EGL_KHR_gl_texture_3D_image is not available."
1424                   << std::endl;
1425         return;
1426     }
1427 
1428     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_OES_texture_3D"))
1429     {
1430         std::cout << "Test skipped because 3D textures are not available." << std::endl;
1431         return;
1432     }
1433 
1434     const size_t depth      = 2;
1435     GLubyte data[4 * depth] = {
1436         255, 0, 255, 255, 255, 255, 0, 255,
1437     };
1438 
1439     for (size_t layer = 0; layer < depth; layer++)
1440     {
1441         // Create the Image
1442         GLuint source;
1443         EGLImageKHR image;
1444         createEGLImage3DTextureSource(1, 1, depth, GL_RGBA, GL_UNSIGNED_BYTE, data, layer, &source,
1445                                       &image);
1446 
1447         // Create the target
1448         GLuint target;
1449         createEGLImageTargetTextureExternal(image, &target);
1450 
1451         // Expect that the target renderbuffer has the same color as the source texture
1452         verifyResultsExternalESSL3(target, &data[layer * 4]);
1453 
1454         // Clean up
1455         glDeleteTextures(1, &source);
1456         eglDestroyImageKHR(window->getDisplay(), image);
1457         glDeleteTextures(1, &target);
1458     }
1459 }
1460 
TEST_P(ImageTest,SourceRenderbufferTargetTexture)1461 TEST_P(ImageTest, SourceRenderbufferTargetTexture)
1462 {
1463     EGLWindow *window = getEGLWindow();
1464     if (!extensionEnabled("OES_EGL_image") ||
1465         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1466         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
1467     {
1468         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1469                      "EGL_KHR_gl_renderbuffer_image is not available."
1470                   << std::endl;
1471         return;
1472     }
1473 
1474     GLubyte data[4] = {255, 0, 255, 255};
1475 
1476     // Create the Image
1477     GLuint source;
1478     EGLImageKHR image;
1479     createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1480 
1481     // Create the target
1482     GLuint target;
1483     createEGLImageTargetTexture2D(image, &target);
1484 
1485     // Expect that the target texture has the same color as the source texture
1486     verifyResults2D(target, data);
1487 
1488     // Clean up
1489     glDeleteRenderbuffers(1, &source);
1490     eglDestroyImageKHR(window->getDisplay(), image);
1491     glDeleteTextures(1, &target);
1492 }
1493 
1494 // Test renderbuffer -> external texture EGL images.
TEST_P(ImageTest,SourceRenderbufferTargetTextureExternal)1495 TEST_P(ImageTest, SourceRenderbufferTargetTextureExternal)
1496 {
1497     EGLWindow *window = getEGLWindow();
1498     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external") ||
1499         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1500         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
1501     {
1502         std::cout
1503             << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
1504                "EGL_KHR_gl_renderbuffer_image is not available."
1505             << std::endl;
1506         return;
1507     }
1508 
1509     GLubyte data[4] = {255, 0, 255, 255};
1510 
1511     // Create the Image
1512     GLuint source;
1513     EGLImageKHR image;
1514     createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1515 
1516     // Create the target
1517     GLuint target;
1518     createEGLImageTargetTextureExternal(image, &target);
1519 
1520     // Expect that the target texture has the same color as the source texture
1521     verifyResultsExternal(target, data);
1522 
1523     // Clean up
1524     glDeleteRenderbuffers(1, &source);
1525     eglDestroyImageKHR(window->getDisplay(), image);
1526     glDeleteTextures(1, &target);
1527 }
1528 
1529 // Test renderbuffer -> external texture EGL images using ESSL3 shaders.
TEST_P(ImageTestES3,SourceRenderbufferTargetTextureExternalESSL3)1530 TEST_P(ImageTestES3, SourceRenderbufferTargetTextureExternalESSL3)
1531 {
1532     EGLWindow *window = getEGLWindow();
1533     if (!extensionEnabled("OES_EGL_image") || !extensionEnabled("OES_EGL_image_external_essl3") ||
1534         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1535         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
1536     {
1537         std::cout
1538             << "Test skipped because OES_EGL_image, OES_EGL_image_external, EGL_KHR_image_base or "
1539                "EGL_KHR_gl_renderbuffer_image is not available."
1540             << std::endl;
1541         return;
1542     }
1543 
1544     GLubyte data[4] = {255, 0, 255, 255};
1545 
1546     // Create the Image
1547     GLuint source;
1548     EGLImageKHR image;
1549     createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1550 
1551     // Create the target
1552     GLuint target;
1553     createEGLImageTargetTextureExternal(image, &target);
1554 
1555     // Expect that the target texture has the same color as the source texture
1556     verifyResultsExternalESSL3(target, data);
1557 
1558     // Clean up
1559     glDeleteRenderbuffers(1, &source);
1560     eglDestroyImageKHR(window->getDisplay(), image);
1561     glDeleteTextures(1, &target);
1562 }
1563 
TEST_P(ImageTest,SourceRenderbufferTargetRenderbuffer)1564 TEST_P(ImageTest, SourceRenderbufferTargetRenderbuffer)
1565 {
1566     EGLWindow *window = getEGLWindow();
1567     if (!extensionEnabled("OES_EGL_image") ||
1568         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1569         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_renderbuffer_image"))
1570     {
1571         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1572                      "EGL_KHR_gl_renderbuffer_image is not available."
1573                   << std::endl;
1574         return;
1575     }
1576 
1577     GLubyte data[4] = {255, 0, 255, 255};
1578 
1579     // Create the Image
1580     GLuint source;
1581     EGLImageKHR image;
1582     createEGLImageRenderbufferSource(1, 1, GL_RGBA8_OES, data, &source, &image);
1583 
1584     // Create the target
1585     GLuint target;
1586     createEGLImageTargetRenderbuffer(image, &target);
1587 
1588     // Expect that the target renderbuffer has the same color as the source texture
1589     verifyResultsRenderbuffer(target, data);
1590 
1591     // Clean up
1592     glDeleteRenderbuffers(1, &source);
1593     eglDestroyImageKHR(window->getDisplay(), image);
1594     glDeleteRenderbuffers(1, &target);
1595 }
1596 
1597 // Delete the source texture and EGL image.  The image targets should still have the same data
1598 // because
1599 // they hold refs to the image.
TEST_P(ImageTest,Deletion)1600 TEST_P(ImageTest, Deletion)
1601 {
1602     EGLWindow *window = getEGLWindow();
1603     if (!extensionEnabled("OES_EGL_image") ||
1604         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1605         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1606     {
1607         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1608                      "EGL_KHR_gl_texture_2D_image is not available."
1609                   << std::endl;
1610         return;
1611     }
1612 
1613     GLubyte originalData[4] = {255, 0, 255, 255};
1614     GLubyte updateData[4]   = {0, 255, 0, 255};
1615 
1616     // Create the Image
1617     GLuint source;
1618     EGLImageKHR image;
1619     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1620 
1621     // Create multiple targets
1622     GLuint targetTexture;
1623     createEGLImageTargetTexture2D(image, &targetTexture);
1624 
1625     GLuint targetRenderbuffer;
1626     createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
1627 
1628     // Delete the source texture
1629     glDeleteTextures(1, &source);
1630     source = 0;
1631 
1632     // Expect that both the targets have the original data
1633     verifyResults2D(targetTexture, originalData);
1634     verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1635 
1636     // Update the data of the target
1637     glBindTexture(GL_TEXTURE_2D, targetTexture);
1638     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1639 
1640     // Expect that both targets have the updated data
1641     verifyResults2D(targetTexture, updateData);
1642     verifyResultsRenderbuffer(targetRenderbuffer, updateData);
1643 
1644     // Delete the EGL image
1645     eglDestroyImageKHR(window->getDisplay(), image);
1646     image = EGL_NO_IMAGE_KHR;
1647 
1648     // Update the data of the target back to the original data
1649     glBindTexture(GL_TEXTURE_2D, targetTexture);
1650     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1651 
1652     // Expect that both targets have the original data again
1653     verifyResults2D(targetTexture, originalData);
1654     verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1655 
1656     // Clean up
1657     glDeleteTextures(1, &targetTexture);
1658     glDeleteRenderbuffers(1, &targetRenderbuffer);
1659 }
1660 
TEST_P(ImageTest,MipLevels)1661 TEST_P(ImageTest, MipLevels)
1662 {
1663     EGLWindow *window = getEGLWindow();
1664     if (!extensionEnabled("OES_EGL_image") ||
1665         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1666         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1667     {
1668         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1669                      "EGL_KHR_gl_texture_2D_image is not available."
1670                   << std::endl;
1671         return;
1672     }
1673 
1674     const size_t mipLevels   = 3;
1675     const size_t textureSize = 4;
1676     std::vector<GLuint> mip0Data(textureSize * textureSize, 0xFFFF0000);
1677     std::vector<GLuint> mip1Data(mip0Data.size() << 1, 0xFF00FF00);
1678     std::vector<GLuint> mip2Data(mip0Data.size() << 2, 0xFF0000FF);
1679     GLubyte *data[mipLevels] = {
1680         reinterpret_cast<GLubyte *>(&mip0Data[0]), reinterpret_cast<GLubyte *>(&mip1Data[0]),
1681         reinterpret_cast<GLubyte *>(&mip2Data[0]),
1682     };
1683 
1684     GLuint source;
1685     glGenTextures(1, &source);
1686     glBindTexture(GL_TEXTURE_2D, source);
1687 
1688     for (size_t level = 0; level < mipLevels; level++)
1689     {
1690         glTexImage2D(GL_TEXTURE_2D, static_cast<GLint>(level), GL_RGBA, textureSize >> level,
1691                      textureSize >> level, 0, GL_RGBA, GL_UNSIGNED_BYTE, data[level]);
1692     }
1693 
1694     ASSERT_GL_NO_ERROR();
1695 
1696     for (size_t level = 0; level < mipLevels; level++)
1697     {
1698         // Create the Image
1699         EGLint attribs[] = {
1700             EGL_GL_TEXTURE_LEVEL_KHR, static_cast<EGLint>(level), EGL_NONE,
1701         };
1702         EGLImageKHR image =
1703             eglCreateImageKHR(window->getDisplay(), window->getContext(), EGL_GL_TEXTURE_2D_KHR,
1704                               reinterpretHelper<EGLClientBuffer>(source), attribs);
1705         ASSERT_EGL_SUCCESS();
1706 
1707         // Create a texture and renderbuffer target
1708         GLuint textureTarget;
1709         createEGLImageTargetTexture2D(image, &textureTarget);
1710 
1711         // Disable mipmapping
1712         glBindTexture(GL_TEXTURE_2D, textureTarget);
1713         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1714         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1715 
1716         GLuint renderbufferTarget;
1717         createEGLImageTargetRenderbuffer(image, &renderbufferTarget);
1718 
1719         // Expect that the targets have the same color as the source texture
1720         verifyResults2D(textureTarget, data[level]);
1721         verifyResultsRenderbuffer(renderbufferTarget, data[level]);
1722 
1723         // Clean up
1724         eglDestroyImageKHR(window->getDisplay(), image);
1725         glDeleteTextures(1, &textureTarget);
1726         glDeleteRenderbuffers(1, &renderbufferTarget);
1727     }
1728 
1729     // Clean up
1730     glDeleteTextures(1, &source);
1731 }
1732 
1733 // Respecify the source texture, orphaning it.  The target texture should not have updated data.
TEST_P(ImageTest,Respecification)1734 TEST_P(ImageTest, Respecification)
1735 {
1736     EGLWindow *window = getEGLWindow();
1737     if (!extensionEnabled("OES_EGL_image") ||
1738         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1739         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1740     {
1741         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1742                      "EGL_KHR_gl_texture_2D_image is not available."
1743                   << std::endl;
1744         return;
1745     }
1746 
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 
1775 // First render to a target texture, then respecify the source texture, orphaning it.
1776 // The target texture's FBO should be notified of the target texture's orphaning.
TEST_P(ImageTest,RespecificationWithFBO)1777 TEST_P(ImageTest, RespecificationWithFBO)
1778 {
1779     EGLWindow *window = getEGLWindow();
1780     if (!extensionEnabled("OES_EGL_image") ||
1781         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1782         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1783     {
1784         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1785                      "EGL_KHR_gl_texture_2D_image is not available."
1786                   << std::endl;
1787         return;
1788     }
1789 
1790     // Simple shader
1791     const std::string &vertexSource =
1792         "attribute vec2 position;\n"
1793         "void main()\n"
1794         "{\n"
1795         "    gl_Position = vec4(position, 0, 1);\n"
1796         "}";
1797     const std::string &fragmentSource =
1798         "void main()\n"
1799         "{\n"
1800         "    gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
1801         "}";
1802     GLuint program = CompileProgram(vertexSource, fragmentSource);
1803     ASSERT_NE(0u, program);
1804 
1805     GLubyte originalData[4] = {255, 0, 255, 255};
1806     GLubyte updateData[4]   = {0, 255, 0, 255};
1807 
1808     // Create the Image
1809     GLuint source;
1810     EGLImageKHR image;
1811     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1812 
1813     // Create the target
1814     GLuint target;
1815     createEGLImageTargetTexture2D(image, &target);
1816 
1817     // Render to the target texture
1818     GLuint fbo;
1819     glGenFramebuffers(1, &fbo);
1820     glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1821     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, target, 0);
1822     drawQuad(program, "position", 0.5f);
1823     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
1824 
1825     // Respecify source with same parameters. This should not change the texture storage in D3D11.
1826     glBindTexture(GL_TEXTURE_2D, source);
1827     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1828 
1829     // Expect that the source texture has the updated data
1830     verifyResults2D(source, updateData);
1831 
1832     // Render to the target texture again and verify it gets the rendered pixels.
1833     drawQuad(program, "position", 0.5f);
1834     EXPECT_PIXEL_EQ(0, 0, 0, 0, 255, 255);
1835 
1836     // Clean up
1837     glDeleteTextures(1, &source);
1838     eglDestroyImageKHR(window->getDisplay(), image);
1839     glDeleteTextures(1, &target);
1840     glDeleteProgram(program);
1841     glDeleteFramebuffers(1, &fbo);
1842 }
1843 
1844 // Test that respecifying a level of the target texture orphans it and keeps a copy of the EGLimage
1845 // data
TEST_P(ImageTest,RespecificationOfOtherLevel)1846 TEST_P(ImageTest, RespecificationOfOtherLevel)
1847 {
1848     EGLWindow *window = getEGLWindow();
1849     if (!extensionEnabled("OES_EGL_image") ||
1850         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1851         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1852     {
1853         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1854                      "EGL_KHR_gl_texture_2D_image is not available."
1855                   << std::endl;
1856         return;
1857     }
1858 
1859     GLubyte originalData[2 * 2 * 4] = {
1860         255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255, 255, 0, 255, 255,
1861     };
1862 
1863     GLubyte updateData[2 * 2 * 4] = {
1864         0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255, 0, 255,
1865     };
1866 
1867     // Create the Image
1868     GLuint source;
1869     EGLImageKHR image;
1870     createEGLImage2DTextureSource(2, 2, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1871 
1872     // Create the target
1873     GLuint target;
1874     createEGLImageTargetTexture2D(image, &target);
1875 
1876     // Expect that the target and source textures have the original data
1877     verifyResults2D(source, originalData);
1878     verifyResults2D(target, originalData);
1879 
1880     // Add a new mipLevel to the target, orphaning it
1881     glBindTexture(GL_TEXTURE_2D, target);
1882     glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1883     EXPECT_GL_NO_ERROR();
1884 
1885     // Expect that the target and source textures still have the original data
1886     verifyResults2D(source, originalData);
1887     verifyResults2D(target, originalData);
1888 
1889     // Update the source's data
1890     glBindTexture(GL_TEXTURE_2D, source);
1891     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 2, 2, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1892 
1893     // Expect that the target still has the original data and source has the updated data
1894     verifyResults2D(source, updateData);
1895     verifyResults2D(target, originalData);
1896 
1897     // Clean up
1898     glDeleteTextures(1, &source);
1899     eglDestroyImageKHR(window->getDisplay(), image);
1900     glDeleteTextures(1, &target);
1901 }
1902 
1903 // Update the data of the source and target textures.  All image siblings should have the new data.
TEST_P(ImageTest,UpdatedData)1904 TEST_P(ImageTest, UpdatedData)
1905 {
1906     EGLWindow *window = getEGLWindow();
1907     if (!extensionEnabled("OES_EGL_image") ||
1908         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_image_base") ||
1909         !eglDisplayExtensionEnabled(window->getDisplay(), "EGL_KHR_gl_texture_2D_image"))
1910     {
1911         std::cout << "Test skipped because OES_EGL_image, EGL_KHR_image_base or "
1912                      "EGL_KHR_gl_texture_2D_image is not available."
1913                   << std::endl;
1914         return;
1915     }
1916 
1917     GLubyte originalData[4] = {255, 0, 255, 255};
1918     GLubyte updateData[4]   = {0, 255, 0, 255};
1919 
1920     // Create the Image
1921     GLuint source;
1922     EGLImageKHR image;
1923     createEGLImage2DTextureSource(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData, &source, &image);
1924 
1925     // Create multiple targets
1926     GLuint targetTexture;
1927     createEGLImageTargetTexture2D(image, &targetTexture);
1928 
1929     GLuint targetRenderbuffer;
1930     createEGLImageTargetRenderbuffer(image, &targetRenderbuffer);
1931 
1932     // Expect that both the source and targets have the original data
1933     verifyResults2D(source, originalData);
1934     verifyResults2D(targetTexture, originalData);
1935     verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1936 
1937     // Update the data of the source
1938     glBindTexture(GL_TEXTURE_2D, source);
1939     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, updateData);
1940 
1941     // Expect that both the source and targets have the updated data
1942     verifyResults2D(source, updateData);
1943     verifyResults2D(targetTexture, updateData);
1944     verifyResultsRenderbuffer(targetRenderbuffer, updateData);
1945 
1946     // Update the data of the target back to the original data
1947     glBindTexture(GL_TEXTURE_2D, targetTexture);
1948     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, originalData);
1949 
1950     // Expect that both the source and targets have the original data again
1951     verifyResults2D(source, originalData);
1952     verifyResults2D(targetTexture, originalData);
1953     verifyResultsRenderbuffer(targetRenderbuffer, originalData);
1954 
1955     // Clean up
1956     glDeleteTextures(1, &source);
1957     eglDestroyImageKHR(window->getDisplay(), image);
1958     glDeleteTextures(1, &targetTexture);
1959     glDeleteRenderbuffers(1, &targetRenderbuffer);
1960 }
1961 
1962 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1963 // tests should be run against.
1964 ANGLE_INSTANTIATE_TEST(ImageTest,
1965                        ES2_D3D9(),
1966                        ES2_D3D11(),
1967                        ES3_D3D11(),
1968                        ES2_OPENGL(),
1969                        ES3_OPENGL(),
1970                        ES2_OPENGLES(),
1971                        ES3_OPENGLES());
1972 ANGLE_INSTANTIATE_TEST(ImageTestES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
1973 }
1974