1 //
2 // Copyright 2019 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 // GetImageTest:
7 // Tests for the ANGLE_get_image extension.
8 //
9
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12
13 using namespace angle;
14
15 namespace
16 {
17 constexpr uint32_t kSize = 32;
18 constexpr char kExtensionName[] = "GL_ANGLE_get_image";
19 constexpr uint32_t kSmallSize = 2;
20 constexpr uint8_t kUNormZero = 0x00;
21 constexpr uint8_t kUNormHalf = 0x7F;
22 constexpr uint8_t kUNormFull = 0xFF;
23
24 class GetImageTest : public ANGLETest
25 {
26 public:
GetImageTest()27 GetImageTest()
28 {
29 setWindowWidth(kSize);
30 setWindowHeight(kSize);
31 setConfigRedBits(8);
32 setConfigGreenBits(8);
33 setConfigBlueBits(8);
34 setConfigAlphaBits(8);
35 }
36 };
37
38 class GetImageTestNoExtensions : public ANGLETest
39 {
40 public:
GetImageTestNoExtensions()41 GetImageTestNoExtensions() { setExtensionsEnabled(false); }
42 };
43
44 class GetImageTestES3 : public GetImageTest
45 {
46 public:
GetImageTestES3()47 GetImageTestES3() {}
48 };
49
50 class GetImageTestES31 : public GetImageTest
51 {
52 public:
GetImageTestES31()53 GetImageTestES31() {}
54 };
55
56 class GetImageTestES32 : public GetImageTest
57 {
58 public:
GetImageTestES32()59 GetImageTestES32() {}
60 };
61
InitTextureWithFormatAndSize(GLenum format,uint32_t size,void * pixelData)62 GLTexture InitTextureWithFormatAndSize(GLenum format, uint32_t size, void *pixelData)
63 {
64 GLTexture tex;
65 glBindTexture(GL_TEXTURE_2D, tex);
66 glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, pixelData);
67 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
68 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
69 return tex;
70 }
71
InitTextureWithSize(uint32_t size,void * pixelData)72 GLTexture InitTextureWithSize(uint32_t size, void *pixelData)
73 {
74 // Create a simple texture.
75 GLTexture tex;
76 glBindTexture(GL_TEXTURE_2D, tex);
77 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
78 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
79 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
80 return tex;
81 }
82
InitSimpleTexture()83 GLTexture InitSimpleTexture()
84 {
85 std::vector<GLColor> pixelData(kSize * kSize, GLColor::red);
86 return InitTextureWithSize(kSize, pixelData.data());
87 }
88
InitRenderbufferWithSize(uint32_t size)89 GLRenderbuffer InitRenderbufferWithSize(uint32_t size)
90 {
91 // Create a simple renderbuffer.
92 GLRenderbuffer renderbuf;
93 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
94 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, size, size);
95 return renderbuf;
96 }
97
InitSimpleRenderbuffer()98 GLRenderbuffer InitSimpleRenderbuffer()
99 {
100 return InitRenderbufferWithSize(kSize);
101 }
102
103 // Test validation for the extension functions.
TEST_P(GetImageTest,NegativeAPI)104 TEST_P(GetImageTest, NegativeAPI)
105 {
106 // Verify the extension is enabled.
107 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
108
109 // Draw once with simple texture.
110 GLTexture tex = InitSimpleTexture();
111 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
112 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
113 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
114 ASSERT_GL_NO_ERROR();
115
116 // Pack pixels tightly.
117 glPixelStorei(GL_PACK_ALIGNMENT, 1);
118
119 // Verify GetTexImage can work with correct parameters.
120 std::vector<GLColor> buffer(kSize * kSize);
121 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
122 EXPECT_GL_NO_ERROR();
123
124 // Test invalid texture target.
125 glGetTexImageANGLE(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
126 EXPECT_GL_ERROR(GL_INVALID_ENUM);
127
128 // Test invalid texture level.
129 glGetTexImageANGLE(GL_TEXTURE_2D, -1, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
130 EXPECT_GL_ERROR(GL_INVALID_VALUE);
131 glGetTexImageANGLE(GL_TEXTURE_2D, 2000, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
132 EXPECT_GL_ERROR(GL_INVALID_VALUE);
133
134 // Test invalid format and type.
135 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
136 EXPECT_GL_ERROR(GL_INVALID_ENUM);
137 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_NONE, buffer.data());
138 EXPECT_GL_ERROR(GL_INVALID_ENUM);
139
140 // Tests GetCompressed on an uncompressed texture.
141 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, buffer.data());
142 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
143
144 // Create a simple renderbuffer.
145 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
146 ASSERT_GL_NO_ERROR();
147
148 // Verify GetRenderbufferImage can work with correct parameters.
149 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
150 EXPECT_GL_NO_ERROR();
151
152 // Test invalid renderbuffer target.
153 glGetRenderbufferImageANGLE(GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
154 EXPECT_GL_ERROR(GL_INVALID_ENUM);
155
156 // Test invalid renderbuffer format/type.
157 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
158 EXPECT_GL_ERROR(GL_INVALID_ENUM);
159 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_NONE, buffer.data());
160 EXPECT_GL_ERROR(GL_INVALID_ENUM);
161
162 // Pack buffer tests. Requires ES 3+ or extension.
163 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_NV_pixel_buffer_object"))
164 {
165 // Test valid pack buffer.
166 GLBuffer packBuffer;
167 glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
168 glBufferData(GL_PIXEL_PACK_BUFFER, kSize * kSize * sizeof(GLColor), nullptr,
169 GL_STATIC_DRAW);
170 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
171 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
172 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
173 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
174
175 // Test too small pack buffer.
176 glBufferData(GL_PIXEL_PACK_BUFFER, kSize, nullptr, GL_STATIC_DRAW);
177 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
178 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
179 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
180 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
181 }
182 }
183
184 // Simple test for GetTexImage
TEST_P(GetImageTest,GetTexImage)185 TEST_P(GetImageTest, GetTexImage)
186 {
187 // Verify the extension is enabled.
188 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
189
190 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
191 GLColor::yellow};
192
193 glViewport(0, 0, kSmallSize, kSmallSize);
194
195 // Draw once with simple texture.
196 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
197 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
198 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
199 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
200 ASSERT_GL_NO_ERROR();
201
202 // Pack pixels tightly.
203 glPixelStorei(GL_PACK_ALIGNMENT, 1);
204
205 // Verify GetImage.
206 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
207 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
208 EXPECT_GL_NO_ERROR();
209 EXPECT_EQ(expectedData, actualData);
210 }
211
212 // Simple cube map test for GetTexImage
TEST_P(GetImageTest,CubeMap)213 TEST_P(GetImageTest, CubeMap)
214 {
215 // Verify the extension is enabled.
216 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
217
218 const std::array<std::array<GLColor, kSmallSize * kSmallSize>, kCubeFaces.size()> expectedData =
219 {{
220 {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
221 {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
222 {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
223 {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
224 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
225 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
226 }};
227
228 GLTexture texture;
229 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
230
231 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
232 {
233 glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA,
234 GL_UNSIGNED_BYTE, expectedData[faceIndex].data());
235 }
236 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
237 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
238
239 // Pack pixels tightly.
240 glPixelStorei(GL_PACK_ALIGNMENT, 1);
241
242 // Verify GetImage.
243 std::array<GLColor, kSmallSize *kSmallSize> actualData = {};
244 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
245 {
246 glGetTexImageANGLE(kCubeFaces[faceIndex], 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
247 EXPECT_GL_NO_ERROR();
248 EXPECT_EQ(expectedData[faceIndex], actualData);
249 }
250 }
251
252 // Simple test for GetRenderbufferImage
TEST_P(GetImageTest,GetRenderbufferImage)253 TEST_P(GetImageTest, GetRenderbufferImage)
254 {
255 // Verify the extension is enabled.
256 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
257
258 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
259 GLColor::yellow};
260
261 glViewport(0, 0, kSmallSize, kSmallSize);
262
263 // Set up a simple Framebuffer with a Renderbuffer.
264 GLRenderbuffer renderbuffer = InitRenderbufferWithSize(kSmallSize);
265 GLFramebuffer framebuffer;
266 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
267 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
268 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
269
270 // Draw once with simple texture.
271 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
272 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
273 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
274 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
275 ASSERT_GL_NO_ERROR();
276
277 // Pack pixels tightly.
278 glPixelStorei(GL_PACK_ALIGNMENT, 1);
279
280 // Verify GetImage.
281 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
282 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
283 EXPECT_GL_NO_ERROR();
284 EXPECT_EQ(expectedData, actualData);
285 }
286
287 // Verifies that the extension enums and entry points are invalid when the extension is disabled.
TEST_P(GetImageTestNoExtensions,EntryPointsInactive)288 TEST_P(GetImageTestNoExtensions, EntryPointsInactive)
289 {
290 // Verify the extension is not enabled.
291 ASSERT_FALSE(IsGLExtensionEnabled(kExtensionName));
292
293 // Draw once with simple texture.
294 GLTexture tex = InitSimpleTexture();
295 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
296 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
297 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
298 ASSERT_GL_NO_ERROR();
299
300 // Query implementation format and type. Should give invalid enum.
301 GLint param;
302 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
303 EXPECT_GL_ERROR(GL_INVALID_ENUM);
304
305 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
306 EXPECT_GL_ERROR(GL_INVALID_ENUM);
307
308 // Verify calling GetTexImage produces an error.
309 std::vector<GLColor> buffer(kSize * kSize, 0);
310 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
311 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
312
313 // Create a simple renderbuffer.
314 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
315 ASSERT_GL_NO_ERROR();
316
317 // Query implementation format and type. Should give invalid enum.
318 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
319 EXPECT_GL_ERROR(GL_INVALID_ENUM);
320
321 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
322 EXPECT_GL_ERROR(GL_INVALID_ENUM);
323
324 // Verify calling GetRenderbufferImage produces an error.
325 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
326 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
327 }
328
329 // Test LUMINANCE_ALPHA (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageLuminanceAlpha)330 TEST_P(GetImageTest, GetTexImageLuminanceAlpha)
331 {
332 // Verify the extension is enabled.
333 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
334
335 constexpr GLColorRG kMediumLumAlpha = GLColorRG(kUNormHalf, kUNormHalf);
336 std::vector<GLColorRG> expectedData = {kMediumLumAlpha, kMediumLumAlpha, kMediumLumAlpha,
337 kMediumLumAlpha};
338
339 glViewport(0, 0, kSmallSize, kSmallSize);
340
341 // Set up a simple LUMINANCE_ALPHA texture
342 GLTexture tex =
343 InitTextureWithFormatAndSize(GL_LUMINANCE_ALPHA, kSmallSize, expectedData.data());
344
345 // Draw once with simple texture.
346 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
347 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
348 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormHalf, kUNormHalf, kUNormHalf, kUNormHalf));
349 ASSERT_GL_NO_ERROR();
350
351 // Pack pixels tightly.
352 glPixelStorei(GL_PACK_ALIGNMENT, 1);
353
354 // Verify GetImage.
355 std::vector<GLColorRG> actualData(kSmallSize * kSmallSize);
356 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, actualData.data());
357 EXPECT_GL_NO_ERROR();
358 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
359 {
360 EXPECT_EQ(expectedData[i].R, actualData[i].R);
361 EXPECT_EQ(expectedData[i].G, actualData[i].G);
362 }
363 }
364
365 // Test LUMINANCE (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageLuminance)366 TEST_P(GetImageTest, GetTexImageLuminance)
367 {
368 // Verify the extension is enabled.
369 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
370
371 constexpr GLColorR kMediumLuminance = GLColorR(kUNormHalf);
372 std::vector<GLColorR> expectedData = {kMediumLuminance, kMediumLuminance, kMediumLuminance,
373 kMediumLuminance};
374
375 glViewport(0, 0, kSmallSize, kSmallSize);
376
377 // Set up a simple LUMINANCE texture
378 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
379 GLTexture tex = InitTextureWithFormatAndSize(GL_LUMINANCE, kSmallSize, expectedData.data());
380
381 // Draw once with simple texture.
382 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
383 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
384 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormHalf, kUNormHalf, kUNormHalf, kUNormFull));
385 ASSERT_GL_NO_ERROR();
386
387 // Pack pixels tightly.
388 glPixelStorei(GL_PACK_ALIGNMENT, 1);
389
390 // Verify GetImage.
391 std::vector<GLColorR> actualData(kSmallSize * kSmallSize);
392 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, actualData.data());
393 EXPECT_GL_NO_ERROR();
394 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
395 {
396 EXPECT_EQ(expectedData[i].R, actualData[i].R);
397 }
398 }
399
400 // Test ALPHA (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageAlpha)401 TEST_P(GetImageTest, GetTexImageAlpha)
402 {
403 // Verify the extension is enabled.
404 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
405
406 constexpr GLColorR kMediumAlpha = GLColorR(kUNormHalf);
407 std::vector<GLColorR> expectedData = {kMediumAlpha, kMediumAlpha, kMediumAlpha, kMediumAlpha};
408
409 glViewport(0, 0, kSmallSize, kSmallSize);
410
411 // Set up a simple ALPHA texture
412 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
413 GLTexture tex = InitTextureWithFormatAndSize(GL_ALPHA, kSmallSize, expectedData.data());
414
415 // Draw once with simple texture
416 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
417 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
418 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormZero, kUNormZero, kUNormZero, kUNormHalf));
419 ASSERT_GL_NO_ERROR();
420
421 // Pack pixels tightly.
422 glPixelStorei(GL_PACK_ALIGNMENT, 1);
423
424 // Verify we get back the correct pixels from GetTexImage
425 std::vector<GLColorR> actualData(kSmallSize * kSmallSize);
426 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, actualData.data());
427 EXPECT_GL_NO_ERROR();
428 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
429 {
430 EXPECT_EQ(expectedData[i].R, actualData[i].R);
431 }
432 }
433
434 // Tests GetImage behaviour with an RGB image.
TEST_P(GetImageTest,GetImageRGB)435 TEST_P(GetImageTest, GetImageRGB)
436 {
437 // Verify the extension is enabled.
438 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
439
440 std::vector<GLColorRGB> expectedData = {GLColorRGB::red, GLColorRGB::blue, GLColorRGB::green,
441 GLColorRGB::yellow};
442
443 glViewport(0, 0, kSmallSize, kSmallSize);
444
445 // Pack pixels tightly.
446 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
447 glPixelStorei(GL_PACK_ALIGNMENT, 1);
448
449 // Init simple texture.
450 GLTexture tex;
451 glBindTexture(GL_TEXTURE_2D, tex);
452 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSmallSize, kSmallSize, 0, GL_RGB, GL_UNSIGNED_BYTE,
453 expectedData.data());
454 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, kSmallSize / 2, kSmallSize / 2, 0, GL_RGB,
455 GL_UNSIGNED_BYTE, expectedData.data());
456 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
457 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
458
459 // Verify GetImage.
460 std::vector<GLColorRGB> actualData(kSmallSize * kSmallSize);
461 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, actualData.data());
462 EXPECT_GL_NO_ERROR();
463 EXPECT_EQ(expectedData, actualData);
464
465 // Draw after the GetImage.
466 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
467 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
468
469 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
470 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
471 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
472 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
473 }
474
475 // Tests GetImage with 2D array textures.
TEST_P(GetImageTestES31,Texture2DArray)476 TEST_P(GetImageTestES31, Texture2DArray)
477 {
478 // Verify the extension is enabled.
479 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
480
481 constexpr GLsizei kTextureSize = 2;
482 constexpr GLsizei kLayers = 4;
483
484 std::vector<GLColor> expectedPixels = {
485 GLColor::red, GLColor::red, GLColor::red, GLColor::red,
486 GLColor::green, GLColor::green, GLColor::green, GLColor::green,
487 GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue,
488 GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow,
489 };
490
491 GLTexture tex;
492 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
493 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, kTextureSize, kTextureSize, kLayers, 0, GL_RGBA,
494 GL_UNSIGNED_BYTE, expectedPixels.data());
495 ASSERT_GL_NO_ERROR();
496
497 std::vector<GLColor> actualPixels(expectedPixels.size(), GLColor::white);
498 glGetTexImageANGLE(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
499 ASSERT_GL_NO_ERROR();
500 EXPECT_EQ(expectedPixels, actualPixels);
501 }
502
503 // Tests GetImage with 3D textures.
TEST_P(GetImageTestES31,Texture3D)504 TEST_P(GetImageTestES31, Texture3D)
505 {
506 // Verify the extension is enabled.
507 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
508
509 constexpr GLsizei kTextureSize = 2;
510
511 std::vector<GLColor> expectedPixels = {
512 GLColor::red, GLColor::red, GLColor::green, GLColor::green,
513 GLColor::blue, GLColor::blue, GLColor::yellow, GLColor::yellow,
514 };
515
516 GLTexture tex;
517 glBindTexture(GL_TEXTURE_3D, tex);
518 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kTextureSize, kTextureSize, kTextureSize, 0, GL_RGBA,
519 GL_UNSIGNED_BYTE, expectedPixels.data());
520 ASSERT_GL_NO_ERROR();
521
522 std::vector<GLColor> actualPixels(expectedPixels.size(), GLColor::white);
523 glGetTexImageANGLE(GL_TEXTURE_3D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
524 ASSERT_GL_NO_ERROR();
525 EXPECT_EQ(expectedPixels, actualPixels);
526 }
527
528 // Tests GetImage with cube map array textures.
TEST_P(GetImageTestES31,TextureCubeMapArray)529 TEST_P(GetImageTestES31, TextureCubeMapArray)
530 {
531 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_cube_map_array") &&
532 !IsGLExtensionEnabled("GL_OES_texture_cube_map_array"));
533
534 // Verify the extension is enabled.
535 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
536
537 constexpr GLsizei kTextureSize = 1;
538 constexpr GLsizei kLayers = 2;
539
540 std::vector<GLColor> expectedPixels = {
541 GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow,
542 GLColor::cyan, GLColor::magenta, GLColor::red, GLColor::green,
543 GLColor::blue, GLColor::yellow, GLColor::cyan, GLColor::magenta,
544 };
545
546 ASSERT_EQ(expectedPixels.size(),
547 static_cast<size_t>(6 * kTextureSize * kTextureSize * kLayers));
548
549 GLTexture tex;
550 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
551 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, kTextureSize, kTextureSize, kLayers * 6, 0,
552 GL_RGBA, GL_UNSIGNED_BYTE, expectedPixels.data());
553 ASSERT_GL_NO_ERROR();
554
555 std::vector<GLColor> actualPixels(expectedPixels.size(), GLColor::white);
556 glGetTexImageANGLE(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE,
557 actualPixels.data());
558 ASSERT_GL_NO_ERROR();
559 EXPECT_EQ(expectedPixels, actualPixels);
560 }
561
562 // Tests GetImage with an inconsistent 2D texture.
TEST_P(GetImageTest,InconsistentTexture2D)563 TEST_P(GetImageTest, InconsistentTexture2D)
564 {
565 // Verify the extension is enabled.
566 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
567
568 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
569 GLColor::yellow};
570
571 glViewport(0, 0, kSmallSize, kSmallSize);
572
573 // Draw once with simple texture.
574 GLTexture tex;
575 glBindTexture(GL_TEXTURE_2D, tex);
576 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
577 expectedData.data());
578 // The texture becomes inconsistent because a second 2x2 image does not fit in the mip chain.
579 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
580 expectedData.data());
581
582 // Pack pixels tightly.
583 glPixelStorei(GL_PACK_ALIGNMENT, 1);
584
585 // Verify GetImage.
586 std::vector<GLColor> actualData(kSmallSize * kSmallSize, GLColor::white);
587 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
588 EXPECT_GL_NO_ERROR();
589 EXPECT_EQ(expectedData, actualData);
590
591 std::fill(actualData.begin(), actualData.end(), GLColor::white);
592 glGetTexImageANGLE(GL_TEXTURE_2D, 1, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
593 EXPECT_GL_NO_ERROR();
594 EXPECT_EQ(expectedData, actualData);
595 }
596
597 // Test GetImage with non-defined textures.
TEST_P(GetImageTest,EmptyTexture)598 TEST_P(GetImageTest, EmptyTexture)
599 {
600 // Verify the extension is enabled.
601 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
602
603 GLTexture tex;
604 glBindTexture(GL_TEXTURE_2D, tex);
605
606 std::vector<GLColor> expectedData(4, GLColor::white);
607 std::vector<GLColor> actualData(4, GLColor::white);
608 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
609 EXPECT_GL_NO_ERROR();
610 EXPECT_EQ(expectedData, actualData);
611 }
612
613 struct CompressedFormat
614 {
615 const GLenum id;
616
617 // Texel/Block size in bytes
618 const GLsizei size;
619
620 // Texel/Block dimensions
621 const GLsizei w;
622 const GLsizei h;
623 };
624
625 struct CompressionExtension
626 {
627 const char *name;
628 const std::vector<CompressedFormat> formats;
629 const bool supports2DArray;
630 const bool supports3D;
631 };
632
633 // clang-format off
634 const CompressionExtension kCompressionExtensions[] = {
635 // BC / DXT
636 {"GL_EXT_texture_compression_dxt1", {{GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 8, 4, 4},
637 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 8, 4, 4}},
638 true, false},
639 {"GL_ANGLE_texture_compression_dxt3", {{GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16, 4, 4}},
640 true, false},
641 {"GL_ANGLE_texture_compression_dxt5", {{GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 16, 4, 4}},
642 true, false},
643 {"GL_EXT_texture_compression_s3tc_srgb", {{GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 8, 4, 4},
644 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 8, 4, 4},
645 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 16, 4, 4},
646 {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 16, 4, 4}},
647 true, false},
648 {"GL_EXT_texture_compression_rgtc", {{GL_COMPRESSED_RED_RGTC1_EXT, 8, 4, 4},
649 {GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 8, 4, 4},
650 {GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 16, 4, 4},
651 {GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 16, 4, 4}},
652 true, false},
653 {"GL_EXT_texture_compression_bptc", {{GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, 16, 4, 4},
654 {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT, 16, 4, 4},
655 {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, 16, 4, 4},
656 {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT, 16, 4, 4}},
657 true, true},
658
659 // ETC
660 {"GL_OES_compressed_ETC1_RGB8_texture", {{GL_ETC1_RGB8_OES, 8, 4, 4}},
661 false, false},
662 {"GL_OES_compressed_EAC_R11_unsigned_texture", {{GL_COMPRESSED_R11_EAC, 8, 4, 4}},
663 true, false},
664 {"GL_OES_compressed_EAC_R11_signed_texture", {{GL_COMPRESSED_SIGNED_R11_EAC, 8, 4, 4}},
665 true, false},
666 {"GL_OES_compressed_EAC_RG11_unsigned_texture", {{GL_COMPRESSED_RG11_EAC, 16, 4, 4}},
667 true, false},
668 {"GL_OES_compressed_EAC_RG11_signed_texture", {{GL_COMPRESSED_SIGNED_RG11_EAC, 16, 4, 4}},
669 true, false},
670 {"GL_OES_compressed_ETC2_RGB8_texture", {{GL_COMPRESSED_RGB8_ETC2, 8, 4, 4}},
671 true, false},
672 {"GL_OES_compressed_ETC2_sRGB8_texture", {{GL_COMPRESSED_SRGB8_ETC2, 8, 4, 4}},
673 true, false},
674 {"GL_OES_compressed_ETC2_punchthroughA_RGBA8_texture", {{GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8, 4, 4}},
675 true, false},
676 {"GL_OES_compressed_ETC2_punchthroughA_sRGB8_alpha_texture", {{GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, 8, 4, 4}},
677 true, false},
678 {"GL_OES_compressed_ETC2_RGBA8_texture", {{GL_COMPRESSED_RGBA8_ETC2_EAC, 16, 4, 4}},
679 true, false},
680 {"GL_OES_compressed_ETC2_sRGB8_alpha8_texture", {{GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, 16, 4, 4}},
681 true, false},
682
683 // ASTC
684 {"GL_KHR_texture_compression_astc_ldr", {{GL_COMPRESSED_RGBA_ASTC_4x4_KHR, 16, 4, 4},
685 {GL_COMPRESSED_RGBA_ASTC_5x4_KHR, 16, 5, 4},
686 {GL_COMPRESSED_RGBA_ASTC_5x5_KHR, 16, 5, 5},
687 {GL_COMPRESSED_RGBA_ASTC_6x5_KHR, 16, 6, 5},
688 {GL_COMPRESSED_RGBA_ASTC_6x6_KHR, 16, 6, 6},
689 {GL_COMPRESSED_RGBA_ASTC_8x5_KHR, 16, 8, 5},
690 {GL_COMPRESSED_RGBA_ASTC_8x6_KHR, 16, 8, 6},
691 {GL_COMPRESSED_RGBA_ASTC_8x8_KHR, 16, 8, 8},
692 {GL_COMPRESSED_RGBA_ASTC_10x5_KHR, 16, 10, 5},
693 {GL_COMPRESSED_RGBA_ASTC_10x6_KHR, 16, 10, 6},
694 {GL_COMPRESSED_RGBA_ASTC_10x8_KHR, 16, 10, 8},
695 {GL_COMPRESSED_RGBA_ASTC_10x10_KHR, 16, 10, 10},
696 {GL_COMPRESSED_RGBA_ASTC_12x10_KHR, 16, 12, 10},
697 {GL_COMPRESSED_RGBA_ASTC_12x12_KHR, 16, 12, 12},
698 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, 16, 4, 4},
699 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, 16, 5, 4},
700 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, 16, 5, 5},
701 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, 16, 6, 5},
702 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, 16, 6, 6},
703 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, 16, 8, 5},
704 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, 16, 8, 6},
705 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, 16, 8, 8},
706 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, 16, 10, 5},
707 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, 16, 10, 6},
708 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, 16, 10, 8},
709 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 16, 10, 10},
710 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 16, 12, 10},
711 {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 16, 12, 12}},
712 true, true},
713 };
714 // clang-format on
715
IsFormatEmulated(GLenum target)716 bool IsFormatEmulated(GLenum target)
717 {
718 GLint readFormat;
719 glGetTexParameteriv(target, GL_IMPLEMENTATION_COLOR_READ_FORMAT, &readFormat);
720 return readFormat == GL_RGBA || readFormat == GL_RG || readFormat == GL_RED;
721 }
722
723 // Basic GetCompressedTexImage.
TEST_P(GetImageTest,CompressedTexImage)724 TEST_P(GetImageTest, CompressedTexImage)
725 {
726 // Verify the extension is enabled.
727 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
728 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC1_RGB8_texture"));
729
730 constexpr GLsizei kRes = 4;
731 constexpr GLsizei kImageSize = 8;
732
733 // This arbitrary 'compressed' data just has to be read back exactly as specified below.
734 constexpr std::array<uint8_t, kImageSize> kExpectedData = {1, 2, 3, 4, 5, 6, 7, 8};
735
736 GLTexture tex;
737 glBindTexture(GL_TEXTURE_2D, tex);
738 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_ETC1_RGB8_OES, kRes, kRes, 0, kImageSize,
739 kExpectedData.data());
740
741 if (IsFormatEmulated(GL_TEXTURE_2D))
742 {
743 INFO()
744 << "Skipping emulated format GL_ETC1_RGB8_OES from GL_OES_compressed_ETC1_RGB8_texture";
745 return;
746 }
747
748 std::array<uint8_t, kImageSize> actualData = {};
749 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, actualData.data());
750 ASSERT_GL_NO_ERROR();
751 EXPECT_EQ(kExpectedData, actualData);
752 }
753
754 // Test validation for the compressed extension function.
TEST_P(GetImageTest,CompressedTexImageNegativeAPI)755 TEST_P(GetImageTest, CompressedTexImageNegativeAPI)
756 {
757 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
758
759 // Verify the extension is enabled.
760 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
761
762 constexpr GLsizei kRes = 4;
763 constexpr GLsizei kImageSize = 8;
764
765 // This arbitrary 'compressed' data just has to be read back exactly as specified below.
766 constexpr std::array<uint8_t, kImageSize> kExpectedData = {1, 2, 3, 4, 5, 6, 7, 8};
767
768 GLTexture tex;
769 glBindTexture(GL_TEXTURE_2D, tex);
770 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, kRes, kRes, 0, kImageSize,
771 kExpectedData.data());
772
773 std::array<uint8_t, kImageSize> actualData = {};
774 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, actualData.data());
775
776 // Verify GetTexImage works with correct parameters or fails if format is emulated.
777 if (IsFormatEmulated(GL_TEXTURE_2D))
778 {
779 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
780 }
781 else
782 {
783 EXPECT_GL_NO_ERROR();
784 }
785
786 // Test invalid texture target.
787 glGetCompressedTexImageANGLE(GL_TEXTURE_CUBE_MAP, 0, actualData.data());
788 EXPECT_GL_ERROR(GL_INVALID_ENUM);
789
790 // Test invalid texture level.
791 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, -1, actualData.data());
792 EXPECT_GL_ERROR(GL_INVALID_VALUE);
793 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 2000, actualData.data());
794 EXPECT_GL_ERROR(GL_INVALID_VALUE);
795
796 // Tests GetTexImage on a compressed texture.
797 if (!IsFormatEmulated(GL_TEXTURE_2D))
798 {
799 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE,
800 actualData.data());
801 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
802 }
803 }
804
805 using TestFormatFunction =
806 std::function<void(const CompressionExtension &, const CompressedFormat &)>;
807
TestAllCompressedFormats(TestFormatFunction fun)808 void TestAllCompressedFormats(TestFormatFunction fun)
809 {
810 for (CompressionExtension ext : kCompressionExtensions)
811 {
812 if (!IsGLExtensionEnabled(ext.name))
813 {
814 continue;
815 }
816
817 for (CompressedFormat format : ext.formats)
818 {
819 fun(ext, format);
820 }
821 }
822 }
823
824 // Test GetCompressedTexImage with all formats and
825 // and multiple resolution of the format's block size.
TEST_P(GetImageTest,CompressedTexImageAll)826 TEST_P(GetImageTest, CompressedTexImageAll)
827 {
828 // Verify the extension is enabled.
829 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
830
831 auto func = [](const CompressionExtension &ext, const CompressedFormat &format) {
832 // Test with multiples of block size
833 constexpr std::array<GLsizei, 2> multipliers = {1, 2};
834 for (GLsizei multiplier : multipliers)
835 {
836 const GLsizei kImageSize = format.size * multiplier * multiplier;
837
838 std::vector<uint8_t> expectedData;
839 for (uint8_t i = 1; i < kImageSize + 1; i++)
840 {
841 expectedData.push_back(i);
842 }
843
844 GLTexture tex;
845 glBindTexture(GL_TEXTURE_2D, tex);
846 glCompressedTexImage2D(GL_TEXTURE_2D, 0, format.id, format.w * multiplier,
847 format.h * multiplier, 0, kImageSize, expectedData.data());
848
849 if (IsFormatEmulated(GL_TEXTURE_2D))
850 {
851 INFO() << "Skipping emulated format 0x" << std::hex << format.id << " from "
852 << ext.name;
853 return;
854 }
855
856 std::vector<uint8_t> actualData(kImageSize);
857 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, actualData.data());
858
859 ASSERT_GL_NO_ERROR();
860 EXPECT_EQ(expectedData, actualData);
861 }
862 };
863 TestAllCompressedFormats(func);
864 }
865
866 // Test a resolution that is not a multiple of the block size with an ETC2 4x4 format.
TEST_P(GetImageTest,CompressedTexImageNotBlockMultiple)867 TEST_P(GetImageTest, CompressedTexImageNotBlockMultiple)
868 {
869 // Verify the extension is enabled.
870 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
871 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_OES_compressed_ETC2_RGB8_texture"));
872
873 constexpr GLsizei kRes = 21;
874 constexpr GLsizei kImageSize = 288;
875
876 // This arbitrary 'compressed' data just has to be read back exactly as specified below.
877 std::vector<uint8_t> expectedData;
878 for (uint16_t j = 0; j < kImageSize; j++)
879 {
880 expectedData.push_back(j % std::numeric_limits<uint8_t>::max());
881 }
882
883 GLTexture tex;
884 glBindTexture(GL_TEXTURE_2D, tex);
885 glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGB8_ETC2, kRes, kRes, 0, kImageSize,
886 expectedData.data());
887
888 if (IsFormatEmulated(GL_TEXTURE_2D))
889 {
890 INFO() << "Skipping emulated format GL_COMPRESSED_RGB8_ETC2 from "
891 "GL_OES_compressed_ETC2_RGB8_texture";
892 return;
893 }
894
895 std::vector<uint8_t> actualData(kImageSize);
896 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, 0, actualData.data());
897
898 ASSERT_GL_NO_ERROR();
899 EXPECT_EQ(expectedData, actualData);
900 }
901
TestCompressedTexImage3D(GLenum target,uint32_t numLayers)902 void TestCompressedTexImage3D(GLenum target, uint32_t numLayers)
903 {
904 auto func = [target, numLayers](const CompressionExtension &ext,
905 const CompressedFormat &format) {
906 // Skip extensions lacking 2D array and 3D support
907 if ((target == GL_TEXTURE_2D_ARRAY && !ext.supports2DArray) ||
908 (target == GL_TEXTURE_3D && !ext.supports3D))
909 {
910 return;
911 }
912
913 // GL_TEXTURE_3D with ASTC requires additional extension
914 if (target == GL_TEXTURE_3D &&
915 strcmp(ext.name, "GL_KHR_texture_compression_astc_ldr") == 0 &&
916 !IsGLExtensionEnabled("GL_KHR_texture_compression_astc_sliced_3d") &&
917 !IsGLExtensionEnabled("GL_KHR_texture_compression_astc_hdr"))
918 {
919 return;
920 }
921
922 const size_t size = format.size * numLayers;
923
924 GLTexture texture;
925 glBindTexture(target, texture);
926
927 std::vector<uint8_t> expectedData;
928 for (uint8_t i = 0; i < size; i++)
929 {
930 expectedData.push_back(i);
931 }
932
933 glCompressedTexImage3D(target, 0, format.id, format.w, format.h, numLayers, 0, size,
934 expectedData.data());
935
936 if (IsFormatEmulated(target))
937 {
938 INFO() << "Skipping emulated format 0x" << std::hex << format.id << " from "
939 << ext.name;
940 return;
941 }
942
943 std::vector<uint8_t> actualData(size);
944 glGetCompressedTexImageANGLE(target, 0, actualData.data());
945 ASSERT_GL_NO_ERROR();
946 EXPECT_EQ(expectedData, actualData);
947 };
948 TestAllCompressedFormats(func);
949 }
950
951 // Tests GetCompressedTexImage with 2D array textures.
TEST_P(GetImageTestES3,CompressedTexImage2DArray)952 TEST_P(GetImageTestES3, CompressedTexImage2DArray)
953 {
954 // Verify the extension is enabled.
955 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
956 TestCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 8);
957 }
958
959 // Tests GetCompressedTexImage with 3D textures.
TEST_P(GetImageTest,CompressedTexImage3D)960 TEST_P(GetImageTest, CompressedTexImage3D)
961 {
962 // Verify the extension is enabled.
963 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
964 TestCompressedTexImage3D(GL_TEXTURE_3D, 8);
965 }
966
967 // Simple cube map test for GetCompressedTexImage
TEST_P(GetImageTest,CompressedTexImageCubeMap)968 TEST_P(GetImageTest, CompressedTexImageCubeMap)
969 {
970 // Verify the extension is enabled.
971 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
972
973 auto func = [](const CompressionExtension &ext, const CompressedFormat &format) {
974 GLTexture texture;
975 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
976
977 std::vector<std::vector<uint8_t>> expectedData;
978 for (uint32_t i = 0; i < kCubeFaces.size(); i++)
979 {
980 std::vector<uint8_t> face;
981 for (uint8_t j = 0; j < format.size; j++)
982 {
983 face.push_back(static_cast<uint8_t>((i * format.size + j) %
984 std::numeric_limits<uint8_t>::max()));
985 }
986 expectedData.push_back(face);
987 }
988
989 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
990 {
991 glCompressedTexImage2D(kCubeFaces[faceIndex], 0, format.id, 4, 4, 0, format.size,
992 expectedData[faceIndex].data());
993 }
994
995 if (IsFormatEmulated(GL_TEXTURE_CUBE_MAP))
996 {
997 INFO() << "Skipping emulated format 0x" << std::hex << format.id << " from "
998 << ext.name;
999 return;
1000 }
1001
1002 // Verify GetImage.
1003 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
1004 {
1005 std::vector<uint8_t> actualData(format.size);
1006 glGetCompressedTexImageANGLE(kCubeFaces[faceIndex], 0, actualData.data());
1007 EXPECT_GL_NO_ERROR();
1008 EXPECT_EQ(expectedData[faceIndex], actualData);
1009 }
1010 };
1011 TestAllCompressedFormats(func);
1012 }
1013
1014 // Tests GetCompressedTexImage with cube map array textures.
TEST_P(GetImageTestES32,CompressedTexImageCubeMapArray)1015 TEST_P(GetImageTestES32, CompressedTexImageCubeMapArray)
1016 {
1017 // Verify the extension is enabled.
1018 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
1019 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_cube_map_array") &&
1020 !IsGLExtensionEnabled("GL_OES_texture_cube_map_array"));
1021
1022 auto func = [](const CompressionExtension &ext, const CompressedFormat &format) {
1023 std::vector<uint8_t> expectedData;
1024 for (uint32_t i = 0; i < format.size * kCubeFaces.size(); i++)
1025 {
1026 expectedData.push_back(static_cast<uint8_t>(i % std::numeric_limits<uint8_t>::max()));
1027 }
1028
1029 GLTexture tex;
1030 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
1031 glCompressedTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, format.id, 4, 4, kCubeFaces.size(), 0,
1032 expectedData.size() * sizeof(uint8_t), expectedData.data());
1033 ASSERT_GL_NO_ERROR();
1034
1035 if (IsFormatEmulated(GL_TEXTURE_CUBE_MAP_ARRAY))
1036 {
1037 INFO() << "Skipping emulated format 0x" << std::hex << format.id << " from "
1038 << ext.name;
1039 return;
1040 }
1041
1042 // Verify GetImage.
1043 std::vector<uint8_t> actualData(format.size * kCubeFaces.size());
1044 glGetCompressedTexImageANGLE(GL_TEXTURE_CUBE_MAP_ARRAY, 0, actualData.data());
1045 EXPECT_GL_NO_ERROR();
1046 EXPECT_EQ(expectedData, actualData);
1047 };
1048 TestAllCompressedFormats(func);
1049 }
1050
1051 // Tests GetCompressedTexImage with multiple mip levels.
TEST_P(GetImageTest,CompressedTexImageMultiLevel)1052 TEST_P(GetImageTest, CompressedTexImageMultiLevel)
1053 {
1054 // Verify the extension is enabled.
1055 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
1056
1057 auto func = [](const CompressionExtension &ext, const CompressedFormat &format) {
1058 constexpr uint8_t kNumMipLevels = 8;
1059 GLTexture tex;
1060 glBindTexture(GL_TEXTURE_2D, tex);
1061
1062 std::vector<std::vector<uint8_t>> expectedData;
1063 for (uint32_t mipLevel = 0; mipLevel < kNumMipLevels; mipLevel++)
1064 {
1065 uint32_t multiplier = static_cast<uint32_t>(pow(2, (kNumMipLevels - mipLevel) - 1));
1066 size_t levelSize = format.size * multiplier * multiplier;
1067
1068 std::vector<uint8_t> levelData;
1069 for (size_t j = 0; j < levelSize; j++)
1070 {
1071 levelData.push_back(static_cast<uint8_t>(j % std::numeric_limits<uint8_t>::max()));
1072 }
1073 expectedData.push_back(levelData);
1074
1075 glCompressedTexImage2D(GL_TEXTURE_2D, mipLevel, format.id, format.w * multiplier,
1076 format.h * multiplier, 0, levelSize, levelData.data());
1077 }
1078
1079 ASSERT_GL_NO_ERROR();
1080
1081 if (IsFormatEmulated(GL_TEXTURE_2D))
1082 {
1083 INFO() << "Skipping emulated format 0x" << std::hex << format.id << " from "
1084 << ext.name;
1085 return;
1086 }
1087
1088 for (uint32_t mipLevel = 0; mipLevel < kNumMipLevels; mipLevel++)
1089 {
1090 uint32_t multiplier = static_cast<uint32_t>(pow(2, (kNumMipLevels - mipLevel) - 1));
1091 size_t levelSize = format.size * multiplier * multiplier;
1092
1093 std::vector<uint8_t> actualData(levelSize);
1094 glGetCompressedTexImageANGLE(GL_TEXTURE_2D, mipLevel, actualData.data());
1095
1096 ASSERT_GL_NO_ERROR();
1097 EXPECT_EQ(expectedData[mipLevel], actualData);
1098 }
1099 };
1100 TestAllCompressedFormats(func);
1101 }
1102
1103 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTest);
1104 ANGLE_INSTANTIATE_TEST(GetImageTest,
1105 ES2_VULKAN(),
1106 ES3_VULKAN(),
1107 ES2_VULKAN_SWIFTSHADER(),
1108 ES3_VULKAN_SWIFTSHADER());
1109
1110 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestES3);
1111 ANGLE_INSTANTIATE_TEST(GetImageTestES3, ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER());
1112
1113 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestES31);
1114 ANGLE_INSTANTIATE_TEST(GetImageTestES31, ES31_VULKAN(), ES31_VULKAN_SWIFTSHADER());
1115
1116 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestES32);
1117 ANGLE_INSTANTIATE_TEST(GetImageTestES32, ES32_VULKAN(), ES32_VULKAN_SWIFTSHADER());
1118
1119 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestNoExtensions);
1120 ANGLE_INSTANTIATE_TEST(GetImageTestNoExtensions,
1121 ES2_VULKAN(),
1122 ES3_VULKAN(),
1123 ES2_VULKAN_SWIFTSHADER(),
1124 ES3_VULKAN_SWIFTSHADER());
1125
1126 } // namespace