1 //
2 // Copyright 2015 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 // ReadPixelsTest:
7 // Tests calls related to glReadPixels.
8 //
9
10 #include "test_utils/ANGLETest.h"
11
12 #include <array>
13
14 #include "test_utils/gl_raii.h"
15 #include "util/random_utils.h"
16
17 using namespace angle;
18
19 namespace
20 {
21
22 class ReadPixelsTest : public ANGLETest<>
23 {
24 protected:
ReadPixelsTest()25 ReadPixelsTest()
26 {
27 setWindowWidth(32);
28 setWindowHeight(32);
29 setConfigRedBits(8);
30 setConfigGreenBits(8);
31 setConfigBlueBits(8);
32 setConfigAlphaBits(8);
33 }
34 };
35
36 // Test out of bounds framebuffer reads.
TEST_P(ReadPixelsTest,OutOfBounds)37 TEST_P(ReadPixelsTest, OutOfBounds)
38 {
39 // TODO: re-enable once root cause of http://anglebug.com/1413 is fixed
40 ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
41
42 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
43 glClear(GL_COLOR_BUFFER_BIT);
44 EXPECT_GL_NO_ERROR();
45
46 GLsizei pixelsWidth = 32;
47 GLsizei pixelsHeight = 32;
48 GLint offset = 16;
49 std::vector<GLColor> pixels((pixelsWidth + offset) * (pixelsHeight + offset));
50
51 glReadPixels(-offset, -offset, pixelsWidth + offset, pixelsHeight + offset, GL_RGBA,
52 GL_UNSIGNED_BYTE, &pixels[0]);
53 EXPECT_GL_NO_ERROR();
54
55 // Expect that all pixels which fell within the framebuffer are red
56 for (int y = pixelsHeight / 2; y < pixelsHeight; y++)
57 {
58 for (int x = pixelsWidth / 2; x < pixelsWidth; x++)
59 {
60 EXPECT_EQ(GLColor::red, pixels[y * (pixelsWidth + offset) + x]);
61 }
62 }
63 }
64
65 class ReadPixelsPBONVTest : public ReadPixelsTest
66 {
67 protected:
ReadPixelsPBONVTest()68 ReadPixelsPBONVTest() : mPBO(0), mTexture(0), mFBO(0) {}
69
testSetUp()70 void testSetUp() override
71 {
72 glGenBuffers(1, &mPBO);
73 glGenFramebuffers(1, &mFBO);
74
75 Reset(4 * getWindowWidth() * getWindowHeight(), 4, 4);
76 }
77
Reset(GLuint bufferSize,GLuint fboWidth,GLuint fboHeight)78 virtual void Reset(GLuint bufferSize, GLuint fboWidth, GLuint fboHeight)
79 {
80 ANGLE_SKIP_TEST_IF(!hasPBOExts());
81
82 mPBOBufferSize = bufferSize;
83 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
84 glBufferData(GL_PIXEL_PACK_BUFFER, mPBOBufferSize, nullptr, GL_STATIC_DRAW);
85 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
86
87 glDeleteTextures(1, &mTexture);
88 glGenTextures(1, &mTexture);
89 glBindTexture(GL_TEXTURE_2D, mTexture);
90 glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, fboWidth, fboHeight);
91 mFBOWidth = fboWidth;
92 mFBOHeight = fboHeight;
93
94 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
95 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
96 glBindFramebuffer(GL_FRAMEBUFFER, 0);
97
98 ASSERT_GL_NO_ERROR();
99 }
100
testTearDown()101 void testTearDown() override
102 {
103 glDeleteBuffers(1, &mPBO);
104 glDeleteTextures(1, &mTexture);
105 glDeleteFramebuffers(1, &mFBO);
106 }
107
hasPBOExts() const108 bool hasPBOExts() const
109 {
110 return IsGLExtensionEnabled("GL_NV_pixel_buffer_object") &&
111 IsGLExtensionEnabled("GL_EXT_texture_storage");
112 }
113
114 GLuint mPBO = 0;
115 GLuint mTexture = 0;
116 GLuint mFBO = 0;
117 GLuint mFBOWidth = 0;
118 GLuint mFBOHeight = 0;
119 GLuint mPBOBufferSize = 0;
120 };
121
122 // Test basic usage of PBOs.
TEST_P(ReadPixelsPBONVTest,Basic)123 TEST_P(ReadPixelsPBONVTest, Basic)
124 {
125 ANGLE_SKIP_TEST_IF(!hasPBOExts() || !IsGLExtensionEnabled("GL_EXT_map_buffer_range") ||
126 !IsGLExtensionEnabled("GL_OES_mapbuffer"));
127
128 // http://anglebug.com/5022
129 ANGLE_SKIP_TEST_IF(IsWindows() && IsDesktopOpenGL());
130 // http://anglebug.com/5386
131 ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsDesktopOpenGL());
132
133 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
134 glClear(GL_COLOR_BUFFER_BIT);
135 // Clear last pixel to green
136 glScissor(15, 15, 1, 1);
137 glEnable(GL_SCISSOR_TEST);
138 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
139 glClear(GL_COLOR_BUFFER_BIT);
140 EXPECT_GL_NO_ERROR();
141
142 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
143 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
144
145 void *mappedPtr = glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, mPBOBufferSize, GL_MAP_READ_BIT);
146 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
147 EXPECT_GL_NO_ERROR();
148
149 EXPECT_EQ(GLColor::red, dataColor[0]);
150 EXPECT_EQ(GLColor::red, dataColor[16 * 16 - 2]);
151 EXPECT_EQ(GLColor::green, dataColor[16 * 16 - 1]);
152
153 glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
154 EXPECT_GL_NO_ERROR();
155 }
156
157 // Test that calling SubData preserves PBO data.
TEST_P(ReadPixelsPBONVTest,SubDataPreservesContents)158 TEST_P(ReadPixelsPBONVTest, SubDataPreservesContents)
159 {
160 ANGLE_SKIP_TEST_IF(!hasPBOExts() || !IsGLExtensionEnabled("GL_EXT_map_buffer_range") ||
161 !IsGLExtensionEnabled("GL_OES_mapbuffer"));
162
163 // anglebug.com/2185
164 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA() && IsDesktopOpenGL());
165
166 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
167 glClear(GL_COLOR_BUFFER_BIT);
168 EXPECT_GL_NO_ERROR();
169
170 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
171 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
172
173 unsigned char data[4] = {1, 2, 3, 4};
174
175 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
176 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
177 glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
178
179 void *mappedPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
180 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
181 EXPECT_GL_NO_ERROR();
182
183 EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[0]);
184 EXPECT_EQ(GLColor::red, dataColor[1]);
185
186 glUnmapBufferOES(GL_ARRAY_BUFFER);
187 EXPECT_GL_NO_ERROR();
188 }
189
190 // Test that calling ReadPixels with GL_DYNAMIC_DRAW buffer works
TEST_P(ReadPixelsPBONVTest,DynamicPBO)191 TEST_P(ReadPixelsPBONVTest, DynamicPBO)
192 {
193 ANGLE_SKIP_TEST_IF(!hasPBOExts() || !IsGLExtensionEnabled("GL_EXT_map_buffer_range") ||
194 !IsGLExtensionEnabled("GL_OES_mapbuffer"));
195
196 // anglebug.com/2185
197 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA() && IsDesktopOpenGL());
198
199 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
200 glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
201 GL_DYNAMIC_DRAW);
202
203 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
204 glClear(GL_COLOR_BUFFER_BIT);
205 EXPECT_GL_NO_ERROR();
206
207 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
208
209 unsigned char data[4] = {1, 2, 3, 4};
210
211 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
212 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
213 glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
214
215 void *mappedPtr = glMapBufferRangeEXT(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
216 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
217 EXPECT_GL_NO_ERROR();
218
219 EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[0]);
220 EXPECT_EQ(GLColor::red, dataColor[1]);
221
222 glUnmapBufferOES(GL_ARRAY_BUFFER);
223 EXPECT_GL_NO_ERROR();
224 }
225
TEST_P(ReadPixelsPBONVTest,ReadFromFBO)226 TEST_P(ReadPixelsPBONVTest, ReadFromFBO)
227 {
228 ANGLE_SKIP_TEST_IF(!hasPBOExts() || !IsGLExtensionEnabled("GL_EXT_map_buffer_range") ||
229 !IsGLExtensionEnabled("GL_OES_mapbuffer"));
230
231 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
232 glViewport(0, 0, mFBOWidth, mFBOHeight);
233 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
234 glClear(GL_COLOR_BUFFER_BIT);
235 // Clear last pixel to green
236 glScissor(mFBOWidth - 1, mFBOHeight - 1, 1, 1);
237 glEnable(GL_SCISSOR_TEST);
238 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
239 glClear(GL_COLOR_BUFFER_BIT);
240 EXPECT_GL_NO_ERROR();
241
242 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
243 glReadPixels(0, 0, mFBOWidth, mFBOHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
244
245 void *mappedPtr =
246 glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4 * mFBOWidth * mFBOHeight, GL_MAP_READ_BIT);
247 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
248 EXPECT_GL_NO_ERROR();
249
250 EXPECT_EQ(GLColor::red, dataColor[0]);
251 EXPECT_EQ(GLColor::red, dataColor[mFBOWidth * mFBOHeight - 2]);
252 EXPECT_EQ(GLColor::green, dataColor[mFBOWidth * mFBOHeight - 1]);
253
254 glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
255 EXPECT_GL_NO_ERROR();
256 }
257
258 // Test calling ReadPixels with a non-zero "data" param into a PBO
TEST_P(ReadPixelsPBONVTest,ReadFromFBOWithDataOffset)259 TEST_P(ReadPixelsPBONVTest, ReadFromFBOWithDataOffset)
260 {
261 ANGLE_SKIP_TEST_IF(!hasPBOExts() || !IsGLExtensionEnabled("GL_EXT_map_buffer_range") ||
262 !IsGLExtensionEnabled("GL_OES_mapbuffer"));
263
264 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
265 glViewport(0, 0, mFBOWidth, mFBOHeight);
266 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
267 glClear(GL_COLOR_BUFFER_BIT);
268 // Clear first pixel to green
269 glScissor(0, 0, 1, 1);
270 glEnable(GL_SCISSOR_TEST);
271 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
272 glClear(GL_COLOR_BUFFER_BIT);
273 EXPECT_GL_NO_ERROR();
274
275 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
276
277 // Read (height - 1) rows offset by width * 4.
278 glReadPixels(0, 0, mFBOWidth, mFBOHeight - 1, GL_RGBA, GL_UNSIGNED_BYTE,
279 reinterpret_cast<void *>(mFBOWidth * static_cast<uintptr_t>(4)));
280
281 void *mappedPtr =
282 glMapBufferRangeEXT(GL_PIXEL_PACK_BUFFER, 0, 4 * mFBOWidth * mFBOHeight, GL_MAP_READ_BIT);
283 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
284 EXPECT_GL_NO_ERROR();
285
286 EXPECT_EQ(GLColor::green, dataColor[mFBOWidth]);
287 EXPECT_EQ(GLColor::red, dataColor[mFBOWidth + 1]);
288 EXPECT_EQ(GLColor::red, dataColor[mFBOWidth * mFBOHeight - 1]);
289
290 glUnmapBufferOES(GL_PIXEL_PACK_BUFFER);
291 EXPECT_GL_NO_ERROR();
292 }
293
294 class ReadPixelsPBOTest : public ReadPixelsPBONVTest
295 {
296 protected:
ReadPixelsPBOTest()297 ReadPixelsPBOTest() : ReadPixelsPBONVTest() {}
298
testSetUp()299 void testSetUp() override
300 {
301 glGenBuffers(1, &mPBO);
302 glGenFramebuffers(1, &mFBO);
303
304 Reset(4 * getWindowWidth() * getWindowHeight(), 4, 1);
305 }
306
Reset(GLuint bufferSize,GLuint fboWidth,GLuint fboHeight)307 void Reset(GLuint bufferSize, GLuint fboWidth, GLuint fboHeight) override
308 {
309 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
310 glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
311 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
312
313 glDeleteTextures(1, &mTexture);
314 glGenTextures(1, &mTexture);
315 glBindTexture(GL_TEXTURE_2D, mTexture);
316 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, fboWidth, fboHeight);
317
318 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
319 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
320 glBindFramebuffer(GL_FRAMEBUFFER, 0);
321
322 mFBOWidth = fboWidth;
323 mFBOHeight = fboHeight;
324
325 ASSERT_GL_NO_ERROR();
326 }
327 };
328
329 // Test basic usage of PBOs.
TEST_P(ReadPixelsPBOTest,Basic)330 TEST_P(ReadPixelsPBOTest, Basic)
331 {
332 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
333 glClear(GL_COLOR_BUFFER_BIT);
334 EXPECT_GL_NO_ERROR();
335
336 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
337 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
338
339 void *mappedPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
340 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
341 EXPECT_GL_NO_ERROR();
342
343 EXPECT_EQ(GLColor::red, dataColor[0]);
344
345 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
346 EXPECT_GL_NO_ERROR();
347 }
348
349 // Test copy to snorm
TEST_P(ReadPixelsPBOTest,Snorm)350 TEST_P(ReadPixelsPBOTest, Snorm)
351 {
352 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
353
354 constexpr GLsizei kSize = 6;
355
356 GLRenderbuffer rbo;
357 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
358 glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_SNORM, kSize, kSize);
359 ASSERT_GL_NO_ERROR();
360
361 GLFramebuffer fbo;
362 glBindFramebuffer(GL_FRAMEBUFFER, fbo);
363 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
364 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
365 ASSERT_GL_NO_ERROR();
366
367 glEnable(GL_SCISSOR_TEST);
368 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
369 glScissor(0, 0, kSize / 2, kSize / 2);
370 glClear(GL_COLOR_BUFFER_BIT);
371
372 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
373 glScissor(kSize / 2, 0, kSize / 2, kSize / 2);
374 glClear(GL_COLOR_BUFFER_BIT);
375
376 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
377 glScissor(0, kSize / 2, kSize / 2, kSize / 2);
378 glClear(GL_COLOR_BUFFER_BIT);
379
380 glClearColor(1.0f, 1.0f, 0.0f, 1.0f);
381 glScissor(kSize / 2, kSize / 2, kSize / 2, kSize / 2);
382 glClear(GL_COLOR_BUFFER_BIT);
383 EXPECT_GL_NO_ERROR();
384
385 glDisable(GL_SCISSOR_TEST);
386
387 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
388 glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_BYTE, 0);
389
390 std::vector<GLColor> result(kSize * kSize);
391 void *mappedPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, kSize * kSize * 4, GL_MAP_READ_BIT);
392 memcpy(result.data(), mappedPtr, kSize * kSize * 4);
393 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
394 EXPECT_GL_NO_ERROR();
395
396 auto verify = [&](const GLColor expect[4]) {
397 for (size_t i = 0; i < kSize; ++i)
398 {
399 for (size_t j = 0; j < kSize; ++j)
400 {
401 uint32_t index = (i < kSize / 2 ? 0 : 1) << 1 | (j < kSize / 2 ? 0 : 1);
402 EXPECT_EQ(result[i * kSize + j], expect[index]) << i << " " << j;
403 }
404 }
405 };
406
407 // The image should have the following colors
408 //
409 // +---+---+
410 // | R | G |
411 // +---+---+
412 // | B | Y |
413 // +---+---+
414 //
415 const GLColor kColors[4] = {
416 GLColor(127, 0, 0, 127),
417 GLColor(0, 127, 0, 127),
418 GLColor(0, 0, 127, 127),
419 GLColor(127, 127, 0, 127),
420 };
421 verify(kColors);
422
423 // Test again, but this time with reverse order
424 if (EnsureGLExtensionEnabled("GL_ANGLE_pack_reverse_row_order"))
425 {
426 glPixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, GL_TRUE);
427 glReadPixels(0, 0, kSize, kSize, GL_RGBA, GL_BYTE, 0);
428
429 mappedPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, kSize * kSize * 4, GL_MAP_READ_BIT);
430 memcpy(result.data(), mappedPtr, kSize * kSize * 4);
431 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
432 EXPECT_GL_NO_ERROR();
433
434 const GLColor kReversedColors[4] = {
435 GLColor(0, 0, 127, 127),
436 GLColor(127, 127, 0, 127),
437 GLColor(127, 0, 0, 127),
438 GLColor(0, 127, 0, 127),
439 };
440 verify(kReversedColors);
441 }
442 }
443
444 // Test an error is generated when the PBO is too small.
TEST_P(ReadPixelsPBOTest,PBOTooSmall)445 TEST_P(ReadPixelsPBOTest, PBOTooSmall)
446 {
447 Reset(4 * 16 * 16 - 1, 16, 16);
448
449 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
450 glClear(GL_COLOR_BUFFER_BIT);
451 EXPECT_GL_NO_ERROR();
452
453 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
454 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
455
456 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
457 }
458
459 // Test an error is generated when the PBO is mapped.
TEST_P(ReadPixelsPBOTest,PBOMapped)460 TEST_P(ReadPixelsPBOTest, PBOMapped)
461 {
462 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
463 glClear(GL_COLOR_BUFFER_BIT);
464 EXPECT_GL_NO_ERROR();
465
466 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
467 glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
468 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
469
470 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
471 }
472
473 // Test that binding a PBO to ARRAY_BUFFER works as expected.
TEST_P(ReadPixelsPBOTest,ArrayBufferTarget)474 TEST_P(ReadPixelsPBOTest, ArrayBufferTarget)
475 {
476 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
477 glClear(GL_COLOR_BUFFER_BIT);
478 EXPECT_GL_NO_ERROR();
479
480 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
481 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
482
483 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
484 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
485
486 void *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
487 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
488 EXPECT_GL_NO_ERROR();
489
490 EXPECT_EQ(GLColor::red, dataColor[0]);
491
492 glUnmapBuffer(GL_ARRAY_BUFFER);
493 EXPECT_GL_NO_ERROR();
494 }
495
496 // Test that using a PBO does not overwrite existing data.
TEST_P(ReadPixelsPBOTest,ExistingDataPreserved)497 TEST_P(ReadPixelsPBOTest, ExistingDataPreserved)
498 {
499 // Clear backbuffer to red
500 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
501 glClear(GL_COLOR_BUFFER_BIT);
502 EXPECT_GL_NO_ERROR();
503
504 // Read 16x16 region from red backbuffer to PBO
505 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
506 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
507
508 // Clear backbuffer to green
509 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
510 glClear(GL_COLOR_BUFFER_BIT);
511 EXPECT_GL_NO_ERROR();
512
513 // Read 16x16 region from green backbuffer to PBO at offset 16
514 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(16));
515 void *mappedPtr =
516 glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 17 * sizeof(GLColor), GL_MAP_READ_BIT);
517 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
518 EXPECT_GL_NO_ERROR();
519
520 // Test pixel 0 is red (existing data)
521 EXPECT_EQ(GLColor::red, dataColor[0]);
522
523 // Test pixel 16 is green (new data)
524 EXPECT_EQ(GLColor::green, dataColor[16]);
525
526 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
527 EXPECT_GL_NO_ERROR();
528 }
529
530 // Test that calling SubData preserves PBO data.
TEST_P(ReadPixelsPBOTest,SubDataPreservesContents)531 TEST_P(ReadPixelsPBOTest, SubDataPreservesContents)
532 {
533 // anglebug.com/2185
534 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA() && IsDesktopOpenGL());
535
536 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
537 glClear(GL_COLOR_BUFFER_BIT);
538 EXPECT_GL_NO_ERROR();
539
540 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
541 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
542
543 unsigned char data[4] = {1, 2, 3, 4};
544
545 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
546 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
547 glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
548
549 void *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
550 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
551 EXPECT_GL_NO_ERROR();
552
553 EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[0]);
554
555 glUnmapBuffer(GL_ARRAY_BUFFER);
556 EXPECT_GL_NO_ERROR();
557 }
558
559 // Same as the prior test, but with an offset.
TEST_P(ReadPixelsPBOTest,SubDataOffsetPreservesContents)560 TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents)
561 {
562 // anglebug.com/1415
563 ANGLE_SKIP_TEST_IF(IsNexus5X() && IsAdreno() && IsOpenGLES());
564 // anglebug.com/2185
565 ANGLE_SKIP_TEST_IF(IsMac() && IsNVIDIA() && IsDesktopOpenGL());
566
567 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
568 glClear(GL_COLOR_BUFFER_BIT);
569 EXPECT_GL_NO_ERROR();
570
571 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
572 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
573
574 unsigned char data[4] = {1, 2, 3, 4};
575
576 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
577 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
578 glBufferSubData(GL_ARRAY_BUFFER, 16, 4, data);
579
580 void *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
581 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
582 EXPECT_GL_NO_ERROR();
583
584 EXPECT_EQ(GLColor::red, dataColor[0]);
585 EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[4]);
586
587 glUnmapBuffer(GL_ARRAY_BUFFER);
588 EXPECT_GL_NO_ERROR();
589 }
590
591 // Test that uploading data to buffer that's in use then writing to it as PBO works.
TEST_P(ReadPixelsPBOTest,UseAsUBOThenUpdateThenReadFromFBO)592 TEST_P(ReadPixelsPBOTest, UseAsUBOThenUpdateThenReadFromFBO)
593 {
594 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
595 glViewport(0, 0, mFBOWidth, mFBOHeight);
596
597 const std::array<GLColor, 4> kInitialData = {GLColor::red, GLColor::red, GLColor::red,
598 GLColor::red};
599 const std::array<GLColor, 4> kUpdateData = {GLColor::white, GLColor::white, GLColor::white,
600 GLColor::white};
601
602 GLBuffer buffer;
603 glBindBuffer(GL_UNIFORM_BUFFER, buffer);
604 glBufferData(GL_UNIFORM_BUFFER, sizeof(kInitialData), kInitialData.data(), GL_DYNAMIC_COPY);
605 glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
606 EXPECT_GL_NO_ERROR();
607
608 constexpr char kVerifyUBO[] = R"(#version 300 es
609 precision mediump float;
610 uniform block {
611 uvec4 data;
612 } ubo;
613 out vec4 colorOut;
614 void main()
615 {
616 if (all(equal(ubo.data, uvec4(0xFF0000FFu))))
617 colorOut = vec4(0, 1.0, 0, 1.0);
618 else
619 colorOut = vec4(1.0, 0, 0, 1.0);
620 })";
621
622 ANGLE_GL_PROGRAM(verifyUbo, essl3_shaders::vs::Simple(), kVerifyUBO);
623 drawQuad(verifyUbo, essl3_shaders::PositionAttrib(), 0.5);
624 EXPECT_GL_NO_ERROR();
625
626 // Update buffer data
627 glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(kInitialData), kUpdateData.data());
628 EXPECT_GL_NO_ERROR();
629
630 // Clear first pixel to blue
631 glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
632 glScissor(0, 0, 1, 1);
633 glEnable(GL_SCISSOR_TEST);
634 glClear(GL_COLOR_BUFFER_BIT);
635 EXPECT_GL_NO_ERROR();
636
637 glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer);
638
639 // Read the framebuffer pixels
640 glReadPixels(0, 0, mFBOWidth, mFBOHeight, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
641
642 void *mappedPtr =
643 glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, sizeof(kInitialData), GL_MAP_READ_BIT);
644 GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
645 EXPECT_GL_NO_ERROR();
646
647 EXPECT_EQ(GLColor::blue, dataColor[0]);
648 EXPECT_EQ(GLColor::green, dataColor[1]);
649 EXPECT_EQ(GLColor::green, dataColor[2]);
650 EXPECT_EQ(GLColor::green, dataColor[3]);
651
652 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
653 EXPECT_GL_NO_ERROR();
654
655 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
656 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
657 EXPECT_PIXEL_COLOR_EQ(1, 0, GLColor::green);
658 EXPECT_PIXEL_COLOR_EQ(2, 0, GLColor::green);
659 EXPECT_PIXEL_COLOR_EQ(3, 0, GLColor::green);
660 }
661
662 class ReadPixelsPBODrawTest : public ReadPixelsPBOTest
663 {
664 protected:
ReadPixelsPBODrawTest()665 ReadPixelsPBODrawTest() : mProgram(0), mPositionVBO(0) {}
666
testSetUp()667 void testSetUp() override
668 {
669 ReadPixelsPBOTest::testSetUp();
670
671 constexpr char kVS[] =
672 "attribute vec4 aTest; attribute vec2 aPosition; varying vec4 vTest;\n"
673 "void main()\n"
674 "{\n"
675 " vTest = aTest;\n"
676 " gl_Position = vec4(aPosition, 0.0, 1.0);\n"
677 " gl_PointSize = 1.0;\n"
678 "}";
679
680 constexpr char kFS[] =
681 "precision mediump float; varying vec4 vTest;\n"
682 "void main()\n"
683 "{\n"
684 " gl_FragColor = vTest;\n"
685 "}";
686
687 mProgram = CompileProgram(kVS, kFS);
688 ASSERT_NE(0u, mProgram);
689
690 glGenBuffers(1, &mPositionVBO);
691 glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
692 glBufferData(GL_ARRAY_BUFFER, 128, nullptr, GL_DYNAMIC_DRAW);
693 glBindBuffer(GL_ARRAY_BUFFER, 0);
694 }
695
testTearDown()696 void testTearDown() override
697 {
698 glDeleteProgram(mProgram);
699 glDeleteBuffers(1, &mPositionVBO);
700 ReadPixelsPBOTest::testTearDown();
701 }
702
703 GLuint mProgram;
704 GLuint mPositionVBO;
705 };
706
707 // Test that we can draw with PBO data.
TEST_P(ReadPixelsPBODrawTest,DrawWithPBO)708 TEST_P(ReadPixelsPBODrawTest, DrawWithPBO)
709 {
710 GLColor color(1, 2, 3, 4);
711 glBindTexture(GL_TEXTURE_2D, mTexture);
712 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
713 EXPECT_GL_NO_ERROR();
714
715 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
716 EXPECT_GL_NO_ERROR();
717
718 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
719 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
720 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
721 EXPECT_GL_NO_ERROR();
722
723 float positionData[] = {0.5f, 0.5f};
724
725 glUseProgram(mProgram);
726 glViewport(0, 0, 1, 1);
727 glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
728 glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData);
729 EXPECT_GL_NO_ERROR();
730
731 GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
732 EXPECT_NE(-1, positionLocation);
733
734 GLint testLocation = glGetAttribLocation(mProgram, "aTest");
735 EXPECT_NE(-1, testLocation);
736
737 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
738 glEnableVertexAttribArray(positionLocation);
739 EXPECT_GL_NO_ERROR();
740
741 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
742 glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
743 glEnableVertexAttribArray(testLocation);
744 EXPECT_GL_NO_ERROR();
745
746 glDrawArrays(GL_POINTS, 0, 1);
747 EXPECT_GL_NO_ERROR();
748
749 color = GLColor(0, 0, 0, 0);
750 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
751 EXPECT_GL_NO_ERROR();
752
753 EXPECT_EQ(GLColor(1, 2, 3, 4), color);
754 }
755
756 // Test that we can correctly update a buffer bound to the vertex stage with PBO.
TEST_P(ReadPixelsPBODrawTest,UpdateVertexArrayWithPixelPack)757 TEST_P(ReadPixelsPBODrawTest, UpdateVertexArrayWithPixelPack)
758 {
759 glUseProgram(mProgram);
760 glViewport(0, 0, 1, 1);
761 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
762 ASSERT_GL_NO_ERROR();
763
764 // First draw with pre-defined data.
765 std::array<float, 2> positionData = {0.5f, 0.5f};
766
767 glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
768 glBufferSubData(GL_ARRAY_BUFFER, 0, positionData.size() * sizeof(positionData[0]),
769 positionData.data());
770 ASSERT_GL_NO_ERROR();
771
772 GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
773 EXPECT_NE(-1, positionLocation);
774
775 GLint testLocation = glGetAttribLocation(mProgram, "aTest");
776 EXPECT_NE(-1, testLocation);
777
778 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
779 glEnableVertexAttribArray(positionLocation);
780 ASSERT_GL_NO_ERROR();
781
782 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
783 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLColor), &GLColor::red);
784 glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
785 glEnableVertexAttribArray(testLocation);
786 ASSERT_GL_NO_ERROR();
787
788 glDrawArrays(GL_POINTS, 0, 1);
789 ASSERT_GL_NO_ERROR();
790
791 // Update the buffer bound to the VAO with a PBO.
792 glBindTexture(GL_TEXTURE_2D, mTexture);
793 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &GLColor::green);
794 ASSERT_GL_NO_ERROR();
795
796 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
797 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
798 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
799 ASSERT_GL_NO_ERROR();
800
801 // Draw again and verify the VAO has the updated data.
802 glDrawArrays(GL_POINTS, 0, 1);
803
804 EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
805 }
806
807 class ReadPixelsMultisampleTest : public ReadPixelsTest
808 {
809 protected:
ReadPixelsMultisampleTest()810 ReadPixelsMultisampleTest() : mFBO(0), mRBO(0), mPBO(0) {}
811
testSetUp()812 void testSetUp() override
813 {
814 glGenFramebuffers(1, &mFBO);
815 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
816
817 glGenRenderbuffers(1, &mRBO);
818 glBindRenderbuffer(GL_RENDERBUFFER, mRBO);
819
820 glGenBuffers(1, &mPBO);
821 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
822 glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
823 GL_STATIC_DRAW);
824 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
825
826 ASSERT_GL_NO_ERROR();
827 }
828
testTearDown()829 void testTearDown() override
830 {
831 glDeleteFramebuffers(1, &mFBO);
832 glDeleteRenderbuffers(1, &mRBO);
833 glDeleteBuffers(1, &mPBO);
834 }
835
836 GLuint mFBO;
837 GLuint mRBO;
838 GLuint mPBO;
839 };
840
841 // Test ReadPixels from a multisampled framebuffer.
TEST_P(ReadPixelsMultisampleTest,BasicClear)842 TEST_P(ReadPixelsMultisampleTest, BasicClear)
843 {
844 if (getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample"))
845 {
846 std::cout
847 << "Test skipped because ES3 or GL_ANGLE_framebuffer_multisample is not available."
848 << std::endl;
849 return;
850 }
851
852 if (IsGLExtensionEnabled("GL_ANGLE_framebuffer_multisample"))
853 {
854 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
855 }
856 else
857 {
858 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
859 }
860
861 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRBO);
862 ASSERT_GL_NO_ERROR();
863
864 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
865 glClear(GL_COLOR_BUFFER_BIT);
866
867 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
868 EXPECT_GL_NO_ERROR();
869
870 glReadPixels(0, 0, 1, 1, GL_RGBA8, GL_UNSIGNED_BYTE, nullptr);
871 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
872 }
873
874 class ReadPixelsTextureTest : public ANGLETest<>
875 {
876 public:
ReadPixelsTextureTest()877 ReadPixelsTextureTest() : mFBO(0), mTextureRGBA(0), mTextureBGRA(0)
878 {
879 setWindowWidth(32);
880 setWindowHeight(32);
881 setConfigRedBits(8);
882 setConfigGreenBits(8);
883 setConfigBlueBits(8);
884 setConfigAlphaBits(8);
885 }
886
testSetUp()887 void testSetUp() override
888 {
889 glGenTextures(1, &mTextureRGBA);
890 glGenTextures(1, &mTextureBGRA);
891 glGenFramebuffers(1, &mFBO);
892 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
893 }
894
testTearDown()895 void testTearDown() override
896 {
897 glDeleteFramebuffers(1, &mFBO);
898 glDeleteTextures(1, &mTextureRGBA);
899 glDeleteTextures(1, &mTextureBGRA);
900 }
901
initTextureRGBA(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)902 void initTextureRGBA(GLenum textureTarget,
903 GLint levels,
904 GLint attachmentLevel,
905 GLint attachmentLayer)
906 {
907 glBindTexture(textureTarget, mTextureRGBA);
908 glTexStorage3D(textureTarget, levels, GL_RGBA8, kSize, kSize, kSize);
909 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextureRGBA,
910 attachmentLevel, attachmentLayer);
911 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
912 ASSERT_GL_NO_ERROR();
913 initializeTextureData(textureTarget, levels, GL_RGBA);
914 }
915
initTextureBGRA(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)916 void initTextureBGRA(GLenum textureTarget,
917 GLint levels,
918 GLint attachmentLevel,
919 GLint attachmentLayer)
920 {
921 glBindTexture(textureTarget, mTextureBGRA);
922 for (GLint level = 0; level < levels; ++level)
923 {
924 glTexImage3D(textureTarget, level, GL_BGRA_EXT, kSize >> level, kSize >> level,
925 textureTarget == GL_TEXTURE_3D ? kSize >> level : kSize, 0, GL_BGRA_EXT,
926 GL_UNSIGNED_BYTE, nullptr);
927 }
928 glTexParameteri(textureTarget, GL_TEXTURE_BASE_LEVEL, 0);
929 glTexParameteri(textureTarget, GL_TEXTURE_MAX_LEVEL, levels - 1);
930 glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTextureBGRA,
931 attachmentLevel, attachmentLayer);
932 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
933 ASSERT_GL_NO_ERROR();
934 initializeTextureData(textureTarget, levels, GL_BGRA_EXT);
935 }
936
testRead(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)937 void testRead(GLenum textureTarget, GLint levels, GLint attachmentLevel, GLint attachmentLayer)
938 {
939 initTextureRGBA(textureTarget, levels, attachmentLevel, attachmentLayer);
940 verifyColor(attachmentLevel, attachmentLayer);
941
942 // Skip BGRA test on GL/Nvidia, leading to internal incomplete framebuffer error.
943 // http://anglebug.com/8239
944 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
945
946 if (IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"))
947 {
948 initTextureBGRA(textureTarget, levels, attachmentLevel, attachmentLayer);
949 verifyColor(attachmentLevel, attachmentLayer);
950 }
951 }
952
initPBO()953 void initPBO()
954 {
955 // Create a buffer big enough to hold mip 0 + allow some offset during readback.
956 glGenBuffers(1, &mBuffer);
957 glBindBuffer(GL_PIXEL_PACK_BUFFER, mBuffer);
958 glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(angle::GLColor) * 16 * 2, nullptr,
959 GL_STREAM_COPY);
960 ASSERT_GL_NO_ERROR();
961 }
962
testPBORead(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)963 void testPBORead(GLenum textureTarget,
964 GLint levels,
965 GLint attachmentLevel,
966 GLint attachmentLayer)
967 {
968 initPBO();
969 initTextureRGBA(textureTarget, levels, attachmentLevel, attachmentLayer);
970 verifyPBO(attachmentLevel, attachmentLayer);
971
972 // Skip BGRA test on GL/Nvidia, leading to internal incomplete framebuffer error.
973 // http://anglebug.com/8239
974 ANGLE_SKIP_TEST_IF(IsNVIDIA() && IsOpenGL());
975
976 if (IsGLExtensionEnabled("GL_EXT_texture_format_BGRA8888"))
977 {
978 initTextureBGRA(textureTarget, levels, attachmentLevel, attachmentLayer);
979 verifyPBO(attachmentLevel, attachmentLayer);
980 }
981 }
982
983 // Give each {level,layer} pair a (probably) unique color via random.
getColorValue(GLint level,GLint layer)984 GLuint getColorValue(GLint level, GLint layer)
985 {
986 mRNG.reseed(level + layer * 32);
987 return mRNG.randomUInt();
988 }
989
verifyColor(GLint level,GLint layer)990 void verifyColor(GLint level, GLint layer)
991 {
992 const angle::GLColor colorValue(getColorValue(level, layer));
993 const GLint size = kSize >> level;
994 EXPECT_PIXEL_RECT_EQ(0, 0, size, size, colorValue);
995 }
996
verifyPBO(GLint level,GLint layer)997 void verifyPBO(GLint level, GLint layer)
998 {
999 const GLint size = kSize >> level;
1000 const GLsizei offset = kSize * (level + layer);
1001 glReadPixels(0, 0, size, size, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<void *>(offset));
1002
1003 const std::vector<angle::GLColor> expectedColor(size * size, getColorValue(level, layer));
1004 std::vector<angle::GLColor> actualColor(size * size);
1005
1006 void *mapPointer = glMapBufferRange(GL_PIXEL_PACK_BUFFER, offset,
1007 sizeof(angle::GLColor) * size * size, GL_MAP_READ_BIT);
1008 ASSERT_NE(nullptr, mapPointer);
1009 memcpy(actualColor.data(), mapPointer, sizeof(angle::GLColor) * size * size);
1010 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
1011
1012 ASSERT_GL_NO_ERROR();
1013 EXPECT_EQ(expectedColor, actualColor);
1014 }
1015
initializeTextureData(GLenum textureTarget,GLint levels,GLenum format)1016 void initializeTextureData(GLenum textureTarget, GLint levels, GLenum format)
1017 {
1018 for (GLint level = 0; level < levels; ++level)
1019 {
1020 GLint mipSize = kSize >> level;
1021 GLint layers = (textureTarget == GL_TEXTURE_3D ? mipSize : kSize);
1022
1023 size_t layerSize = mipSize * mipSize;
1024 std::vector<GLuint> textureData(layers * layerSize);
1025
1026 for (GLint layer = 0; layer < layers; ++layer)
1027 {
1028 GLuint colorValue = getColorValue(level, layer);
1029 size_t offset = (layer * layerSize);
1030
1031 if (format == GL_BGRA_EXT)
1032 {
1033 const GLuint rb = colorValue & 0x00FF00FF;
1034 const GLuint br = (rb & 0xFF) << 16 | rb >> 16;
1035 const GLuint ga = colorValue & 0xFF00FF00;
1036 colorValue = ga | br;
1037 }
1038
1039 std::fill(textureData.begin() + offset, textureData.begin() + offset + layerSize,
1040 colorValue);
1041 }
1042
1043 glTexSubImage3D(textureTarget, level, 0, 0, 0, mipSize, mipSize, layers, format,
1044 GL_UNSIGNED_BYTE, textureData.data());
1045 }
1046 }
1047
1048 static constexpr GLint kSize = 4;
1049
1050 angle::RNG mRNG;
1051 GLuint mFBO;
1052 GLuint mTextureRGBA;
1053 GLuint mTextureBGRA;
1054 GLuint mBuffer;
1055 };
1056
1057 // Test 3D attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment3D)1058 TEST_P(ReadPixelsTextureTest, BasicAttachment3D)
1059 {
1060 testRead(GL_TEXTURE_3D, 1, 0, 0);
1061 }
1062
1063 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment3D)1064 TEST_P(ReadPixelsTextureTest, MipAttachment3D)
1065 {
1066 testRead(GL_TEXTURE_3D, 2, 1, 0);
1067 }
1068
1069 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment3D)1070 TEST_P(ReadPixelsTextureTest, LayerAttachment3D)
1071 {
1072 testRead(GL_TEXTURE_3D, 1, 0, 1);
1073 }
1074
1075 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment3D)1076 TEST_P(ReadPixelsTextureTest, MipLayerAttachment3D)
1077 {
1078 testRead(GL_TEXTURE_3D, 2, 1, 1);
1079 }
1080
1081 // Test 2D array attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment2DArray)1082 TEST_P(ReadPixelsTextureTest, BasicAttachment2DArray)
1083 {
1084 testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
1085 }
1086
1087 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment2DArray)1088 TEST_P(ReadPixelsTextureTest, MipAttachment2DArray)
1089 {
1090 testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
1091 }
1092
1093 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment2DArray)1094 TEST_P(ReadPixelsTextureTest, LayerAttachment2DArray)
1095 {
1096 testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
1097 }
1098
1099 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment2DArray)1100 TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArray)
1101 {
1102 testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
1103 }
1104
1105 // Test 3D attachment PBO readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment3DPBO)1106 TEST_P(ReadPixelsTextureTest, BasicAttachment3DPBO)
1107 {
1108 testPBORead(GL_TEXTURE_3D, 1, 0, 0);
1109 }
1110
1111 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment3DPBO)1112 TEST_P(ReadPixelsTextureTest, MipAttachment3DPBO)
1113 {
1114 testPBORead(GL_TEXTURE_3D, 2, 1, 0);
1115 }
1116
1117 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment3DPBO)1118 TEST_P(ReadPixelsTextureTest, LayerAttachment3DPBO)
1119 {
1120 // http://anglebug.com/5267
1121 ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
1122
1123 testPBORead(GL_TEXTURE_3D, 1, 0, 1);
1124 }
1125
1126 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment3DPBO)1127 TEST_P(ReadPixelsTextureTest, MipLayerAttachment3DPBO)
1128 {
1129 // http://anglebug.com/5267
1130 ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
1131
1132 testPBORead(GL_TEXTURE_3D, 2, 1, 1);
1133 }
1134
1135 // Test 2D array attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment2DArrayPBO)1136 TEST_P(ReadPixelsTextureTest, BasicAttachment2DArrayPBO)
1137 {
1138 testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
1139 }
1140
1141 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment2DArrayPBO)1142 TEST_P(ReadPixelsTextureTest, MipAttachment2DArrayPBO)
1143 {
1144 testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
1145 }
1146
1147 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment2DArrayPBO)1148 TEST_P(ReadPixelsTextureTest, LayerAttachment2DArrayPBO)
1149 {
1150 // http://anglebug.com/5267
1151 ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
1152
1153 testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
1154 }
1155
1156 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment2DArrayPBO)1157 TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArrayPBO)
1158 {
1159 // http://anglebug.com/5267
1160 ANGLE_SKIP_TEST_IF(IsMac() && IsIntelUHD630Mobile() && IsDesktopOpenGL());
1161
1162 testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
1163 }
1164
1165 // a test class to be used for error checking of glReadPixels
1166 class ReadPixelsErrorTest : public ReadPixelsTest
1167 {
1168 protected:
ReadPixelsErrorTest()1169 ReadPixelsErrorTest() : mTexture(0), mFBO(0) {}
1170
testSetUp()1171 void testSetUp() override
1172 {
1173 glGenTextures(1, &mTexture);
1174 glBindTexture(GL_TEXTURE_2D, mTexture);
1175 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 1);
1176
1177 glGenFramebuffers(1, &mFBO);
1178 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1179 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
1180 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1181
1182 ASSERT_GL_NO_ERROR();
1183 }
1184
testTearDown()1185 void testTearDown() override
1186 {
1187 glDeleteTextures(1, &mTexture);
1188 glDeleteFramebuffers(1, &mFBO);
1189 }
1190
testUnsupportedTypeConversions(std::vector<GLenum> internalFormats,std::vector<GLenum> unsupportedTypes)1191 void testUnsupportedTypeConversions(std::vector<GLenum> internalFormats,
1192 std::vector<GLenum> unsupportedTypes)
1193 {
1194 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1195 for (GLenum internalFormat : internalFormats)
1196 {
1197 GLRenderbuffer rbo;
1198 glBindRenderbuffer(GL_RENDERBUFFER, rbo);
1199 glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 1, 1);
1200 ASSERT_GL_NO_ERROR();
1201
1202 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
1203 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1204
1205 GLenum implementationFormat, implementationType;
1206 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT,
1207 reinterpret_cast<GLint *>(&implementationFormat));
1208 ASSERT_GL_NO_ERROR();
1209 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE,
1210 reinterpret_cast<GLint *>(&implementationType));
1211 ASSERT_GL_NO_ERROR();
1212
1213 for (GLenum type : unsupportedTypes)
1214 {
1215 uint8_t pixel[8] = {};
1216 if (implementationFormat != GL_RGBA || implementationType != type)
1217 {
1218 glReadPixels(0, 0, 1, 1, GL_RGBA, type, pixel);
1219 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1220 }
1221 }
1222 }
1223 }
1224
1225 GLuint mTexture;
1226 GLuint mFBO;
1227 };
1228
1229 // The test verifies that glReadPixels generates a GL_INVALID_OPERATION error
1230 // when the read buffer is GL_NONE.
1231 // Reference: GLES 3.0.4, Section 4.3.2 Reading Pixels
TEST_P(ReadPixelsErrorTest,ReadBufferIsNone)1232 TEST_P(ReadPixelsErrorTest, ReadBufferIsNone)
1233 {
1234 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1235 glReadBuffer(GL_NONE);
1236 std::vector<GLubyte> pixels(4);
1237 EXPECT_GL_NO_ERROR();
1238 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
1239 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
1240 }
1241
1242 // The test verifies that glReadPixels generates a GL_INVALID_OPERATION
1243 // error when reading signed 8-bit color buffers using incompatible types.
TEST_P(ReadPixelsErrorTest,ColorBufferSnorm8)1244 TEST_P(ReadPixelsErrorTest, ColorBufferSnorm8)
1245 {
1246 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1247
1248 testUnsupportedTypeConversions({GL_R8_SNORM, GL_RG8_SNORM, GL_RGBA8_SNORM},
1249 {GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT});
1250 }
1251
1252 // The test verifies that glReadPixels generates a GL_INVALID_OPERATION
1253 // error when reading signed 16-bit color buffers using incompatible types.
TEST_P(ReadPixelsErrorTest,ColorBufferSnorm16)1254 TEST_P(ReadPixelsErrorTest, ColorBufferSnorm16)
1255 {
1256 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_render_snorm"));
1257 ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_norm16"));
1258
1259 testUnsupportedTypeConversions({GL_R16_SNORM_EXT, GL_RG16_SNORM_EXT, GL_RGBA16_SNORM_EXT},
1260 {GL_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT});
1261 }
1262
1263 // a test class to be used for error checking of glReadPixels with WebGLCompatibility
1264 class ReadPixelsWebGLErrorTest : public ReadPixelsTest
1265 {
1266 protected:
ReadPixelsWebGLErrorTest()1267 ReadPixelsWebGLErrorTest() : mTexture(0), mFBO(0) { setWebGLCompatibilityEnabled(true); }
1268
testSetUp()1269 void testSetUp() override
1270 {
1271 glGenTextures(1, &mTexture);
1272 glBindTexture(GL_TEXTURE_2D, mTexture);
1273 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 1);
1274
1275 glGenFramebuffers(1, &mFBO);
1276 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1277 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
1278 ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
1279
1280 ASSERT_GL_NO_ERROR();
1281 }
1282
testTearDown()1283 void testTearDown() override
1284 {
1285 glDeleteTextures(1, &mTexture);
1286 glDeleteFramebuffers(1, &mFBO);
1287 }
1288
1289 GLuint mTexture;
1290 GLuint mFBO;
1291 };
1292
1293 // Test that WebGL context readpixels generates an error when reading GL_UNSIGNED_INT_24_8 type.
TEST_P(ReadPixelsWebGLErrorTest,TypeIsUnsignedInt24_8)1294 TEST_P(ReadPixelsWebGLErrorTest, TypeIsUnsignedInt24_8)
1295 {
1296 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1297 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
1298 glReadBuffer(GL_COLOR_ATTACHMENT0);
1299 std::vector<GLuint> pixels(4);
1300 EXPECT_GL_NO_ERROR();
1301 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_INT_24_8, pixels.data());
1302 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1303 }
1304
1305 // Test that WebGL context readpixels generates an error when reading GL_DEPTH_COMPONENT format.
TEST_P(ReadPixelsWebGLErrorTest,FormatIsDepthComponent)1306 TEST_P(ReadPixelsWebGLErrorTest, FormatIsDepthComponent)
1307 {
1308 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
1309 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
1310 glReadBuffer(GL_COLOR_ATTACHMENT0);
1311 std::vector<GLubyte> pixels(4);
1312 EXPECT_GL_NO_ERROR();
1313 glReadPixels(0, 0, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels.data());
1314 EXPECT_GL_ERROR(GL_INVALID_ENUM);
1315 }
1316
1317 } // anonymous namespace
1318
1319 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
1320 // tests should be run against.
1321 ANGLE_INSTANTIATE_TEST_ES2(ReadPixelsTest);
1322 ANGLE_INSTANTIATE_TEST_ES2(ReadPixelsPBONVTest);
1323
1324 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsPBOTest);
1325 ANGLE_INSTANTIATE_TEST_ES3(ReadPixelsPBOTest);
1326
1327 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsPBODrawTest);
1328 ANGLE_INSTANTIATE_TEST_ES3_AND(ReadPixelsPBODrawTest,
1329 ES3_VULKAN().enable(Feature::ForceFallbackFormat));
1330
1331 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsMultisampleTest);
1332 ANGLE_INSTANTIATE_TEST_ES3(ReadPixelsMultisampleTest);
1333
1334 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsTextureTest);
1335 ANGLE_INSTANTIATE_TEST_ES3(ReadPixelsTextureTest);
1336
1337 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsErrorTest);
1338 ANGLE_INSTANTIATE_TEST_ES3(ReadPixelsErrorTest);
1339
1340 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ReadPixelsWebGLErrorTest);
1341 ANGLE_INSTANTIATE_TEST_ES3(ReadPixelsWebGLErrorTest);
1342