1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/run_loop.h"
15 #include "gpu/command_buffer/tests/gl_manager.h"
16 #include "gpu/command_buffer/tests/gl_test_utils.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 class GLReadbackTest
: public testing::Test
{
24 virtual void SetUp() {
25 gl_
.Initialize(GLManager::Options());
28 virtual void TearDown() {
32 static void WaitForQueryCallback(int q
, base::Closure cb
) {
33 unsigned int done
= 0;
34 glGetQueryObjectuivEXT(q
, GL_QUERY_RESULT_AVAILABLE_EXT
, &done
);
38 base::MessageLoop::current()->PostDelayedTask(
40 base::Bind(&WaitForQueryCallback
, q
, cb
),
41 base::TimeDelta::FromMilliseconds(3));
45 void WaitForQuery(int q
) {
46 base::RunLoop run_loop
;
47 WaitForQueryCallback(q
, run_loop
.QuitClosure());
55 TEST_F(GLReadbackTest
, ReadPixelsWithPBOAndQuery
) {
56 const GLint kBytesPerPixel
= 4;
57 const GLint kWidth
= 2;
58 const GLint kHeight
= 2;
61 glClearColor(0.0, 0.0, 1.0, 1.0);
62 glClear(GL_COLOR_BUFFER_BIT
);
64 glGenQueriesEXT(1, &q
);
65 glBindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
, b
);
66 glBufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
,
67 kWidth
* kHeight
* kBytesPerPixel
,
70 glBeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
, q
);
71 glReadPixels(0, 0, kWidth
, kHeight
, GL_RGBA
, GL_UNSIGNED_BYTE
, 0);
72 glEndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM
);
76 // TODO(hubbe): Check that glMapBufferCHROMIUM does not block here.
77 unsigned char *data
= static_cast<unsigned char *>(
79 GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
,
82 EXPECT_EQ(data
[0], 0); // red
83 EXPECT_EQ(data
[1], 0); // green
84 EXPECT_EQ(data
[2], 255); // blue
85 glUnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
);
86 glBindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM
, 0);
87 glDeleteBuffers(1, &b
);
88 glDeleteQueriesEXT(1, &q
);
89 GLTestHelper::CheckGLError("no errors", __LINE__
);
92 static float HalfToFloat32(uint16 value
) {
93 int32 s
= (value
>> 15) & 0x00000001;
94 int32 e
= (value
>> 10) & 0x0000001f;
95 int32 m
= value
& 0x000003ff;
99 uint32 result
= s
<< 31;
100 return bit_cast
<float>(result
);
102 while (!(m
& 0x00000400)) {
110 } else if (e
== 31) {
112 uint32 result
= (s
<< 31) | 0x7f800000;
113 return bit_cast
<float>(result
);
115 uint32 result
= (s
<< 31) | 0x7f800000 | (m
<< 13);
116 return bit_cast
<float>(result
);
123 uint32 result
= (s
<< 31) | (e
<< 23) | m
;
124 return bit_cast
<float>(result
);
127 static GLuint
CompileShader(GLenum type
, const char *data
) {
128 const char *shaderStrings
[1] = { data
};
130 GLuint shader
= glCreateShader(type
);
131 glShaderSource(shader
, 1, shaderStrings
, NULL
);
132 glCompileShader(shader
);
134 GLint compile_status
= 0;
135 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &compile_status
);
136 if (compile_status
!= GL_TRUE
) {
137 glDeleteShader(shader
);
144 TEST_F(GLReadbackTest
, ReadPixelsFloat
) {
145 const GLsizei kTextureSize
= 4;
146 const GLfloat kDrawColor
[4] = { -10.9f
, 0.5f
, 10.5f
, 100.12f
};
147 const GLfloat kEpsilon
= 0.01f
;
154 TestFormat test_formats
[4];
155 size_t test_count
= 0;
156 const char *extensions
= reinterpret_cast<const char*>(
157 glGetString(GL_EXTENSIONS
));
158 if (strstr(extensions
, "GL_OES_texture_half_float") != NULL
) {
159 TestFormat rgb16f
= { GL_RGB
, GL_HALF_FLOAT_OES
, 3 };
160 test_formats
[test_count
++] = rgb16f
;
162 TestFormat rgba16f
= { GL_RGBA
, GL_HALF_FLOAT_OES
, 4 };
163 test_formats
[test_count
++] = rgba16f
;
165 if (strstr(extensions
, "GL_OES_texture_float") != NULL
) {
166 TestFormat rgb32f
= { GL_RGB
, GL_FLOAT
, 3 };
167 test_formats
[test_count
++] = rgb32f
;
169 TestFormat rgba32f
= { GL_RGBA
, GL_FLOAT
, 4 };
170 test_formats
[test_count
++] = rgba32f
;
173 const char *vs_source
=
174 "precision mediump float;\n"
175 "attribute vec4 a_position;\n"
177 " gl_Position = a_position;\n"
180 GLuint vertex_shader
= CompileShader(GL_VERTEX_SHADER
, vs_source
);
181 ASSERT_NE(vertex_shader
, GLuint(0));
183 const char *fs_source
=
184 "precision mediump float;\n"
185 "uniform vec4 u_color;\n"
187 " gl_FragColor = u_color;\n"
190 GLuint fragment_shader
= CompileShader(GL_FRAGMENT_SHADER
, fs_source
);
191 ASSERT_NE(fragment_shader
, GLuint(0));
193 GLuint program
= glCreateProgram();
194 glAttachShader(program
, vertex_shader
);
195 glDeleteShader(vertex_shader
);
196 glAttachShader(program
, fragment_shader
);
197 glDeleteShader(fragment_shader
);
198 glLinkProgram(program
);
200 GLint link_status
= 0;
201 glGetProgramiv(program
, GL_LINK_STATUS
, &link_status
);
202 if (link_status
!= GL_TRUE
) {
203 glDeleteProgram(program
);
206 ASSERT_NE(program
, GLuint(0));
208 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
210 float quad_vertices
[] = {
217 GLuint vertex_buffer
;
218 glGenBuffers(1, &vertex_buffer
);
219 glBindBuffer(GL_ARRAY_BUFFER
, vertex_buffer
);
221 GL_ARRAY_BUFFER
, sizeof(quad_vertices
),
222 reinterpret_cast<void*>(quad_vertices
), GL_STATIC_DRAW
);
224 GLint position_location
= glGetAttribLocation(program
, "a_position");
225 glVertexAttribPointer(
226 position_location
, 2, GL_FLOAT
, GL_FALSE
, 2 * sizeof(float), NULL
);
227 glEnableVertexAttribArray(position_location
);
229 glUseProgram(program
);
230 glUniform4fv(glGetUniformLocation(program
, "u_color"), 1, kDrawColor
);
232 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
234 for (size_t ii
= 0; ii
< test_count
; ++ii
) {
235 GLuint texture_id
= 0;
236 glGenTextures(1, &texture_id
);
237 glBindTexture(GL_TEXTURE_2D
, texture_id
);
239 GL_TEXTURE_2D
, 0, test_formats
[ii
].format
, kTextureSize
, kTextureSize
,
240 0, test_formats
[ii
].format
, test_formats
[ii
].type
, NULL
);
242 GLuint framebuffer
= 0;
243 glGenFramebuffers(1, &framebuffer
);
244 glBindFramebuffer(GL_FRAMEBUFFER
, framebuffer
);
245 glFramebufferTexture2D(
246 GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, texture_id
, 0);
248 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
250 // Make sure this floating point framebuffer is supported
251 if (glCheckFramebufferStatus(GL_FRAMEBUFFER
) == GL_FRAMEBUFFER_COMPLETE
) {
252 // Check if this implementation supports reading floats back from this
254 GLint read_format
= 0;
255 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT
, &read_format
);
257 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE
, &read_type
);
259 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
261 if ((read_format
== GL_RGB
|| read_format
== GL_RGBA
) &&
262 read_type
== test_formats
[ii
].type
) {
263 glClear(GL_COLOR_BUFFER_BIT
);
264 glDrawArrays(GL_TRIANGLE_FAN
, 0, 4);
266 uint32 read_comp_count
= 0;
267 switch (read_format
) {
277 case GL_HALF_FLOAT_OES
: {
278 scoped_ptr
<GLushort
[]> buf(
279 new GLushort
[kTextureSize
* kTextureSize
* read_comp_count
]);
281 0, 0, kTextureSize
, kTextureSize
, read_format
, read_type
,
283 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
284 for (uint32 jj
= 0; jj
< kTextureSize
* kTextureSize
; ++jj
) {
285 for (uint32 kk
= 0; kk
< test_formats
[ii
].comp_count
; ++kk
) {
287 std::abs(HalfToFloat32(buf
[jj
* read_comp_count
+ kk
]) -
289 std::abs(kDrawColor
[kk
] * kEpsilon
));
295 scoped_ptr
<GLfloat
[]> buf(
296 new GLfloat
[kTextureSize
* kTextureSize
* read_comp_count
]);
298 0, 0, kTextureSize
, kTextureSize
, read_format
, read_type
,
300 EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR
));
301 for (uint32 jj
= 0; jj
< kTextureSize
* kTextureSize
; ++jj
) {
302 for (uint32 kk
= 0; kk
< test_formats
[ii
].comp_count
; ++kk
) {
304 std::abs(buf
[jj
* read_comp_count
+ kk
] - kDrawColor
[kk
]),
305 std::abs(kDrawColor
[kk
] * kEpsilon
));
314 glDeleteFramebuffers(1, &framebuffer
);
315 glDeleteTextures(1, &texture_id
);
318 glDeleteBuffers(1, &vertex_buffer
);
319 glDeleteProgram(program
);