Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / tests / gl_readback_unittest.cc
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.
4
5 #include <GLES2/gl2.h>
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
8
9 #include <cmath>
10
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"
19
20 namespace gpu {
21
22 class GLReadbackTest : public testing::Test {
23  protected:
24   void SetUp() override { gl_.Initialize(GLManager::Options()); }
25
26   void TearDown() override { gl_.Destroy(); }
27
28   static void WaitForQueryCallback(int q, base::Closure cb) {
29     unsigned int done = 0;
30     glGetQueryObjectuivEXT(q, GL_QUERY_RESULT_AVAILABLE_EXT, &done);
31     if (done) {
32       cb.Run();
33     } else {
34       base::MessageLoop::current()->PostDelayedTask(
35           FROM_HERE,
36           base::Bind(&WaitForQueryCallback, q, cb),
37           base::TimeDelta::FromMilliseconds(3));
38     }
39   }
40
41   void WaitForQuery(int q) {
42     base::RunLoop run_loop;
43     WaitForQueryCallback(q, run_loop.QuitClosure());
44     run_loop.Run();
45   }
46
47   GLManager gl_;
48 };
49
50
51 TEST_F(GLReadbackTest, ReadPixelsWithPBOAndQuery) {
52   const GLint kBytesPerPixel = 4;
53   const GLint kWidth = 2;
54   const GLint kHeight = 2;
55
56   GLuint b, q;
57   glClearColor(0.0, 0.0, 1.0, 1.0);
58   glClear(GL_COLOR_BUFFER_BIT);
59   glGenBuffers(1, &b);
60   glGenQueriesEXT(1, &q);
61   glBindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, b);
62   glBufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
63                kWidth * kHeight * kBytesPerPixel,
64                NULL,
65                GL_STREAM_READ);
66   glBeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, q);
67   glReadPixels(0, 0, kWidth, kHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
68   glEndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
69   glFlush();
70   WaitForQuery(q);
71
72   // TODO(hubbe): Check that glMapBufferCHROMIUM does not block here.
73   unsigned char *data = static_cast<unsigned char *>(
74       glMapBufferCHROMIUM(
75           GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
76           GL_READ_ONLY));
77   EXPECT_TRUE(data);
78   EXPECT_EQ(data[0], 0);   // red
79   EXPECT_EQ(data[1], 0);   // green
80   EXPECT_EQ(data[2], 255); // blue
81   glUnmapBufferCHROMIUM(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM);
82   glBindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
83   glDeleteBuffers(1, &b);
84   glDeleteQueriesEXT(1, &q);
85   GLTestHelper::CheckGLError("no errors", __LINE__);
86 }
87
88 static float HalfToFloat32(uint16 value) {
89   int32 s = (value >> 15) & 0x00000001;
90   int32 e = (value >> 10) & 0x0000001f;
91   int32 m =  value        & 0x000003ff;
92
93   if (e == 0) {
94     if (m == 0) {
95       uint32 result = s << 31;
96       return bit_cast<float>(result);
97     } else {
98       while (!(m & 0x00000400)) {
99         m <<= 1;
100         e -=  1;
101       }
102
103       e += 1;
104       m &= ~0x00000400;
105     }
106   } else if (e == 31) {
107     if (m == 0) {
108       uint32 result = (s << 31) | 0x7f800000;
109       return bit_cast<float>(result);
110     } else {
111       uint32 result = (s << 31) | 0x7f800000 | (m << 13);
112       return bit_cast<float>(result);
113     }
114   }
115
116   e = e + (127 - 15);
117   m = m << 13;
118
119   uint32 result = (s << 31) | (e << 23) | m;
120   return bit_cast<float>(result);
121 }
122
123 static GLuint CompileShader(GLenum type, const char *data) {
124   const char *shaderStrings[1] = { data };
125
126   GLuint shader = glCreateShader(type);
127   glShaderSource(shader, 1, shaderStrings, NULL);
128   glCompileShader(shader);
129
130   GLint compile_status = 0;
131   glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_status);
132   if (compile_status != GL_TRUE) {
133     glDeleteShader(shader);
134     shader = 0;
135   }
136
137   return shader;
138 }
139
140 TEST_F(GLReadbackTest, ReadPixelsFloat) {
141   const GLsizei kTextureSize = 4;
142   const GLfloat kDrawColor[4] = { -10.9f, 0.5f, 10.5f, 100.12f };
143   const GLfloat kEpsilon = 0.01f;
144
145   struct TestFormat {
146     GLint format;
147     GLint type;
148     uint32 comp_count;
149   };
150   TestFormat test_formats[4];
151   size_t test_count = 0;
152   const char *extensions = reinterpret_cast<const char*>(
153       glGetString(GL_EXTENSIONS));
154   if (strstr(extensions, "GL_OES_texture_half_float") != NULL) {
155       TestFormat rgb16f = { GL_RGB, GL_HALF_FLOAT_OES, 3 };
156       test_formats[test_count++] = rgb16f;
157
158       TestFormat rgba16f = { GL_RGBA, GL_HALF_FLOAT_OES, 4 };
159       test_formats[test_count++] = rgba16f;
160   }
161   if (strstr(extensions, "GL_OES_texture_float") != NULL) {
162       TestFormat rgb32f = { GL_RGB, GL_FLOAT, 3 };
163       test_formats[test_count++] = rgb32f;
164
165       TestFormat rgba32f = { GL_RGBA, GL_FLOAT, 4 };
166       test_formats[test_count++] = rgba32f;
167   }
168
169   const char *vs_source =
170       "precision mediump float;\n"
171       "attribute vec4 a_position;\n"
172       "void main() {\n"
173       "  gl_Position =  a_position;\n"
174       "}\n";
175
176   GLuint vertex_shader = CompileShader(GL_VERTEX_SHADER, vs_source);
177   ASSERT_NE(vertex_shader, GLuint(0));
178
179   const char *fs_source =
180       "precision mediump float;\n"
181       "uniform vec4 u_color;\n"
182       "void main() {\n"
183       "  gl_FragColor = u_color;\n"
184       "}\n";
185
186   GLuint fragment_shader = CompileShader(GL_FRAGMENT_SHADER, fs_source);
187   ASSERT_NE(fragment_shader, GLuint(0));
188
189   GLuint program = glCreateProgram();
190   glAttachShader(program, vertex_shader);
191   glDeleteShader(vertex_shader);
192   glAttachShader(program, fragment_shader);
193   glDeleteShader(fragment_shader);
194   glLinkProgram(program);
195
196   GLint link_status = 0;
197   glGetProgramiv(program, GL_LINK_STATUS, &link_status);
198   if (link_status != GL_TRUE) {
199     glDeleteProgram(program);
200     program = 0;
201   }
202   ASSERT_NE(program, GLuint(0));
203
204   EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
205
206   float quad_vertices[] = {
207       -1.0, -1.0,
208       1.0, -1.0,
209       1.0, 1.0,
210       -1.0, 1.0
211   };
212
213   GLuint vertex_buffer;
214   glGenBuffers(1, &vertex_buffer);
215   glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
216   glBufferData(
217       GL_ARRAY_BUFFER, sizeof(quad_vertices),
218       reinterpret_cast<void*>(quad_vertices), GL_STATIC_DRAW);
219
220   GLint position_location = glGetAttribLocation(program, "a_position");
221   glVertexAttribPointer(
222       position_location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), NULL);
223   glEnableVertexAttribArray(position_location);
224
225   glUseProgram(program);
226   glUniform4fv(glGetUniformLocation(program, "u_color"), 1, kDrawColor);
227
228   EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
229
230   for (size_t ii = 0; ii < test_count; ++ii) {
231     GLuint texture_id = 0;
232     glGenTextures(1, &texture_id);
233     glBindTexture(GL_TEXTURE_2D, texture_id);
234     glTexImage2D(
235         GL_TEXTURE_2D, 0, test_formats[ii].format, kTextureSize, kTextureSize,
236         0, test_formats[ii].format, test_formats[ii].type, NULL);
237
238     GLuint framebuffer = 0;
239     glGenFramebuffers(1, &framebuffer);
240     glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
241     glFramebufferTexture2D(
242         GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
243
244     EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
245
246     // Make sure this floating point framebuffer is supported
247     if (glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) {
248       // Check if this implementation supports reading floats back from this
249       // framebuffer
250       GLint read_format = 0;
251       glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format);
252       GLint read_type = 0;
253       glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type);
254
255       EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
256
257       if ((read_format == GL_RGB || read_format == GL_RGBA) &&
258           read_type == test_formats[ii].type) {
259         glClear(GL_COLOR_BUFFER_BIT);
260         glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
261
262         uint32 read_comp_count = 0;
263         switch (read_format) {
264           case GL_RGB:
265             read_comp_count = 3;
266             break;
267           case GL_RGBA:
268             read_comp_count = 4;
269             break;
270         }
271
272         switch (read_type) {
273           case GL_HALF_FLOAT_OES: {
274             scoped_ptr<GLushort[]> buf(
275                 new GLushort[kTextureSize * kTextureSize * read_comp_count]);
276             glReadPixels(
277                 0, 0, kTextureSize, kTextureSize, read_format, read_type,
278                 buf.get());
279             EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
280             for (uint32 jj = 0; jj < kTextureSize * kTextureSize; ++jj) {
281               for (uint32 kk = 0; kk < test_formats[ii].comp_count; ++kk) {
282                 EXPECT_LE(
283                     std::abs(HalfToFloat32(buf[jj * read_comp_count + kk]) -
284                         kDrawColor[kk]),
285                     std::abs(kDrawColor[kk] * kEpsilon));
286               }
287             }
288             break;
289           }
290           case GL_FLOAT: {
291             scoped_ptr<GLfloat[]> buf(
292                 new GLfloat[kTextureSize * kTextureSize * read_comp_count]);
293             glReadPixels(
294                 0, 0, kTextureSize, kTextureSize, read_format, read_type,
295                 buf.get());
296             EXPECT_EQ(glGetError(), GLenum(GL_NO_ERROR));
297             for (uint32 jj = 0; jj < kTextureSize * kTextureSize; ++jj) {
298               for (uint32 kk = 0; kk < test_formats[ii].comp_count; ++kk) {
299                 EXPECT_LE(
300                     std::abs(buf[jj * read_comp_count + kk] - kDrawColor[kk]),
301                     std::abs(kDrawColor[kk] * kEpsilon));
302               }
303             }
304             break;
305           }
306         }
307       }
308     }
309
310     glDeleteFramebuffers(1, &framebuffer);
311     glDeleteTextures(1, &texture_id);
312   }
313
314   glDeleteBuffers(1, &vertex_buffer);
315   glDeleteProgram(program);
316 }
317
318 }  // namespace gpu