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