xref: /haiku/src/servers/app/BitmapManager.cpp (revision 410ed2fbba58819ac21e27d3676739728416761d)
1 /*
2  * Copyright 2001-2009, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 /*!	Whenever a ServerBitmap associated with a client-side BBitmap needs to be
12 	created or destroyed, the BitmapManager needs to handle it. It takes care of
13 	all memory management related to them.
14 */
15 
16 
17 #include "BitmapManager.h"
18 
19 #include "ClientMemoryAllocator.h"
20 #include "HWInterface.h"
21 #include "Overlay.h"
22 #include "ServerApp.h"
23 #include "ServerBitmap.h"
24 #include "ServerProtocol.h"
25 #include "ServerTokenSpace.h"
26 
27 #include <BitmapPrivate.h>
28 #include <ObjectList.h>
29 #include <video_overlay.h>
30 
31 #include <AppDefs.h>
32 #include <Autolock.h>
33 #include <Bitmap.h>
34 #include <Message.h>
35 
36 #include <new>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 
41 using std::nothrow;
42 
43 
44 //! The one and only bitmap manager for the server, created by the AppServer
45 BitmapManager *gBitmapManager = NULL;
46 
47 
48 int
49 compare_app_pointer(const ServerApp* a, const ServerApp* b)
50 {
51 	return (addr_t)a - (addr_t)b;
52 }
53 
54 
55 //	#pragma mark -
56 
57 
58 //! Sets up stuff to be ready to allocate space for bitmaps
59 BitmapManager::BitmapManager()
60 	:
61 	fBitmapList(1024),
62 	fLock("BitmapManager Lock")
63 {
64 }
65 
66 
67 //! Deallocates everything associated with the manager
68 BitmapManager::~BitmapManager()
69 {
70 	int32 count = fBitmapList.CountItems();
71 	for (int32 i = 0; i < count; i++)
72 		delete (ServerBitmap*)fBitmapList.ItemAt(i);
73 }
74 
75 
76 /*!	\brief Allocates a new ServerBitmap.
77 
78 	\param bounds Size of the bitmap
79 	\param space Color space of the bitmap
80 	\param flags Bitmap flags as defined in Bitmap.h
81 	\param bytesPerRow Number of bytes per row.
82 	\param screen Screen id of the screen associated with it. Unused.
83 	\return A new ServerBitmap or NULL if unable to allocate one.
84 */
85 ServerBitmap*
86 BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator,
87 	HWInterface& hwInterface, BRect bounds, color_space space, uint32 flags,
88 	int32 bytesPerRow, int32 screen, uint8* _allocationFlags)
89 {
90 	BAutolock locker(fLock);
91 	if (!locker.IsLocked())
92 		return NULL;
93 
94 	overlay_token overlayToken = NULL;
95 
96 	if (flags & B_BITMAP_WILL_OVERLAY) {
97 		if (!hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1,
98 				bounds.IntegerHeight() + 1, space))
99 			return NULL;
100 
101 		if (flags & B_BITMAP_RESERVE_OVERLAY_CHANNEL) {
102 			overlayToken = hwInterface.AcquireOverlayChannel();
103 			if (overlayToken == NULL)
104 				return NULL;
105 		}
106 	}
107 
108 	ServerBitmap* bitmap = new(std::nothrow) ServerBitmap(bounds, space, flags,
109 		bytesPerRow);
110 	if (bitmap == NULL) {
111 		if (overlayToken != NULL)
112 			hwInterface.ReleaseOverlayChannel(overlayToken);
113 
114 		return NULL;
115 	}
116 
117 	uint8* buffer = NULL;
118 
119 	if (flags & B_BITMAP_WILL_OVERLAY) {
120 		Overlay* overlay = new(std::nothrow) Overlay(hwInterface, bitmap,
121 			overlayToken);
122 
123 		overlay_client_data* clientData = NULL;
124 		bool newArea = false;
125 
126 		if (overlay != NULL && overlay->InitCheck() == B_OK) {
127 			// allocate client memory to communicate the overlay semaphore
128 			// and buffer location to the BBitmap
129 			clientData = (overlay_client_data*)bitmap->fClientMemory.Allocate(
130 				allocator, sizeof(overlay_client_data), newArea);
131 		}
132 
133 		if (clientData != NULL) {
134 			overlay->SetClientData(clientData);
135 
136 			bitmap->fMemory = &bitmap->fClientMemory;
137 			bitmap->SetOverlay(overlay);
138 			bitmap->fBytesPerRow = overlay->OverlayBuffer()->bytes_per_row;
139 
140 			buffer = (uint8*)overlay->OverlayBuffer()->buffer;
141 			if (_allocationFlags)
142 				*_allocationFlags = kFramebuffer | (newArea ? kNewAllocatorArea : 0);
143 		} else
144 			delete overlay;
145 	} else if (allocator != NULL) {
146 		// standard bitmaps
147 		bool newArea;
148 		buffer = (uint8*)bitmap->fClientMemory.Allocate(allocator,
149 			bitmap->BitsLength(), newArea);
150 		if (buffer != NULL) {
151 			bitmap->fMemory = &bitmap->fClientMemory;
152 
153 			if (_allocationFlags)
154 				*_allocationFlags = kAllocator | (newArea ? kNewAllocatorArea : 0);
155 		}
156 	} else {
157 		// server side only bitmaps
158 		buffer = (uint8*)malloc(bitmap->BitsLength());
159 		if (buffer != NULL) {
160 			bitmap->fMemory = NULL;
161 
162 			if (_allocationFlags)
163 				*_allocationFlags = kHeap;
164 		}
165 	}
166 
167 	bool success = false;
168 	if (buffer != NULL) {
169 		success = fBitmapList.AddItem(bitmap);
170 		if (success && bitmap->Overlay() != NULL) {
171 			success = fOverlays.AddItem(bitmap);
172 			if (!success)
173 				fBitmapList.RemoveItem(bitmap);
174 		}
175 	}
176 
177 	if (success) {
178 		bitmap->fBuffer = buffer;
179 		bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
180 		// NOTE: the client handles clearing to white in case the flags
181 		// indicate this is needed
182 	} else {
183 		// Allocation failed for buffer or bitmap list
184 		free(buffer);
185 		delete bitmap;
186 		bitmap = NULL;
187 	}
188 
189 	return bitmap;
190 }
191 
192 
193 ServerBitmap*
194 BitmapManager::CloneFromClient(area_id clientArea, int32 areaOffset,
195 	BRect bounds, color_space space, uint32 flags, int32 bytesPerRow)
196 {
197 	BAutolock locker(fLock);
198 	if (!locker.IsLocked())
199 		return NULL;
200 	BReference<ServerBitmap> bitmap(new(std::nothrow) ServerBitmap(bounds, space, flags,
201 		bytesPerRow), true);
202 	if (bitmap == NULL)
203 		return NULL;
204 
205 	ClonedAreaMemory* memory = new(std::nothrow) ClonedAreaMemory;
206 	if (memory == NULL) {
207 		return NULL;
208 	}
209 	int8* buffer = (int8*)memory->Clone(clientArea, areaOffset);
210 	if (buffer == NULL) {
211 		delete memory;
212 		return NULL;
213 	}
214 
215 	bitmap->fMemory = memory;
216 	bitmap->fBuffer = memory->Address();
217 	bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap);
218 	return bitmap.Detach();
219 }
220 
221 
222 /*!	\brief Called when a ServerBitmap is deleted.
223 */
224 void
225 BitmapManager::BitmapRemoved(ServerBitmap* bitmap)
226 {
227 	BAutolock locker(fLock);
228 	if (!locker.IsLocked())
229 		return;
230 
231 	if (bitmap->Overlay() != NULL)
232 		fOverlays.RemoveItem(bitmap);
233 
234 	fBitmapList.RemoveItem(bitmap);
235 }
236 
237 
238 void
239 BitmapManager::SuspendOverlays()
240 {
241 	BAutolock locker(fLock);
242 	if (!locker.IsLocked())
243 		return;
244 
245 	// first, tell all applications owning an overlay to release their locks
246 
247 	BObjectList<ServerApp> apps;
248 	for (int32 i = 0; i < fOverlays.CountItems(); i++) {
249 		ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
250 		apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer);
251 	}
252 	for (int32 i = 0; i < apps.CountItems(); i++) {
253 		BMessage notify(B_RELEASE_OVERLAY_LOCK);
254 		apps.ItemAt(i)->SendMessageToClient(&notify);
255 	}
256 
257 	// suspend overlays
258 
259 	for (int32 i = 0; i < fOverlays.CountItems(); i++) {
260 		ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
261 		bitmap->Overlay()->Suspend(bitmap, false);
262 	}
263 }
264 
265 
266 void
267 BitmapManager::ResumeOverlays()
268 {
269 	BAutolock locker(fLock);
270 	if (!locker.IsLocked())
271 		return;
272 
273 	// first, tell all applications owning an overlay that
274 	// they can reacquire their locks
275 
276 	BObjectList<ServerApp> apps;
277 	for (int32 i = 0; i < fOverlays.CountItems(); i++) {
278 		ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
279 		apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer);
280 	}
281 	for (int32 i = 0; i < apps.CountItems(); i++) {
282 		BMessage notify(B_RELEASE_OVERLAY_LOCK);
283 		apps.ItemAt(i)->SendMessageToClient(&notify);
284 	}
285 
286 	// resume overlays
287 
288 	for (int32 i = 0; i < fOverlays.CountItems(); i++) {
289 		ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i);
290 
291 		bitmap->Overlay()->Resume(bitmap);
292 	}
293 }
294 
295