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"
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.
14 const uint8
GLTestHelper::kCheckClearValue
;
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
) {
25 GLenum error
= GL_NO_ERROR
;
26 while ((error
= glGetError()) != GL_NO_ERROR
) {
28 EXPECT_EQ(static_cast<GLenum
>(GL_NO_ERROR
), error
)
29 << "GL ERROR in " << msg
<< " at line " << line
<< " : " << error
;
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
);
39 glCompileShader(shader
);
44 GLuint
GLTestHelper::LoadShader(GLenum type
, const char* shaderSrc
) {
45 GLuint shader
= CompileShader(type
, shaderSrc
);
47 // Check the compile status
49 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &value
);
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
);
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
);
69 glLinkProgram(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
79 glGetProgramiv(program
, GL_LINK_STATUS
, &linked
);
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
);
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
) {
102 return SetupProgram(vertex_shader
, fragment_shader
);
105 GLuint
GLTestHelper::SetupUnitQuad(GLint position_location
) {
107 glGenBuffers(1, &vbo
);
108 glBindBuffer(GL_ARRAY_BUFFER
, vbo
);
109 static float vertices
[] = {
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);
124 GLuint
GLTestHelper::SetupColorsForUnitQuad(
125 GLint location
, const GLfloat color
[4], GLenum usage
) {
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);
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());
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
;
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) {
171 return bad_count
== 0;
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
{
195 struct BitmapInfoHeader
{
201 uint8 compression
[4];
203 uint8 x_pels_per_meter
[4];
204 uint8 y_pels_per_meter
[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
);
223 for (int ii
= 0; ii
< num_pixels
; ++ii
) {
225 uint8 t
= pixels
[offset
+ 0];
226 pixels
[offset
+ 0] = pixels
[offset
+ 2];
227 pixels
[offset
+ 2] = t
;
230 BitmapHeaderFile bhf
;
231 BitmapInfoHeader bih
;
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
);