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 23namespace android { 24 25static int abs(int value) { 26 return value > 0 ? value : -value; 27} 28 29void 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 111void 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 139EGLint 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 154EGLint const* GLTest::getContextAttribs() { 155 static const EGLint sDefaultContextAttribs[] = { 156 EGL_CONTEXT_CLIENT_VERSION, 2, 157 EGL_NONE }; 158 159 return sDefaultContextAttribs; 160} 161 162EGLint GLTest::getSurfaceWidth() { 163 return 512; 164} 165 166EGLint GLTest::getSurfaceHeight() { 167 return 512; 168} 169 170EGLSurface 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 252void 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 293void 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