1#ifndef _TCUANDROIDRENDERACTIVITY_HPP
2#define _TCUANDROIDRENDERACTIVITY_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program Tester Core
5 * ----------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief RenderActivity base class.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuAndroidNativeActivity.hpp"
28#include "deThread.hpp"
29#include "deThreadSafeRingBuffer.hpp"
30
31namespace tcu
32{
33namespace Android
34{
35
36enum MessageType
37{
38	// Execution control messages. No data argument.
39	MESSAGE_RESUME = 0,
40	MESSAGE_PAUSE,
41	MESSAGE_FINISH,
42
43	// Window messages. Argument is ANativeWindow pointer.
44	MESSAGE_WINDOW_CREATED,
45	MESSAGE_WINDOW_RESIZED,
46	MESSAGE_WINDOW_DESTROYED,
47
48	// Input queue messages. Argument is AInputQueue pointer.
49	MESSAGE_INPUT_QUEUE_CREATED,
50	MESSAGE_INPUT_QUEUE_DESTROYED,
51
52	MESSAGE_SYNC,					//!< Main thread requests sync. Data argument is de::Semaphore* that needs to be incremented.
53
54	MESSAGETYPE_LAST
55};
56
57struct Message
58{
59	MessageType			type;			//!< Message type.
60	union
61	{
62		ANativeWindow*	window;
63		AInputQueue*	inputQueue;
64		de::Semaphore*	semaphore;
65	} payload;							//!< Optional data argument.
66
67	Message (void)
68		: type(MESSAGETYPE_LAST)
69	{
70	}
71
72	explicit Message (MessageType type_)
73		: type(type_)
74	{
75		DE_ASSERT(type_ == MESSAGE_RESUME	||
76				  type_ == MESSAGE_PAUSE	||
77				  type_ == MESSAGE_FINISH);
78	}
79
80	Message (MessageType type_, ANativeWindow* window)
81		: type(type_)
82	{
83		DE_ASSERT(type_ == MESSAGE_WINDOW_CREATED	||
84				  type_ == MESSAGE_WINDOW_DESTROYED	||
85				  type_ == MESSAGE_WINDOW_RESIZED);
86		DE_ASSERT(window);
87		payload.window = window;
88	}
89
90	Message (MessageType type_, AInputQueue* inputQueue)
91		: type(type_)
92	{
93		DE_ASSERT(type_ == MESSAGE_INPUT_QUEUE_CREATED	||
94				  type_ == MESSAGE_INPUT_QUEUE_DESTROYED);
95		DE_ASSERT(inputQueue);
96		payload.inputQueue = inputQueue;
97	}
98
99	Message (MessageType type_, de::Semaphore* semaphore)
100		: type(type_)
101	{
102		DE_ASSERT(type_ == MESSAGE_SYNC);
103		DE_ASSERT(semaphore);
104		payload.semaphore = semaphore;
105	}
106};
107
108enum WindowState
109{
110	WINDOWSTATE_NOT_CREATED = 0,	//!< Framework hasn't signaled window creation.
111	WINDOWSTATE_NOT_INITIALIZED,	//!< Framework hasn't signaled first resize after creation and thus size is not final.
112	WINDOWSTATE_READY,				//!< Window is ready for use.
113	WINDOWSTATE_DESTROYED,			//!< Window has been destroyed.
114
115	WINDOWSTATE_LAST
116};
117
118typedef de::ThreadSafeRingBuffer<Message> MessageQueue;
119
120class RenderThread : private de::Thread
121{
122public:
123							RenderThread				(NativeActivity& activity);
124							~RenderThread				(void);
125
126	void					start						(void);
127	void					resume						(void);
128	void					pause						(void);
129	void					stop						(void);
130
131	void					enqueue						(const Message& message);
132	void					sync						(void);
133
134	void					run							(void);
135
136protected:
137	virtual void			onInputEvent				(AInputEvent* event) { DE_UNREF(event); }
138	virtual void			onWindowCreated				(ANativeWindow* window) = 0;
139	virtual void			onWindowResized				(ANativeWindow* window) = 0;
140	virtual void			onWindowDestroyed			(ANativeWindow* window) = 0;
141	virtual bool			render						(void) = 0;
142
143	NativeActivity&			getNativeActivity			(void) { return m_activity; }
144
145private:
146	void					processMessage				(const Message& message);
147
148	// Shared state.
149	NativeActivity&			m_activity;
150	MessageQueue			m_msgQueue;
151
152	// Parent thread state.
153	bool					m_threadRunning;
154
155	// Thread state.
156	AInputQueue*			m_inputQueue;
157	WindowState				m_windowState;
158	ANativeWindow*			m_window;
159	bool					m_paused;					//!< Is rendering paused?
160	bool					m_finish;					//!< Has thread received FINISH message?
161};
162
163class RenderActivity : public NativeActivity
164{
165public:
166							RenderActivity				(ANativeActivity* activity);
167	virtual					~RenderActivity				(void);
168
169	virtual void			onStart						(void);
170	virtual void			onResume					(void);
171	virtual void			onPause						(void);
172	virtual void			onStop						(void);
173	virtual void			onDestroy					(void);
174
175	virtual void			onNativeWindowCreated		(ANativeWindow* window);
176	virtual void			onNativeWindowResized		(ANativeWindow* window);
177	virtual void			onNativeWindowRedrawNeeded	(ANativeWindow* window);
178	virtual void			onNativeWindowDestroyed		(ANativeWindow* window);
179
180	virtual void			onInputQueueCreated			(AInputQueue* queue);
181	virtual void			onInputQueueDestroyed		(AInputQueue* queue);
182
183protected:
184	//! Set rendering thread. Must be called at construction time.
185	void					setThread					(RenderThread* thread);
186
187private:
188							RenderActivity				(const RenderActivity& other);
189	RenderActivity&			operator=					(const RenderActivity& other);
190
191	RenderThread*			m_thread;
192};
193
194} // Android
195} // tcu
196
197#endif // _TCUANDROIDRENDERACTIVITY_HPP
198