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);
174cb1fcdedaaf95acabeac6a2d5bff423d6ca62296Dan Stoza        producerThread->run();
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