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