1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief RenderActivity base class.
22 *//*--------------------------------------------------------------------*/
24 #include "tcuAndroidRenderActivity.hpp"
25 #include "deSemaphore.hpp"
27 #include <android/window.h>
35 # define DBG_PRINT(X) print X
47 MESSAGE_QUEUE_SIZE = 8 //!< Length of RenderThread message queue.
52 RenderThread::RenderThread (NativeActivity& activity)
53 : m_activity (activity)
54 , m_msgQueue (MESSAGE_QUEUE_SIZE)
55 , m_threadRunning (false)
56 , m_inputQueue (DE_NULL)
57 , m_windowState (WINDOWSTATE_NOT_CREATED)
64 RenderThread::~RenderThread (void)
68 void RenderThread::start (void)
70 m_threadRunning = true;
74 void RenderThread::destroy (void)
76 // Queue finish command
77 enqueue(Message(MESSAGE_FINISH));
79 // Wait for thread to terminate
82 m_threadRunning = false;
85 void RenderThread::enqueue (const Message& message)
87 // \note Thread must be running or otherwise nobody is going to drain the queue.
88 DE_ASSERT(m_threadRunning);
89 m_msgQueue.pushFront(message);
92 void RenderThread::pause (void)
94 enqueue(Message(MESSAGE_PAUSE));
97 void RenderThread::resume (void)
99 enqueue(Message(MESSAGE_RESUME));
102 void RenderThread::sync (void)
104 de::Semaphore waitSem(0);
105 enqueue(Message(MESSAGE_SYNC, &waitSem));
109 void RenderThread::processMessage (const Message& message)
111 switch (message.type)
113 case MESSAGE_RESUME: m_paused = false; break;
114 case MESSAGE_PAUSE: m_paused = true; break;
115 case MESSAGE_FINISH: m_finish = true; break;
117 case MESSAGE_WINDOW_CREATED:
118 if (m_windowState != WINDOWSTATE_NOT_CREATED && m_windowState != WINDOWSTATE_DESTROYED)
119 throw InternalError("Got unexpected onNativeWindowCreated() event from system");
120 m_windowState = WINDOWSTATE_NOT_INITIALIZED;
121 m_window = message.payload.window;
124 case MESSAGE_WINDOW_RESIZED:
125 DE_ASSERT(m_window == message.payload.window);
126 if (m_windowState == WINDOWSTATE_NOT_INITIALIZED)
128 // Got first resize event, window is ready for use.
129 m_windowState = WINDOWSTATE_READY;
130 onWindowCreated(message.payload.window);
132 else if (m_windowState == WINDOWSTATE_READY)
133 onWindowResized(message.payload.window);
135 throw InternalError("Got unexpected onNativeWindowResized() event from system");
138 case MESSAGE_WINDOW_DESTROYED:
139 DE_ASSERT(m_window == message.payload.window);
140 if (m_windowState != WINDOWSTATE_NOT_INITIALIZED && m_windowState != WINDOWSTATE_READY)
141 throw InternalError("Got unexpected onNativeWindowDestroyed() event from system");
143 onWindowDestroyed(message.payload.window);
144 m_windowState = WINDOWSTATE_DESTROYED;
148 case MESSAGE_INPUT_QUEUE_CREATED:
149 m_inputQueue = message.payload.inputQueue;
152 case MESSAGE_INPUT_QUEUE_DESTROYED:
153 m_inputQueue = message.payload.inputQueue;
157 message.payload.semaphore->increment();
161 throw std::runtime_error("Unknown message type");
166 void RenderThread::run (void)
169 m_windowState = WINDOWSTATE_NOT_CREATED;
177 if (m_paused || m_windowState != WINDOWSTATE_READY)
179 // Block until we are not paused and window is ready.
180 Message msg = m_msgQueue.popBack();
185 // Process available commands
188 if (m_msgQueue.tryPopBack(msg))
195 DE_ASSERT(m_windowState == WINDOWSTATE_READY);
197 // Process input events.
198 // \todo [2013-05-08 pyry] What if system fills up the input queue before we have window ready?
199 while (m_inputQueue &&
200 AInputQueue_hasEvents(m_inputQueue) > 0)
203 TCU_CHECK(AInputQueue_getEvent(m_inputQueue, &event) >= 0);
205 AInputQueue_finishEvent(m_inputQueue, event, 1);
208 // Everything set up - safe to render.
213 if (m_windowState == WINDOWSTATE_READY)
215 // Clean up window use
216 onWindowDestroyed(m_window);
217 m_windowState = WINDOWSTATE_DESTROYED;
221 catch (const std::exception& e)
223 print("RenderThread: %s\n", e.what());
226 // Tell activity to finish.
227 DBG_PRINT(("RenderThread::run(): done, waiting for FINISH\n"));
230 // Thread must keep draining message queue until FINISH message is encountered.
235 Message msg = m_msgQueue.popBack();
237 // Ignore all but SYNC and FINISH messages.
238 if (msg.type == MESSAGE_SYNC || msg.type == MESSAGE_FINISH)
242 catch (const std::exception& e)
244 die("RenderThread: %s\n", e.what());
247 DBG_PRINT(("RenderThread::run(): exiting...\n"));
252 RenderActivity::RenderActivity (ANativeActivity* activity)
253 : NativeActivity(activity)
256 DBG_PRINT(("RenderActivity::RenderActivity()"));
259 RenderActivity::~RenderActivity (void)
261 DBG_PRINT(("RenderActivity::~RenderActivity()"));
264 void RenderActivity::setThread (RenderThread* thread)
266 DE_ASSERT(!m_thread && thread);
270 void RenderActivity::onStart (void)
272 DBG_PRINT(("RenderActivity::onStart()"));
274 // Launch tester thread when activity is created. It will remain in paused state until resume() is called.
278 void RenderActivity::onResume (void)
280 DBG_PRINT(("RenderActivity::onResume()"));
282 // Resume (or start) test execution
286 void RenderActivity::onPause (void)
288 DBG_PRINT(("RenderActivity::onPause()"));
290 // Pause test execution
294 void RenderActivity::onStop (void)
296 DBG_PRINT(("RenderActivity::onStop()"));
300 void RenderActivity::onDestroy (void)
302 DBG_PRINT(("RenderActivity::onDestroy()"));
305 void RenderActivity::onNativeWindowCreated (ANativeWindow* window)
307 DBG_PRINT(("RenderActivity::onNativeWindowCreated()"));
308 m_thread->enqueue(Message(MESSAGE_WINDOW_CREATED, window));
311 void RenderActivity::onNativeWindowResized (ANativeWindow* window)
313 DBG_PRINT(("RenderActivity::onNativeWindowResized()"));
314 m_thread->enqueue(Message(MESSAGE_WINDOW_RESIZED, window));
317 void RenderActivity::onNativeWindowRedrawNeeded (ANativeWindow* window)
322 void RenderActivity::onNativeWindowDestroyed (ANativeWindow* window)
324 DBG_PRINT(("RenderActivity::onNativeWindowDestroyed()"));
325 m_thread->enqueue(Message(MESSAGE_WINDOW_DESTROYED, window));
326 m_thread->sync(); // Block until thread has processed all messages.
329 void RenderActivity::onInputQueueCreated (AInputQueue* queue)
331 DBG_PRINT(("RenderActivity::onInputQueueCreated()"));
332 m_thread->enqueue(Message(MESSAGE_INPUT_QUEUE_CREATED, queue));
335 void RenderActivity::onInputQueueDestroyed (AInputQueue* queue)
337 DBG_PRINT(("RenderActivity::onInputQueueDestroyed()"));
338 m_thread->enqueue(Message(MESSAGE_INPUT_QUEUE_DESTROYED, queue));