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