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