• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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