• 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 "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, &param);
303     EXPECT_GL_ERROR(GL_INVALID_ENUM);
304 
305     glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_TYPE, &param);
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, &param);
319     EXPECT_GL_ERROR(GL_INVALID_ENUM);
320 
321     glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, &param);
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