GLTest.cpp revision f3730fb8f7da368740f9e5ed2603b405aeb4be72
1#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
325