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 GetImageTestES31 : public GetImageTest
45 {
46 public:
GetImageTestES31()47 GetImageTestES31() {}
48 };
49
InitTextureWithFormatAndSize(GLenum format,uint32_t size,void * pixelData)50 GLTexture InitTextureWithFormatAndSize(GLenum format, uint32_t size, void *pixelData)
51 {
52 GLTexture tex;
53 glBindTexture(GL_TEXTURE_2D, tex);
54 glTexImage2D(GL_TEXTURE_2D, 0, format, size, size, 0, format, GL_UNSIGNED_BYTE, pixelData);
55 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
56 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
57 return tex;
58 }
59
InitTextureWithSize(uint32_t size,void * pixelData)60 GLTexture InitTextureWithSize(uint32_t size, void *pixelData)
61 {
62 // Create a simple texture.
63 GLTexture tex;
64 glBindTexture(GL_TEXTURE_2D, tex);
65 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
66 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
67 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
68 return tex;
69 }
70
InitSimpleTexture()71 GLTexture InitSimpleTexture()
72 {
73 std::vector<GLColor> pixelData(kSize * kSize, GLColor::red);
74 return InitTextureWithSize(kSize, pixelData.data());
75 }
76
InitRenderbufferWithSize(uint32_t size)77 GLRenderbuffer InitRenderbufferWithSize(uint32_t size)
78 {
79 // Create a simple renderbuffer.
80 GLRenderbuffer renderbuf;
81 glBindRenderbuffer(GL_RENDERBUFFER, renderbuf);
82 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA4, size, size);
83 return renderbuf;
84 }
85
InitSimpleRenderbuffer()86 GLRenderbuffer InitSimpleRenderbuffer()
87 {
88 return InitRenderbufferWithSize(kSize);
89 }
90
91 // Test validation for the extension functions.
TEST_P(GetImageTest,NegativeAPI)92 TEST_P(GetImageTest, NegativeAPI)
93 {
94 // Verify the extension is enabled.
95 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
96
97 // Draw once with simple texture.
98 GLTexture tex = InitSimpleTexture();
99 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
100 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
101 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
102 ASSERT_GL_NO_ERROR();
103
104 // Pack pixels tightly.
105 glPixelStorei(GL_PACK_ALIGNMENT, 1);
106
107 // Verify GetTexImage can work with correct parameters.
108 std::vector<GLColor> buffer(kSize * kSize);
109 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
110 EXPECT_GL_NO_ERROR();
111
112 // Test invalid texture target.
113 glGetTexImageANGLE(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
114 EXPECT_GL_ERROR(GL_INVALID_ENUM);
115
116 // Test invalid texture level.
117 glGetTexImageANGLE(GL_TEXTURE_2D, -1, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
118 EXPECT_GL_ERROR(GL_INVALID_VALUE);
119 glGetTexImageANGLE(GL_TEXTURE_2D, 2000, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
120 EXPECT_GL_ERROR(GL_INVALID_VALUE);
121
122 // Test invalid format and type.
123 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
124 EXPECT_GL_ERROR(GL_INVALID_ENUM);
125 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_NONE, buffer.data());
126 EXPECT_GL_ERROR(GL_INVALID_ENUM);
127
128 // Create a simple renderbuffer.
129 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
130 ASSERT_GL_NO_ERROR();
131
132 // Verify GetRenderbufferImage can work with correct parameters.
133 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
134 EXPECT_GL_NO_ERROR();
135
136 // Test invalid renderbuffer target.
137 glGetRenderbufferImageANGLE(GL_TEXTURE_2D, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
138 EXPECT_GL_ERROR(GL_INVALID_ENUM);
139
140 // Test invalid renderbuffer format/type.
141 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_NONE, GL_UNSIGNED_BYTE, buffer.data());
142 EXPECT_GL_ERROR(GL_INVALID_ENUM);
143 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_NONE, buffer.data());
144 EXPECT_GL_ERROR(GL_INVALID_ENUM);
145
146 // Pack buffer tests. Requires ES 3+ or extension.
147 if (getClientMajorVersion() >= 3 || IsGLExtensionEnabled("GL_NV_pixel_buffer_object"))
148 {
149 // Test valid pack buffer.
150 GLBuffer packBuffer;
151 glBindBuffer(GL_PIXEL_PACK_BUFFER, packBuffer);
152 glBufferData(GL_PIXEL_PACK_BUFFER, kSize * kSize * sizeof(GLColor), nullptr,
153 GL_STATIC_DRAW);
154 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
155 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
156 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
157 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
158
159 // Test too small pack buffer.
160 glBufferData(GL_PIXEL_PACK_BUFFER, kSize, nullptr, GL_STATIC_DRAW);
161 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
162 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
163 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
164 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
165 }
166 }
167
168 // Simple test for GetTexImage
TEST_P(GetImageTest,GetTexImage)169 TEST_P(GetImageTest, GetTexImage)
170 {
171 // Verify the extension is enabled.
172 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
173
174 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
175 GLColor::yellow};
176
177 glViewport(0, 0, kSmallSize, kSmallSize);
178
179 // Draw once with simple texture.
180 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
181 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
182 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
183 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
184 ASSERT_GL_NO_ERROR();
185
186 // Pack pixels tightly.
187 glPixelStorei(GL_PACK_ALIGNMENT, 1);
188
189 // Verify GetImage.
190 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
191 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
192 EXPECT_GL_NO_ERROR();
193 EXPECT_EQ(expectedData, actualData);
194 }
195
196 // Simple cube map test for GetTexImage
TEST_P(GetImageTest,CubeMap)197 TEST_P(GetImageTest, CubeMap)
198 {
199 // Verify the extension is enabled.
200 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
201
202 const std::array<std::array<GLColor, kSmallSize * kSmallSize>, kCubeFaces.size()> expectedData =
203 {{
204 {GLColor::red, GLColor::red, GLColor::red, GLColor::red},
205 {GLColor::green, GLColor::green, GLColor::green, GLColor::green},
206 {GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue},
207 {GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow},
208 {GLColor::cyan, GLColor::cyan, GLColor::cyan, GLColor::cyan},
209 {GLColor::magenta, GLColor::magenta, GLColor::magenta, GLColor::magenta},
210 }};
211
212 GLTexture texture;
213 glBindTexture(GL_TEXTURE_CUBE_MAP, texture);
214
215 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
216 {
217 glTexImage2D(kCubeFaces[faceIndex], 0, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA,
218 GL_UNSIGNED_BYTE, expectedData[faceIndex].data());
219 }
220 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
221 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
222
223 // Pack pixels tightly.
224 glPixelStorei(GL_PACK_ALIGNMENT, 1);
225
226 // Verify GetImage.
227 std::array<GLColor, kSmallSize *kSmallSize> actualData = {};
228 for (size_t faceIndex = 0; faceIndex < kCubeFaces.size(); ++faceIndex)
229 {
230 glGetTexImageANGLE(kCubeFaces[faceIndex], 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
231 EXPECT_GL_NO_ERROR();
232 EXPECT_EQ(expectedData[faceIndex], actualData);
233 }
234 }
235
236 // Simple test for GetRenderbufferImage
TEST_P(GetImageTest,GetRenderbufferImage)237 TEST_P(GetImageTest, GetRenderbufferImage)
238 {
239 // Verify the extension is enabled.
240 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
241
242 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
243 GLColor::yellow};
244
245 glViewport(0, 0, kSmallSize, kSmallSize);
246
247 // Set up a simple Framebuffer with a Renderbuffer.
248 GLRenderbuffer renderbuffer = InitRenderbufferWithSize(kSmallSize);
249 GLFramebuffer framebuffer;
250 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
251 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
252 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
253
254 // Draw once with simple texture.
255 GLTexture tex = InitTextureWithSize(kSmallSize, expectedData.data());
256 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
257 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
258 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
259 ASSERT_GL_NO_ERROR();
260
261 // Pack pixels tightly.
262 glPixelStorei(GL_PACK_ALIGNMENT, 1);
263
264 // Verify GetImage.
265 std::vector<GLColor> actualData(kSmallSize * kSmallSize);
266 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
267 EXPECT_GL_NO_ERROR();
268 EXPECT_EQ(expectedData, actualData);
269 }
270
271 // Verifies that the extension enums and entry points are invalid when the extension is disabled.
TEST_P(GetImageTestNoExtensions,EntryPointsInactive)272 TEST_P(GetImageTestNoExtensions, EntryPointsInactive)
273 {
274 // Verify the extension is not enabled.
275 ASSERT_FALSE(IsGLExtensionEnabled(kExtensionName));
276
277 // Draw once with simple texture.
278 GLTexture tex = InitSimpleTexture();
279 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
280 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
281 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
282 ASSERT_GL_NO_ERROR();
283
284 // Query implementation format and type. Should give invalid enum.
285 GLint param;
286 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
287 EXPECT_GL_ERROR(GL_INVALID_ENUM);
288
289 glGetTexParameteriv(GL_TEXTURE_2D, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
290 EXPECT_GL_ERROR(GL_INVALID_ENUM);
291
292 // Verify calling GetTexImage produces an error.
293 std::vector<GLColor> buffer(kSize * kSize, 0);
294 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
295 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
296
297 // Create a simple renderbuffer.
298 GLRenderbuffer renderbuf = InitSimpleRenderbuffer();
299 ASSERT_GL_NO_ERROR();
300
301 // Query implementation format and type. Should give invalid enum.
302 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_FORMAT, ¶m);
303 EXPECT_GL_ERROR(GL_INVALID_ENUM);
304
305 glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_IMPLEMENTATION_COLOR_READ_TYPE, ¶m);
306 EXPECT_GL_ERROR(GL_INVALID_ENUM);
307
308 // Verify calling GetRenderbufferImage produces an error.
309 glGetRenderbufferImageANGLE(GL_RENDERBUFFER, GL_RGBA, GL_UNSIGNED_BYTE, buffer.data());
310 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
311 }
312
313 // Test LUMINANCE_ALPHA (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageLuminanceAlpha)314 TEST_P(GetImageTest, GetTexImageLuminanceAlpha)
315 {
316 // Verify the extension is enabled.
317 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
318
319 constexpr GLColorRG kMediumLumAlpha = GLColorRG(kUNormHalf, kUNormHalf);
320 std::vector<GLColorRG> expectedData = {kMediumLumAlpha, kMediumLumAlpha, kMediumLumAlpha,
321 kMediumLumAlpha};
322
323 glViewport(0, 0, kSmallSize, kSmallSize);
324
325 // Set up a simple LUMINANCE_ALPHA texture
326 GLTexture tex =
327 InitTextureWithFormatAndSize(GL_LUMINANCE_ALPHA, kSmallSize, expectedData.data());
328
329 // Draw once with simple texture.
330 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
331 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
332 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormHalf, kUNormHalf, kUNormHalf, kUNormHalf));
333 ASSERT_GL_NO_ERROR();
334
335 // Pack pixels tightly.
336 glPixelStorei(GL_PACK_ALIGNMENT, 1);
337
338 // Verify GetImage.
339 std::vector<GLColorRG> actualData(kSmallSize * kSmallSize);
340 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, actualData.data());
341 EXPECT_GL_NO_ERROR();
342 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
343 {
344 EXPECT_EQ(expectedData[i].R, actualData[i].R);
345 EXPECT_EQ(expectedData[i].G, actualData[i].G);
346 }
347 }
348
349 // Test LUMINANCE (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageLuminance)350 TEST_P(GetImageTest, GetTexImageLuminance)
351 {
352 // Verify the extension is enabled.
353 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
354
355 constexpr GLColorR kMediumLuminance = GLColorR(kUNormHalf);
356 std::vector<GLColorR> expectedData = {kMediumLuminance, kMediumLuminance, kMediumLuminance,
357 kMediumLuminance};
358
359 glViewport(0, 0, kSmallSize, kSmallSize);
360
361 // Set up a simple LUMINANCE texture
362 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
363 GLTexture tex = InitTextureWithFormatAndSize(GL_LUMINANCE, kSmallSize, expectedData.data());
364
365 // Draw once with simple texture.
366 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
367 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
368 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormHalf, kUNormHalf, kUNormHalf, kUNormFull));
369 ASSERT_GL_NO_ERROR();
370
371 // Pack pixels tightly.
372 glPixelStorei(GL_PACK_ALIGNMENT, 1);
373
374 // Verify GetImage.
375 std::vector<GLColorR> actualData(kSmallSize * kSmallSize);
376 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, actualData.data());
377 EXPECT_GL_NO_ERROR();
378 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
379 {
380 EXPECT_EQ(expectedData[i].R, actualData[i].R);
381 }
382 }
383
384 // Test ALPHA (non-renderable) format with GetTexImage
TEST_P(GetImageTest,GetTexImageAlpha)385 TEST_P(GetImageTest, GetTexImageAlpha)
386 {
387 // Verify the extension is enabled.
388 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
389
390 constexpr GLColorR kMediumAlpha = GLColorR(kUNormHalf);
391 std::vector<GLColorR> expectedData = {kMediumAlpha, kMediumAlpha, kMediumAlpha, kMediumAlpha};
392
393 glViewport(0, 0, kSmallSize, kSmallSize);
394
395 // Set up a simple ALPHA texture
396 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
397 GLTexture tex = InitTextureWithFormatAndSize(GL_ALPHA, kSmallSize, expectedData.data());
398
399 // Draw once with simple texture
400 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
401 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
402 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor(kUNormZero, kUNormZero, kUNormZero, kUNormHalf));
403 ASSERT_GL_NO_ERROR();
404
405 // Pack pixels tightly.
406 glPixelStorei(GL_PACK_ALIGNMENT, 1);
407
408 // Verify we get back the correct pixels from GetTexImage
409 std::vector<GLColorR> actualData(kSmallSize * kSmallSize);
410 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_ALPHA, GL_UNSIGNED_BYTE, actualData.data());
411 EXPECT_GL_NO_ERROR();
412 for (uint32_t i = 0; i < kSmallSize * kSmallSize; ++i)
413 {
414 EXPECT_EQ(expectedData[i].R, actualData[i].R);
415 }
416 }
417
418 // Tests GetImage behaviour with an RGB image.
TEST_P(GetImageTest,GetImageRGB)419 TEST_P(GetImageTest, GetImageRGB)
420 {
421 // Verify the extension is enabled.
422 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
423
424 std::vector<GLColorRGB> expectedData = {GLColorRGB::red, GLColorRGB::blue, GLColorRGB::green,
425 GLColorRGB::yellow};
426
427 glViewport(0, 0, kSmallSize, kSmallSize);
428
429 // Pack pixels tightly.
430 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
431 glPixelStorei(GL_PACK_ALIGNMENT, 1);
432
433 // Init simple texture.
434 GLTexture tex;
435 glBindTexture(GL_TEXTURE_2D, tex);
436 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, kSmallSize, kSmallSize, 0, GL_RGB, GL_UNSIGNED_BYTE,
437 expectedData.data());
438 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, kSmallSize / 2, kSmallSize / 2, 0, GL_RGB,
439 GL_UNSIGNED_BYTE, expectedData.data());
440 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
441 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
442
443 // Verify GetImage.
444 std::vector<GLColorRGB> actualData(kSmallSize * kSmallSize);
445 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, actualData.data());
446 EXPECT_GL_NO_ERROR();
447 EXPECT_EQ(expectedData, actualData);
448
449 // Draw after the GetImage.
450 ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
451 drawQuad(program, essl1_shaders::PositionAttrib(), 0.5, 1.0f, true);
452
453 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
454 EXPECT_PIXEL_COLOR_EQ(0, 1, GLColor::green);
455 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::blue);
456 EXPECT_PIXEL_COLOR_EQ(1, 1, GLColor::yellow);
457 }
458
459 // Tests GetImage with 2D array textures.
TEST_P(GetImageTestES31,Texture2DArray)460 TEST_P(GetImageTestES31, Texture2DArray)
461 {
462 // Verify the extension is enabled.
463 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
464
465 constexpr GLsizei kTextureSize = 2;
466 constexpr GLsizei kLayers = 4;
467
468 std::vector<GLColor> expectedPixels = {
469 GLColor::red, GLColor::red, GLColor::red, GLColor::red,
470 GLColor::green, GLColor::green, GLColor::green, GLColor::green,
471 GLColor::blue, GLColor::blue, GLColor::blue, GLColor::blue,
472 GLColor::yellow, GLColor::yellow, GLColor::yellow, GLColor::yellow,
473 };
474
475 GLTexture tex;
476 glBindTexture(GL_TEXTURE_2D_ARRAY, tex);
477 glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, kTextureSize, kTextureSize, kLayers, 0, GL_RGBA,
478 GL_UNSIGNED_BYTE, expectedPixels.data());
479 ASSERT_GL_NO_ERROR();
480
481 std::vector<GLColor> actualPixels(expectedPixels.size(), GLColor::white);
482 glGetTexImageANGLE(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
483 ASSERT_GL_NO_ERROR();
484 EXPECT_EQ(expectedPixels, actualPixels);
485 }
486
487 // Tests GetImage with 3D textures.
TEST_P(GetImageTestES31,Texture3D)488 TEST_P(GetImageTestES31, Texture3D)
489 {
490 // Verify the extension is enabled.
491 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
492
493 constexpr GLsizei kTextureSize = 2;
494
495 std::vector<GLColor> expectedPixels = {
496 GLColor::red, GLColor::red, GLColor::green, GLColor::green,
497 GLColor::blue, GLColor::blue, GLColor::yellow, GLColor::yellow,
498 };
499
500 GLTexture tex;
501 glBindTexture(GL_TEXTURE_3D, tex);
502 glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, kTextureSize, kTextureSize, kTextureSize, 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_3D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualPixels.data());
508 ASSERT_GL_NO_ERROR();
509 EXPECT_EQ(expectedPixels, actualPixels);
510 }
511
512 // Tests GetImage with cube map array textures.
TEST_P(GetImageTestES31,TextureCubeMapArray)513 TEST_P(GetImageTestES31, TextureCubeMapArray)
514 {
515 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_cube_map_array") &&
516 !IsGLExtensionEnabled("GL_OES_texture_cube_map_array"));
517
518 // Verify the extension is enabled.
519 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
520
521 constexpr GLsizei kTextureSize = 1;
522 constexpr GLsizei kLayers = 2;
523
524 std::vector<GLColor> expectedPixels = {
525 GLColor::red, GLColor::green, GLColor::blue, GLColor::yellow,
526 GLColor::cyan, GLColor::magenta, GLColor::red, GLColor::green,
527 GLColor::blue, GLColor::yellow, GLColor::cyan, GLColor::magenta,
528 };
529
530 ASSERT_EQ(expectedPixels.size(),
531 static_cast<size_t>(6 * kTextureSize * kTextureSize * kLayers));
532
533 GLTexture tex;
534 glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, tex);
535 glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, kTextureSize, kTextureSize, kLayers * 6, 0,
536 GL_RGBA, GL_UNSIGNED_BYTE, expectedPixels.data());
537 ASSERT_GL_NO_ERROR();
538
539 std::vector<GLColor> actualPixels(expectedPixels.size(), GLColor::white);
540 glGetTexImageANGLE(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE,
541 actualPixels.data());
542 ASSERT_GL_NO_ERROR();
543 EXPECT_EQ(expectedPixels, actualPixels);
544 }
545
546 // Tests GetImage with an inconsistent 2D texture.
TEST_P(GetImageTest,InconsistentTexture2D)547 TEST_P(GetImageTest, InconsistentTexture2D)
548 {
549 // Verify the extension is enabled.
550 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
551
552 std::vector<GLColor> expectedData = {GLColor::red, GLColor::blue, GLColor::green,
553 GLColor::yellow};
554
555 glViewport(0, 0, kSmallSize, kSmallSize);
556
557 // Draw once with simple texture.
558 GLTexture tex;
559 glBindTexture(GL_TEXTURE_2D, tex);
560 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
561 expectedData.data());
562 // The texture becomes inconsistent because a second 2x2 image does not fit in the mip chain.
563 glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, kSmallSize, kSmallSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
564 expectedData.data());
565
566 // Pack pixels tightly.
567 glPixelStorei(GL_PACK_ALIGNMENT, 1);
568
569 // Verify GetImage.
570 std::vector<GLColor> actualData(kSmallSize * kSmallSize, GLColor::white);
571 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
572 EXPECT_GL_NO_ERROR();
573 EXPECT_EQ(expectedData, actualData);
574
575 std::fill(actualData.begin(), actualData.end(), GLColor::white);
576 glGetTexImageANGLE(GL_TEXTURE_2D, 1, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
577 EXPECT_GL_NO_ERROR();
578 EXPECT_EQ(expectedData, actualData);
579 }
580
581 // Test GetImage with non-defined textures.
TEST_P(GetImageTest,EmptyTexture)582 TEST_P(GetImageTest, EmptyTexture)
583 {
584 // Verify the extension is enabled.
585 ASSERT_TRUE(IsGLExtensionEnabled(kExtensionName));
586
587 GLTexture tex;
588 glBindTexture(GL_TEXTURE_2D, tex);
589
590 std::vector<GLColor> expectedData(4, GLColor::white);
591 std::vector<GLColor> actualData(4, GLColor::white);
592 glGetTexImageANGLE(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, actualData.data());
593 EXPECT_GL_NO_ERROR();
594 EXPECT_EQ(expectedData, actualData);
595 }
596
597 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTest);
598 ANGLE_INSTANTIATE_TEST(GetImageTest, ES2_VULKAN(), ES3_VULKAN());
599
600 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestES31);
601 ANGLE_INSTANTIATE_TEST(GetImageTestES31, ES31_VULKAN());
602
603 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetImageTestNoExtensions);
604 ANGLE_INSTANTIATE_TEST(GetImageTestNoExtensions, ES2_VULKAN(), ES3_VULKAN());
605
606 } // namespace