xref: /aosp_15_r20/frameworks/native/libs/gui/tests/SurfaceTextureGLThreadToGL.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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