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