1 /* 2 * Copyright 2001-2007, 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 <string.h> 39 40 using std::nothrow; 41 42 43 //! The one and only bitmap manager for the server, created by the AppServer 44 BitmapManager *gBitmapManager = NULL; 45 46 47 int 48 compare_app_pointer(const ServerApp* a, const ServerApp* b) 49 { 50 return (addr_t)b - (addr_t)b; 51 } 52 53 54 // #pragma mark - 55 56 57 //! Sets up stuff to be ready to allocate space for bitmaps 58 BitmapManager::BitmapManager() 59 : 60 fBitmapList(1024), 61 fLock("BitmapManager Lock") 62 { 63 } 64 65 66 //! Deallocates everything associated with the manager 67 BitmapManager::~BitmapManager() 68 { 69 int32 count = fBitmapList.CountItems(); 70 for (int32 i = 0; i < count; i++) { 71 if (ServerBitmap* bitmap = (ServerBitmap*)fBitmapList.ItemAt(i)) { 72 if (bitmap->AllocationCookie() != NULL) 73 debugger("We're not supposed to keep our cookies..."); 74 75 delete bitmap; 76 } 77 } 78 } 79 80 81 /*! 82 \brief Allocates a new ServerBitmap. 83 \param bounds Size of the bitmap 84 \param space Color space of the bitmap 85 \param flags Bitmap flags as defined in Bitmap.h 86 \param bytesPerRow Number of bytes per row. 87 \param screen Screen id of the screen associated with it. Unused. 88 \return A new ServerBitmap or NULL if unable to allocate one. 89 */ 90 ServerBitmap* 91 BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, 92 HWInterface& hwInterface, BRect bounds, color_space space, int32 flags, 93 int32 bytesPerRow, screen_id screen, uint8* _allocationFlags) 94 { 95 BAutolock locker(fLock); 96 97 if (!locker.IsLocked()) 98 return NULL; 99 100 overlay_token overlayToken = NULL; 101 102 if (flags & B_BITMAP_WILL_OVERLAY) { 103 if (!hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1, 104 bounds.IntegerHeight() + 1, space)) 105 return NULL; 106 107 if (flags & B_BITMAP_RESERVE_OVERLAY_CHANNEL) { 108 overlayToken = hwInterface.AcquireOverlayChannel(); 109 if (overlayToken == NULL) 110 return NULL; 111 } 112 } 113 114 ServerBitmap* bitmap = new(nothrow) ServerBitmap(bounds, space, flags, 115 bytesPerRow); 116 if (bitmap == NULL) { 117 if (overlayToken != NULL) 118 hwInterface.ReleaseOverlayChannel(overlayToken); 119 120 return NULL; 121 } 122 123 void* cookie = NULL; 124 uint8* buffer = NULL; 125 126 if (flags & B_BITMAP_WILL_OVERLAY) { 127 Overlay* overlay = new (std::nothrow) Overlay(hwInterface, bitmap, 128 overlayToken); 129 130 overlay_client_data* clientData = NULL; 131 bool newArea = false; 132 133 if (overlay != NULL && overlay->InitCheck() == B_OK) { 134 // allocate client memory to communicate the overlay semaphore 135 // and buffer location to the BBitmap 136 cookie = allocator->Allocate(sizeof(overlay_client_data), 137 (void**)&clientData, newArea); 138 } 139 140 if (cookie != NULL) { 141 overlay->SetClientData(clientData); 142 143 bitmap->fAllocator = allocator; 144 bitmap->fAllocationCookie = cookie; 145 bitmap->SetOverlay(overlay); 146 bitmap->fBytesPerRow = overlay->OverlayBuffer()->bytes_per_row; 147 148 buffer = (uint8*)overlay->OverlayBuffer()->buffer; 149 if (_allocationFlags) 150 *_allocationFlags = kFramebuffer | (newArea ? kNewAllocatorArea : 0); 151 } else { 152 delete overlay; 153 allocator->Free(cookie); 154 } 155 } else if (allocator != NULL) { 156 // standard bitmaps 157 bool newArea; 158 cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea); 159 if (cookie != NULL) { 160 bitmap->fAllocator = allocator; 161 bitmap->fAllocationCookie = cookie; 162 163 if (_allocationFlags) 164 *_allocationFlags = kAllocator | (newArea ? kNewAllocatorArea : 0); 165 } 166 } else { 167 // server side only bitmaps 168 buffer = (uint8*)malloc(bitmap->BitsLength()); 169 if (buffer != NULL) { 170 bitmap->fAllocator = NULL; 171 bitmap->fAllocationCookie = NULL; 172 173 if (_allocationFlags) 174 *_allocationFlags = kHeap; 175 } 176 } 177 178 bool success = false; 179 if (buffer != NULL) { 180 success = fBitmapList.AddItem(bitmap); 181 if (success && bitmap->Overlay() != NULL) { 182 success = fOverlays.AddItem(bitmap); 183 if (!success) 184 fBitmapList.RemoveItem(bitmap); 185 } 186 } 187 188 if (success) { 189 bitmap->fBuffer = buffer; 190 bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap); 191 192 if (flags & B_BITMAP_CLEAR_TO_WHITE) { 193 if (space == B_CMAP8) { 194 // "255" is the "transparent magic" index for B_CMAP8 bitmaps 195 memset(bitmap->Bits(), 65, bitmap->BitsLength()); 196 } else { 197 // should work for most colorspaces 198 memset(bitmap->Bits(), 0xff, bitmap->BitsLength()); 199 } 200 } 201 } else { 202 // Allocation failed for buffer or bitmap list 203 delete bitmap; 204 bitmap = NULL; 205 } 206 207 return bitmap; 208 } 209 210 211 /*! 212 \brief Deletes a ServerBitmap. 213 \param bitmap The bitmap to delete 214 */ 215 void 216 BitmapManager::DeleteBitmap(ServerBitmap* bitmap) 217 { 218 if (bitmap == NULL || !bitmap->_Release()) { 219 // there are other references to this bitmap, we don't have to delete it yet 220 return; 221 } 222 223 BAutolock locker(fLock); 224 if (!locker.IsLocked()) 225 return; 226 227 if (bitmap->Overlay() != NULL) 228 fOverlays.AddItem(bitmap); 229 230 if (fBitmapList.RemoveItem(bitmap)) 231 delete bitmap; 232 } 233 234 235 void 236 BitmapManager::SuspendOverlays() 237 { 238 BAutolock locker(fLock); 239 if (!locker.IsLocked()) 240 return; 241 242 // first, tell all applications owning an overlay to release their locks 243 244 BObjectList<ServerApp> apps; 245 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 246 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 247 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 248 } 249 for (int32 i = 0; i < apps.CountItems(); i++) { 250 BMessage notify(B_RELEASE_OVERLAY_LOCK); 251 apps.ItemAt(i)->SendMessageToClient(¬ify); 252 } 253 254 // suspend overlays 255 256 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 257 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 258 bitmap->Overlay()->Suspend(bitmap, false); 259 } 260 } 261 262 263 void 264 BitmapManager::ResumeOverlays() 265 { 266 BAutolock locker(fLock); 267 if (!locker.IsLocked()) 268 return; 269 270 // first, tell all applications owning an overlay that 271 // they can reacquire their locks 272 273 BObjectList<ServerApp> apps; 274 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 275 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 276 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 277 } 278 for (int32 i = 0; i < apps.CountItems(); i++) { 279 BMessage notify(B_RELEASE_OVERLAY_LOCK); 280 apps.ItemAt(i)->SendMessageToClient(¬ify); 281 } 282 283 // resume overlays 284 285 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 286 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 287 288 bitmap->Overlay()->Resume(bitmap); 289 } 290 } 291 292