1/*
2 * Copyright 2006-2009, Haiku, Inc.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Axel D��rfler, axeld@pinc-software.de
7 */
8
9
10#include "Overlay.h"
11
12#include <BitmapPrivate.h>
13
14#include "HWInterface.h"
15#include "ServerBitmap.h"
16
17
18//#define TRACE_OVERLAY
19#ifdef TRACE_OVERLAY
20#	define TRACE(x...) ktrace_printf(x);
21#else
22#	define TRACE(x...) ;
23#endif
24
25
26const static bigtime_t kOverlayTimeout = 1000000LL;
27	// after 1 second, the team holding the lock will be killed
28
29class SemaphoreLocker {
30public:
31	SemaphoreLocker(sem_id semaphore, bigtime_t timeout = B_INFINITE_TIMEOUT)
32		:
33		fSemaphore(semaphore)
34	{
35		do {
36			fStatus = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT,
37				timeout);
38		} while (fStatus == B_INTERRUPTED);
39	}
40
41	~SemaphoreLocker()
42	{
43		if (fStatus == B_OK)
44			release_sem_etc(fSemaphore, 1, B_DO_NOT_RESCHEDULE);
45	}
46
47	status_t LockStatus()
48	{
49		return fStatus;
50	}
51
52private:
53	sem_id		fSemaphore;
54	status_t	fStatus;
55};
56
57
58//	#pragma mark -
59
60
61Overlay::Overlay(HWInterface& interface, ServerBitmap* bitmap,
62		overlay_token token)
63	:
64	fHWInterface(interface),
65	fOverlayBuffer(NULL),
66	fClientData(NULL),
67	fOverlayToken(token)
68{
69	fSemaphore = create_sem(1, "overlay lock");
70	fColor = (rgb_color){ 0, 80, 0, 0 };
71		// TODO: whatever fine color we want to use here...
72
73	fWindow.offset_top = 0;
74	fWindow.offset_left = 0;
75	fWindow.offset_right = 0;
76	fWindow.offset_bottom = 0;
77
78	fWindow.flags = B_OVERLAY_COLOR_KEY;
79
80	_AllocateBuffer(bitmap);
81
82	TRACE("overlay: created %p, bitmap %p\n", this, bitmap);
83}
84
85
86Overlay::~Overlay()
87{
88	fHWInterface.ReleaseOverlayChannel(fOverlayToken);
89	_FreeBuffer();
90
91	delete_sem(fSemaphore);
92	TRACE("overlay: deleted %p\n", this);
93}
94
95
96status_t
97Overlay::InitCheck() const
98{
99	if (fSemaphore < B_OK)
100		return fSemaphore;
101
102	if (fOverlayBuffer == NULL)
103		return B_NO_MEMORY;
104
105	return B_OK;
106}
107
108
109status_t
110Overlay::Resume(ServerBitmap* bitmap)
111{
112	SemaphoreLocker locker(fSemaphore, kOverlayTimeout);
113	if (locker.LockStatus() == B_TIMED_OUT) {
114		// TODO: kill app!
115	}
116
117	TRACE("overlay: resume %p (lock status %ld)\n", this, locker.LockStatus());
118
119	status_t status = _AllocateBuffer(bitmap);
120	if (status < B_OK)
121		return status;
122
123	fClientData->buffer = (uint8*)fOverlayBuffer->buffer;
124	return B_OK;
125}
126
127
128status_t
129Overlay::Suspend(ServerBitmap* bitmap, bool needTemporary)
130{
131	SemaphoreLocker locker(fSemaphore, kOverlayTimeout);
132	if (locker.LockStatus() == B_TIMED_OUT) {
133		// TODO: kill app!
134	}
135
136	TRACE("overlay: suspend %p (lock status %ld)\n", this, locker.LockStatus());
137
138	_FreeBuffer();
139	fClientData->buffer = NULL;
140
141	return B_OK;
142}
143
144
145void
146Overlay::_FreeBuffer()
147{
148	fHWInterface.FreeOverlayBuffer(fOverlayBuffer);
149	fOverlayBuffer = NULL;
150}
151
152
153status_t
154Overlay::_AllocateBuffer(ServerBitmap* bitmap)
155{
156	fOverlayBuffer = fHWInterface.AllocateOverlayBuffer(bitmap->Width(),
157		bitmap->Height(), bitmap->ColorSpace());
158	if (fOverlayBuffer == NULL)
159		return B_NO_MEMORY;
160
161	return B_OK;
162}
163
164
165void
166Overlay::SetClientData(overlay_client_data* clientData)
167{
168	fClientData = clientData;
169	fClientData->lock = fSemaphore;
170	fClientData->buffer = (uint8*)fOverlayBuffer->buffer;
171}
172
173
174void
175Overlay::SetFlags(uint32 flags)
176{
177	if (flags & B_OVERLAY_FILTER_HORIZONTAL)
178		fWindow.flags |= B_OVERLAY_HORIZONTAL_FILTERING;
179	if (flags & B_OVERLAY_FILTER_VERTICAL)
180		fWindow.flags |= B_OVERLAY_VERTICAL_FILTERING;
181	if (flags & B_OVERLAY_MIRROR)
182		fWindow.flags |= B_OVERLAY_HORIZONTAL_MIRRORING;
183}
184
185
186void
187Overlay::TakeOverToken(Overlay* other)
188{
189	overlay_token token = other->OverlayToken();
190	if (token == NULL)
191		return;
192
193	fOverlayToken = token;
194	//other->fOverlayToken = NULL;
195}
196
197
198const overlay_buffer*
199Overlay::OverlayBuffer() const
200{
201	return fOverlayBuffer;
202}
203
204
205overlay_client_data*
206Overlay::ClientData() const
207{
208	return fClientData;
209}
210
211
212overlay_token
213Overlay::OverlayToken() const
214{
215	return fOverlayToken;
216}
217
218
219void
220Overlay::Hide()
221{
222	if (fOverlayToken == NULL)
223		return;
224
225	fHWInterface.HideOverlay(this);
226	TRACE("overlay: hide %p\n", this);
227}
228
229
230void
231Overlay::SetColorSpace(uint32 colorSpace)
232{
233	if ((fWindow.flags & B_OVERLAY_COLOR_KEY) == 0)
234		return;
235
236	uint8 colorShift = 0, greenShift = 0, alphaShift = 0;
237	rgb_color colorKey = fColor;
238
239	switch (colorSpace) {
240		case B_RGB15:
241			greenShift = colorShift = 3;
242			alphaShift = 7;
243			break;
244		case B_RGB16:
245			colorShift = 3;
246			greenShift = 2;
247			alphaShift = 8;
248			break;
249	}
250
251	fWindow.red.value = colorKey.red >> colorShift;
252	fWindow.green.value = colorKey.green >> greenShift;
253	fWindow.blue.value = colorKey.blue >> colorShift;
254	fWindow.alpha.value = colorKey.alpha >> alphaShift;
255	fWindow.red.mask = 0xff >> colorShift;
256	fWindow.green.mask = 0xff >> greenShift;
257	fWindow.blue.mask = 0xff >> colorShift;
258	fWindow.alpha.mask = 0xff >> alphaShift;
259}
260
261
262void
263Overlay::Configure(const BRect& source, const BRect& destination)
264{
265	if (fOverlayToken == NULL) {
266		fOverlayToken = fHWInterface.AcquireOverlayChannel();
267		if (fOverlayToken == NULL)
268			return;
269	}
270
271	TRACE("overlay: configure %p\n", this);
272
273	fView.h_start = (uint16)source.left;
274	fView.v_start = (uint16)source.top;
275	fView.width = (uint16)source.IntegerWidth() + 1;
276	fView.height = (uint16)source.IntegerHeight() + 1;
277
278	fWindow.h_start = (int16)destination.left;
279	fWindow.v_start = (int16)destination.top;
280	fWindow.width = (uint16)destination.IntegerWidth() + 1;
281	fWindow.height = (uint16)destination.IntegerHeight() + 1;
282
283	fHWInterface.ConfigureOverlay(this);
284}
285
286