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, ¶m);
312 EXPECT_GL_ERROR(GL_INVALID_ENUM);
313
314 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
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, ¶m);
328 EXPECT_GL_ERROR(GL_INVALID_ENUM);
329
330 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
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