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