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