/* * Copyright 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "SurfaceTextureGLThreadToGL_test" //#define LOG_NDEBUG 0 #include "SurfaceTextureGLThreadToGL.h" namespace android { TEST_F(SurfaceTextureGLThreadToGLTest, UpdateTexImageBeforeFrameFinishedCompletes) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); swapBuffers(); } }; SetUpWindowAndContext(); runProducerThread(new PT()); mFC->waitForFrame(); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); mFC->finishFrame(); // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } TEST_F(SurfaceTextureGLThreadToGLTest, UpdateTexImageAfterFrameFinishedCompletes) { class PT : public ProducerThread { virtual void render() { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); swapBuffers(); } }; SetUpWindowAndContext(); runProducerThread(new PT()); mFC->waitForFrame(); mFC->finishFrame(); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } TEST_F(SurfaceTextureGLThreadToGLTest, RepeatedUpdateTexImageBeforeFrameFinishedCompletes) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { virtual void render() { for (int i = 0; i < NUM_ITERATIONS; i++) { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ALOGV("+swapBuffers"); swapBuffers(); ALOGV("-swapBuffers"); } } }; SetUpWindowAndContext(); runProducerThread(new PT()); for (int i = 0; i < NUM_ITERATIONS; i++) { mFC->waitForFrame(); ALOGV("+updateTexImage"); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); ALOGV("-updateTexImage"); mFC->finishFrame(); // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } } TEST_F(SurfaceTextureGLThreadToGLTest, RepeatedUpdateTexImageAfterFrameFinishedCompletes) { enum { NUM_ITERATIONS = 1024 }; class PT : public ProducerThread { virtual void render() { for (int i = 0; i < NUM_ITERATIONS; i++) { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ALOGV("+swapBuffers"); swapBuffers(); ALOGV("-swapBuffers"); } } }; SetUpWindowAndContext(); runProducerThread(new PT()); for (int i = 0; i < NUM_ITERATIONS; i++) { mFC->waitForFrame(); mFC->finishFrame(); ALOGV("+updateTexImage"); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); ALOGV("-updateTexImage"); // TODO: Add frame verification once RGB TEX_EXTERNAL_OES is supported! } } // XXX: This test is disabled because it is currently hanging on some devices. TEST_F(SurfaceTextureGLThreadToGLTest, DISABLED_RepeatedSwapBuffersWhileDequeueStalledCompletes) { enum { NUM_ITERATIONS = 64 }; class PT : public ProducerThread { virtual void render() { for (int i = 0; i < NUM_ITERATIONS; i++) { glClearColor(0.0f, 1.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); ALOGV("+swapBuffers"); swapBuffers(); ALOGV("-swapBuffers"); } } }; SetUpWindowAndContext(); runProducerThread(new PT()); // Allow three frames to be rendered and queued before starting the // rendering in this thread. For the latter two frames we don't call // updateTexImage so the next dequeue from the producer thread will block // waiting for a frame to become available. mFC->waitForFrame(); mFC->finishFrame(); // We must call updateTexImage to consume the first frame so that the // SurfaceTexture is able to reduce the buffer count to 2. This is because // the GL driver may dequeue a buffer when the EGLSurface is created, and // that happens before we call setDefaultMaxBufferCount. It's possible that the // driver does not dequeue a buffer at EGLSurface creation time, so we // cannot rely on this to cause the second dequeueBuffer call to block. ASSERT_EQ(NO_ERROR, mST->updateTexImage()); mFC->waitForFrame(); mFC->finishFrame(); mFC->waitForFrame(); mFC->finishFrame(); // Sleep for 100ms to allow the producer thread's dequeueBuffer call to // block waiting for a buffer to become available. usleep(100000); // Render and present a number of images. This thread should not be blocked // by the fact that the producer thread is blocking in dequeue. for (int i = 0; i < NUM_ITERATIONS; i++) { glClear(GL_COLOR_BUFFER_BIT); eglSwapBuffers(mEglDisplay, mEglSurface); } // Consume the two pending buffers to unblock the producer thread. ASSERT_EQ(NO_ERROR, mST->updateTexImage()); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); // Consume the remaining buffers from the producer thread. for (int i = 0; i < NUM_ITERATIONS-3; i++) { mFC->waitForFrame(); mFC->finishFrame(); ALOGV("+updateTexImage"); ASSERT_EQ(NO_ERROR, mST->updateTexImage()); ALOGV("-updateTexImage"); } } } // namespace android