blob: d7acb4da20c159cd293fff83f9ff7d6691b38000 [file] [log] [blame]
Dan Stozaf3730fb2013-11-26 15:10:10 -08001#include "GLTest.h"
2
3#include <gui/Surface.h>
4
5#include <GLES2/gl2.h>
6
7namespace android {
8
9static int abs(int value) {
10 return value > 0 ? value : -value;
11}
12
13void GLTest::SetUp() {
14 const ::testing::TestInfo* const testInfo =
15 ::testing::UnitTest::GetInstance()->current_test_info();
16 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), testInfo->name());
17
18 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
19 ASSERT_EQ(EGL_SUCCESS, eglGetError());
20 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
21
22 EGLint majorVersion;
23 EGLint minorVersion;
24 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
25 ASSERT_EQ(EGL_SUCCESS, eglGetError());
26 RecordProperty("EglVersionMajor", majorVersion);
27 RecordProperty("EglVersionMinor", minorVersion);
28
29 EGLint numConfigs = 0;
30 EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig, 1,
31 &numConfigs));
32 ASSERT_EQ(EGL_SUCCESS, eglGetError());
33
34 char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
35 if (displaySecsEnv != NULL) {
36 mDisplaySecs = atoi(displaySecsEnv);
37 if (mDisplaySecs < 0) {
38 mDisplaySecs = 0;
39 }
40 } else {
41 mDisplaySecs = 0;
42 }
43
44 if (mDisplaySecs > 0) {
45 mComposerClient = new SurfaceComposerClient;
46 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
47
48 mSurfaceControl = mComposerClient->createSurface(
49 String8("Test Surface"), getSurfaceWidth(), getSurfaceHeight(),
50 PIXEL_FORMAT_RGB_888, 0);
51
52 ASSERT_TRUE(mSurfaceControl != NULL);
53 ASSERT_TRUE(mSurfaceControl->isValid());
54
55 SurfaceComposerClient::openGlobalTransaction();
56 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF));
57 ASSERT_EQ(NO_ERROR, mSurfaceControl->show());
58 SurfaceComposerClient::closeGlobalTransaction();
59
60 sp<ANativeWindow> window = mSurfaceControl->getSurface();
61 mEglSurface = createWindowSurface(mEglDisplay, mGlConfig, window);
62 } else {
63 EGLint pbufferAttribs[] = {
64 EGL_WIDTH, getSurfaceWidth(),
65 EGL_HEIGHT, getSurfaceHeight(),
66 EGL_NONE };
67
68 mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
69 pbufferAttribs);
70 }
71 ASSERT_EQ(EGL_SUCCESS, eglGetError());
72 ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
73
74 mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
75 getContextAttribs());
76 ASSERT_EQ(EGL_SUCCESS, eglGetError());
77 ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
78
79 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
80 mEglContext));
81 ASSERT_EQ(EGL_SUCCESS, eglGetError());
82
83 EGLint w, h;
84 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
85 ASSERT_EQ(EGL_SUCCESS, eglGetError());
86 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
87 ASSERT_EQ(EGL_SUCCESS, eglGetError());
88 RecordProperty("EglSurfaceWidth", w);
89 RecordProperty("EglSurfaceHeight", h);
90
91 glViewport(0, 0, w, h);
92 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
93}
94
95void GLTest::TearDown() {
96 // Display the result
97 if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
98 eglSwapBuffers(mEglDisplay, mEglSurface);
99 sleep(mDisplaySecs);
100 }
101
102 if (mComposerClient != NULL) {
103 mComposerClient->dispose();
104 }
105 if (mEglContext != EGL_NO_CONTEXT) {
106 eglDestroyContext(mEglDisplay, mEglContext);
107 }
108 if (mEglSurface != EGL_NO_SURFACE) {
109 eglDestroySurface(mEglDisplay, mEglSurface);
110 }
111 if (mEglDisplay != EGL_NO_DISPLAY) {
112 eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
113 EGL_NO_CONTEXT);
114 eglTerminate(mEglDisplay);
115 }
116 ASSERT_EQ(EGL_SUCCESS, eglGetError());
117
118 const ::testing::TestInfo* const testInfo =
119 ::testing::UnitTest::GetInstance()->current_test_info();
120 ALOGV("End test: %s.%s", testInfo->test_case_name(), testInfo->name());
121}
122
123EGLint const* GLTest::getConfigAttribs() {
124 static const EGLint sDefaultConfigAttribs[] = {
125 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
126 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
127 EGL_RED_SIZE, 8,
128 EGL_GREEN_SIZE, 8,
129 EGL_BLUE_SIZE, 8,
130 EGL_ALPHA_SIZE, 8,
131 EGL_DEPTH_SIZE, 16,
132 EGL_STENCIL_SIZE, 8,
133 EGL_NONE };
134
135 return sDefaultConfigAttribs;
136}
137
138EGLint const* GLTest::getContextAttribs() {
139 static const EGLint sDefaultContextAttribs[] = {
140 EGL_CONTEXT_CLIENT_VERSION, 2,
141 EGL_NONE };
142
143 return sDefaultContextAttribs;
144}
145
146EGLint GLTest::getSurfaceWidth() {
147 return 512;
148}
149
150EGLint GLTest::getSurfaceHeight() {
151 return 512;
152}
153
154EGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config,
155 sp<ANativeWindow>& window) const {
156 ALOGI("Creating window surface (non-SRGB)");
157 return eglCreateWindowSurface(display, config, window.get(), NULL);
158}
159
160::testing::AssertionResult GLTest::checkPixel(int x, int y,
161 int r, int g, int b, int a, int tolerance) {
162 GLubyte pixel[4];
163 String8 msg;
164 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
165 GLenum err = glGetError();
166 if (err != GL_NO_ERROR) {
167 msg += String8::format("error reading pixel: %#x", err);
168 while ((err = glGetError()) != GL_NO_ERROR) {
169 msg += String8::format(", %#x", err);
170 }
171 return ::testing::AssertionFailure(::testing::Message(msg.string()));
172 }
173 if (r >= 0 && abs(r - int(pixel[0])) > tolerance) {
174 msg += String8::format("r(%d isn't %d)", pixel[0], r);
175 }
176 if (g >= 0 && abs(g - int(pixel[1])) > tolerance) {
177 if (!msg.isEmpty()) {
178 msg += " ";
179 }
180 msg += String8::format("g(%d isn't %d)", pixel[1], g);
181 }
182 if (b >= 0 && abs(b - int(pixel[2])) > tolerance) {
183 if (!msg.isEmpty()) {
184 msg += " ";
185 }
186 msg += String8::format("b(%d isn't %d)", pixel[2], b);
187 }
188 if (a >= 0 && abs(a - int(pixel[3])) > tolerance) {
189 if (!msg.isEmpty()) {
190 msg += " ";
191 }
192 msg += String8::format("a(%d isn't %d)", pixel[3], a);
193 }
194 if (!msg.isEmpty()) {
195 return ::testing::AssertionFailure(::testing::Message(msg.string()));
196 } else {
197 return ::testing::AssertionSuccess();
198 }
199}
200
201::testing::AssertionResult GLTest::assertRectEq(const Rect &r1, const Rect &r2,
202 int tolerance) {
203 String8 msg;
204
205 if (abs(r1.left - r2.left) > tolerance) {
206 msg += String8::format("left(%d isn't %d)", r1.left, r2.left);
207 }
208 if (abs(r1.top - r2.top) > tolerance) {
209 if (!msg.isEmpty()) {
210 msg += " ";
211 }
212 msg += String8::format("top(%d isn't %d)", r1.top, r2.top);
213 }
214 if (abs(r1.right - r2.right) > tolerance) {
215 if (!msg.isEmpty()) {
216 msg += " ";
217 }
218 msg += String8::format("right(%d isn't %d)", r1.right, r2.right);
219 }
220 if (abs(r1.bottom - r2.bottom) > tolerance) {
221 if (!msg.isEmpty()) {
222 msg += " ";
223 }
224 msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom);
225 }
226 if (!msg.isEmpty()) {
227 msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]",
228 r1.left, r1.top, r1.right, r1.bottom,
229 r2.left, r2.top, r2.right, r2.bottom);
230 fprintf(stderr, "assertRectEq: %s\n", msg.string());
231 return ::testing::AssertionFailure(::testing::Message(msg.string()));
232 } else {
233 return ::testing::AssertionSuccess();
234 }
235}
236
237void GLTest::loadShader(GLenum shaderType, const char* pSource,
238 GLuint* outShader) {
239 GLuint shader = glCreateShader(shaderType);
240 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
241 if (shader) {
242 glShaderSource(shader, 1, &pSource, NULL);
243 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
244 glCompileShader(shader);
245 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
246 GLint compiled = 0;
247 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
248 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
249 if (!compiled) {
250 GLint infoLen = 0;
251 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
252 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
253 if (infoLen) {
254 char* buf = (char*) malloc(infoLen);
255 if (buf) {
256 glGetShaderInfoLog(shader, infoLen, NULL, buf);
257 printf("Shader compile log:\n%s\n", buf);
258 free(buf);
259 FAIL();
260 }
261 } else {
262 char* buf = (char*) malloc(0x1000);
263 if (buf) {
264 glGetShaderInfoLog(shader, 0x1000, NULL, buf);
265 printf("Shader compile log:\n%s\n", buf);
266 free(buf);
267 FAIL();
268 }
269 }
270 glDeleteShader(shader);
271 shader = 0;
272 }
273 }
274 ASSERT_TRUE(shader != 0);
275 *outShader = shader;
276}
277
278void GLTest::createProgram(const char* pVertexSource,
279 const char* pFragmentSource, GLuint* outPgm) {
280 GLuint vertexShader, fragmentShader;
281 {
282 SCOPED_TRACE("compiling vertex shader");
283 ASSERT_NO_FATAL_FAILURE(loadShader(GL_VERTEX_SHADER, pVertexSource,
284 &vertexShader));
285 }
286 {
287 SCOPED_TRACE("compiling fragment shader");
288 ASSERT_NO_FATAL_FAILURE(loadShader(GL_FRAGMENT_SHADER, pFragmentSource,
289 &fragmentShader));
290 }
291
292 GLuint program = glCreateProgram();
293 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
294 if (program) {
295 glAttachShader(program, vertexShader);
296 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
297 glAttachShader(program, fragmentShader);
298 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
299 glLinkProgram(program);
300 GLint linkStatus = GL_FALSE;
301 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
302 if (linkStatus != GL_TRUE) {
303 GLint bufLength = 0;
304 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
305 if (bufLength) {
306 char* buf = (char*) malloc(bufLength);
307 if (buf) {
308 glGetProgramInfoLog(program, bufLength, NULL, buf);
309 printf("Program link log:\n%s\n", buf);
310 free(buf);
311 FAIL();
312 }
313 }
314 glDeleteProgram(program);
315 program = 0;
316 }
317 }
318 glDeleteShader(vertexShader);
319 glDeleteShader(fragmentShader);
320 ASSERT_TRUE(program != 0);
321 *outPgm = program;
322}
323
324} // namespace android