Home | History | Annotate | Download | only in tests
      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_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 
     43 TEST_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 
     58 TEST_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 
     75 TEST_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 
     88 TEST_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 
    103 TEST_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 
    120 TEST_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 
    137 TEST_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 
    149 TEST_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 
    179 TEST_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 
    211 TEST_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 
    243 TEST_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 
    261 TEST_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 
    273 TEST_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 
    282 TEST_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 
    302 TEST_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 
    340 TEST_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 
    379 TEST_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 
    406 TEST_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