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 using Transaction = SurfaceComposerClient::Transaction;
     26 
     27 static int abs(int value) {
     28     return value > 0 ? value : -value;
     29 }
     30 
     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 
    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 
    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 
    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 
    164 EGLint GLTest::getSurfaceWidth() {
    165     return 512;
    166 }
    167 
    168 EGLint GLTest::getSurfaceHeight() {
    169     return 512;
    170 }
    171 
    172 EGLSurface GLTest::createWindowSurface(EGLDisplay display, EGLConfig config,
    173                                        sp<ANativeWindow>& window) const {
    174     return eglCreateWindowSurface(display, config, window.get(), nullptr);
    175 }
    176 
    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 
    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 
    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 
    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