- add sources.
[platform/framework/web/crosswalk.git] / src / gpu / command_buffer / tests / gl_test_utils.cc
1 // Copyright (c) 2012 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 "gpu/command_buffer/tests/gl_test_utils.h"
6 #include <string>
7 #include <stdio.h>
8 #include "base/basictypes.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "testing/gmock/include/gmock/gmock.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 // GCC requires these declarations, but MSVC requires they not be present.
14 #ifndef COMPILER_MSVC
15 const uint8 GLTestHelper::kCheckClearValue;
16 #endif
17
18 bool GLTestHelper::HasExtension(const char* extension) {
19   std::string extensions(
20       reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)));
21   return extensions.find(extension) != std::string::npos;
22 }
23
24 bool GLTestHelper::CheckGLError(const char* msg, int line) {
25    bool success = true;
26    GLenum error = GL_NO_ERROR;
27    while ((error = glGetError()) != GL_NO_ERROR) {
28      success = false;
29      EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), error)
30          << "GL ERROR in " << msg << " at line " << line << " : " << error;
31    }
32    return success;
33 }
34
35 GLuint GLTestHelper::LoadShader(GLenum type, const char* shaderSrc) {
36   GLuint shader = glCreateShader(type);
37   // Load the shader source
38   glShaderSource(shader, 1, &shaderSrc, NULL);
39   // Compile the shader
40   glCompileShader(shader);
41   // Check the compile status
42   GLint value = 0;
43   glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
44   if (value == 0) {
45     char buffer[1024];
46     GLsizei length = 0;
47     glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer);
48     std::string log(buffer, length);
49     EXPECT_EQ(1, value) << "Error compiling shader: " << log;
50     glDeleteShader(shader);
51     shader = 0;
52   }
53   return shader;
54 }
55
56 GLuint GLTestHelper::SetupProgram(
57     GLuint vertex_shader, GLuint fragment_shader) {
58   // Create the program object
59   GLuint program = glCreateProgram();
60   glAttachShader(program, vertex_shader);
61   glAttachShader(program, fragment_shader);
62   // Link the program
63   glLinkProgram(program);
64   // Check the link status
65   GLint linked = 0;
66   glGetProgramiv(program, GL_LINK_STATUS, &linked);
67   if (linked == 0) {
68     char buffer[1024];
69     GLsizei length = 0;
70     glGetProgramInfoLog(program, sizeof(buffer), &length, buffer);
71     std::string log(buffer, length);
72     EXPECT_EQ(1, linked) << "Error linking program: " << log;
73     glDeleteProgram(program);
74     program = 0;
75   }
76   return program;
77 }
78
79 GLuint GLTestHelper::LoadProgram(
80     const char* vertex_shader_source,
81     const char* fragment_shader_source) {
82   GLuint vertex_shader = LoadShader(
83       GL_VERTEX_SHADER, vertex_shader_source);
84   GLuint fragment_shader = LoadShader(
85       GL_FRAGMENT_SHADER, fragment_shader_source);
86   if (!vertex_shader || !fragment_shader) {
87     return 0;
88   }
89   return SetupProgram(vertex_shader, fragment_shader);
90 }
91
92 GLuint GLTestHelper::SetupUnitQuad(GLint position_location) {
93   GLuint vbo = 0;
94   glGenBuffers(1, &vbo);
95   glBindBuffer(GL_ARRAY_BUFFER, vbo);
96   static float vertices[] = {
97       1.0f,  1.0f,
98      -1.0f,  1.0f,
99      -1.0f, -1.0f,
100       1.0f,  1.0f,
101      -1.0f, -1.0f,
102       1.0f, -1.0f,
103   };
104   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
105   glEnableVertexAttribArray(position_location);
106   glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE, 0, 0);
107
108   return vbo;
109 }
110
111 GLuint GLTestHelper::SetupColorsForUnitQuad(
112     GLint location, const GLfloat color[4], GLenum usage) {
113   GLuint vbo = 0;
114   glGenBuffers(1, &vbo);
115   glBindBuffer(GL_ARRAY_BUFFER, vbo);
116   GLfloat vertices[6 * 4];
117   for (int ii = 0; ii < 6; ++ii) {
118     for (int jj = 0; jj < 4; ++jj) {
119       vertices[ii * 4 + jj] = color[jj];
120     }
121   }
122   glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, usage);
123   glEnableVertexAttribArray(location);
124   glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, 0, 0);
125
126   return vbo;
127 }
128
129 bool GLTestHelper::CheckPixels(
130     GLint x, GLint y, GLsizei width, GLsizei height, GLint tolerance,
131     const uint8* color) {
132   GLsizei size = width * height * 4;
133   scoped_ptr<uint8[]> pixels(new uint8[size]);
134   memset(pixels.get(), kCheckClearValue, size);
135   glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
136   int bad_count = 0;
137   for (GLint yy = 0; yy < height; ++yy) {
138     for (GLint xx = 0; xx < width; ++xx) {
139       int offset = yy * width * 4 + xx * 4;
140       for (int jj = 0; jj < 4; ++jj) {
141         uint8 actual = pixels[offset + jj];
142         uint8 expected = color[jj];
143         int diff = actual - expected;
144         diff = diff < 0 ? -diff: diff;
145         if (diff > tolerance) {
146           EXPECT_EQ(expected, actual) << " at " << (xx + x) << ", " << (yy + y)
147                                       << " channel " << jj;
148           ++bad_count;
149           // Exit early just so we don't spam the log but we print enough
150           // to hopefully make it easy to diagnose the issue.
151           if (bad_count > 16) {
152             return false;
153           }
154         }
155       }
156     }
157   }
158   return bad_count == 0;
159 }
160
161 namespace {
162
163 void Set16BitValue(uint8 dest[2], uint16 value) {
164   dest[0] = value & 0xFFu;
165   dest[1] = value >> 8;
166 }
167
168 void Set32BitValue(uint8 dest[4], uint32 value) {
169   dest[0] = (value >> 0) & 0xFFu;
170   dest[1] = (value >> 8) & 0xFFu;
171   dest[2] = (value >> 16) & 0xFFu;
172   dest[3] = (value >> 24) & 0xFFu;
173 }
174
175 struct BitmapHeaderFile {
176   uint8 magic[2];
177   uint8 size[4];
178   uint8 reserved[4];
179   uint8 offset[4];
180 };
181
182 struct BitmapInfoHeader{
183   uint8 size[4];
184   uint8 width[4];
185   uint8 height[4];
186   uint8 planes[2];
187   uint8 bit_count[2];
188   uint8 compression[4];
189   uint8 size_image[4];
190   uint8 x_pels_per_meter[4];
191   uint8 y_pels_per_meter[4];
192   uint8 clr_used[4];
193   uint8 clr_important[4];
194 };
195
196 }
197
198 bool GLTestHelper::SaveBackbufferAsBMP(
199     const char* filename, int width, int height) {
200   FILE* fp = fopen(filename, "wb");
201   EXPECT_TRUE(fp != NULL);
202   glPixelStorei(GL_PACK_ALIGNMENT, 1);
203   int num_pixels = width * height;
204   int size = num_pixels * 4;
205   scoped_ptr<uint8[]> data(new uint8[size]);
206   uint8* pixels = data.get();
207   glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
208
209   // RGBA to BGRA
210   for (int ii = 0; ii < num_pixels; ++ii) {
211     int offset = ii * 4;
212     uint8 t = pixels[offset + 0];
213     pixels[offset + 0] = pixels[offset + 2];
214     pixels[offset + 2] = t;
215   }
216
217   BitmapHeaderFile bhf;
218   BitmapInfoHeader bih;
219
220   bhf.magic[0] = 'B';
221   bhf.magic[1] = 'M';
222   Set32BitValue(bhf.size, 0);
223   Set32BitValue(bhf.reserved, 0);
224   Set32BitValue(bhf.offset, sizeof(bhf) + sizeof(bih));
225
226   Set32BitValue(bih.size, sizeof(bih));
227   Set32BitValue(bih.width, width);
228   Set32BitValue(bih.height, height);
229   Set16BitValue(bih.planes, 1);
230   Set16BitValue(bih.bit_count, 32);
231   Set32BitValue(bih.compression, 0);
232   Set32BitValue(bih.x_pels_per_meter, 0);
233   Set32BitValue(bih.y_pels_per_meter, 0);
234   Set32BitValue(bih.clr_used, 0);
235   Set32BitValue(bih.clr_important, 0);
236
237   fwrite(&bhf, sizeof(bhf), 1, fp);
238   fwrite(&bih, sizeof(bih), 1, fp);
239   fwrite(pixels, size, 1, fp);
240   fclose(fp);
241   return true;
242 }
243
244 int GLTestHelper::RunTests(int argc, char** argv) {
245   testing::InitGoogleMock(&argc, argv);
246   return RUN_ALL_TESTS();
247 }