1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2013 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker 17*38e8c45fSAndroid Build Coastguard Worker #ifndef ANDROID_SURFACE_TEXTURE_GL_THREAD_TO_GL_H 18*38e8c45fSAndroid Build Coastguard Worker #define ANDROID_SURFACE_TEXTURE_GL_THREAD_TO_GL_H 19*38e8c45fSAndroid Build Coastguard Worker 20*38e8c45fSAndroid Build Coastguard Worker #include "SurfaceTextureGLToGL.h" 21*38e8c45fSAndroid Build Coastguard Worker 22*38e8c45fSAndroid Build Coastguard Worker namespace android { 23*38e8c45fSAndroid Build Coastguard Worker 24*38e8c45fSAndroid Build Coastguard Worker /* 25*38e8c45fSAndroid Build Coastguard Worker * This test fixture is for testing GL -> GL texture streaming from one thread 26*38e8c45fSAndroid Build Coastguard Worker * to another. It contains functionality to create a producer thread that will 27*38e8c45fSAndroid Build Coastguard Worker * perform GL rendering to an ANativeWindow that feeds frames to a 28*38e8c45fSAndroid Build Coastguard Worker * GLConsumer. Additionally it supports interlocking the producer and 29*38e8c45fSAndroid Build Coastguard Worker * consumer threads so that a specific sequence of calls can be 30*38e8c45fSAndroid Build Coastguard Worker * deterministically created by the test. 31*38e8c45fSAndroid Build Coastguard Worker * 32*38e8c45fSAndroid Build Coastguard Worker * The intended usage is as follows: 33*38e8c45fSAndroid Build Coastguard Worker * 34*38e8c45fSAndroid Build Coastguard Worker * TEST_F(...) { 35*38e8c45fSAndroid Build Coastguard Worker * class PT : public ProducerThread { 36*38e8c45fSAndroid Build Coastguard Worker * virtual void render() { 37*38e8c45fSAndroid Build Coastguard Worker * ... 38*38e8c45fSAndroid Build Coastguard Worker * swapBuffers(); 39*38e8c45fSAndroid Build Coastguard Worker * } 40*38e8c45fSAndroid Build Coastguard Worker * }; 41*38e8c45fSAndroid Build Coastguard Worker * 42*38e8c45fSAndroid Build Coastguard Worker * runProducerThread(new PT()); 43*38e8c45fSAndroid Build Coastguard Worker * 44*38e8c45fSAndroid Build Coastguard Worker * // The order of these calls will vary from test to test and may include 45*38e8c45fSAndroid Build Coastguard Worker * // multiple frames and additional operations (e.g. GL rendering from the 46*38e8c45fSAndroid Build Coastguard Worker * // texture). 47*38e8c45fSAndroid Build Coastguard Worker * fc->waitForFrame(); 48*38e8c45fSAndroid Build Coastguard Worker * mST->updateTexImage(); 49*38e8c45fSAndroid Build Coastguard Worker * fc->finishFrame(); 50*38e8c45fSAndroid Build Coastguard Worker * } 51*38e8c45fSAndroid Build Coastguard Worker * 52*38e8c45fSAndroid Build Coastguard Worker */ 53*38e8c45fSAndroid Build Coastguard Worker class SurfaceTextureGLThreadToGLTest : public SurfaceTextureGLToGLTest { 54*38e8c45fSAndroid Build Coastguard Worker protected: 55*38e8c45fSAndroid Build Coastguard Worker 56*38e8c45fSAndroid Build Coastguard Worker // ProducerThread is an abstract base class to simplify the creation of 57*38e8c45fSAndroid Build Coastguard Worker // OpenGL ES frame producer threads. 58*38e8c45fSAndroid Build Coastguard Worker class ProducerThread : public Thread { 59*38e8c45fSAndroid Build Coastguard Worker public: ~ProducerThread()60*38e8c45fSAndroid Build Coastguard Worker virtual ~ProducerThread() { 61*38e8c45fSAndroid Build Coastguard Worker } 62*38e8c45fSAndroid Build Coastguard Worker setEglObjects(EGLDisplay producerEglDisplay,EGLSurface producerEglSurface,EGLContext producerEglContext)63*38e8c45fSAndroid Build Coastguard Worker void setEglObjects(EGLDisplay producerEglDisplay, 64*38e8c45fSAndroid Build Coastguard Worker EGLSurface producerEglSurface, 65*38e8c45fSAndroid Build Coastguard Worker EGLContext producerEglContext) { 66*38e8c45fSAndroid Build Coastguard Worker mProducerEglDisplay = producerEglDisplay; 67*38e8c45fSAndroid Build Coastguard Worker mProducerEglSurface = producerEglSurface; 68*38e8c45fSAndroid Build Coastguard Worker mProducerEglContext = producerEglContext; 69*38e8c45fSAndroid Build Coastguard Worker } 70*38e8c45fSAndroid Build Coastguard Worker threadLoop()71*38e8c45fSAndroid Build Coastguard Worker virtual bool threadLoop() { 72*38e8c45fSAndroid Build Coastguard Worker eglMakeCurrent(mProducerEglDisplay, mProducerEglSurface, 73*38e8c45fSAndroid Build Coastguard Worker mProducerEglSurface, mProducerEglContext); 74*38e8c45fSAndroid Build Coastguard Worker render(); 75*38e8c45fSAndroid Build Coastguard Worker eglMakeCurrent(mProducerEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, 76*38e8c45fSAndroid Build Coastguard Worker EGL_NO_CONTEXT); 77*38e8c45fSAndroid Build Coastguard Worker return false; 78*38e8c45fSAndroid Build Coastguard Worker } 79*38e8c45fSAndroid Build Coastguard Worker 80*38e8c45fSAndroid Build Coastguard Worker protected: 81*38e8c45fSAndroid Build Coastguard Worker virtual void render() = 0; 82*38e8c45fSAndroid Build Coastguard Worker swapBuffers()83*38e8c45fSAndroid Build Coastguard Worker void swapBuffers() { 84*38e8c45fSAndroid Build Coastguard Worker eglSwapBuffers(mProducerEglDisplay, mProducerEglSurface); 85*38e8c45fSAndroid Build Coastguard Worker } 86*38e8c45fSAndroid Build Coastguard Worker 87*38e8c45fSAndroid Build Coastguard Worker EGLDisplay mProducerEglDisplay; 88*38e8c45fSAndroid Build Coastguard Worker EGLSurface mProducerEglSurface; 89*38e8c45fSAndroid Build Coastguard Worker EGLContext mProducerEglContext; 90*38e8c45fSAndroid Build Coastguard Worker }; 91*38e8c45fSAndroid Build Coastguard Worker 92*38e8c45fSAndroid Build Coastguard Worker // FrameCondition is a utility class for interlocking between the producer 93*38e8c45fSAndroid Build Coastguard Worker // and consumer threads. The FrameCondition object should be created and 94*38e8c45fSAndroid Build Coastguard Worker // destroyed in the consumer thread only. The consumer thread should set 95*38e8c45fSAndroid Build Coastguard Worker // the FrameCondition as the FrameAvailableListener of the GLConsumer, 96*38e8c45fSAndroid Build Coastguard Worker // and should call both waitForFrame and finishFrame once for each expected 97*38e8c45fSAndroid Build Coastguard Worker // frame. 98*38e8c45fSAndroid Build Coastguard Worker // 99*38e8c45fSAndroid Build Coastguard Worker // This interlocking relies on the fact that onFrameAvailable gets called 100*38e8c45fSAndroid Build Coastguard Worker // synchronously from GLConsumer::queueBuffer. 101*38e8c45fSAndroid Build Coastguard Worker class FrameCondition : public GLConsumer::FrameAvailableListener { 102*38e8c45fSAndroid Build Coastguard Worker public: FrameCondition()103*38e8c45fSAndroid Build Coastguard Worker FrameCondition(): 104*38e8c45fSAndroid Build Coastguard Worker mFrameAvailable(false), 105*38e8c45fSAndroid Build Coastguard Worker mFrameFinished(false) { 106*38e8c45fSAndroid Build Coastguard Worker } 107*38e8c45fSAndroid Build Coastguard Worker 108*38e8c45fSAndroid Build Coastguard Worker // waitForFrame waits for the next frame to arrive. This should be 109*38e8c45fSAndroid Build Coastguard Worker // called from the consumer thread once for every frame expected by the 110*38e8c45fSAndroid Build Coastguard Worker // test. waitForFrame()111*38e8c45fSAndroid Build Coastguard Worker void waitForFrame() { 112*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex); 113*38e8c45fSAndroid Build Coastguard Worker ALOGV("+waitForFrame"); 114*38e8c45fSAndroid Build Coastguard Worker while (!mFrameAvailable) { 115*38e8c45fSAndroid Build Coastguard Worker mFrameAvailableCondition.wait(mMutex); 116*38e8c45fSAndroid Build Coastguard Worker } 117*38e8c45fSAndroid Build Coastguard Worker mFrameAvailable = false; 118*38e8c45fSAndroid Build Coastguard Worker ALOGV("-waitForFrame"); 119*38e8c45fSAndroid Build Coastguard Worker } 120*38e8c45fSAndroid Build Coastguard Worker 121*38e8c45fSAndroid Build Coastguard Worker // Allow the producer to return from its swapBuffers call and continue 122*38e8c45fSAndroid Build Coastguard Worker // on to produce the next frame. This should be called by the consumer 123*38e8c45fSAndroid Build Coastguard Worker // thread once for every frame expected by the test. finishFrame()124*38e8c45fSAndroid Build Coastguard Worker void finishFrame() { 125*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex); 126*38e8c45fSAndroid Build Coastguard Worker ALOGV("+finishFrame"); 127*38e8c45fSAndroid Build Coastguard Worker mFrameFinished = true; 128*38e8c45fSAndroid Build Coastguard Worker mFrameFinishCondition.signal(); 129*38e8c45fSAndroid Build Coastguard Worker ALOGV("-finishFrame"); 130*38e8c45fSAndroid Build Coastguard Worker } 131*38e8c45fSAndroid Build Coastguard Worker 132*38e8c45fSAndroid Build Coastguard Worker // This should be called by GLConsumer on the producer thread. onFrameAvailable(const BufferItem &)133*38e8c45fSAndroid Build Coastguard Worker virtual void onFrameAvailable(const BufferItem& /* item */) { 134*38e8c45fSAndroid Build Coastguard Worker Mutex::Autolock lock(mMutex); 135*38e8c45fSAndroid Build Coastguard Worker ALOGV("+onFrameAvailable"); 136*38e8c45fSAndroid Build Coastguard Worker mFrameAvailable = true; 137*38e8c45fSAndroid Build Coastguard Worker mFrameAvailableCondition.signal(); 138*38e8c45fSAndroid Build Coastguard Worker while (!mFrameFinished) { 139*38e8c45fSAndroid Build Coastguard Worker mFrameFinishCondition.wait(mMutex); 140*38e8c45fSAndroid Build Coastguard Worker } 141*38e8c45fSAndroid Build Coastguard Worker mFrameFinished = false; 142*38e8c45fSAndroid Build Coastguard Worker ALOGV("-onFrameAvailable"); 143*38e8c45fSAndroid Build Coastguard Worker } 144*38e8c45fSAndroid Build Coastguard Worker 145*38e8c45fSAndroid Build Coastguard Worker protected: 146*38e8c45fSAndroid Build Coastguard Worker bool mFrameAvailable; 147*38e8c45fSAndroid Build Coastguard Worker bool mFrameFinished; 148*38e8c45fSAndroid Build Coastguard Worker 149*38e8c45fSAndroid Build Coastguard Worker Mutex mMutex; 150*38e8c45fSAndroid Build Coastguard Worker Condition mFrameAvailableCondition; 151*38e8c45fSAndroid Build Coastguard Worker Condition mFrameFinishCondition; 152*38e8c45fSAndroid Build Coastguard Worker }; 153*38e8c45fSAndroid Build Coastguard Worker SetUp()154*38e8c45fSAndroid Build Coastguard Worker virtual void SetUp() { 155*38e8c45fSAndroid Build Coastguard Worker SurfaceTextureGLToGLTest::SetUp(); 156*38e8c45fSAndroid Build Coastguard Worker mFC = new FrameCondition(); 157*38e8c45fSAndroid Build Coastguard Worker mST->setFrameAvailableListener(mFC); 158*38e8c45fSAndroid Build Coastguard Worker } 159*38e8c45fSAndroid Build Coastguard Worker TearDown()160*38e8c45fSAndroid Build Coastguard Worker virtual void TearDown() { 161*38e8c45fSAndroid Build Coastguard Worker if (mProducerThread != nullptr) { 162*38e8c45fSAndroid Build Coastguard Worker mProducerThread->requestExitAndWait(); 163*38e8c45fSAndroid Build Coastguard Worker } 164*38e8c45fSAndroid Build Coastguard Worker mProducerThread.clear(); 165*38e8c45fSAndroid Build Coastguard Worker mFC.clear(); 166*38e8c45fSAndroid Build Coastguard Worker SurfaceTextureGLToGLTest::TearDown(); 167*38e8c45fSAndroid Build Coastguard Worker } 168*38e8c45fSAndroid Build Coastguard Worker runProducerThread(const sp<ProducerThread> producerThread)169*38e8c45fSAndroid Build Coastguard Worker void runProducerThread(const sp<ProducerThread> producerThread) { 170*38e8c45fSAndroid Build Coastguard Worker ASSERT_TRUE(mProducerThread == nullptr); 171*38e8c45fSAndroid Build Coastguard Worker mProducerThread = producerThread; 172*38e8c45fSAndroid Build Coastguard Worker producerThread->setEglObjects(mEglDisplay, mProducerEglSurface, 173*38e8c45fSAndroid Build Coastguard Worker mProducerEglContext); 174*38e8c45fSAndroid Build Coastguard Worker producerThread->run("ProducerThread"); 175*38e8c45fSAndroid Build Coastguard Worker } 176*38e8c45fSAndroid Build Coastguard Worker 177*38e8c45fSAndroid Build Coastguard Worker sp<ProducerThread> mProducerThread; 178*38e8c45fSAndroid Build Coastguard Worker sp<FrameCondition> mFC; 179*38e8c45fSAndroid Build Coastguard Worker }; 180*38e8c45fSAndroid Build Coastguard Worker 181*38e8c45fSAndroid Build Coastguard Worker } // namespace android 182*38e8c45fSAndroid Build Coastguard Worker 183*38e8c45fSAndroid Build Coastguard Worker #endif 184