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