Home | History | Annotate | Download | only in tests
      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 static int abs(int value) {
     26     return value > 0 ? value : -value;
     27 }
     28 
     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 
    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 
    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 
    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 
    162 EGLint GLTest::getSurfaceWidth() {
    163     return 512;
    164 }
    165 
    166 EGLint GLTest::getSurfaceHeight() {
    167     return 512;
    168 }
    169 
    170 EGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config,
    171                                        sp<ANativeWindow>& window) const {
    172     return eglCreateWindowSurface(display, config, window.get(), NULL);
    173 }
    174 
    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 
    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 
    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 
    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