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