1 /* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "SurfaceTextureMultiContextGL_test" 18 //#define LOG_NDEBUG 0 19 20 #include "SurfaceTextureMultiContextGL.h" 21 22 #include "FillBuffer.h" 23 24 #include <GLES/glext.h> 25 26 namespace android { 27 28 TEST_F(SurfaceTextureMultiContextGLTest, UpdateFromMultipleContextsFails) { 29 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 30 31 // Latch the texture contents on the primary context. 32 mFW->waitForFrame(); 33 ASSERT_EQ(OK, mST->updateTexImage()); 34 35 // Attempt to latch the texture on the secondary context. 36 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 37 mSecondEglContext)); 38 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 39 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage()); 40 } 41 42 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextSucceeds) { 43 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 44 45 // Latch the texture contents on the primary context. 46 mFW->waitForFrame(); 47 ASSERT_EQ(OK, mST->updateTexImage()); 48 49 // Detach from the primary context. 50 ASSERT_EQ(OK, mST->detachFromContext()); 51 52 // Check that the GL texture was deleted. 53 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID)); 54 } 55 56 TEST_F(SurfaceTextureMultiContextGLTest, 57 DetachFromContextSucceedsAfterProducerDisconnect) { 58 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 59 60 // Latch the texture contents on the primary context. 61 mFW->waitForFrame(); 62 ASSERT_EQ(OK, mST->updateTexImage()); 63 64 // Detach from the primary context. 65 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 66 ASSERT_EQ(OK, mST->detachFromContext()); 67 68 // Check that the GL texture was deleted. 69 EXPECT_EQ(GL_FALSE, glIsTexture(TEX_ID)); 70 } 71 72 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenAbandoned) { 73 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 74 75 // Latch the texture contents on the primary context. 76 mFW->waitForFrame(); 77 ASSERT_EQ(OK, mST->updateTexImage()); 78 79 // Attempt to detach from the primary context. 80 mST->abandon(); 81 ASSERT_EQ(NO_INIT, mST->detachFromContext()); 82 } 83 84 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWhenDetached) { 85 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 86 87 // Latch the texture contents on the primary context. 88 mFW->waitForFrame(); 89 ASSERT_EQ(OK, mST->updateTexImage()); 90 91 // Detach from the primary context. 92 ASSERT_EQ(OK, mST->detachFromContext()); 93 94 // Attempt to detach from the primary context again. 95 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 96 } 97 98 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoDisplay) { 99 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 100 101 // Latch the texture contents on the primary context. 102 mFW->waitForFrame(); 103 ASSERT_EQ(OK, mST->updateTexImage()); 104 105 // Make there be no current display. 106 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 107 EGL_NO_CONTEXT)); 108 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 109 110 // Attempt to detach from the primary context. 111 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 112 } 113 114 TEST_F(SurfaceTextureMultiContextGLTest, DetachFromContextFailsWithNoContext) { 115 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 116 117 // Latch the texture contents on the primary context. 118 mFW->waitForFrame(); 119 ASSERT_EQ(OK, mST->updateTexImage()); 120 121 // Make current context be incorrect. 122 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 123 mSecondEglContext)); 124 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 125 126 // Attempt to detach from the primary context. 127 ASSERT_EQ(INVALID_OPERATION, mST->detachFromContext()); 128 } 129 130 TEST_F(SurfaceTextureMultiContextGLTest, UpdateTexImageFailsWhenDetached) { 131 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 132 133 // Detach from the primary context. 134 ASSERT_EQ(OK, mST->detachFromContext()); 135 136 // Attempt to latch the texture contents on the primary context. 137 mFW->waitForFrame(); 138 ASSERT_EQ(INVALID_OPERATION, mST->updateTexImage()); 139 } 140 141 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceeds) { 142 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 143 144 // Latch the texture contents on the primary context. 145 mFW->waitForFrame(); 146 ASSERT_EQ(OK, mST->updateTexImage()); 147 148 // Detach from the primary context. 149 ASSERT_EQ(OK, mST->detachFromContext()); 150 151 // Attach to the secondary context. 152 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 153 mSecondEglContext)); 154 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 155 156 // Verify that the texture object was created and bound. 157 GLint texBinding = -1; 158 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 159 EXPECT_EQ(SECOND_TEX_ID, texBinding); 160 161 // Try to use the texture from the secondary context. 162 glClearColor(0.2, 0.2, 0.2, 0.2); 163 glClear(GL_COLOR_BUFFER_BIT); 164 glViewport(0, 0, 1, 1); 165 mSecondTextureRenderer->drawTexture(); 166 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 167 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 168 } 169 170 TEST_F(SurfaceTextureMultiContextGLTest, 171 AttachToContextSucceedsAfterProducerDisconnect) { 172 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 173 174 // Latch the texture contents on the primary context. 175 mFW->waitForFrame(); 176 ASSERT_EQ(OK, mST->updateTexImage()); 177 178 // Detach from the primary context. 179 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 180 ASSERT_EQ(OK, mST->detachFromContext()); 181 182 // Attach to the secondary context. 183 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 184 mSecondEglContext)); 185 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 186 187 // Verify that the texture object was created and bound. 188 GLint texBinding = -1; 189 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 190 EXPECT_EQ(SECOND_TEX_ID, texBinding); 191 192 // Try to use the texture from the secondary context. 193 glClearColor(0.2, 0.2, 0.2, 0.2); 194 glClear(GL_COLOR_BUFFER_BIT); 195 glViewport(0, 0, 1, 1); 196 mSecondTextureRenderer->drawTexture(); 197 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 198 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 199 } 200 201 TEST_F(SurfaceTextureMultiContextGLTest, 202 AttachToContextSucceedsBeforeUpdateTexImage) { 203 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 204 205 // Detach from the primary context. 206 native_window_api_disconnect(mANW.get(), NATIVE_WINDOW_API_CPU); 207 ASSERT_EQ(OK, mST->detachFromContext()); 208 209 // Attach to the secondary context. 210 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 211 mSecondEglContext)); 212 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 213 214 // Verify that the texture object was created and bound. 215 GLint texBinding = -1; 216 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 217 EXPECT_EQ(SECOND_TEX_ID, texBinding); 218 219 // Latch the texture contents on the primary context. 220 mFW->waitForFrame(); 221 ASSERT_EQ(OK, mST->updateTexImage()); 222 223 // Try to use the texture from the secondary context. 224 glClearColor(0.2, 0.2, 0.2, 0.2); 225 glClear(GL_COLOR_BUFFER_BIT); 226 glViewport(0, 0, 1, 1); 227 mSecondTextureRenderer->drawTexture(); 228 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 229 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 230 } 231 232 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAbandoned) { 233 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 234 235 // Latch the texture contents on the primary context. 236 mFW->waitForFrame(); 237 ASSERT_EQ(OK, mST->updateTexImage()); 238 239 // Detach from the primary context. 240 ASSERT_EQ(OK, mST->detachFromContext()); 241 242 // Attempt to attach to the secondary context. 243 mST->abandon(); 244 245 // Attempt to attach to the primary context. 246 ASSERT_EQ(NO_INIT, mST->attachToContext(SECOND_TEX_ID)); 247 } 248 249 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWhenAttached) { 250 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 251 252 // Latch the texture contents on the primary context. 253 mFW->waitForFrame(); 254 ASSERT_EQ(OK, mST->updateTexImage()); 255 256 // Attempt to attach to the primary context. 257 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 258 } 259 260 TEST_F(SurfaceTextureMultiContextGLTest, 261 AttachToContextFailsWhenAttachedBeforeUpdateTexImage) { 262 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 263 264 // Attempt to attach to the primary context. 265 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 266 } 267 268 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextFailsWithNoDisplay) { 269 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 270 271 // Latch the texture contents on the primary context. 272 mFW->waitForFrame(); 273 ASSERT_EQ(OK, mST->updateTexImage()); 274 275 // Detach from the primary context. 276 ASSERT_EQ(OK, mST->detachFromContext()); 277 278 // Make there be no current display. 279 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 280 EGL_NO_CONTEXT)); 281 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 282 283 // Attempt to attach with no context current. 284 ASSERT_EQ(INVALID_OPERATION, mST->attachToContext(SECOND_TEX_ID)); 285 } 286 287 TEST_F(SurfaceTextureMultiContextGLTest, AttachToContextSucceedsTwice) { 288 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 289 290 // Latch the texture contents on the primary context. 291 mFW->waitForFrame(); 292 ASSERT_EQ(OK, mST->updateTexImage()); 293 294 // Detach from the primary context. 295 ASSERT_EQ(OK, mST->detachFromContext()); 296 297 // Attach to the secondary context. 298 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 299 mSecondEglContext)); 300 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 301 302 // Detach from the secondary context. 303 ASSERT_EQ(OK, mST->detachFromContext()); 304 305 // Attach to the tertiary context. 306 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 307 mThirdEglContext)); 308 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID)); 309 310 // Verify that the texture object was created and bound. 311 GLint texBinding = -1; 312 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 313 EXPECT_EQ(THIRD_TEX_ID, texBinding); 314 315 // Try to use the texture from the tertiary context. 316 glClearColor(0.2, 0.2, 0.2, 0.2); 317 glClear(GL_COLOR_BUFFER_BIT); 318 glViewport(0, 0, 1, 1); 319 mThirdTextureRenderer->drawTexture(); 320 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 321 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 322 } 323 324 TEST_F(SurfaceTextureMultiContextGLTest, 325 AttachToContextSucceedsTwiceBeforeUpdateTexImage) { 326 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 327 328 // Detach from the primary context. 329 ASSERT_EQ(OK, mST->detachFromContext()); 330 331 // Attach to the secondary context. 332 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 333 mSecondEglContext)); 334 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 335 336 // Detach from the secondary context. 337 ASSERT_EQ(OK, mST->detachFromContext()); 338 339 // Attach to the tertiary context. 340 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 341 mThirdEglContext)); 342 ASSERT_EQ(OK, mST->attachToContext(THIRD_TEX_ID)); 343 344 // Verify that the texture object was created and bound. 345 GLint texBinding = -1; 346 glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texBinding); 347 EXPECT_EQ(THIRD_TEX_ID, texBinding); 348 349 // Latch the texture contents on the tertiary context. 350 mFW->waitForFrame(); 351 ASSERT_EQ(OK, mST->updateTexImage()); 352 353 // Try to use the texture from the tertiary context. 354 glClearColor(0.2, 0.2, 0.2, 0.2); 355 glClear(GL_COLOR_BUFFER_BIT); 356 glViewport(0, 0, 1, 1); 357 mThirdTextureRenderer->drawTexture(); 358 ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError()); 359 ASSERT_TRUE(checkPixel( 0, 0, 35, 35, 35, 35)); 360 } 361 362 TEST_F(SurfaceTextureMultiContextGLTest, 363 UpdateTexImageSucceedsForBufferConsumedBeforeDetach) { 364 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); 365 366 // produce two frames and consume them both on the primary context 367 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 368 mFW->waitForFrame(); 369 ASSERT_EQ(OK, mST->updateTexImage()); 370 371 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 372 mFW->waitForFrame(); 373 ASSERT_EQ(OK, mST->updateTexImage()); 374 375 // produce one more frame 376 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 377 378 // Detach from the primary context and attach to the secondary context 379 ASSERT_EQ(OK, mST->detachFromContext()); 380 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 381 mSecondEglContext)); 382 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 383 384 // Consume final frame on secondary context 385 mFW->waitForFrame(); 386 ASSERT_EQ(OK, mST->updateTexImage()); 387 } 388 389 TEST_F(SurfaceTextureMultiContextGLTest, 390 AttachAfterDisplayTerminatedSucceeds) { 391 ASSERT_EQ(NO_ERROR, mST->setDefaultMaxBufferCount(2)); 392 393 // produce two frames and consume them both on the primary context 394 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 395 mFW->waitForFrame(); 396 ASSERT_EQ(OK, mST->updateTexImage()); 397 398 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 399 mFW->waitForFrame(); 400 ASSERT_EQ(OK, mST->updateTexImage()); 401 402 // produce one more frame 403 ASSERT_NO_FATAL_FAILURE(produceOneRGBA8Frame(mANW)); 404 405 // Detach from the primary context. 406 ASSERT_EQ(OK, mST->releaseTexImage()); 407 ASSERT_EQ(OK, mST->detachFromContext()); 408 409 // Terminate and then initialize the display. All contexts, surfaces 410 // and images are invalid at this point. 411 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 412 ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay); 413 EGLint majorVersion = 0; 414 EGLint minorVersion = 0; 415 EXPECT_TRUE(eglTerminate(display)); 416 EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion)); 417 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 418 419 // The surface is invalid so create it again. 420 EGLint pbufferAttribs[] = { 421 EGL_WIDTH, 64, 422 EGL_HEIGHT, 64, 423 EGL_NONE }; 424 mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig, 425 pbufferAttribs); 426 427 // The second context is invalid so create it again. 428 mSecondEglContext = eglCreateContext(mEglDisplay, mGlConfig, 429 EGL_NO_CONTEXT, getContextAttribs()); 430 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 431 ASSERT_NE(EGL_NO_CONTEXT, mSecondEglContext); 432 433 ASSERT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, 434 mSecondEglContext)); 435 ASSERT_EQ(EGL_SUCCESS, eglGetError()); 436 437 // Now attach to and consume final frame on secondary context. 438 ASSERT_EQ(OK, mST->attachToContext(SECOND_TEX_ID)); 439 mFW->waitForFrame(); 440 ASSERT_EQ(OK, mST->updateTexImage()); 441 } 442 443 444 } // namespace android 445