blob: 15ccd9491ebbd3025508f1cfe9a3c5ba580e07b5 [file] [log] [blame]
Jamie Madillfa05f602015-05-07 13:47:11 -04001//
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//
Jamie Madill3e1b4f82016-01-27 12:39:27 -05006// ReadPixelsTest:
7// Tests calls related to glReadPixels.
8//
Jamie Madillfa05f602015-05-07 13:47:11 -04009
Corentin Wallezd3970de2015-05-14 11:07:48 -040010#include "test_utils/ANGLETest.h"
Geoff Langf11dbdb2013-10-23 14:37:58 -040011
Jamie Madill3e1b4f82016-01-27 12:39:27 -050012#include <array>
13
14#include "random_utils.h"
15
Jamie Madillfa05f602015-05-07 13:47:11 -040016using namespace angle;
Austin Kinross18b931d2014-09-29 12:58:31 -070017
Jamie Madill3e1b4f82016-01-27 12:39:27 -050018namespace
19{
20
Geoff Langf11dbdb2013-10-23 14:37:58 -040021class ReadPixelsTest : public ANGLETest
22{
Jamie Madillfa05f602015-05-07 13:47:11 -040023 protected:
24 ReadPixelsTest()
Geoff Langf11dbdb2013-10-23 14:37:58 -040025 {
26 setWindowWidth(32);
27 setWindowHeight(32);
28 setConfigRedBits(8);
29 setConfigGreenBits(8);
30 setConfigBlueBits(8);
31 setConfigAlphaBits(8);
32 }
33};
34
Jamie Madill3e1b4f82016-01-27 12:39:27 -050035// Test out of bounds reads.
Jamie Madillfa05f602015-05-07 13:47:11 -040036TEST_P(ReadPixelsTest, OutOfBounds)
Geoff Langf11dbdb2013-10-23 14:37:58 -040037{
38 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
39 glClear(GL_COLOR_BUFFER_BIT);
40 EXPECT_GL_NO_ERROR();
41
42 GLsizei pixelsWidth = 32;
43 GLsizei pixelsHeight = 32;
Jamie Madill1eb5bd72014-03-28 10:43:39 -040044 GLint offset = 16;
45 std::vector<GLubyte> pixels((pixelsWidth + offset) * (pixelsHeight + offset) * 4);
Geoff Langf11dbdb2013-10-23 14:37:58 -040046
Jamie Madillb4fd0c92014-10-01 17:40:24 -040047 glReadPixels(-offset, -offset, pixelsWidth + offset, pixelsHeight + offset, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
Geoff Langf11dbdb2013-10-23 14:37:58 -040048 EXPECT_GL_NO_ERROR();
49
50 for (int y = pixelsHeight / 2; y < pixelsHeight; y++)
51 {
52 for (int x = pixelsWidth / 2; x < pixelsWidth; x++)
53 {
Jamie Madillb4fd0c92014-10-01 17:40:24 -040054 const GLubyte* pixel = &pixels[0] + ((y * (pixelsWidth + offset) + x) * 4);
Jamie Madill1eb5bd72014-03-28 10:43:39 -040055 unsigned int r = static_cast<unsigned int>(pixel[0]);
56 unsigned int g = static_cast<unsigned int>(pixel[1]);
57 unsigned int b = static_cast<unsigned int>(pixel[2]);
58 unsigned int a = static_cast<unsigned int>(pixel[3]);
Geoff Langf11dbdb2013-10-23 14:37:58 -040059
60 // Expect that all pixels which fell within the framebuffer are red
Corentin Wallez322653b2015-06-17 18:33:56 +020061 EXPECT_EQ(255u, r);
62 EXPECT_EQ(0u, g);
63 EXPECT_EQ(0u, b);
64 EXPECT_EQ(255u, a);
Geoff Langf11dbdb2013-10-23 14:37:58 -040065 }
66 }
67}
Jamie Madill8a7bed82014-05-01 14:51:07 -040068
Jamie Madill3e1b4f82016-01-27 12:39:27 -050069class ReadPixelsPBOTest : public ReadPixelsTest
70{
71 protected:
72 ReadPixelsPBOTest() : mPBO(0), mTexture(0), mFBO(0) {}
73
74 void SetUp() override
75 {
76 ANGLETest::SetUp();
77
78 glGenBuffers(1, &mPBO);
79 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
80 glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
81 GL_STATIC_DRAW);
82 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
83
84 glGenTextures(1, &mTexture);
85 glBindTexture(GL_TEXTURE_2D, mTexture);
86 glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 4, 1);
87
88 glGenFramebuffers(1, &mFBO);
89 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
90 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
91 glBindFramebuffer(GL_FRAMEBUFFER, 0);
92
93 ASSERT_GL_NO_ERROR();
94 }
95
96 void TearDown() override
97 {
98 ANGLETest::TearDown();
99
100 glDeleteBuffers(1, &mPBO);
101 glDeleteTextures(1, &mTexture);
102 glDeleteFramebuffers(1, &mFBO);
103 }
104
105 GLuint mPBO;
106 GLuint mTexture;
107 GLuint mFBO;
108};
109
110// Test that binding a PBO to ARRAY_BUFFER works as expected.
111TEST_P(ReadPixelsPBOTest, ArrayBufferTarget)
Jamie Madill8a7bed82014-05-01 14:51:07 -0400112{
113 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
114 glClear(GL_COLOR_BUFFER_BIT);
115 EXPECT_GL_NO_ERROR();
116
117 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
118 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
119
120 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
121 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
122
123 GLvoid *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
124 unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
125 EXPECT_GL_NO_ERROR();
126
127 EXPECT_EQ(255, dataPtr[0]);
128 EXPECT_EQ(0, dataPtr[1]);
129 EXPECT_EQ(0, dataPtr[2]);
130 EXPECT_EQ(255, dataPtr[3]);
131
132 glUnmapBuffer(GL_ARRAY_BUFFER);
133 EXPECT_GL_NO_ERROR();
134}
Jamie Madill2b5c9cb2014-04-29 16:17:22 -0400135
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500136// Test that using a PBO does not overwrite existing data.
137TEST_P(ReadPixelsPBOTest, ExistingDataPreserved)
Jamie Madill2b5c9cb2014-04-29 16:17:22 -0400138{
Geoff Lange0cc2a42016-01-20 10:58:17 -0500139 // TODO(geofflang): Figure out why this fails on AMD OpenGL (http://anglebug.com/1291)
140 if (isAMD() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE)
141 {
142 std::cout << "Test disabled on AMD OpenGL." << std::endl;
143 return;
144 }
145
Jamie Madill2b5c9cb2014-04-29 16:17:22 -0400146 // Clear backbuffer to red
147 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
148 glClear(GL_COLOR_BUFFER_BIT);
149 EXPECT_GL_NO_ERROR();
150
151 // Read 16x16 region from red backbuffer to PBO
152 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
153 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
154
155 // Clear backbuffer to green
156 glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
157 glClear(GL_COLOR_BUFFER_BIT);
158 EXPECT_GL_NO_ERROR();
159
160 // Read 16x16 region from green backbuffer to PBO at offset 16
161 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*>(16));
162 GLvoid * mappedPtr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, 32, GL_MAP_READ_BIT);
163 unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
164 EXPECT_GL_NO_ERROR();
165
166 // Test pixel 0 is red (existing data)
167 EXPECT_EQ(255, dataPtr[0]);
168 EXPECT_EQ(0, dataPtr[1]);
169 EXPECT_EQ(0, dataPtr[2]);
170 EXPECT_EQ(255, dataPtr[3]);
171
172 // Test pixel 16 is green (new data)
173 EXPECT_EQ(0, dataPtr[16 * 4 + 0]);
174 EXPECT_EQ(255, dataPtr[16 * 4 + 1]);
175 EXPECT_EQ(0, dataPtr[16 * 4 + 2]);
176 EXPECT_EQ(255, dataPtr[16 * 4 + 3]);
177
178 glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
179 EXPECT_GL_NO_ERROR();
180}
Jamie Madill14764a02014-05-08 10:19:20 -0400181
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500182// Test that calling SubData preserves PBO data.
183TEST_P(ReadPixelsPBOTest, SubDataPreservesContents)
Jamie Madill14764a02014-05-08 10:19:20 -0400184{
185 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
186 glClear(GL_COLOR_BUFFER_BIT);
187 EXPECT_GL_NO_ERROR();
188
189 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
190 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
191
192 unsigned char data[4] = { 1, 2, 3, 4 };
193
194 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
195 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
196 glBufferSubData(GL_ARRAY_BUFFER, 0, 4, data);
197
198 GLvoid *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
199 unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
200 EXPECT_GL_NO_ERROR();
201
202 EXPECT_EQ(1, dataPtr[0]);
203 EXPECT_EQ(2, dataPtr[1]);
204 EXPECT_EQ(3, dataPtr[2]);
205 EXPECT_EQ(4, dataPtr[3]);
206
207 glUnmapBuffer(GL_ARRAY_BUFFER);
208 EXPECT_GL_NO_ERROR();
209}
210
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500211// Same as the prior test, but with an offset.
212TEST_P(ReadPixelsPBOTest, SubDataOffsetPreservesContents)
Jamie Madill14764a02014-05-08 10:19:20 -0400213{
214 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
215 glClear(GL_COLOR_BUFFER_BIT);
216 EXPECT_GL_NO_ERROR();
217
218 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
219 glReadPixels(0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_BYTE, 0);
220
221 unsigned char data[4] = { 1, 2, 3, 4 };
222
223 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
224 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
225 glBufferSubData(GL_ARRAY_BUFFER, 16, 4, data);
226
227 GLvoid *mappedPtr = glMapBufferRange(GL_ARRAY_BUFFER, 0, 32, GL_MAP_READ_BIT);
228 unsigned char *dataPtr = static_cast<unsigned char *>(mappedPtr);
229 EXPECT_GL_NO_ERROR();
230
231 EXPECT_EQ(255, dataPtr[0]);
232 EXPECT_EQ(0, dataPtr[1]);
233 EXPECT_EQ(0, dataPtr[2]);
234 EXPECT_EQ(255, dataPtr[3]);
235
236 EXPECT_EQ(1, dataPtr[16]);
237 EXPECT_EQ(2, dataPtr[17]);
238 EXPECT_EQ(3, dataPtr[18]);
239 EXPECT_EQ(4, dataPtr[19]);
240
241 glUnmapBuffer(GL_ARRAY_BUFFER);
242 EXPECT_GL_NO_ERROR();
243}
Jamie Madill5fedd012014-05-08 10:19:36 -0400244
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500245class ReadPixelsPBODrawTest : public ReadPixelsPBOTest
246{
247 protected:
248 ReadPixelsPBODrawTest() : mProgram(0), mPositionVBO(0) {}
249
250 void SetUp() override
251 {
252 ReadPixelsPBOTest::SetUp();
253
254 const char *vertexShaderSrc =
255 "attribute vec4 aTest; attribute vec2 aPosition; varying vec4 vTest;\n"
256 "void main()\n"
257 "{\n"
258 " vTest = aTest;\n"
259 " gl_Position = vec4(aPosition, 0.0, 1.0);\n"
260 " gl_PointSize = 1.0;\n"
261 "}";
262
263 const char *fragmentShaderSrc =
264 "precision mediump float; varying vec4 vTest;\n"
265 "void main()\n"
266 "{\n"
267 " gl_FragColor = vTest;\n"
268 "}";
269
270 mProgram = CompileProgram(vertexShaderSrc, fragmentShaderSrc);
271 ASSERT_NE(0u, mProgram);
272
273 glGenBuffers(1, &mPositionVBO);
274 glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
275 glBufferData(GL_ARRAY_BUFFER, 128, NULL, GL_DYNAMIC_DRAW);
276 glBindBuffer(GL_ARRAY_BUFFER, 0);
277 }
278
279 void TearDown() override
280 {
281 glDeleteProgram(mProgram);
282 glDeleteBuffers(1, &mPositionVBO);
283 ReadPixelsPBOTest::TearDown();
284 }
285
286 GLuint mProgram;
287 GLuint mPositionVBO;
288};
289
290// Test that we can draw with PBO data.
291TEST_P(ReadPixelsPBODrawTest, DrawWithPBO)
Jamie Madill5fedd012014-05-08 10:19:36 -0400292{
293 unsigned char data[4] = { 1, 2, 3, 4 };
294
295 glBindTexture(GL_TEXTURE_2D, mTexture);
296 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
297 EXPECT_GL_NO_ERROR();
298
Jamie Madill5fedd012014-05-08 10:19:36 -0400299 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFBO);
300 EXPECT_GL_NO_ERROR();
301
302 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
303 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 0);
304 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
305 EXPECT_GL_NO_ERROR();
306
307 float positionData[] = { 0.5f, 0.5f };
308
309 glUseProgram(mProgram);
310 glViewport(0, 0, 1, 1);
311 glBindBuffer(GL_ARRAY_BUFFER, mPositionVBO);
312 glBufferSubData(GL_ARRAY_BUFFER, 0, 1 * 2 * 4, positionData);
313 EXPECT_GL_NO_ERROR();
314
315 GLint positionLocation = glGetAttribLocation(mProgram, "aPosition");
316 EXPECT_NE(-1, positionLocation);
317
318 GLint testLocation = glGetAttribLocation(mProgram, "aTest");
319 EXPECT_NE(-1, testLocation);
320
321 glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0);
322 glEnableVertexAttribArray(positionLocation);
323 EXPECT_GL_NO_ERROR();
324
325 glBindBuffer(GL_ARRAY_BUFFER, mPBO);
326 glVertexAttribPointer(testLocation, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
327 glEnableVertexAttribArray(testLocation);
328 EXPECT_GL_NO_ERROR();
329
330 glDrawArrays(GL_POINTS, 0, 1);
331 EXPECT_GL_NO_ERROR();
332
333 memset(data, 0, 4);
334 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
335 EXPECT_GL_NO_ERROR();
336
337 EXPECT_EQ(1, data[0]);
338 EXPECT_EQ(2, data[1]);
339 EXPECT_EQ(3, data[2]);
340 EXPECT_EQ(4, data[3]);
341}
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400342
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500343class ReadPixelsMultisampleTest : public ReadPixelsTest
344{
345 protected:
346 ReadPixelsMultisampleTest() : mFBO(0), mRBO(0), mPBO(0) {}
347
348 void SetUp() override
349 {
350 ANGLETest::SetUp();
351
352 glGenFramebuffers(1, &mFBO);
353 glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
354
355 glGenRenderbuffers(1, &mRBO);
356 glBindRenderbuffer(GL_RENDERBUFFER, mRBO);
357
358 glGenBuffers(1, &mPBO);
359 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
360 glBufferData(GL_PIXEL_PACK_BUFFER, 4 * getWindowWidth() * getWindowHeight(), nullptr,
361 GL_STATIC_DRAW);
362 glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
363
364 ASSERT_GL_NO_ERROR();
365 }
366
367 void TearDown() override
368 {
369 ANGLETest::TearDown();
370
371 glDeleteFramebuffers(1, &mFBO);
372 glDeleteRenderbuffers(1, &mRBO);
373 glDeleteBuffers(1, &mPBO);
374 }
375
376 GLuint mFBO;
377 GLuint mRBO;
378 GLuint mPBO;
379};
380
381// Test ReadPixels from a multisampled framebuffer.
382TEST_P(ReadPixelsMultisampleTest, BasicClear)
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400383{
Geoff Langa8091652015-04-27 10:53:55 -0400384 if (getClientVersion() < 3 && !extensionEnabled("GL_ANGLE_framebuffer_multisample"))
385 {
386 std::cout << "Test skipped because ES3 or GL_ANGLE_framebuffer_multisample is not available." << std::endl;
387 return;
388 }
389
Geoff Langa8091652015-04-27 10:53:55 -0400390 if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
391 {
392 glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
393 }
394 else
395 {
396 glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 4, 4);
397 }
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400398
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500399 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRBO);
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400400 ASSERT_GL_NO_ERROR();
401
402 glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
403 glClear(GL_COLOR_BUFFER_BIT);
404
405 glBindBuffer(GL_PIXEL_PACK_BUFFER, mPBO);
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400406 EXPECT_GL_NO_ERROR();
407
408 glReadPixels(0, 0, 1, 1, GL_RGBA8, GL_UNSIGNED_BYTE, NULL);
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400409 EXPECT_GL_ERROR(GL_INVALID_OPERATION);
Jamie Madill4fbd36e2014-07-29 15:20:48 -0400410}
Jamie Madillfa05f602015-05-07 13:47:11 -0400411
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500412} // anonymous namespace
413
Jamie Madillfa05f602015-05-07 13:47:11 -0400414// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
Jamie Madill3e1b4f82016-01-27 12:39:27 -0500415ANGLE_INSTANTIATE_TEST(ReadPixelsTest, ES2_D3D11(), ES2_OPENGL(), ES2_OPENGLES());
416ANGLE_INSTANTIATE_TEST(ReadPixelsPBOTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
417ANGLE_INSTANTIATE_TEST(ReadPixelsPBODrawTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());
418ANGLE_INSTANTIATE_TEST(ReadPixelsMultisampleTest, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES());