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 "random_utils.h"
15 
16 using namespace angle;
17 
18 namespace
19 {
20 
21 class ReadPixelsTest : public ANGLETest
22 {
23   protected:
ReadPixelsTest()24     ReadPixelsTest()
25     {
26         setWindowWidth(32);
27         setWindowHeight(32);
28         setConfigRedBits(8);
29         setConfigGreenBits(8);
30         setConfigBlueBits(8);
31         setConfigAlphaBits(8);
32     }
33 };
34 
35 // Test out of bounds framebuffer reads.
TEST_P(ReadPixelsTest,OutOfBounds)36 TEST_P(ReadPixelsTest, OutOfBounds)
37 {
38     // TODO: re-enable once root cause of http://anglebug.com/1413 is fixed
39     if (IsAndroid() && IsAdreno() && IsOpenGLES())
40     {
41         std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
42         return;
43     }
44 
45     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
46     glClear(GL_COLOR_BUFFER_BIT);
47     EXPECT_GL_NO_ERROR();
48 
49     GLsizei pixelsWidth = 32;
50     GLsizei pixelsHeight = 32;
51     GLint offset = 16;
52     std::vector<GLColor> pixels((pixelsWidth + offset) * (pixelsHeight + offset));
53 
54     glReadPixels(-offset, -offset, pixelsWidth + offset, pixelsHeight + offset, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
55     EXPECT_GL_NO_ERROR();
56 
57     // Expect that all pixels which fell within the framebuffer are red
58     for (int y = pixelsHeight / 2; y < pixelsHeight; y++)
59     {
60         for (int x = pixelsWidth / 2; x < pixelsWidth; x++)
61         {
62             EXPECT_EQ(GLColor::red, pixels[y * (pixelsWidth + offset) + x]);
63         }
64     }
65 }
66 
67 class ReadPixelsPBOTest : public ReadPixelsTest
68 {
69   protected:
ReadPixelsPBOTest()70     ReadPixelsPBOTest() : mPBO(0), mTexture(0), mFBO(0) {}
71 
SetUp()72     void SetUp() override
73     {
74         ANGLETest::SetUp();
75 
76         glGenBuffers(1, &mPBO);
77         glGenFramebuffers(1, &mFBO);
78 
79         Reset(4 * getWindowWidth() * getWindowHeight(), 4, 1);
80     }
81 
Reset(GLuint bufferSize,GLuint fboWidth,GLuint fboHeight)82     void Reset(GLuint bufferSize, GLuint fboWidth, GLuint fboHeight)
83     {
84         glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
85         glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW);
86         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
87 
88         glDeleteTextures(1, &mTexture);
89         glGenTextures(1, &mTexture);
90         glBindTexture(GL_TEXTURE_2D, mTexture);
91         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, fboWidth, fboHeight);
92 
93         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
94         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
95         glBindFramebuffer(GL_FRAMEBUFFER, 0);
96 
97         ASSERT_GL_NO_ERROR();
98     }
99 
TearDown()100     void TearDown() override
101     {
102         glDeleteBuffers(1, &mPBO);
103         glDeleteTextures(1, &mTexture);
104         glDeleteFramebuffers(1, &mFBO);
105 
106         ANGLETest::TearDown();
107     }
108 
109     GLuint mPBO     = 0;
110     GLuint mTexture = 0;
111     GLuint mFBO     = 0;
112 };
113 
114 // Test basic usage of PBOs.
TEST_P(ReadPixelsPBOTest,Basic)115 TEST_P(ReadPixelsPBOTest, Basic)
116 {
117     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
118     glClear(GL_COLOR_BUFFER_BIT);
119     EXPECT_GL_NO_ERROR();
120 
121     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
122     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
123 
124     GLvoid *mappedPtr  = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
125     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
126     EXPECT_GL_NO_ERROR();
127 
128     EXPECT_EQ(GLColor::red, dataColor[0]);
129 
130     glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
131     EXPECT_GL_NO_ERROR();
132 }
133 
134 // Test an error is generated when the PBO is too small.
TEST_P(ReadPixelsPBOTest,PBOTooSmall)135 TEST_P(ReadPixelsPBOTest, PBOTooSmall)
136 {
137     Reset(4 * 16 * 16 - 1, 16, 16);
138 
139     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
140     glClear(GL_COLOR_BUFFER_BIT);
141     EXPECT_GL_NO_ERROR();
142 
143     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
144     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
145 
146     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
147 }
148 
149 // Test an error is generated when the PBO is mapped.
TEST_P(ReadPixelsPBOTest,PBOMapped)150 TEST_P(ReadPixelsPBOTest, PBOMapped)
151 {
152     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
153     glClear(GL_COLOR_BUFFER_BIT);
154     EXPECT_GL_NO_ERROR();
155 
156     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
157     glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
158     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
159 
160     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
161 }
162 
163 // Test that binding a PBO to ARRAY_BUFFER works as expected.
TEST_P(ReadPixelsPBOTest,ArrayBufferTarget)164 TEST_P(ReadPixelsPBOTest, ArrayBufferTarget)
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     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
174     glBindBuffer(GL_ARRAY_BUFFER, mPBO);
175 
176     GLvoid *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
177     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
178     EXPECT_GL_NO_ERROR();
179 
180     EXPECT_EQ(GLColor::red, dataColor[0]);
181 
182     glUnmapBuffer(GL_ARRAY_BUFFER);
183     EXPECT_GL_NO_ERROR();
184 }
185 
186 // Test that using a PBO does not overwrite existing data.
TEST_P(ReadPixelsPBOTest,ExistingDataPreserved)187 TEST_P(ReadPixelsPBOTest, ExistingDataPreserved)
188 {
189     // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
190     if (IsAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
191     {
192         std::cout << "Test disabled on AMD OpenGL." << std::endl;
193         return;
194     }
195 
196     // Clear backbuffer to red
197     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
198     glClear(GL_COLOR_BUFFER_BIT);
199     EXPECT_GL_NO_ERROR();
200 
201     // Read 16x16 region from red backbuffer to PBO
202     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
203     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
204 
205     // Clear backbuffer to green
206     glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
207     glClear(GL_COLOR_BUFFER_BIT);
208     EXPECT_GL_NO_ERROR();
209 
210     // Read 16x16 region from green backbuffer to PBO at offset 16
211     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(16));
212     GLvoid *mappedPtr  = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
213     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
214     EXPECT_GL_NO_ERROR();
215 
216     // Test pixel 0 is red (existing data)
217     EXPECT_EQ(GLColor::red, dataColor[0]);
218 
219     // Test pixel 16 is green (new data)
220     EXPECT_EQ(GLColor::green, dataColor[16]);
221 
222     glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
223     EXPECT_GL_NO_ERROR();
224 }
225 
226 // Test that calling SubData preserves PBO data.
TEST_P(ReadPixelsPBOTest,SubDataPreservesContents)227 TEST_P(ReadPixelsPBOTest, SubDataPreservesContents)
228 {
229     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
230     glClear(GL_COLOR_BUFFER_BIT);
231     EXPECT_GL_NO_ERROR();
232 
233     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
234     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
235 
236     unsigned char data[4] = { 1, 2, 3, 4 };
237 
238     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
239     glBindBuffer(GL_ARRAY_BUFFER, mPBO);
240     glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
241 
242     GLvoid *mappedPtr  = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
243     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
244     EXPECT_GL_NO_ERROR();
245 
246     EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[0]);
247 
248     glUnmapBuffer(GL_ARRAY_BUFFER);
249     EXPECT_GL_NO_ERROR();
250 }
251 
252 // Same as the prior test, but with an offset.
TEST_P(ReadPixelsPBOTest,SubDataOffsetPreservesContents)253 TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents)
254 {
255     // TODO: re-enable once root cause of http://anglebug.com/1415 is fixed
256     if (IsAndroid() && IsAdreno() && IsOpenGLES())
257     {
258         std::cout << "Test skipped on Adreno OpenGLES on Android." << std::endl;
259         return;
260     }
261 
262     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
263     glClear(GL_COLOR_BUFFER_BIT);
264     EXPECT_GL_NO_ERROR();
265 
266     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
267     glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
268 
269     unsigned char data[4] = { 1, 2, 3, 4 };
270 
271     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
272     glBindBuffer(GL_ARRAY_BUFFER, mPBO);
273     glBufferSubData(GL_ARRAY_BUFFER, 16, 4, data);
274 
275     GLvoid *mappedPtr  = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
276     GLColor *dataColor = static_cast<GLColor *>(mappedPtr);
277     EXPECT_GL_NO_ERROR();
278 
279     EXPECT_EQ(GLColor::red, dataColor[0]);
280     EXPECT_EQ(GLColor(1, 2, 3, 4), dataColor[4]);
281 
282     glUnmapBuffer(GL_ARRAY_BUFFER);
283     EXPECT_GL_NO_ERROR();
284 }
285 
286 class ReadPixelsPBODrawTest : public ReadPixelsPBOTest
287 {
288   protected:
ReadPixelsPBODrawTest()289     ReadPixelsPBODrawTest() : mProgram(0), mPositionVBO(0) {}
290 
SetUp()291     void SetUp() override
292     {
293         ReadPixelsPBOTest::SetUp();
294 
295         const char *vertexShaderSrc =
296             "attribute vec4 aTest; attribute vec2 aPosition; varying vec4 vTest;\n"
297             "void main()\n"
298             "{\n"
299             "    vTest        = aTest;\n"
300             "    gl_Position  = vec4(aPosition, 0.0, 1.0);\n"
301             "    gl_PointSize = 1.0;\n"
302             "}";
303 
304         const char *fragmentShaderSrc =
305             "precision mediump float; varying vec4 vTest;\n"
306             "void main()\n"
307             "{\n"
308             "    gl_FragColor = vTest;\n"
309             "}";
310 
311         mProgram = CompileProgram(vertexShaderSrc, fragmentShaderSrc);
312         ASSERT_NE(0u, mProgram);
313 
314         glGenBuffers(1, &mPositionVBO);
315         glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
316         glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_DYNAMIC_DRAW);
317         glBindBuffer(GL_ARRAY_BUFFER, 0);
318     }
319 
TearDown()320     void TearDown() override
321     {
322         glDeleteProgram(mProgram);
323         glDeleteBuffers(1, &mPositionVBO);
324         ReadPixelsPBOTest::TearDown();
325     }
326 
327     GLuint mProgram;
328     GLuint mPositionVBO;
329 };
330 
331 // Test that we can draw with PBO data.
TEST_P(ReadPixelsPBODrawTest,DrawWithPBO)332 TEST_P(ReadPixelsPBODrawTest, DrawWithPBO)
333 {
334     GLColor color(1, 2, 3, 4);
335     glBindTexture(GL_TEXTURE_2D, mTexture);
336     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
337     EXPECT_GL_NO_ERROR();
338 
339     glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
340     EXPECT_GL_NO_ERROR();
341 
342     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
343     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
344     glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
345     EXPECT_GL_NO_ERROR();
346 
347     float positionData[] = { 0.5f, 0.5f };
348 
349     glUseProgram(mProgram);
350     glViewport(0, 0, 1, 1);
351     glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
352     glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData);
353     EXPECT_GL_NO_ERROR();
354 
355     GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
356     EXPECT_NE(-1, positionLocation);
357 
358     GLint testLocation = glGetAttribLocation(mProgram, "aTest");
359     EXPECT_NE(-1, testLocation);
360 
361     glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
362     glEnableVertexAttribArray(positionLocation);
363     EXPECT_GL_NO_ERROR();
364 
365     glBindBuffer(GL_ARRAY_BUFFER, mPBO);
366     glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
367     glEnableVertexAttribArray(testLocation);
368     EXPECT_GL_NO_ERROR();
369 
370     glDrawArrays(GL_POINTS, 0, 1);
371     EXPECT_GL_NO_ERROR();
372 
373     color = GLColor(0, 0, 0, 0);
374     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &color);
375     EXPECT_GL_NO_ERROR();
376 
377     EXPECT_EQ(GLColor(1, 2, 3, 4), color);
378 }
379 
380 class ReadPixelsMultisampleTest : public ReadPixelsTest
381 {
382   protected:
ReadPixelsMultisampleTest()383     ReadPixelsMultisampleTest() : mFBO(0), mRBO(0), mPBO(0) {}
384 
SetUp()385     void SetUp() override
386     {
387         ANGLETest::SetUp();
388 
389         glGenFramebuffers(1, &mFBO);
390         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
391 
392         glGenRenderbuffers(1, &mRBO);
393         glBindRenderbuffer(GL_RENDERBUFFER, mRBO);
394 
395         glGenBuffers(1, &mPBO);
396         glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
397         glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
398                      GL_STATIC_DRAW);
399         glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
400 
401         ASSERT_GL_NO_ERROR();
402     }
403 
TearDown()404     void TearDown() override
405     {
406         ANGLETest::TearDown();
407 
408         glDeleteFramebuffers(1, &mFBO);
409         glDeleteRenderbuffers(1, &mRBO);
410         glDeleteBuffers(1, &mPBO);
411     }
412 
413     GLuint mFBO;
414     GLuint mRBO;
415     GLuint mPBO;
416 };
417 
418 // Test ReadPixels from a multisampled framebuffer.
TEST_P(ReadPixelsMultisampleTest,BasicClear)419 TEST_P(ReadPixelsMultisampleTest, BasicClear)
420 {
421     if (getClientMajorVersion() < 3 && !extensionEnabled("GL_ANGLE_framebuffer_multisample"))
422     {
423         std::cout << "Test skipped because ES3 or GL_ANGLE_framebuffer_multisample is not available." << std::endl;
424         return;
425     }
426 
427     if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
428     {
429         glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
430     }
431     else
432     {
433         glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
434     }
435 
436     glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRBO);
437     ASSERT_GL_NO_ERROR();
438 
439     glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
440     glClear(GL_COLOR_BUFFER_BIT);
441 
442     glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
443     EXPECT_GL_NO_ERROR();
444 
445     glReadPixels(0, 0, 1, 1, GL_RGBA8, GL_UNSIGNED_BYTE, NULL);
446     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
447 }
448 
449 class ReadPixelsTextureTest : public ANGLETest
450 {
451   public:
ReadPixelsTextureTest()452     ReadPixelsTextureTest() : mFBO(0), mTexture(0)
453     {
454         setWindowWidth(32);
455         setWindowHeight(32);
456         setConfigRedBits(8);
457         setConfigGreenBits(8);
458         setConfigBlueBits(8);
459         setConfigAlphaBits(8);
460     }
461 
SetUp()462     void SetUp() override
463     {
464         ANGLETest::SetUp();
465 
466         glGenTextures(1, &mTexture);
467         glGenFramebuffers(1, &mFBO);
468         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
469     }
470 
TearDown()471     void TearDown() override
472     {
473         glDeleteFramebuffers(1, &mFBO);
474         glDeleteTextures(1, &mTexture);
475 
476         ANGLETest::TearDown();
477     }
478 
initTexture(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)479     void initTexture(GLenum textureTarget,
480                      GLint levels,
481                      GLint attachmentLevel,
482                      GLint attachmentLayer)
483     {
484         glBindTexture(textureTarget, mTexture);
485         glTexStorage3D(textureTarget, levels, GL_RGBA8, 4, 4, 4);
486         glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture, attachmentLevel,
487                                   attachmentLayer);
488         initializeTextureData(textureTarget, levels);
489     }
490 
testRead(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)491     void testRead(GLenum textureTarget, GLint levels, GLint attachmentLevel, GLint attachmentLayer)
492     {
493         initTexture(textureTarget, levels, attachmentLevel, attachmentLayer);
494         verifyColor(attachmentLevel, attachmentLayer);
495     }
496 
initPBO()497     void initPBO()
498     {
499         glGenBuffers(1, &mBuffer);
500         glBindBuffer(GL_PIXEL_PACK_BUFFER, mBuffer);
501         glBufferData(GL_PIXEL_PACK_BUFFER, sizeof(angle::GLColor), nullptr, GL_STREAM_COPY);
502         ASSERT_GL_NO_ERROR();
503     }
504 
testPBORead(GLenum textureTarget,GLint levels,GLint attachmentLevel,GLint attachmentLayer)505     void testPBORead(GLenum textureTarget,
506                      GLint levels,
507                      GLint attachmentLevel,
508                      GLint attachmentLayer)
509     {
510         initPBO();
511         initTexture(textureTarget, levels, attachmentLevel, attachmentLayer);
512         verifyPBO(attachmentLevel, attachmentLayer);
513     }
514 
515     // Give each {level,layer} pair a (probably) unique color via random.
getColorValue(GLint level,GLint layer)516     GLuint getColorValue(GLint level, GLint layer)
517     {
518         mRNG.reseed(level + layer * 32);
519         return mRNG.randomUInt();
520     }
521 
verifyColor(GLint level,GLint layer)522     void verifyColor(GLint level, GLint layer)
523     {
524         angle::GLColor colorValue(getColorValue(level, layer));
525         EXPECT_PIXEL_COLOR_EQ(0, 0, colorValue);
526     }
527 
verifyPBO(GLint level,GLint layer)528     void verifyPBO(GLint level, GLint layer)
529     {
530         glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
531 
532         angle::GLColor expectedColor(getColorValue(level, layer));
533         void *mapPointer =
534             glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, sizeof(angle::GLColor), GL_MAP_READ_BIT);
535         ASSERT_NE(nullptr, mapPointer);
536         angle::GLColor actualColor;
537         memcpy(&actualColor, mapPointer, sizeof(angle::GLColor));
538         glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
539         ASSERT_GL_NO_ERROR();
540         EXPECT_EQ(expectedColor, actualColor);
541     }
542 
initializeTextureData(GLenum textureTarget,GLint levels)543     void initializeTextureData(GLenum textureTarget, GLint levels)
544     {
545         for (GLint level = 0; level < levels; ++level)
546         {
547             GLint mipSize = 4 >> level;
548             GLint layers  = (textureTarget == GL_TEXTURE_3D ? mipSize : 4);
549 
550             size_t layerSize = mipSize * mipSize;
551             std::vector<GLuint> textureData(layers * layerSize);
552 
553             for (GLint layer = 0; layer < layers; ++layer)
554             {
555                 GLuint colorValue = getColorValue(level, layer);
556                 size_t offset = (layer * layerSize);
557                 std::fill(textureData.begin() + offset, textureData.begin() + offset + layerSize,
558                           colorValue);
559             }
560 
561             glTexSubImage3D(textureTarget, level, 0, 0, 0, mipSize, mipSize, layers, GL_RGBA,
562                             GL_UNSIGNED_BYTE, textureData.data());
563         }
564     }
565 
566     angle::RNG mRNG;
567     GLuint mFBO;
568     GLuint mTexture;
569     GLuint mBuffer;
570 };
571 
572 // Test 3D attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment3D)573 TEST_P(ReadPixelsTextureTest, BasicAttachment3D)
574 {
575     testRead(GL_TEXTURE_3D, 1, 0, 0);
576 }
577 
578 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment3D)579 TEST_P(ReadPixelsTextureTest, MipAttachment3D)
580 {
581     testRead(GL_TEXTURE_3D, 2, 1, 0);
582 }
583 
584 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment3D)585 TEST_P(ReadPixelsTextureTest, LayerAttachment3D)
586 {
587     testRead(GL_TEXTURE_3D, 1, 0, 1);
588 }
589 
590 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment3D)591 TEST_P(ReadPixelsTextureTest, MipLayerAttachment3D)
592 {
593     testRead(GL_TEXTURE_3D, 2, 1, 1);
594 }
595 
596 // Test 2D array attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment2DArray)597 TEST_P(ReadPixelsTextureTest, BasicAttachment2DArray)
598 {
599     testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
600 }
601 
602 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment2DArray)603 TEST_P(ReadPixelsTextureTest, MipAttachment2DArray)
604 {
605     testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
606 }
607 
608 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment2DArray)609 TEST_P(ReadPixelsTextureTest, LayerAttachment2DArray)
610 {
611     testRead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
612 }
613 
614 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment2DArray)615 TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArray)
616 {
617     testRead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
618 }
619 
620 // Test 3D attachment PBO readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment3DPBO)621 TEST_P(ReadPixelsTextureTest, BasicAttachment3DPBO)
622 {
623     testPBORead(GL_TEXTURE_3D, 1, 0, 0);
624 }
625 
626 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment3DPBO)627 TEST_P(ReadPixelsTextureTest, MipAttachment3DPBO)
628 {
629     testPBORead(GL_TEXTURE_3D, 2, 1, 0);
630 }
631 
632 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment3DPBO)633 TEST_P(ReadPixelsTextureTest, LayerAttachment3DPBO)
634 {
635     testPBORead(GL_TEXTURE_3D, 1, 0, 1);
636 }
637 
638 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment3DPBO)639 TEST_P(ReadPixelsTextureTest, MipLayerAttachment3DPBO)
640 {
641     testPBORead(GL_TEXTURE_3D, 2, 1, 1);
642 }
643 
644 // Test 2D array attachment readback.
TEST_P(ReadPixelsTextureTest,BasicAttachment2DArrayPBO)645 TEST_P(ReadPixelsTextureTest, BasicAttachment2DArrayPBO)
646 {
647     testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 0);
648 }
649 
650 // Test 3D attachment readback, non-zero mip.
TEST_P(ReadPixelsTextureTest,MipAttachment2DArrayPBO)651 TEST_P(ReadPixelsTextureTest, MipAttachment2DArrayPBO)
652 {
653     testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 0);
654 }
655 
656 // Test 3D attachment readback, non-zero layer.
TEST_P(ReadPixelsTextureTest,LayerAttachment2DArrayPBO)657 TEST_P(ReadPixelsTextureTest, LayerAttachment2DArrayPBO)
658 {
659     testPBORead(GL_TEXTURE_2D_ARRAY, 1, 0, 1);
660 }
661 
662 // Test 3D attachment readback, non-zero mip and layer.
TEST_P(ReadPixelsTextureTest,MipLayerAttachment2DArrayPBO)663 TEST_P(ReadPixelsTextureTest, MipLayerAttachment2DArrayPBO)
664 {
665     testPBORead(GL_TEXTURE_2D_ARRAY, 2, 1, 1);
666 }
667 
668 // a test class to be used for error checking of glReadPixels
669 class ReadPixelsErrorTest : public ReadPixelsTest
670 {
671   protected:
ReadPixelsErrorTest()672     ReadPixelsErrorTest() : mTexture(0), mFBO(0) {}
673 
SetUp()674     void SetUp() override
675     {
676         ANGLETest::SetUp();
677 
678         glGenTextures(1, &mTexture);
679         glBindTexture(GL_TEXTURE_2D, mTexture);
680         glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 1);
681 
682         glGenFramebuffers(1, &mFBO);
683         glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
684         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
685         glBindFramebuffer(GL_FRAMEBUFFER, 0);
686 
687         ASSERT_GL_NO_ERROR();
688     }
689 
TearDown()690     void TearDown() override
691     {
692         ANGLETest::TearDown();
693 
694         glDeleteTextures(1, &mTexture);
695         glDeleteFramebuffers(1, &mFBO);
696     }
697 
698     GLuint mTexture;
699     GLuint mFBO;
700 };
701 
702 //  The test verifies that glReadPixels generates a GL_INVALID_OPERATION error
703 //  when the read buffer is GL_NONE.
704 //  Reference: GLES 3.0.4, Section 4.3.2 Reading Pixels
TEST_P(ReadPixelsErrorTest,ReadBufferIsNone)705 TEST_P(ReadPixelsErrorTest, ReadBufferIsNone)
706 {
707     glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
708     glReadBuffer(GL_NONE);
709     std::vector<GLubyte> pixels(4);
710     glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
711     EXPECT_GL_ERROR(GL_INVALID_OPERATION);
712 }
713 
714 }  // anonymous namespace
715 
716 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
717 ANGLE_INSTANTIATE_TEST(ReadPixelsTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
718 ANGLE_INSTANTIATE_TEST(ReadPixelsPBOTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
719 ANGLE_INSTANTIATE_TEST(ReadPixelsPBODrawTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
720 ANGLE_INSTANTIATE_TEST(ReadPixelsMultisampleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
721 ANGLE_INSTANTIATE_TEST(ReadPixelsTextureTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
722 ANGLE_INSTANTIATE_TEST(ReadPixelsErrorTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
723