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