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