1 /* 2 * Copyright (C) 2011 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 #define LOG_TAG "SurfaceTexture_test" 18 //#define LOG_NDEBUG 0 19 20 #include <gtest/gtest.h> 21 #include <gui/SurfaceTexture.h> 22 #include <gui/SurfaceTextureClient.h> 23 #include <ui/GraphicBuffer.h> 24 #include <utils/String8.h> 25 #include <utils/threads.h> 26 27 #include <gui/ISurfaceComposer.h> 28 #include <gui/Surface.h> 29 #include <gui/SurfaceComposerClient.h> 30 31 #include <EGL/egl.h> 32 #include <EGL/eglext.h> 33 #include <GLES2/gl2.h> 34 #include <GLES2/gl2ext.h> 35 36 #include <ui/FramebufferNativeWindow.h> 37 38 namespace android { 39 40 class GLTest : public ::testing::Test { 41 protected: 42 43 GLTest(): 44 mEglDisplay(EGL_NO_DISPLAY), 45 mEglSurface(EGL_NO_SURFACE), 46 mEglContext(EGL_NO_CONTEXT) { 47 } 48 49 virtual void SetUp() { 50 const ::testing::TestInfo* const testInfo = 51 ::testing::UnitTest::GetInstance()->current_test_info(); 52 ALOGV("Begin test: %s.%s", testInfo->test_case_name(), 53 testInfo->name()); 54 55 mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); 56 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 57 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); 58 59 EGLint majorVersion; 60 EGLint minorVersion; 61 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); 62 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 63 RecordProperty("EglVersionMajor", majorVersion); 64 RecordProperty("EglVersionMajor", minorVersion); 65 66 EGLint numConfigs = 0; 67 EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig, 68 1, &numConfigs)); 69 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 70 71 char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS"); 72 if (displaySecsEnv != NULL) { 73 mDisplaySecs = atoi(displaySecsEnv); 74 if (mDisplaySecs < 0) { 75 mDisplaySecs = 0; 76 } 77 } else { 78 mDisplaySecs = 0; 79 } 80 81 if (mDisplaySecs > 0) { 82 mComposerClient = new SurfaceComposerClient; 83 ASSERT_EQ(NO_ERROR, mComposerClient->initCheck()); 84 85 mSurfaceControl = mComposerClient->createSurface( 86 String8("Test Surface"), 87 getSurfaceWidth(), getSurfaceHeight(), 88 PIXEL_FORMAT_RGB_888, 0); 89 90 ASSERT_TRUE(mSurfaceControl != NULL); 91 ASSERT_TRUE(mSurfaceControl->isValid()); 92 93 SurfaceComposerClient::openGlobalTransaction(); 94 ASSERT_EQ(NO_ERROR, mSurfaceControl->setLayer(0x7FFFFFFF)); 95 ASSERT_EQ(NO_ERROR, mSurfaceControl->show()); 96 SurfaceComposerClient::closeGlobalTransaction(); 97 98 sp<ANativeWindow> window = mSurfaceControl->getSurface(); 99 mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, 100 window.get(), NULL); 101 } else { 102 EGLint pbufferAttribs[] = { 103 EGL_WIDTH, getSurfaceWidth(), 104 EGL_HEIGHT, getSurfaceHeight(), 105 EGL_NONE }; 106 107 mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig, 108 pbufferAttribs); 109 } 110 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 111 ASSERT_NE(EGL_NO_SURFACE, mEglSurface); 112 113 mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT, 114 getContextAttribs()); 115 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 116 ASSERT_NE(EGL_NO_CONTEXT, mEglContext); 117 118 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 119 mEglContext)); 120 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 121 122 EGLint w, h; 123 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w)); 124 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 125 EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h)); 126 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 127 RecordProperty("EglSurfaceWidth", w); 128 RecordProperty("EglSurfaceHeight", h); 129 130 glViewport(0, 0, w, h); 131 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 132 } 133 134 virtual void TearDown() { 135 // Display the result 136 if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) { 137 eglSwapBuffers(mEglDisplay, mEglSurface); 138 sleep(mDisplaySecs); 139 } 140 141 if (mComposerClient != NULL) { 142 mComposerClient->dispose(); 143 } 144 if (mEglContext != EGL_NO_CONTEXT) { 145 eglDestroyContext(mEglDisplay, mEglContext); 146 } 147 if (mEglSurface != EGL_NO_SURFACE) { 148 eglDestroySurface(mEglDisplay, mEglSurface); 149 } 150 if (mEglDisplay != EGL_NO_DISPLAY) { 151 eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 152 EGL_NO_CONTEXT); 153 eglTerminate(mEglDisplay); 154 } 155 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 156 157 const ::testing::TestInfo* const testInfo = 158 ::testing::UnitTest::GetInstance()->current_test_info(); 159 ALOGV("End test: %s.%s", testInfo->test_case_name(), 160 testInfo->name()); 161 } 162 163 virtual EGLint const* getConfigAttribs() { 164 static EGLint sDefaultConfigAttribs[] = { 165 EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 166 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 167 EGL_RED_SIZE, 8, 168 EGL_GREEN_SIZE, 8, 169 EGL_BLUE_SIZE, 8, 170 EGL_ALPHA_SIZE, 8, 171 EGL_DEPTH_SIZE, 16, 172 EGL_STENCIL_SIZE, 8, 173 EGL_NONE }; 174 175 return sDefaultConfigAttribs; 176 } 177 178 virtual EGLint const* getContextAttribs() { 179 static EGLint sDefaultContextAttribs[] = { 180 EGL_CONTEXT_CLIENT_VERSION, 2, 181 EGL_NONE }; 182 183 return sDefaultContextAttribs; 184 } 185 186 virtual EGLint getSurfaceWidth() { 187 return 512; 188 } 189 190 virtual EGLint getSurfaceHeight() { 191 return 512; 192 } 193 194 ::testing::AssertionResult checkPixel(int x, int y, int r, 195 int g, int b, int a, int tolerance=2) { 196 GLubyte pixel[4]; 197 String8 msg; 198 glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); 199 GLenum err = glGetError(); 200 if (err != GL_NO_ERROR) { 201 msg += String8::format("error reading pixel: %#x", err); 202 while ((err = glGetError()) != GL_NO_ERROR) { 203 msg += String8::format(", %#x", err); 204 } 205 fprintf(stderr, "pixel check failure: %s\n", msg.string()); 206 return ::testing::AssertionFailure( 207 ::testing::Message(msg.string())); 208 } 209 if (r >= 0 && abs(r - int(pixel[0])) > tolerance) { 210 msg += String8::format("r(%d isn't %d)", pixel[0], r); 211 } 212 if (g >= 0 && abs(g - int(pixel[1])) > tolerance) { 213 if (!msg.isEmpty()) { 214 msg += " "; 215 } 216 msg += String8::format("g(%d isn't %d)", pixel[1], g); 217 } 218 if (b >= 0 && abs(b - int(pixel[2])) > tolerance) { 219 if (!msg.isEmpty()) { 220 msg += " "; 221 } 222 msg += String8::format("b(%d isn't %d)", pixel[2], b); 223 } 224 if (a >= 0 && abs(a - int(pixel[3])) > tolerance) { 225 if (!msg.isEmpty()) { 226 msg += " "; 227 } 228 msg += String8::format("a(%d isn't %d)", pixel[3], a); 229 } 230 if (!msg.isEmpty()) { 231 fprintf(stderr, "pixel check failure: %s\n", msg.string()); 232 return ::testing::AssertionFailure( 233 ::testing::Message(msg.string())); 234 } else { 235 return ::testing::AssertionSuccess(); 236 } 237 } 238 239 ::testing::AssertionResult assertRectEq(const Rect &r1, 240 const Rect &r2, int tolerance=1) { 241 242 String8 msg; 243 244 if (abs(r1.left - r2.left) > tolerance) { 245 msg += String8::format("left(%d isn't %d)", r1.left, r2.left); 246 } 247 if (abs(r1.top - r2.top) > tolerance) { 248 if (!msg.isEmpty()) { 249 msg += " "; 250 } 251 msg += String8::format("top(%d isn't %d)", r1.top, r2.top); 252 } 253 if (abs(r1.right - r2.right) > tolerance) { 254 if (!msg.isEmpty()) { 255 msg += " "; 256 } 257 msg += String8::format("right(%d isn't %d)", r1.right, r2.right); 258 } 259 if (abs(r1.bottom - r2.bottom) > tolerance) { 260 if (!msg.isEmpty()) { 261 msg += " "; 262 } 263 msg += String8::format("bottom(%d isn't %d)", r1.bottom, r2.bottom); 264 } 265 if (!msg.isEmpty()) { 266 msg += String8::format(" R1: [%d %d %d %d] R2: [%d %d %d %d]", 267 r1.left, r1.top, r1.right, r1.bottom, 268 r2.left, r2.top, r2.right, r2.bottom); 269 fprintf(stderr, "assertRectEq: %s\n", msg.string()); 270 return ::testing::AssertionFailure( 271 ::testing::Message(msg.string())); 272 } else { 273 return ::testing::AssertionSuccess(); 274 } 275 } 276 277 int mDisplaySecs; 278 sp<SurfaceComposerClient> mComposerClient; 279 sp<SurfaceControl> mSurfaceControl; 280 281 EGLDisplay mEglDisplay; 282 EGLSurface mEglSurface; 283 EGLContext mEglContext; 284 EGLConfig mGlConfig; 285 }; 286 287 static void loadShader(GLenum shaderType, const char* pSource, 288 GLuint* outShader) { 289 GLuint shader = glCreateShader(shaderType); 290 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 291 if (shader) { 292 glShaderSource(shader, 1, &pSource, NULL); 293 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 294 glCompileShader(shader); 295 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 296 GLint compiled = 0; 297 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 298 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 299 if (!compiled) { 300 GLint infoLen = 0; 301 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); 302 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 303 if (infoLen) { 304 char* buf = (char*) malloc(infoLen); 305 if (buf) { 306 glGetShaderInfoLog(shader, infoLen, NULL, buf); 307 printf("Shader compile log:\n%s\n", buf); 308 free(buf); 309 FAIL(); 310 } 311 } else { 312 char* buf = (char*) malloc(0x1000); 313 if (buf) { 314 glGetShaderInfoLog(shader, 0x1000, NULL, buf); 315 printf("Shader compile log:\n%s\n", buf); 316 free(buf); 317 FAIL(); 318 } 319 } 320 glDeleteShader(shader); 321 shader = 0; 322 } 323 } 324 ASSERT_TRUE(shader != 0); 325 *outShader = shader; 326 } 327 328 static void createProgram(const char* pVertexSource, 329 const char* pFragmentSource, GLuint* outPgm) { 330 GLuint vertexShader, fragmentShader; 331 { 332 SCOPED_TRACE("compiling vertex shader"); 333 ASSERT_NO_FATAL_FAILURE(loadShader(GL_VERTEX_SHADER, pVertexSource, 334 &vertexShader)); 335 } 336 { 337 SCOPED_TRACE("compiling fragment shader"); 338 ASSERT_NO_FATAL_FAILURE(loadShader(GL_FRAGMENT_SHADER, pFragmentSource, 339 &fragmentShader)); 340 } 341 342 GLuint program = glCreateProgram(); 343 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 344 if (program) { 345 glAttachShader(program, vertexShader); 346 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 347 glAttachShader(program, fragmentShader); 348 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 349 glLinkProgram(program); 350 GLint linkStatus = GL_FALSE; 351 glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); 352 if (linkStatus != GL_TRUE) { 353 GLint bufLength = 0; 354 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength); 355 if (bufLength) { 356 char* buf = (char*) malloc(bufLength); 357 if (buf) { 358 glGetProgramInfoLog(program, bufLength, NULL, buf); 359 printf("Program link log:\n%s\n", buf); 360 free(buf); 361 FAIL(); 362 } 363 } 364 glDeleteProgram(program); 365 program = 0; 366 } 367 } 368 glDeleteShader(vertexShader); 369 glDeleteShader(fragmentShader); 370 ASSERT_TRUE(program != 0); 371 *outPgm = program; 372 } 373 374 static int abs(int value) { 375 return value > 0 ? value : -value; 376 } 377 378 379 // XXX: Code above this point should live elsewhere 380 381 class SurfaceTextureGLTest : public GLTest { 382 protected: 383 enum { TEX_ID = 123 }; 384 385 virtual void SetUp() { 386 GLTest::SetUp(); 387 mST = new SurfaceTexture(TEX_ID); 388 mSTC = new SurfaceTextureClient(mST); 389 mANW = mSTC; 390 mTextureRenderer = new TextureRenderer(TEX_ID, mST); 391 ASSERT_NO_FATAL_FAILURE(mTextureRenderer->SetUp()); 392 mFW = new FrameWaiter; 393 mST->setFrameAvailableListener(mFW); 394 } 395 396 virtual void TearDown() { 397 mANW.clear(); 398 mSTC.clear(); 399 mST.clear(); 400 GLTest::TearDown(); 401 } 402 403 void drawTexture() { 404 mTextureRenderer->drawTexture(); 405 } 406 407 class TextureRenderer: public RefBase { 408 public: 409 TextureRenderer(GLuint texName, const sp<SurfaceTexture>& st): 410 mTexName(texName), 411 mST(st) { 412 } 413 414 void SetUp() { 415 const char vsrc[] = 416 "attribute vec4 vPosition;\n" 417 "varying vec2 texCoords;\n" 418 "uniform mat4 texMatrix;\n" 419 "void main() {\n" 420 " vec2 vTexCoords = 0.5 * (vPosition.xy + vec2(1.0, 1.0));\n" 421 " texCoords = (texMatrix * vec4(vTexCoords, 0.0, 1.0)).xy;\n" 422 " gl_Position = vPosition;\n" 423 "}\n"; 424 425 const char fsrc[] = 426 "#extension GL_OES_EGL_image_external : require\n" 427 "precision mediump float;\n" 428 "uniform samplerExternalOES texSampler;\n" 429 "varying vec2 texCoords;\n" 430 "void main() {\n" 431 " gl_FragColor = texture2D(texSampler, texCoords);\n" 432 "}\n"; 433 434 { 435 SCOPED_TRACE("creating shader program"); 436 ASSERT_NO_FATAL_FAILURE(createProgram(vsrc, fsrc, &mPgm)); 437 } 438 439 mPositionHandle = glGetAttribLocation(mPgm, "vPosition"); 440 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 441 ASSERT_NE(-1, mPositionHandle); 442 mTexSamplerHandle = glGetUniformLocation(mPgm, "texSampler"); 443 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 444 ASSERT_NE(-1, mTexSamplerHandle); 445 mTexMatrixHandle = glGetUniformLocation(mPgm, "texMatrix"); 446 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 447 ASSERT_NE(-1, mTexMatrixHandle); 448 } 449 450 // drawTexture draws the SurfaceTexture over the entire GL viewport. 451 void drawTexture() { 452 static const GLfloat triangleVertices[] = { 453 -1.0f, 1.0f, 454 -1.0f, -1.0f, 455 1.0f, -1.0f, 456 1.0f, 1.0f, 457 }; 458 459 glVertexAttribPointer(mPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, 460 triangleVertices); 461 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 462 glEnableVertexAttribArray(mPositionHandle); 463 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 464 465 glUseProgram(mPgm); 466 glUniform1i(mTexSamplerHandle, 0); 467 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 468 glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTexName); 469 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 470 471 // XXX: These calls are not needed for GL_TEXTURE_EXTERNAL_OES as 472 // they're setting the defautls for that target, but when hacking 473 // things to use GL_TEXTURE_2D they are needed to achieve the same 474 // behavior. 475 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, 476 GL_LINEAR); 477 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 478 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, 479 GL_LINEAR); 480 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 481 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, 482 GL_CLAMP_TO_EDGE); 483 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 484 glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, 485 GL_CLAMP_TO_EDGE); 486 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 487 488 GLfloat texMatrix[16]; 489 mST->getTransformMatrix(texMatrix); 490 glUniformMatrix4fv(mTexMatrixHandle, 1, GL_FALSE, texMatrix); 491 492 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 493 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 494 } 495 496 GLuint mTexName; 497 sp<SurfaceTexture> mST; 498 GLuint mPgm; 499 GLint mPositionHandle; 500 GLint mTexSamplerHandle; 501 GLint mTexMatrixHandle; 502 }; 503 504 class FrameWaiter : public SurfaceTexture::FrameAvailableListener { 505 public: 506 FrameWaiter(): 507 mPendingFrames(0) { 508 } 509 510 void waitForFrame() { 511 Mutex::Autolock lock(mMutex); 512 while (mPendingFrames == 0) { 513 mCondition.wait(mMutex); 514 } 515 mPendingFrames--; 516 } 517 518 virtual void onFrameAvailable() { 519 Mutex::Autolock lock(mMutex); 520 mPendingFrames++; 521 mCondition.signal(); 522 } 523 524 int mPendingFrames; 525 Mutex mMutex; 526 Condition mCondition; 527 }; 528 529 // Note that SurfaceTexture will lose the notifications 530 // onBuffersReleased and onFrameAvailable as there is currently 531 // no way to forward the events. This DisconnectWaiter will not let the 532 // disconnect finish until finishDisconnect() is called. It will 533 // also block until a disconnect is called 534 class DisconnectWaiter : public BufferQueue::ConsumerListener { 535 public: 536 DisconnectWaiter () : 537 mWaitForDisconnect(false), 538 mPendingFrames(0) { 539 } 540 541 void waitForFrame() { 542 Mutex::Autolock lock(mMutex); 543 while (mPendingFrames == 0) { 544 mFrameCondition.wait(mMutex); 545 } 546 mPendingFrames--; 547 } 548 549 virtual void onFrameAvailable() { 550 Mutex::Autolock lock(mMutex); 551 mPendingFrames++; 552 mFrameCondition.signal(); 553 } 554 555 virtual void onBuffersReleased() { 556 Mutex::Autolock lock(mMutex); 557 while (!mWaitForDisconnect) { 558 mDisconnectCondition.wait(mMutex); 559 } 560 } 561 562 void finishDisconnect() { 563 Mutex::Autolock lock(mMutex); 564 mWaitForDisconnect = true; 565 mDisconnectCondition.signal(); 566 } 567 568 private: 569 Mutex mMutex; 570 571 bool mWaitForDisconnect; 572 Condition mDisconnectCondition; 573 574 int mPendingFrames; 575 Condition mFrameCondition; 576 }; 577 578 sp<SurfaceTexture> mST; 579 sp<SurfaceTextureClient> mSTC; 580 sp<ANativeWindow> mANW; 581 sp<TextureRenderer> mTextureRenderer; 582 sp<FrameWaiter> mFW; 583 }; 584 585 // Fill a YV12 buffer with a multi-colored checkerboard pattern 586 void fillYV12Buffer(uint8_t* buf, int w, int h, int stride) { 587 const int blockWidth = w > 16 ? w / 16 : 1; 588 const int blockHeight = h > 16 ? h / 16 : 1; 589 const int yuvTexOffsetY = 0; 590 int yuvTexStrideY = stride; 591 int yuvTexOffsetV = yuvTexStrideY * h; 592 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 593 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; 594 int yuvTexStrideU = yuvTexStrideV; 595 for (int x = 0; x < w; x++) { 596 for (int y = 0; y < h; y++) { 597 int parityX = (x / blockWidth) & 1; 598 int parityY = (y / blockHeight) & 1; 599 unsigned char intensity = (parityX ^ parityY) ? 63 : 191; 600 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = intensity; 601 if (x < w / 2 && y < h / 2) { 602 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = intensity; 603 if (x * 2 < w / 2 && y * 2 < h / 2) { 604 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 0] = 605 buf[yuvTexOffsetV + (y*2 * yuvTexStrideV) + x*2 + 1] = 606 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 0] = 607 buf[yuvTexOffsetV + ((y*2+1) * yuvTexStrideV) + x*2 + 1] = 608 intensity; 609 } 610 } 611 } 612 } 613 } 614 615 // Fill a YV12 buffer with red outside a given rectangle and green inside it. 616 void fillYV12BufferRect(uint8_t* buf, int w, int h, int stride, 617 const android_native_rect_t& rect) { 618 const int yuvTexOffsetY = 0; 619 int yuvTexStrideY = stride; 620 int yuvTexOffsetV = yuvTexStrideY * h; 621 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 622 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * h/2; 623 int yuvTexStrideU = yuvTexStrideV; 624 for (int x = 0; x < w; x++) { 625 for (int y = 0; y < h; y++) { 626 bool inside = rect.left <= x && x < rect.right && 627 rect.top <= y && y < rect.bottom; 628 buf[yuvTexOffsetY + (y * yuvTexStrideY) + x] = inside ? 240 : 64; 629 if (x < w / 2 && y < h / 2) { 630 bool inside = rect.left <= 2*x && 2*x < rect.right && 631 rect.top <= 2*y && 2*y < rect.bottom; 632 buf[yuvTexOffsetU + (y * yuvTexStrideU) + x] = 16; 633 buf[yuvTexOffsetV + (y * yuvTexStrideV) + x] = 634 inside ? 16 : 255; 635 } 636 } 637 } 638 } 639 640 void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) { 641 const size_t PIXEL_SIZE = 4; 642 for (int x = 0; x < w; x++) { 643 for (int y = 0; y < h; y++) { 644 off_t offset = (y * stride + x) * PIXEL_SIZE; 645 for (int c = 0; c < 4; c++) { 646 int parityX = (x / (1 << (c+2))) & 1; 647 int parityY = (y / (1 << (c+2))) & 1; 648 buf[offset + c] = (parityX ^ parityY) ? 231 : 35; 649 } 650 } 651 } 652 } 653 654 void fillRGBA8BufferSolid(uint8_t* buf, int w, int h, int stride, uint8_t r, 655 uint8_t g, uint8_t b, uint8_t a) { 656 const size_t PIXEL_SIZE = 4; 657 for (int y = 0; y < h; y++) { 658 for (int x = 0; x < h; x++) { 659 off_t offset = (y * stride + x) * PIXEL_SIZE; 660 buf[offset + 0] = r; 661 buf[offset + 1] = g; 662 buf[offset + 2] = b; 663 buf[offset + 3] = a; 664 } 665 } 666 } 667 668 // Produce a single RGBA8 frame by filling a buffer with a checkerboard pattern 669 // using the CPU. This assumes that the ANativeWindow is already configured to 670 // allow this to be done (e.g. the format is set to RGBA8). 671 // 672 // Calls to this function should be wrapped in an ASSERT_NO_FATAL_FAILURE(). 673 void produceOneRGBA8Frame(const sp<ANativeWindow>& anw) { 674 android_native_buffer_t* anb; 675 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(anw.get(), 676 &anb)); 677 ASSERT_TRUE(anb != NULL); 678 679 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 680 681 uint8_t* img = NULL; 682 ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, 683 (void**)(&img))); 684 fillRGBA8Buffer(img, buf->getWidth(), buf->getHeight(), buf->getStride()); 685 ASSERT_EQ(NO_ERROR, buf->unlock()); 686 ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf->getNativeBuffer(), 687 -1)); 688 } 689 690 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferNpot) { 691 const int texWidth = 64; 692 const int texHeight = 66; 693 694 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 695 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); 696 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 697 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 698 699 ANativeWindowBuffer* anb; 700 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 701 &anb)); 702 ASSERT_TRUE(anb != NULL); 703 704 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 705 706 // Fill the buffer with the a checkerboard pattern 707 uint8_t* img = NULL; 708 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 709 fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); 710 buf->unlock(); 711 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), 712 -1)); 713 714 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 715 716 glClearColor(0.2, 0.2, 0.2, 0.2); 717 glClear(GL_COLOR_BUFFER_BIT); 718 719 glViewport(0, 0, texWidth, texHeight); 720 drawTexture(); 721 722 EXPECT_TRUE(checkPixel( 0, 0, 255, 127, 255, 255)); 723 EXPECT_TRUE(checkPixel(63, 0, 0, 133, 0, 255)); 724 EXPECT_TRUE(checkPixel(63, 65, 0, 133, 0, 255)); 725 EXPECT_TRUE(checkPixel( 0, 65, 255, 127, 255, 255)); 726 727 EXPECT_TRUE(checkPixel(22, 44, 255, 127, 255, 255)); 728 EXPECT_TRUE(checkPixel(45, 52, 255, 127, 255, 255)); 729 EXPECT_TRUE(checkPixel(52, 51, 98, 255, 73, 255)); 730 EXPECT_TRUE(checkPixel( 7, 31, 155, 0, 118, 255)); 731 EXPECT_TRUE(checkPixel(31, 9, 107, 24, 87, 255)); 732 EXPECT_TRUE(checkPixel(29, 35, 255, 127, 255, 255)); 733 EXPECT_TRUE(checkPixel(36, 22, 155, 29, 0, 255)); 734 } 735 736 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferPow2) { 737 const int texWidth = 64; 738 const int texHeight = 64; 739 740 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 741 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); 742 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 743 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 744 745 ANativeWindowBuffer* anb; 746 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 747 &anb)); 748 ASSERT_TRUE(anb != NULL); 749 750 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 751 752 // Fill the buffer with the a checkerboard pattern 753 uint8_t* img = NULL; 754 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 755 fillYV12Buffer(img, texWidth, texHeight, buf->getStride()); 756 buf->unlock(); 757 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), 758 -1)); 759 760 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 761 762 glClearColor(0.2, 0.2, 0.2, 0.2); 763 glClear(GL_COLOR_BUFFER_BIT); 764 765 glViewport(0, 0, texWidth, texHeight); 766 drawTexture(); 767 768 EXPECT_TRUE(checkPixel( 0, 0, 0, 133, 0, 255)); 769 EXPECT_TRUE(checkPixel(63, 0, 255, 127, 255, 255)); 770 EXPECT_TRUE(checkPixel(63, 63, 0, 133, 0, 255)); 771 EXPECT_TRUE(checkPixel( 0, 63, 255, 127, 255, 255)); 772 773 EXPECT_TRUE(checkPixel(22, 19, 100, 255, 74, 255)); 774 EXPECT_TRUE(checkPixel(45, 11, 100, 255, 74, 255)); 775 EXPECT_TRUE(checkPixel(52, 12, 155, 0, 181, 255)); 776 EXPECT_TRUE(checkPixel( 7, 32, 150, 237, 170, 255)); 777 EXPECT_TRUE(checkPixel(31, 54, 0, 71, 117, 255)); 778 EXPECT_TRUE(checkPixel(29, 28, 0, 133, 0, 255)); 779 EXPECT_TRUE(checkPixel(36, 41, 100, 232, 255, 255)); 780 } 781 782 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BufferWithCrop) { 783 const int texWidth = 64; 784 const int texHeight = 66; 785 786 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 787 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); 788 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 789 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 790 791 android_native_rect_t crops[] = { 792 {4, 6, 22, 36}, 793 {0, 6, 22, 36}, 794 {4, 0, 22, 36}, 795 {4, 6, texWidth, 36}, 796 {4, 6, 22, texHeight}, 797 }; 798 799 for (int i = 0; i < 5; i++) { 800 const android_native_rect_t& crop(crops[i]); 801 SCOPED_TRACE(String8::format("rect{ l: %d t: %d r: %d b: %d }", 802 crop.left, crop.top, crop.right, crop.bottom).string()); 803 804 ASSERT_EQ(NO_ERROR, native_window_set_crop(mANW.get(), &crop)); 805 806 ANativeWindowBuffer* anb; 807 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 808 &anb)); 809 ASSERT_TRUE(anb != NULL); 810 811 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 812 813 uint8_t* img = NULL; 814 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 815 fillYV12BufferRect(img, texWidth, texHeight, buf->getStride(), crop); 816 buf->unlock(); 817 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), 818 buf->getNativeBuffer(), -1)); 819 820 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 821 822 glClearColor(0.2, 0.2, 0.2, 0.2); 823 glClear(GL_COLOR_BUFFER_BIT); 824 825 glViewport(0, 0, 64, 64); 826 drawTexture(); 827 828 EXPECT_TRUE(checkPixel( 0, 0, 82, 255, 35, 255)); 829 EXPECT_TRUE(checkPixel(63, 0, 82, 255, 35, 255)); 830 EXPECT_TRUE(checkPixel(63, 63, 82, 255, 35, 255)); 831 EXPECT_TRUE(checkPixel( 0, 63, 82, 255, 35, 255)); 832 833 EXPECT_TRUE(checkPixel(25, 14, 82, 255, 35, 255)); 834 EXPECT_TRUE(checkPixel(35, 31, 82, 255, 35, 255)); 835 EXPECT_TRUE(checkPixel(57, 6, 82, 255, 35, 255)); 836 EXPECT_TRUE(checkPixel( 5, 42, 82, 255, 35, 255)); 837 EXPECT_TRUE(checkPixel(32, 33, 82, 255, 35, 255)); 838 EXPECT_TRUE(checkPixel(16, 26, 82, 255, 35, 255)); 839 EXPECT_TRUE(checkPixel(46, 51, 82, 255, 35, 255)); 840 } 841 } 842 843 // This test is intended to catch synchronization bugs between the CPU-written 844 // and GPU-read buffers. 845 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledYV12BuffersRepeatedly) { 846 enum { texWidth = 16 }; 847 enum { texHeight = 16 }; 848 enum { numFrames = 1024 }; 849 850 ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); 851 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); 852 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 853 texWidth, texHeight, HAL_PIXEL_FORMAT_YV12)); 854 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 855 GRALLOC_USAGE_SW_WRITE_OFTEN)); 856 857 struct TestPixel { 858 int x; 859 int y; 860 }; 861 const TestPixel testPixels[] = { 862 { 4, 11 }, 863 { 12, 14 }, 864 { 7, 2 }, 865 }; 866 enum {numTestPixels = sizeof(testPixels) / sizeof(testPixels[0])}; 867 868 class ProducerThread : public Thread { 869 public: 870 ProducerThread(const sp<ANativeWindow>& anw, 871 const TestPixel* testPixels): 872 mANW(anw), 873 mTestPixels(testPixels) { 874 } 875 876 virtual ~ProducerThread() { 877 } 878 879 virtual bool threadLoop() { 880 for (int i = 0; i < numFrames; i++) { 881 ANativeWindowBuffer* anb; 882 if (native_window_dequeue_buffer_and_wait(mANW.get(), 883 &anb) != NO_ERROR) { 884 return false; 885 } 886 if (anb == NULL) { 887 return false; 888 } 889 890 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 891 892 const int yuvTexOffsetY = 0; 893 int stride = buf->getStride(); 894 int yuvTexStrideY = stride; 895 int yuvTexOffsetV = yuvTexStrideY * texHeight; 896 int yuvTexStrideV = (yuvTexStrideY/2 + 0xf) & ~0xf; 897 int yuvTexOffsetU = yuvTexOffsetV + yuvTexStrideV * texHeight/2; 898 int yuvTexStrideU = yuvTexStrideV; 899 900 uint8_t* img = NULL; 901 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 902 903 // Gray out all the test pixels first, so we're more likely to 904 // see a failure if GL is still texturing from the buffer we 905 // just dequeued. 906 for (int j = 0; j < numTestPixels; j++) { 907 int x = mTestPixels[j].x; 908 int y = mTestPixels[j].y; 909 uint8_t value = 128; 910 img[y*stride + x] = value; 911 } 912 913 // Fill the buffer with gray. 914 for (int y = 0; y < texHeight; y++) { 915 for (int x = 0; x < texWidth; x++) { 916 img[yuvTexOffsetY + y*yuvTexStrideY + x] = 128; 917 img[yuvTexOffsetU + (y/2)*yuvTexStrideU + x/2] = 128; 918 img[yuvTexOffsetV + (y/2)*yuvTexStrideV + x/2] = 128; 919 } 920 } 921 922 // Set the test pixels to either white or black. 923 for (int j = 0; j < numTestPixels; j++) { 924 int x = mTestPixels[j].x; 925 int y = mTestPixels[j].y; 926 uint8_t value = 0; 927 if (j == (i % numTestPixels)) { 928 value = 255; 929 } 930 img[y*stride + x] = value; 931 } 932 933 buf->unlock(); 934 if (mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), -1) 935 != NO_ERROR) { 936 return false; 937 } 938 } 939 return false; 940 } 941 942 sp<ANativeWindow> mANW; 943 const TestPixel* mTestPixels; 944 }; 945 946 sp<Thread> pt(new ProducerThread(mANW, testPixels)); 947 pt->run(); 948 949 glViewport(0, 0, texWidth, texHeight); 950 951 glClearColor(0.2, 0.2, 0.2, 0.2); 952 glClear(GL_COLOR_BUFFER_BIT); 953 954 // We wait for the first two frames up front so that the producer will be 955 // likely to dequeue the buffer that's currently being textured from. 956 mFW->waitForFrame(); 957 mFW->waitForFrame(); 958 959 for (int i = 0; i < numFrames; i++) { 960 SCOPED_TRACE(String8::format("frame %d", i).string()); 961 962 // We must wait for each frame to come in because if we ever do an 963 // updateTexImage call that doesn't consume a newly available buffer 964 // then the producer and consumer will get out of sync, which will cause 965 // a deadlock. 966 if (i > 1) { 967 mFW->waitForFrame(); 968 } 969 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 970 drawTexture(); 971 972 for (int j = 0; j < numTestPixels; j++) { 973 int x = testPixels[j].x; 974 int y = testPixels[j].y; 975 uint8_t value = 0; 976 if (j == (i % numTestPixels)) { 977 // We must y-invert the texture coords 978 EXPECT_TRUE(checkPixel(x, texHeight-y-1, 255, 255, 255, 255)); 979 } else { 980 // We must y-invert the texture coords 981 EXPECT_TRUE(checkPixel(x, texHeight-y-1, 0, 0, 0, 255)); 982 } 983 } 984 } 985 986 pt->requestExitAndWait(); 987 } 988 989 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferNpot) { 990 const int texWidth = 64; 991 const int texHeight = 66; 992 993 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 994 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); 995 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 996 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 997 998 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 999 1000 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1001 1002 glClearColor(0.2, 0.2, 0.2, 0.2); 1003 glClear(GL_COLOR_BUFFER_BIT); 1004 1005 glViewport(0, 0, texWidth, texHeight); 1006 drawTexture(); 1007 1008 EXPECT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 1009 EXPECT_TRUE(checkPixel(63, 0, 231, 231, 231, 231)); 1010 EXPECT_TRUE(checkPixel(63, 65, 231, 231, 231, 231)); 1011 EXPECT_TRUE(checkPixel( 0, 65, 35, 35, 35, 35)); 1012 1013 EXPECT_TRUE(checkPixel(15, 10, 35, 231, 231, 231)); 1014 EXPECT_TRUE(checkPixel(23, 65, 231, 35, 231, 35)); 1015 EXPECT_TRUE(checkPixel(19, 40, 35, 231, 35, 35)); 1016 EXPECT_TRUE(checkPixel(38, 30, 231, 35, 35, 35)); 1017 EXPECT_TRUE(checkPixel(42, 54, 35, 35, 35, 231)); 1018 EXPECT_TRUE(checkPixel(37, 34, 35, 231, 231, 231)); 1019 EXPECT_TRUE(checkPixel(31, 8, 231, 35, 35, 231)); 1020 EXPECT_TRUE(checkPixel(37, 47, 231, 35, 231, 231)); 1021 EXPECT_TRUE(checkPixel(25, 38, 35, 35, 35, 35)); 1022 EXPECT_TRUE(checkPixel(49, 6, 35, 231, 35, 35)); 1023 EXPECT_TRUE(checkPixel(54, 50, 35, 231, 231, 231)); 1024 EXPECT_TRUE(checkPixel(27, 26, 231, 231, 231, 231)); 1025 EXPECT_TRUE(checkPixel(10, 6, 35, 35, 231, 231)); 1026 EXPECT_TRUE(checkPixel(29, 4, 35, 35, 35, 231)); 1027 EXPECT_TRUE(checkPixel(55, 28, 35, 35, 231, 35)); 1028 EXPECT_TRUE(checkPixel(58, 55, 35, 35, 231, 231)); 1029 } 1030 1031 TEST_F(SurfaceTextureGLTest, TexturingFromCpuFilledRGBABufferPow2) { 1032 const int texWidth = 64; 1033 const int texHeight = 64; 1034 1035 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 1036 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); 1037 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 1038 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 1039 1040 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 1041 1042 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1043 1044 glClearColor(0.2, 0.2, 0.2, 0.2); 1045 glClear(GL_COLOR_BUFFER_BIT); 1046 1047 glViewport(0, 0, texWidth, texHeight); 1048 drawTexture(); 1049 1050 EXPECT_TRUE(checkPixel( 0, 0, 231, 231, 231, 231)); 1051 EXPECT_TRUE(checkPixel(63, 0, 35, 35, 35, 35)); 1052 EXPECT_TRUE(checkPixel(63, 63, 231, 231, 231, 231)); 1053 EXPECT_TRUE(checkPixel( 0, 63, 35, 35, 35, 35)); 1054 1055 EXPECT_TRUE(checkPixel(12, 46, 231, 231, 231, 35)); 1056 EXPECT_TRUE(checkPixel(16, 1, 231, 231, 35, 231)); 1057 EXPECT_TRUE(checkPixel(21, 12, 231, 35, 35, 231)); 1058 EXPECT_TRUE(checkPixel(26, 51, 231, 35, 231, 35)); 1059 EXPECT_TRUE(checkPixel( 5, 32, 35, 231, 231, 35)); 1060 EXPECT_TRUE(checkPixel(13, 8, 35, 231, 231, 231)); 1061 EXPECT_TRUE(checkPixel(46, 3, 35, 35, 231, 35)); 1062 EXPECT_TRUE(checkPixel(30, 33, 35, 35, 35, 35)); 1063 EXPECT_TRUE(checkPixel( 6, 52, 231, 231, 35, 35)); 1064 EXPECT_TRUE(checkPixel(55, 33, 35, 231, 35, 231)); 1065 EXPECT_TRUE(checkPixel(16, 29, 35, 35, 231, 231)); 1066 EXPECT_TRUE(checkPixel( 1, 30, 35, 35, 35, 231)); 1067 EXPECT_TRUE(checkPixel(41, 37, 35, 35, 231, 231)); 1068 EXPECT_TRUE(checkPixel(46, 29, 231, 231, 35, 35)); 1069 EXPECT_TRUE(checkPixel(15, 25, 35, 231, 35, 231)); 1070 EXPECT_TRUE(checkPixel( 3, 52, 35, 231, 35, 35)); 1071 } 1072 1073 // Tests if SurfaceTexture and BufferQueue are robust enough 1074 // to handle a special case where updateTexImage is called 1075 // in the middle of disconnect. This ordering is enforced 1076 // by blocking in the disconnect callback. 1077 TEST_F(SurfaceTextureGLTest, DisconnectStressTest) { 1078 1079 class ProducerThread : public Thread { 1080 public: 1081 ProducerThread(const sp<ANativeWindow>& anw): 1082 mANW(anw) { 1083 } 1084 1085 virtual ~ProducerThread() { 1086 } 1087 1088 virtual bool threadLoop() { 1089 ANativeWindowBuffer* anb; 1090 1091 native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_EGL); 1092 1093 for (int numFrames =0 ; numFrames < 2; numFrames ++) { 1094 1095 if (native_window_dequeue_buffer_and_wait(mANW.get(), 1096 &anb) != NO_ERROR) { 1097 return false; 1098 } 1099 if (anb == NULL) { 1100 return false; 1101 } 1102 if (mANW->queueBuffer(mANW.get(), anb, -1) 1103 != NO_ERROR) { 1104 return false; 1105 } 1106 } 1107 1108 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_EGL); 1109 1110 return false; 1111 } 1112 1113 private: 1114 sp<ANativeWindow> mANW; 1115 }; 1116 1117 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1118 1119 sp<DisconnectWaiter> dw(new DisconnectWaiter()); 1120 mST->getBufferQueue()->consumerConnect(dw); 1121 1122 1123 sp<Thread> pt(new ProducerThread(mANW)); 1124 pt->run(); 1125 1126 // eat a frame so SurfaceTexture will own an at least one slot 1127 dw->waitForFrame(); 1128 EXPECT_EQ(OK,mST->updateTexImage()); 1129 1130 dw->waitForFrame(); 1131 // Could fail here as SurfaceTexture thinks it still owns the slot 1132 // but bufferQueue has released all slots 1133 EXPECT_EQ(OK,mST->updateTexImage()); 1134 1135 dw->finishDisconnect(); 1136 } 1137 1138 1139 // This test ensures that the SurfaceTexture clears the mCurrentTexture 1140 // when it is disconnected and reconnected. Otherwise it will 1141 // attempt to release a buffer that it does not owned 1142 TEST_F(SurfaceTextureGLTest, DisconnectClearsCurrentTexture) { 1143 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1144 1145 ASSERT_EQ(OK, native_window_api_connect(mANW.get(), 1146 NATIVE_WINDOW_API_EGL)); 1147 1148 ANativeWindowBuffer *anb; 1149 1150 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1151 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1152 1153 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1154 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1155 1156 EXPECT_EQ(OK,mST->updateTexImage()); 1157 EXPECT_EQ(OK,mST->updateTexImage()); 1158 1159 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(), 1160 NATIVE_WINDOW_API_EGL)); 1161 ASSERT_EQ(OK, native_window_api_connect(mANW.get(), 1162 NATIVE_WINDOW_API_EGL)); 1163 1164 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1165 1166 EXPECT_EQ(OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1167 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1168 1169 // Will fail here if mCurrentTexture is not cleared properly 1170 mFW->waitForFrame(); 1171 EXPECT_EQ(OK,mST->updateTexImage()); 1172 1173 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(), 1174 NATIVE_WINDOW_API_EGL)); 1175 } 1176 1177 TEST_F(SurfaceTextureGLTest, ScaleToWindowMode) { 1178 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1179 1180 ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(), 1181 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW)); 1182 1183 // The producer image size 1184 ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512)); 1185 1186 // The consumer image size (16 x 9) ratio 1187 mST->setDefaultBufferSize(1280, 720); 1188 1189 ASSERT_EQ(OK, native_window_api_connect(mANW.get(), 1190 NATIVE_WINDOW_API_CPU)); 1191 1192 ANativeWindowBuffer *anb; 1193 1194 android_native_rect_t odd = {23, 78, 123, 477}; 1195 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &odd)); 1196 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1197 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1198 mFW->waitForFrame(); 1199 EXPECT_EQ(OK, mST->updateTexImage()); 1200 Rect r = mST->getCurrentCrop(); 1201 assertRectEq(Rect(23, 78, 123, 477), r); 1202 1203 ASSERT_EQ(OK, native_window_api_disconnect(mANW.get(), 1204 NATIVE_WINDOW_API_CPU)); 1205 } 1206 1207 // This test ensures the scaling mode does the right thing 1208 // ie NATIVE_WINDOW_SCALING_MODE_CROP should crop 1209 // the image such that it has the same aspect ratio as the 1210 // default buffer size 1211 TEST_F(SurfaceTextureGLTest, CroppedScalingMode) { 1212 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1213 1214 ASSERT_EQ(OK, native_window_set_scaling_mode(mANW.get(), 1215 NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)); 1216 1217 // The producer image size 1218 ASSERT_EQ(OK, native_window_set_buffers_dimensions(mANW.get(), 512, 512)); 1219 1220 // The consumer image size (16 x 9) ratio 1221 mST->setDefaultBufferSize(1280, 720); 1222 1223 native_window_api_connect(mANW.get(), NATIVE_WINDOW_API_CPU); 1224 1225 ANativeWindowBuffer *anb; 1226 1227 // The crop is in the shape of (320, 180) === 16 x 9 1228 android_native_rect_t standard = {10, 20, 330, 200}; 1229 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &standard)); 1230 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1231 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1232 mFW->waitForFrame(); 1233 EXPECT_EQ(OK, mST->updateTexImage()); 1234 Rect r = mST->getCurrentCrop(); 1235 // crop should be the same as crop (same aspect ratio) 1236 assertRectEq(Rect(10, 20, 330, 200), r); 1237 1238 // make this wider then desired aspect 239 x 100 (2.39:1) 1239 android_native_rect_t wide = {20, 30, 259, 130}; 1240 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &wide)); 1241 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1242 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1243 mFW->waitForFrame(); 1244 EXPECT_EQ(OK, mST->updateTexImage()); 1245 r = mST->getCurrentCrop(); 1246 // crop should be the same height, but have cropped left and right borders 1247 // offset is 30.6 px L+, R- 1248 assertRectEq(Rect(51, 30, 228, 130), r); 1249 1250 // This image is taller then desired aspect 400 x 300 (4:3) 1251 android_native_rect_t narrow = {0, 0, 400, 300}; 1252 ASSERT_EQ(OK, native_window_set_crop(mANW.get(), &narrow)); 1253 EXPECT_EQ (OK, native_window_dequeue_buffer_and_wait(mANW.get(), &anb)); 1254 EXPECT_EQ(OK, mANW->queueBuffer(mANW.get(), anb, -1)); 1255 mFW->waitForFrame(); 1256 EXPECT_EQ(OK, mST->updateTexImage()); 1257 r = mST->getCurrentCrop(); 1258 // crop should be the same width, but have cropped top and bottom borders 1259 // offset is 37.5 px 1260 assertRectEq(Rect(0, 37, 400, 262), r); 1261 1262 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 1263 } 1264 1265 TEST_F(SurfaceTextureGLTest, AbandonUnblocksDequeueBuffer) { 1266 class ProducerThread : public Thread { 1267 public: 1268 ProducerThread(const sp<ANativeWindow>& anw): 1269 mANW(anw), 1270 mDequeueError(NO_ERROR) { 1271 } 1272 1273 virtual ~ProducerThread() { 1274 } 1275 1276 virtual bool threadLoop() { 1277 Mutex::Autolock lock(mMutex); 1278 ANativeWindowBuffer* anb; 1279 1280 // Frame 1 1281 if (native_window_dequeue_buffer_and_wait(mANW.get(), 1282 &anb) != NO_ERROR) { 1283 return false; 1284 } 1285 if (anb == NULL) { 1286 return false; 1287 } 1288 if (mANW->queueBuffer(mANW.get(), anb, -1) 1289 != NO_ERROR) { 1290 return false; 1291 } 1292 1293 // Frame 2 1294 if (native_window_dequeue_buffer_and_wait(mANW.get(), 1295 &anb) != NO_ERROR) { 1296 return false; 1297 } 1298 if (anb == NULL) { 1299 return false; 1300 } 1301 if (mANW->queueBuffer(mANW.get(), anb, -1) 1302 != NO_ERROR) { 1303 return false; 1304 } 1305 1306 // Frame 3 - error expected 1307 mDequeueError = native_window_dequeue_buffer_and_wait(mANW.get(), 1308 &anb); 1309 return false; 1310 } 1311 1312 status_t getDequeueError() { 1313 Mutex::Autolock lock(mMutex); 1314 return mDequeueError; 1315 } 1316 1317 private: 1318 sp<ANativeWindow> mANW; 1319 status_t mDequeueError; 1320 Mutex mMutex; 1321 }; 1322 1323 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 1324 ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2)); 1325 1326 sp<Thread> pt(new ProducerThread(mANW)); 1327 pt->run(); 1328 1329 mFW->waitForFrame(); 1330 mFW->waitForFrame(); 1331 1332 // Sleep for 100ms to allow the producer thread's dequeueBuffer call to 1333 // block waiting for a buffer to become available. 1334 usleep(100000); 1335 1336 mST->abandon(); 1337 1338 pt->requestExitAndWait(); 1339 ASSERT_EQ(NO_INIT, 1340 reinterpret_cast<ProducerThread*>(pt.get())->getDequeueError()); 1341 } 1342 1343 TEST_F(SurfaceTextureGLTest, InvalidWidthOrHeightFails) { 1344 int texHeight = 16; 1345 ANativeWindowBuffer* anb; 1346 1347 GLint maxTextureSize; 1348 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); 1349 1350 // make sure it works with small textures 1351 mST->setDefaultBufferSize(16, texHeight); 1352 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 1353 &anb)); 1354 EXPECT_EQ(16, anb->width); 1355 EXPECT_EQ(texHeight, anb->height); 1356 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); 1357 EXPECT_EQ(NO_ERROR, mST->updateTexImage()); 1358 1359 // make sure it works with GL_MAX_TEXTURE_SIZE 1360 mST->setDefaultBufferSize(maxTextureSize, texHeight); 1361 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 1362 &anb)); 1363 EXPECT_EQ(maxTextureSize, anb->width); 1364 EXPECT_EQ(texHeight, anb->height); 1365 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); 1366 EXPECT_EQ(NO_ERROR, mST->updateTexImage()); 1367 1368 // make sure it fails with GL_MAX_TEXTURE_SIZE+1 1369 mST->setDefaultBufferSize(maxTextureSize+1, texHeight); 1370 EXPECT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 1371 &anb)); 1372 EXPECT_EQ(maxTextureSize+1, anb->width); 1373 EXPECT_EQ(texHeight, anb->height); 1374 EXPECT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), anb, -1)); 1375 ASSERT_NE(NO_ERROR, mST->updateTexImage()); 1376 } 1377 1378 /* 1379 * This test fixture is for testing GL -> GL texture streaming. It creates an 1380 * EGLSurface and an EGLContext for the image producer to use. 1381 */ 1382 class SurfaceTextureGLToGLTest : public SurfaceTextureGLTest { 1383 protected: 1384 SurfaceTextureGLToGLTest(): 1385 mProducerEglSurface(EGL_NO_SURFACE), 1386 mProducerEglContext(EGL_NO_CONTEXT) { 1387 } 1388 1389 virtual void SetUp() { 1390 SurfaceTextureGLTest::SetUp(); 1391 1392 mProducerEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig, 1393 mANW.get(), NULL); 1394 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1395 ASSERT_NE(EGL_NO_SURFACE, mProducerEglSurface); 1396 1397 mProducerEglContext = eglCreateContext(mEglDisplay, mGlConfig, 1398 EGL_NO_CONTEXT, getContextAttribs()); 1399 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1400 ASSERT_NE(EGL_NO_CONTEXT, mProducerEglContext); 1401 } 1402 1403 virtual void TearDown() { 1404 if (mProducerEglContext != EGL_NO_CONTEXT) { 1405 eglDestroyContext(mEglDisplay, mProducerEglContext); 1406 } 1407 if (mProducerEglSurface != EGL_NO_SURFACE) { 1408 eglDestroySurface(mEglDisplay, mProducerEglSurface); 1409 } 1410 SurfaceTextureGLTest::TearDown(); 1411 } 1412 1413 EGLSurface mProducerEglSurface; 1414 EGLContext mProducerEglContext; 1415 }; 1416 1417 TEST_F(SurfaceTextureGLToGLTest, TransformHintGetsRespected) { 1418 const uint32_t texWidth = 32; 1419 const uint32_t texHeight = 64; 1420 1421 mST->setDefaultBufferSize(texWidth, texHeight); 1422 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90); 1423 1424 // This test requires 3 buffers to avoid deadlock because we're 1425 // both producer and consumer, and only using one thread. 1426 mST->setDefaultMaxBufferCount(3); 1427 1428 // Do the producer side of things 1429 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1430 mProducerEglSurface, mProducerEglContext)); 1431 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1432 1433 // Start a buffer with our chosen size and transform hint moving 1434 // through the system. 1435 glClear(GL_COLOR_BUFFER_BIT); // give the driver something to do 1436 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1437 mST->updateTexImage(); // consume it 1438 // Swap again. 1439 glClear(GL_COLOR_BUFFER_BIT); 1440 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1441 mST->updateTexImage(); 1442 1443 // The current buffer should either show the effects of the transform 1444 // hint (in the form of an inverse transform), or show that the 1445 // transform hint has been ignored. 1446 sp<GraphicBuffer> buf = mST->getCurrentBuffer(); 1447 if (mST->getCurrentTransform() == NATIVE_WINDOW_TRANSFORM_ROT_270) { 1448 ASSERT_EQ(texWidth, buf->getHeight()); 1449 ASSERT_EQ(texHeight, buf->getWidth()); 1450 } else { 1451 ASSERT_EQ(texWidth, buf->getWidth()); 1452 ASSERT_EQ(texHeight, buf->getHeight()); 1453 } 1454 1455 // Reset the transform hint and confirm that it takes. 1456 mST->setTransformHint(0); 1457 glClear(GL_COLOR_BUFFER_BIT); 1458 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1459 mST->updateTexImage(); 1460 glClear(GL_COLOR_BUFFER_BIT); 1461 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1462 mST->updateTexImage(); 1463 1464 buf = mST->getCurrentBuffer(); 1465 ASSERT_EQ((uint32_t) 0, mST->getCurrentTransform()); 1466 ASSERT_EQ(texWidth, buf->getWidth()); 1467 ASSERT_EQ(texHeight, buf->getHeight()); 1468 } 1469 1470 TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) { 1471 const int texWidth = 64; 1472 const int texHeight = 64; 1473 1474 mST->setDefaultBufferSize(texWidth, texHeight); 1475 1476 // This test requires 3 buffers to complete run on a single thread. 1477 mST->setDefaultMaxBufferCount(3); 1478 1479 // Do the producer side of things 1480 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1481 mProducerEglSurface, mProducerEglContext)); 1482 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1483 1484 // This is needed to ensure we pick up a buffer of the correct size. 1485 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1486 1487 glClearColor(0.6, 0.6, 0.6, 0.6); 1488 glClear(GL_COLOR_BUFFER_BIT); 1489 1490 glEnable(GL_SCISSOR_TEST); 1491 glScissor(4, 4, 4, 4); 1492 glClearColor(1.0, 0.0, 0.0, 1.0); 1493 glClear(GL_COLOR_BUFFER_BIT); 1494 1495 glScissor(24, 48, 4, 4); 1496 glClearColor(0.0, 1.0, 0.0, 1.0); 1497 glClear(GL_COLOR_BUFFER_BIT); 1498 1499 glScissor(37, 17, 4, 4); 1500 glClearColor(0.0, 0.0, 1.0, 1.0); 1501 glClear(GL_COLOR_BUFFER_BIT); 1502 1503 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1504 1505 // Do the consumer side of things 1506 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1507 mEglContext)); 1508 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1509 1510 glDisable(GL_SCISSOR_TEST); 1511 1512 // Skip the first frame, which was empty 1513 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1514 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1515 1516 glClearColor(0.2, 0.2, 0.2, 0.2); 1517 glClear(GL_COLOR_BUFFER_BIT); 1518 1519 glViewport(0, 0, texWidth, texHeight); 1520 drawTexture(); 1521 1522 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153)); 1523 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153)); 1524 EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153)); 1525 EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153)); 1526 1527 EXPECT_TRUE(checkPixel( 4, 7, 255, 0, 0, 255)); 1528 EXPECT_TRUE(checkPixel(25, 51, 0, 255, 0, 255)); 1529 EXPECT_TRUE(checkPixel(40, 19, 0, 0, 255, 255)); 1530 EXPECT_TRUE(checkPixel(29, 51, 153, 153, 153, 153)); 1531 EXPECT_TRUE(checkPixel( 5, 32, 153, 153, 153, 153)); 1532 EXPECT_TRUE(checkPixel(13, 8, 153, 153, 153, 153)); 1533 EXPECT_TRUE(checkPixel(46, 3, 153, 153, 153, 153)); 1534 EXPECT_TRUE(checkPixel(30, 33, 153, 153, 153, 153)); 1535 EXPECT_TRUE(checkPixel( 6, 52, 153, 153, 153, 153)); 1536 EXPECT_TRUE(checkPixel(55, 33, 153, 153, 153, 153)); 1537 EXPECT_TRUE(checkPixel(16, 29, 153, 153, 153, 153)); 1538 EXPECT_TRUE(checkPixel( 1, 30, 153, 153, 153, 153)); 1539 EXPECT_TRUE(checkPixel(41, 37, 153, 153, 153, 153)); 1540 EXPECT_TRUE(checkPixel(46, 29, 153, 153, 153, 153)); 1541 EXPECT_TRUE(checkPixel(15, 25, 153, 153, 153, 153)); 1542 EXPECT_TRUE(checkPixel( 3, 52, 153, 153, 153, 153)); 1543 } 1544 1545 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceUnrefsBuffers) { 1546 sp<GraphicBuffer> buffers[2]; 1547 1548 // This test requires async mode to run on a single thread. 1549 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1550 mProducerEglSurface, mProducerEglContext)); 1551 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1552 EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0)); 1553 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1554 1555 for (int i = 0; i < 2; i++) { 1556 // Produce a frame 1557 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1558 mProducerEglSurface, mProducerEglContext)); 1559 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1560 glClear(GL_COLOR_BUFFER_BIT); 1561 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1562 1563 // Consume a frame 1564 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1565 mEglContext)); 1566 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1567 mFW->waitForFrame(); 1568 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1569 buffers[i] = mST->getCurrentBuffer(); 1570 } 1571 1572 // Destroy the GL texture object to release its ref on buffers[2]. 1573 GLuint texID = TEX_ID; 1574 glDeleteTextures(1, &texID); 1575 1576 // Destroy the EGLSurface 1577 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface)); 1578 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1579 mProducerEglSurface = EGL_NO_SURFACE; 1580 1581 // This test should have the only reference to buffer 0. 1582 EXPECT_EQ(1, buffers[0]->getStrongCount()); 1583 1584 // The SurfaceTexture should hold a single reference to buffer 1 in its 1585 // mCurrentBuffer member. All of the references in the slots should have 1586 // been released. 1587 EXPECT_EQ(2, buffers[1]->getStrongCount()); 1588 } 1589 1590 TEST_F(SurfaceTextureGLToGLTest, EglDestroySurfaceAfterAbandonUnrefsBuffers) { 1591 sp<GraphicBuffer> buffers[3]; 1592 1593 // This test requires async mode to run on a single thread. 1594 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1595 mProducerEglSurface, mProducerEglContext)); 1596 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1597 EXPECT_TRUE(eglSwapInterval(mEglDisplay, 0)); 1598 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1599 1600 for (int i = 0; i < 3; i++) { 1601 // Produce a frame 1602 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1603 mProducerEglSurface, mProducerEglContext)); 1604 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1605 glClear(GL_COLOR_BUFFER_BIT); 1606 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface)); 1607 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1608 1609 // Consume a frame 1610 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1611 mEglContext)); 1612 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1613 mFW->waitForFrame(); 1614 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1615 buffers[i] = mST->getCurrentBuffer(); 1616 } 1617 1618 // Abandon the SurfaceTexture, releasing the ref that the SurfaceTexture has 1619 // on buffers[2]. 1620 mST->abandon(); 1621 1622 // Destroy the GL texture object to release its ref on buffers[2]. 1623 GLuint texID = TEX_ID; 1624 glDeleteTextures(1, &texID); 1625 1626 // Destroy the EGLSurface. 1627 EXPECT_TRUE(eglDestroySurface(mEglDisplay, mProducerEglSurface)); 1628 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1629 mProducerEglSurface = EGL_NO_SURFACE; 1630 1631 EXPECT_EQ(1, buffers[0]->getStrongCount()); 1632 EXPECT_EQ(1, buffers[1]->getStrongCount()); 1633 1634 // Depending on how lazily the GL driver dequeues buffers, we may end up 1635 // with either two or three total buffers. If there are three, make sure 1636 // the last one was properly down-ref'd. 1637 if (buffers[2] != buffers[0]) { 1638 EXPECT_EQ(1, buffers[2]->getStrongCount()); 1639 } 1640 } 1641 1642 TEST_F(SurfaceTextureGLToGLTest, EglSurfaceDefaultsToSynchronousMode) { 1643 // This test requires 3 buffers to run on a single thread. 1644 mST->setDefaultMaxBufferCount(3); 1645 1646 ASSERT_TRUE(mST->isSynchronousMode()); 1647 1648 for (int i = 0; i < 10; i++) { 1649 // Produce a frame 1650 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1651 mProducerEglSurface, mProducerEglContext)); 1652 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1653 glClear(GL_COLOR_BUFFER_BIT); 1654 EXPECT_TRUE(eglSwapBuffers(mEglDisplay, mProducerEglSurface)); 1655 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1656 1657 // Consume a frame 1658 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1659 mEglContext)); 1660 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1661 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1662 } 1663 1664 ASSERT_TRUE(mST->isSynchronousMode()); 1665 } 1666 1667 TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) { 1668 enum { texWidth = 64 }; 1669 enum { texHeight = 64 }; 1670 1671 // This test requires 3 buffers to complete run on a single thread. 1672 mST->setDefaultMaxBufferCount(3); 1673 1674 // Set the user buffer size. 1675 native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight); 1676 1677 // Do the producer side of things 1678 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1679 mProducerEglSurface, mProducerEglContext)); 1680 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1681 1682 // This is needed to ensure we pick up a buffer of the correct size. 1683 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1684 1685 glClearColor(0.6, 0.6, 0.6, 0.6); 1686 glClear(GL_COLOR_BUFFER_BIT); 1687 1688 glEnable(GL_SCISSOR_TEST); 1689 glScissor(4, 4, 1, 1); 1690 glClearColor(1.0, 0.0, 0.0, 1.0); 1691 glClear(GL_COLOR_BUFFER_BIT); 1692 1693 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1694 1695 // Do the consumer side of things 1696 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1697 mEglContext)); 1698 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1699 1700 glDisable(GL_SCISSOR_TEST); 1701 1702 // Skip the first frame, which was empty 1703 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1704 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1705 1706 glClearColor(0.2, 0.2, 0.2, 0.2); 1707 glClear(GL_COLOR_BUFFER_BIT); 1708 1709 glViewport(0, 0, texWidth, texHeight); 1710 drawTexture(); 1711 1712 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153)); 1713 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153)); 1714 EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153)); 1715 EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153)); 1716 1717 EXPECT_TRUE(checkPixel( 4, 4, 255, 0, 0, 255)); 1718 EXPECT_TRUE(checkPixel( 5, 5, 153, 153, 153, 153)); 1719 EXPECT_TRUE(checkPixel( 3, 3, 153, 153, 153, 153)); 1720 EXPECT_TRUE(checkPixel(45, 52, 153, 153, 153, 153)); 1721 EXPECT_TRUE(checkPixel(12, 36, 153, 153, 153, 153)); 1722 } 1723 1724 TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedUserSizedGLFilledBuffer) { 1725 enum { texWidth = 64 }; 1726 enum { texHeight = 16 }; 1727 1728 // This test requires 3 buffers to complete run on a single thread. 1729 mST->setDefaultMaxBufferCount(3); 1730 1731 // Set the transform hint. 1732 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90); 1733 1734 // Set the user buffer size. 1735 native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight); 1736 1737 // Do the producer side of things 1738 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1739 mProducerEglSurface, mProducerEglContext)); 1740 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1741 1742 // This is needed to ensure we pick up a buffer of the correct size and the 1743 // new rotation hint. 1744 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1745 1746 glClearColor(0.6, 0.6, 0.6, 0.6); 1747 glClear(GL_COLOR_BUFFER_BIT); 1748 1749 glEnable(GL_SCISSOR_TEST); 1750 glScissor(24, 4, 1, 1); 1751 glClearColor(1.0, 0.0, 0.0, 1.0); 1752 glClear(GL_COLOR_BUFFER_BIT); 1753 1754 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1755 1756 // Do the consumer side of things 1757 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1758 mEglContext)); 1759 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1760 1761 glDisable(GL_SCISSOR_TEST); 1762 1763 // Skip the first frame, which was empty 1764 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1765 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1766 1767 glClearColor(0.2, 0.2, 0.2, 0.2); 1768 glClear(GL_COLOR_BUFFER_BIT); 1769 1770 glViewport(0, 0, texWidth, texHeight); 1771 drawTexture(); 1772 1773 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153)); 1774 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153)); 1775 EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153)); 1776 EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153)); 1777 1778 EXPECT_TRUE(checkPixel(24, 4, 255, 0, 0, 255)); 1779 EXPECT_TRUE(checkPixel(25, 5, 153, 153, 153, 153)); 1780 EXPECT_TRUE(checkPixel(23, 3, 153, 153, 153, 153)); 1781 EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153)); 1782 EXPECT_TRUE(checkPixel(12, 8, 153, 153, 153, 153)); 1783 } 1784 1785 TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedGLFilledBuffer) { 1786 enum { texWidth = 64 }; 1787 enum { texHeight = 16 }; 1788 1789 // This test requires 3 buffers to complete run on a single thread. 1790 mST->setDefaultMaxBufferCount(3); 1791 1792 // Set the transform hint. 1793 mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90); 1794 1795 // Set the default buffer size. 1796 mST->setDefaultBufferSize(texWidth, texHeight); 1797 1798 // Do the producer side of things 1799 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface, 1800 mProducerEglSurface, mProducerEglContext)); 1801 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1802 1803 // This is needed to ensure we pick up a buffer of the correct size and the 1804 // new rotation hint. 1805 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1806 1807 glClearColor(0.6, 0.6, 0.6, 0.6); 1808 glClear(GL_COLOR_BUFFER_BIT); 1809 1810 glEnable(GL_SCISSOR_TEST); 1811 glScissor(24, 4, 1, 1); 1812 glClearColor(1.0, 0.0, 0.0, 1.0); 1813 glClear(GL_COLOR_BUFFER_BIT); 1814 1815 eglSwapBuffers(mEglDisplay, mProducerEglSurface); 1816 1817 // Do the consumer side of things 1818 EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 1819 mEglContext)); 1820 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 1821 1822 glDisable(GL_SCISSOR_TEST); 1823 1824 // Skip the first frame, which was empty 1825 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1826 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 1827 1828 glClearColor(0.2, 0.2, 0.2, 0.2); 1829 glClear(GL_COLOR_BUFFER_BIT); 1830 1831 glViewport(0, 0, texWidth, texHeight); 1832 drawTexture(); 1833 1834 EXPECT_TRUE(checkPixel( 0, 0, 153, 153, 153, 153)); 1835 EXPECT_TRUE(checkPixel(63, 0, 153, 153, 153, 153)); 1836 EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153)); 1837 EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153)); 1838 1839 EXPECT_TRUE(checkPixel(24, 4, 255, 0, 0, 255)); 1840 EXPECT_TRUE(checkPixel(25, 5, 153, 153, 153, 153)); 1841 EXPECT_TRUE(checkPixel(23, 3, 153, 153, 153, 153)); 1842 EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153)); 1843 EXPECT_TRUE(checkPixel(12, 8, 153, 153, 153, 153)); 1844 } 1845 1846 /* 1847 * This test fixture is for testing GL -> GL texture streaming from one thread 1848 * to another. It contains functionality to create a producer thread that will 1849 * perform GL rendering to an ANativeWindow that feeds frames to a 1850 * SurfaceTexture. Additionally it supports interlocking the producer and 1851 * consumer threads so that a specific sequence of calls can be 1852 * deterministically created by the test. 1853 * 1854 * The intended usage is as follows: 1855 * 1856 * TEST_F(...) { 1857 * class PT : public ProducerThread { 1858 * virtual void render() { 1859 * ... 1860 * swapBuffers(); 1861 * } 1862 * }; 1863 * 1864 * runProducerThread(new PT()); 1865 * 1866 * // The order of these calls will vary from test to test and may include 1867 * // multiple frames and additional operations (e.g. GL rendering from the 1868 * // texture). 1869 * fc->waitForFrame(); 1870 * mST->updateTexImage(); 1871 * fc->finishFrame(); 1872 * } 1873 * 1874 */ 1875 class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest { 1876 protected: 1877 1878 // ProducerThread is an abstract base class to simplify the creation of 1879 // OpenGL ES frame producer threads. 1880 class ProducerThread : public Thread { 1881 public: 1882 virtual ~ProducerThread() { 1883 } 1884 1885 void setEglObjects(EGLDisplay producerEglDisplay, 1886 EGLSurface producerEglSurface, 1887 EGLContext producerEglContext) { 1888 mProducerEglDisplay = producerEglDisplay; 1889 mProducerEglSurface = producerEglSurface; 1890 mProducerEglContext = producerEglContext; 1891 } 1892 1893 virtual bool threadLoop() { 1894 eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface, 1895 mProducerEglSurface, mProducerEglContext); 1896 render(); 1897 eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 1898 EGL_NO_CONTEXT); 1899 return false; 1900 } 1901 1902 protected: 1903 virtual void render() = 0; 1904 1905 void swapBuffers() { 1906 eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface); 1907 } 1908 1909 EGLDisplay mProducerEglDisplay; 1910 EGLSurface mProducerEglSurface; 1911 EGLContext mProducerEglContext; 1912 }; 1913 1914 // FrameCondition is a utility class for interlocking between the producer 1915 // and consumer threads. The FrameCondition object should be created and 1916 // destroyed in the consumer thread only. The consumer thread should set 1917 // the FrameCondition as the FrameAvailableListener of the SurfaceTexture, 1918 // and should call both waitForFrame and finishFrame once for each expected 1919 // frame. 1920 // 1921 // This interlocking relies on the fact that onFrameAvailable gets called 1922 // synchronously from SurfaceTexture::queueBuffer. 1923 class FrameCondition : public SurfaceTexture::FrameAvailableListener { 1924 public: 1925 FrameCondition(): 1926 mFrameAvailable(false), 1927 mFrameFinished(false) { 1928 } 1929 1930 // waitForFrame waits for the next frame to arrive. This should be 1931 // called from the consumer thread once for every frame expected by the 1932 // test. 1933 void waitForFrame() { 1934 Mutex::Autolock lock(mMutex); 1935 ALOGV("+waitForFrame"); 1936 while (!mFrameAvailable) { 1937 mFrameAvailableCondition.wait(mMutex); 1938 } 1939 mFrameAvailable = false; 1940 ALOGV("-waitForFrame"); 1941 } 1942 1943 // Allow the producer to return from its swapBuffers call and continue 1944 // on to produce the next frame. This should be called by the consumer 1945 // thread once for every frame expected by the test. 1946 void finishFrame() { 1947 Mutex::Autolock lock(mMutex); 1948 ALOGV("+finishFrame"); 1949 mFrameFinished = true; 1950 mFrameFinishCondition.signal(); 1951 ALOGV("-finishFrame"); 1952 } 1953 1954 // This should be called by SurfaceTexture on the producer thread. 1955 virtual void onFrameAvailable() { 1956 Mutex::Autolock lock(mMutex); 1957 ALOGV("+onFrameAvailable"); 1958 mFrameAvailable = true; 1959 mFrameAvailableCondition.signal(); 1960 while (!mFrameFinished) { 1961 mFrameFinishCondition.wait(mMutex); 1962 } 1963 mFrameFinished = false; 1964 ALOGV("-onFrameAvailable"); 1965 } 1966 1967 protected: 1968 bool mFrameAvailable; 1969 bool mFrameFinished; 1970 1971 Mutex mMutex; 1972 Condition mFrameAvailableCondition; 1973 Condition mFrameFinishCondition; 1974 }; 1975 1976 virtual void SetUp() { 1977 SurfaceTextureGLToGLTest::SetUp(); 1978 mFC = new FrameCondition(); 1979 mST->setFrameAvailableListener(mFC); 1980 } 1981 1982 virtual void TearDown() { 1983 if (mProducerThread != NULL) { 1984 mProducerThread->requestExitAndWait(); 1985 } 1986 mProducerThread.clear(); 1987 mFC.clear(); 1988 SurfaceTextureGLToGLTest::TearDown(); 1989 } 1990 1991 void runProducerThread(const sp<ProducerThread> producerThread) { 1992 ASSERT_TRUE(mProducerThread == NULL); 1993 mProducerThread = producerThread; 1994 producerThread->setEglObjects(mEglDisplay, mProducerEglSurface, 1995 mProducerEglContext); 1996 producerThread->run(); 1997 } 1998 1999 sp<ProducerThread> mProducerThread; 2000 sp<FrameCondition> mFC; 2001 }; 2002 2003 TEST_F(SurfaceTextureGLThreadToGLTest, 2004 UpdateTexImageBeforeFrameFinishedCompletes) { 2005 class PT : public ProducerThread { 2006 virtual void render() { 2007 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 2008 glClear(GL_COLOR_BUFFER_BIT); 2009 swapBuffers(); 2010 } 2011 }; 2012 2013 runProducerThread(new PT()); 2014 2015 mFC->waitForFrame(); 2016 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2017 mFC->finishFrame(); 2018 2019 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! 2020 } 2021 2022 TEST_F(SurfaceTextureGLThreadToGLTest, 2023 UpdateTexImageAfterFrameFinishedCompletes) { 2024 class PT : public ProducerThread { 2025 virtual void render() { 2026 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 2027 glClear(GL_COLOR_BUFFER_BIT); 2028 swapBuffers(); 2029 } 2030 }; 2031 2032 runProducerThread(new PT()); 2033 2034 mFC->waitForFrame(); 2035 mFC->finishFrame(); 2036 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2037 2038 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! 2039 } 2040 2041 TEST_F(SurfaceTextureGLThreadToGLTest, 2042 RepeatedUpdateTexImageBeforeFrameFinishedCompletes) { 2043 enum { NUM_ITERATIONS = 1024 }; 2044 2045 class PT : public ProducerThread { 2046 virtual void render() { 2047 for (int i = 0; i < NUM_ITERATIONS; i++) { 2048 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 2049 glClear(GL_COLOR_BUFFER_BIT); 2050 ALOGV("+swapBuffers"); 2051 swapBuffers(); 2052 ALOGV("-swapBuffers"); 2053 } 2054 } 2055 }; 2056 2057 runProducerThread(new PT()); 2058 2059 for (int i = 0; i < NUM_ITERATIONS; i++) { 2060 mFC->waitForFrame(); 2061 ALOGV("+updateTexImage"); 2062 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2063 ALOGV("-updateTexImage"); 2064 mFC->finishFrame(); 2065 2066 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! 2067 } 2068 } 2069 2070 TEST_F(SurfaceTextureGLThreadToGLTest, 2071 RepeatedUpdateTexImageAfterFrameFinishedCompletes) { 2072 enum { NUM_ITERATIONS = 1024 }; 2073 2074 class PT : public ProducerThread { 2075 virtual void render() { 2076 for (int i = 0; i < NUM_ITERATIONS; i++) { 2077 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 2078 glClear(GL_COLOR_BUFFER_BIT); 2079 ALOGV("+swapBuffers"); 2080 swapBuffers(); 2081 ALOGV("-swapBuffers"); 2082 } 2083 } 2084 }; 2085 2086 runProducerThread(new PT()); 2087 2088 for (int i = 0; i < NUM_ITERATIONS; i++) { 2089 mFC->waitForFrame(); 2090 mFC->finishFrame(); 2091 ALOGV("+updateTexImage"); 2092 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2093 ALOGV("-updateTexImage"); 2094 2095 // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! 2096 } 2097 } 2098 2099 // XXX: This test is disabled because it is currently hanging on some devices. 2100 TEST_F(SurfaceTextureGLThreadToGLTest, 2101 DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) { 2102 enum { NUM_ITERATIONS = 64 }; 2103 2104 class PT : public ProducerThread { 2105 virtual void render() { 2106 for (int i = 0; i < NUM_ITERATIONS; i++) { 2107 glClearColor(0.0f, 1.0f, 0.0f, 1.0f); 2108 glClear(GL_COLOR_BUFFER_BIT); 2109 ALOGV("+swapBuffers"); 2110 swapBuffers(); 2111 ALOGV("-swapBuffers"); 2112 } 2113 } 2114 }; 2115 2116 ASSERT_EQ(OK, mST->setSynchronousMode(true)); 2117 ASSERT_EQ(OK, mST->setDefaultMaxBufferCount(2)); 2118 2119 runProducerThread(new PT()); 2120 2121 // Allow three frames to be rendered and queued before starting the 2122 // rendering in this thread. For the latter two frames we don't call 2123 // updateTexImage so the next dequeue from the producer thread will block 2124 // waiting for a frame to become available. 2125 mFC->waitForFrame(); 2126 mFC->finishFrame(); 2127 2128 // We must call updateTexImage to consume the first frame so that the 2129 // SurfaceTexture is able to reduce the buffer count to 2. This is because 2130 // the GL driver may dequeue a buffer when the EGLSurface is created, and 2131 // that happens before we call setDefaultMaxBufferCount. It's possible that the 2132 // driver does not dequeue a buffer at EGLSurface creation time, so we 2133 // cannot rely on this to cause the second dequeueBuffer call to block. 2134 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2135 2136 mFC->waitForFrame(); 2137 mFC->finishFrame(); 2138 mFC->waitForFrame(); 2139 mFC->finishFrame(); 2140 2141 // Sleep for 100ms to allow the producer thread's dequeueBuffer call to 2142 // block waiting for a buffer to become available. 2143 usleep(100000); 2144 2145 // Render and present a number of images. This thread should not be blocked 2146 // by the fact that the producer thread is blocking in dequeue. 2147 for (int i = 0; i < NUM_ITERATIONS; i++) { 2148 glClear(GL_COLOR_BUFFER_BIT); 2149 eglSwapBuffers(mEglDisplay, mEglSurface); 2150 } 2151 2152 // Consume the two pending buffers to unblock the producer thread. 2153 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2154 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2155 2156 // Consume the remaining buffers from the producer thread. 2157 for (int i = 0; i < NUM_ITERATIONS-3; i++) { 2158 mFC->waitForFrame(); 2159 mFC->finishFrame(); 2160 ALOGV("+updateTexImage"); 2161 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2162 ALOGV("-updateTexImage"); 2163 } 2164 } 2165 2166 class SurfaceTextureFBOTest : public SurfaceTextureGLTest { 2167 protected: 2168 2169 virtual void SetUp() { 2170 SurfaceTextureGLTest::SetUp(); 2171 2172 glGenFramebuffers(1, &mFbo); 2173 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2174 2175 glGenTextures(1, &mFboTex); 2176 glBindTexture(GL_TEXTURE_2D, mFboTex); 2177 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSurfaceWidth(), 2178 getSurfaceHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 2179 glBindTexture(GL_TEXTURE_2D, 0); 2180 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2181 2182 glBindFramebuffer(GL_FRAMEBUFFER, mFbo); 2183 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 2184 GL_TEXTURE_2D, mFboTex, 0); 2185 glBindFramebuffer(GL_FRAMEBUFFER, 0); 2186 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2187 } 2188 2189 virtual void TearDown() { 2190 SurfaceTextureGLTest::TearDown(); 2191 2192 glDeleteTextures(1, &mFboTex); 2193 glDeleteFramebuffers(1, &mFbo); 2194 } 2195 2196 GLuint mFbo; 2197 GLuint mFboTex; 2198 }; 2199 2200 // This test is intended to verify that proper synchronization is done when 2201 // rendering into an FBO. 2202 TEST_F(SurfaceTextureFBOTest, BlitFromCpuFilledBufferToFbo) { 2203 const int texWidth = 64; 2204 const int texHeight = 64; 2205 2206 ASSERT_EQ(NO_ERROR, native_window_set_buffers_geometry(mANW.get(), 2207 texWidth, texHeight, HAL_PIXEL_FORMAT_RGBA_8888)); 2208 ASSERT_EQ(NO_ERROR, native_window_set_usage(mANW.get(), 2209 GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN)); 2210 2211 android_native_buffer_t* anb; 2212 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 2213 &anb)); 2214 ASSERT_TRUE(anb != NULL); 2215 2216 sp<GraphicBuffer> buf(new GraphicBuffer(anb, false)); 2217 2218 // Fill the buffer with green 2219 uint8_t* img = NULL; 2220 buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img)); 2221 fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 0, 255, 2222 0, 255); 2223 buf->unlock(); 2224 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(), 2225 -1)); 2226 2227 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2228 2229 glBindFramebuffer(GL_FRAMEBUFFER, mFbo); 2230 drawTexture(); 2231 glBindFramebuffer(GL_FRAMEBUFFER, 0); 2232 2233 for (int i = 0; i < 4; i++) { 2234 SCOPED_TRACE(String8::format("frame %d", i).string()); 2235 2236 ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), 2237 &anb)); 2238 ASSERT_TRUE(anb != NULL); 2239 2240 buf = new GraphicBuffer(anb, false); 2241 2242 // Fill the buffer with red 2243 ASSERT_EQ(NO_ERROR, buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, 2244 (void**)(&img))); 2245 fillRGBA8BufferSolid(img, texWidth, texHeight, buf->getStride(), 255, 0, 2246 0, 255); 2247 ASSERT_EQ(NO_ERROR, buf->unlock()); 2248 ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), 2249 buf->getNativeBuffer(), -1)); 2250 2251 ASSERT_EQ(NO_ERROR, mST->updateTexImage()); 2252 2253 drawTexture(); 2254 2255 EXPECT_TRUE(checkPixel( 24, 39, 255, 0, 0, 255)); 2256 } 2257 2258 glBindFramebuffer(GL_FRAMEBUFFER, mFbo); 2259 2260 EXPECT_TRUE(checkPixel( 24, 39, 0, 255, 0, 255)); 2261 } 2262 2263 class SurfaceTextureMultiContextGLTest : public SurfaceTextureGLTest { 2264 protected: 2265 enum { SECOND_TEX_ID = 123 }; 2266 enum { THIRD_TEX_ID = 456 }; 2267 2268 SurfaceTextureMultiContextGLTest(): 2269 mSecondEglContext(EGL_NO_CONTEXT) { 2270 } 2271 2272 virtual void SetUp() { 2273 SurfaceTextureGLTest::SetUp(); 2274 2275 // Set up the secondary context and texture renderer. 2276 mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig, 2277 EGL_NO_CONTEXT, getContextAttribs()); 2278 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2279 ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext); 2280 2281 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2282 mSecondEglContext)); 2283 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2284 mSecondTextureRenderer = new TextureRenderer(SECOND_TEX_ID, mST); 2285 ASSERT_NO_FATAL_FAILURE(mSecondTextureRenderer->SetUp()); 2286 2287 // Set up the tertiary context and texture renderer. 2288 mThirdEglContext = eglCreateContext(mEglDisplay, mGlConfig, 2289 EGL_NO_CONTEXT, getContextAttribs()); 2290 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2291 ASSERT_NE(EGL_NO_CONTEXT, mThirdEglContext); 2292 2293 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2294 mThirdEglContext)); 2295 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2296 mThirdTextureRenderer = new TextureRenderer(THIRD_TEX_ID, mST); 2297 ASSERT_NO_FATAL_FAILURE(mThirdTextureRenderer->SetUp()); 2298 2299 // Switch back to the primary context to start the tests. 2300 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2301 mEglContext)); 2302 } 2303 2304 virtual void TearDown() { 2305 if (mThirdEglContext != EGL_NO_CONTEXT) { 2306 eglDestroyContext(mEglDisplay, mThirdEglContext); 2307 } 2308 if (mSecondEglContext != EGL_NO_CONTEXT) { 2309 eglDestroyContext(mEglDisplay, mSecondEglContext); 2310 } 2311 SurfaceTextureGLTest::TearDown(); 2312 } 2313 2314 EGLContext mSecondEglContext; 2315 sp<TextureRenderer> mSecondTextureRenderer; 2316 2317 EGLContext mThirdEglContext; 2318 sp<TextureRenderer> mThirdTextureRenderer; 2319 }; 2320 2321 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) { 2322 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2323 2324 // Latch the texture contents on the primary context. 2325 mFW->waitForFrame(); 2326 ASSERT_EQ(OK, mST->updateTexImage()); 2327 2328 // Attempt to latch the texture on the secondary context. 2329 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2330 mSecondEglContext)); 2331 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2332 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage()); 2333 } 2334 2335 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) { 2336 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2337 2338 // Latch the texture contents on the primary context. 2339 mFW->waitForFrame(); 2340 ASSERT_EQ(OK, mST->updateTexImage()); 2341 2342 // Detach from the primary context. 2343 ASSERT_EQ(OK, mST->detachFromContext()); 2344 2345 // Check that the GL texture was deleted. 2346 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID)); 2347 } 2348 2349 TEST_F(SurfaceTextureMultiContextGLTest, 2350 DetachFromContextSucceedsAfterProducerDisconnect) { 2351 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2352 2353 // Latch the texture contents on the primary context. 2354 mFW->waitForFrame(); 2355 ASSERT_EQ(OK, mST->updateTexImage()); 2356 2357 // Detach from the primary context. 2358 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 2359 ASSERT_EQ(OK, mST->detachFromContext()); 2360 2361 // Check that the GL texture was deleted. 2362 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID)); 2363 } 2364 2365 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) { 2366 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2367 2368 // Latch the texture contents on the primary context. 2369 mFW->waitForFrame(); 2370 ASSERT_EQ(OK, mST->updateTexImage()); 2371 2372 // Attempt to detach from the primary context. 2373 mST->abandon(); 2374 ASSERT_EQ(NO_INIT, mST->detachFromContext()); 2375 } 2376 2377 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) { 2378 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2379 2380 // Latch the texture contents on the primary context. 2381 mFW->waitForFrame(); 2382 ASSERT_EQ(OK, mST->updateTexImage()); 2383 2384 // Detach from the primary context. 2385 ASSERT_EQ(OK, mST->detachFromContext()); 2386 2387 // Attempt to detach from the primary context again. 2388 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 2389 } 2390 2391 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) { 2392 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2393 2394 // Latch the texture contents on the primary context. 2395 mFW->waitForFrame(); 2396 ASSERT_EQ(OK, mST->updateTexImage()); 2397 2398 // Make there be no current display. 2399 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 2400 EGL_NO_CONTEXT)); 2401 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2402 2403 // Attempt to detach from the primary context. 2404 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 2405 } 2406 2407 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) { 2408 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2409 2410 // Latch the texture contents on the primary context. 2411 mFW->waitForFrame(); 2412 ASSERT_EQ(OK, mST->updateTexImage()); 2413 2414 // Make current context be incorrect. 2415 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2416 mSecondEglContext)); 2417 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2418 2419 // Attempt to detach from the primary context. 2420 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 2421 } 2422 2423 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) { 2424 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2425 2426 // Detach from the primary context. 2427 ASSERT_EQ(OK, mST->detachFromContext()); 2428 2429 // Attempt to latch the texture contents on the primary context. 2430 mFW->waitForFrame(); 2431 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage()); 2432 } 2433 2434 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) { 2435 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2436 2437 // Latch the texture contents on the primary context. 2438 mFW->waitForFrame(); 2439 ASSERT_EQ(OK, mST->updateTexImage()); 2440 2441 // Detach from the primary context. 2442 ASSERT_EQ(OK, mST->detachFromContext()); 2443 2444 // Attach to the secondary context. 2445 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2446 mSecondEglContext)); 2447 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2448 2449 // Verify that the texture object was created and bound. 2450 GLint texBinding = -1; 2451 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 2452 EXPECT_EQ(SECOND_TEX_ID, texBinding); 2453 2454 // Try to use the texture from the secondary context. 2455 glClearColor(0.2, 0.2, 0.2, 0.2); 2456 glClear(GL_COLOR_BUFFER_BIT); 2457 glViewport(0, 0, 1, 1); 2458 mSecondTextureRenderer->drawTexture(); 2459 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 2460 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2461 } 2462 2463 TEST_F(SurfaceTextureMultiContextGLTest, 2464 AttachToContextSucceedsAfterProducerDisconnect) { 2465 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2466 2467 // Latch the texture contents on the primary context. 2468 mFW->waitForFrame(); 2469 ASSERT_EQ(OK, mST->updateTexImage()); 2470 2471 // Detach from the primary context. 2472 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 2473 ASSERT_EQ(OK, mST->detachFromContext()); 2474 2475 // Attach to the secondary context. 2476 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2477 mSecondEglContext)); 2478 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2479 2480 // Verify that the texture object was created and bound. 2481 GLint texBinding = -1; 2482 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 2483 EXPECT_EQ(SECOND_TEX_ID, texBinding); 2484 2485 // Try to use the texture from the secondary context. 2486 glClearColor(0.2, 0.2, 0.2, 0.2); 2487 glClear(GL_COLOR_BUFFER_BIT); 2488 glViewport(0, 0, 1, 1); 2489 mSecondTextureRenderer->drawTexture(); 2490 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2491 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 2492 } 2493 2494 TEST_F(SurfaceTextureMultiContextGLTest, 2495 AttachToContextSucceedsBeforeUpdateTexImage) { 2496 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2497 2498 // Detach from the primary context. 2499 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 2500 ASSERT_EQ(OK, mST->detachFromContext()); 2501 2502 // Attach to the secondary context. 2503 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2504 mSecondEglContext)); 2505 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2506 2507 // Verify that the texture object was created and bound. 2508 GLint texBinding = -1; 2509 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 2510 EXPECT_EQ(SECOND_TEX_ID, texBinding); 2511 2512 // Latch the texture contents on the primary context. 2513 mFW->waitForFrame(); 2514 ASSERT_EQ(OK, mST->updateTexImage()); 2515 2516 // Try to use the texture from the secondary context. 2517 glClearColor(0.2, 0.2, 0.2, 0.2); 2518 glClear(GL_COLOR_BUFFER_BIT); 2519 glViewport(0, 0, 1, 1); 2520 mSecondTextureRenderer->drawTexture(); 2521 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2522 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 2523 } 2524 2525 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) { 2526 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2527 2528 // Latch the texture contents on the primary context. 2529 mFW->waitForFrame(); 2530 ASSERT_EQ(OK, mST->updateTexImage()); 2531 2532 // Detach from the primary context. 2533 ASSERT_EQ(OK, mST->detachFromContext()); 2534 2535 // Attempt to attach to the secondary context. 2536 mST->abandon(); 2537 2538 // Attempt to attach to the primary context. 2539 ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID)); 2540 } 2541 2542 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) { 2543 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2544 2545 // Latch the texture contents on the primary context. 2546 mFW->waitForFrame(); 2547 ASSERT_EQ(OK, mST->updateTexImage()); 2548 2549 // Attempt to attach to the primary context. 2550 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 2551 } 2552 2553 TEST_F(SurfaceTextureMultiContextGLTest, 2554 AttachToContextFailsWhenAttachedBeforeUpdateTexImage) { 2555 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2556 2557 // Attempt to attach to the primary context. 2558 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 2559 } 2560 2561 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) { 2562 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2563 2564 // Latch the texture contents on the primary context. 2565 mFW->waitForFrame(); 2566 ASSERT_EQ(OK, mST->updateTexImage()); 2567 2568 // Detach from the primary context. 2569 ASSERT_EQ(OK, mST->detachFromContext()); 2570 2571 // Make there be no current display. 2572 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 2573 EGL_NO_CONTEXT)); 2574 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 2575 2576 // Attempt to attach with no context current. 2577 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 2578 } 2579 2580 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) { 2581 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2582 2583 // Latch the texture contents on the primary context. 2584 mFW->waitForFrame(); 2585 ASSERT_EQ(OK, mST->updateTexImage()); 2586 2587 // Detach from the primary context. 2588 ASSERT_EQ(OK, mST->detachFromContext()); 2589 2590 // Attach to the secondary context. 2591 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2592 mSecondEglContext)); 2593 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2594 2595 // Detach from the secondary context. 2596 ASSERT_EQ(OK, mST->detachFromContext()); 2597 2598 // Attach to the tertiary context. 2599 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2600 mThirdEglContext)); 2601 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID)); 2602 2603 // Verify that the texture object was created and bound. 2604 GLint texBinding = -1; 2605 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 2606 EXPECT_EQ(THIRD_TEX_ID, texBinding); 2607 2608 // Try to use the texture from the tertiary context. 2609 glClearColor(0.2, 0.2, 0.2, 0.2); 2610 glClear(GL_COLOR_BUFFER_BIT); 2611 glViewport(0, 0, 1, 1); 2612 mThirdTextureRenderer->drawTexture(); 2613 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2614 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 2615 } 2616 2617 TEST_F(SurfaceTextureMultiContextGLTest, 2618 AttachToContextSucceedsTwiceBeforeUpdateTexImage) { 2619 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2620 2621 // Detach from the primary context. 2622 ASSERT_EQ(OK, mST->detachFromContext()); 2623 2624 // Attach to the secondary context. 2625 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2626 mSecondEglContext)); 2627 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2628 2629 // Detach from the secondary context. 2630 ASSERT_EQ(OK, mST->detachFromContext()); 2631 2632 // Attach to the tertiary context. 2633 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2634 mThirdEglContext)); 2635 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID)); 2636 2637 // Verify that the texture object was created and bound. 2638 GLint texBinding = -1; 2639 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 2640 EXPECT_EQ(THIRD_TEX_ID, texBinding); 2641 2642 // Latch the texture contents on the tertiary context. 2643 mFW->waitForFrame(); 2644 ASSERT_EQ(OK, mST->updateTexImage()); 2645 2646 // Try to use the texture from the tertiary context. 2647 glClearColor(0.2, 0.2, 0.2, 0.2); 2648 glClear(GL_COLOR_BUFFER_BIT); 2649 glViewport(0, 0, 1, 1); 2650 mThirdTextureRenderer->drawTexture(); 2651 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 2652 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 2653 } 2654 2655 TEST_F(SurfaceTextureMultiContextGLTest, 2656 UpdateTexImageSucceedsForBufferConsumedBeforeDetach) { 2657 ASSERT_EQ(NO_ERROR, mST->setSynchronousMode(true)); 2658 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); 2659 2660 // produce two frames and consume them both on the primary context 2661 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2662 mFW->waitForFrame(); 2663 ASSERT_EQ(OK, mST->updateTexImage()); 2664 2665 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2666 mFW->waitForFrame(); 2667 ASSERT_EQ(OK, mST->updateTexImage()); 2668 2669 // produce one more frame 2670 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 2671 2672 // Detach from the primary context and attach to the secondary context 2673 ASSERT_EQ(OK, mST->detachFromContext()); 2674 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 2675 mSecondEglContext)); 2676 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 2677 2678 // Consume final frame on secondary context 2679 mFW->waitForFrame(); 2680 ASSERT_EQ(OK, mST->updateTexImage()); 2681 } 2682 2683 } // namespace android 2684