• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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