|  | /* | 
|  | * 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 |