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, uint32 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 // NOTE: the client handles clearing to white in case the flags 192 // indicate this is needed 193 } else { 194 // Allocation failed for buffer or bitmap list 195 delete bitmap; 196 bitmap = NULL; 197 } 198 199 return bitmap; 200 } 201 202 203 /*! 204 \brief Deletes a ServerBitmap. 205 \param bitmap The bitmap to delete 206 */ 207 void 208 BitmapManager::DeleteBitmap(ServerBitmap* bitmap) 209 { 210 if (bitmap == NULL || !bitmap->_Release()) { 211 // there are other references to this bitmap, we don't have to delete it yet 212 return; 213 } 214 215 BAutolock locker(fLock); 216 if (!locker.IsLocked()) 217 return; 218 219 if (bitmap->Overlay() != NULL) 220 fOverlays.AddItem(bitmap); 221 222 if (fBitmapList.RemoveItem(bitmap)) 223 delete bitmap; 224 } 225 226 227 void 228 BitmapManager::SuspendOverlays() 229 { 230 BAutolock locker(fLock); 231 if (!locker.IsLocked()) 232 return; 233 234 // first, tell all applications owning an overlay to release their locks 235 236 BObjectList<ServerApp> apps; 237 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 238 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 239 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 240 } 241 for (int32 i = 0; i < apps.CountItems(); i++) { 242 BMessage notify(B_RELEASE_OVERLAY_LOCK); 243 apps.ItemAt(i)->SendMessageToClient(¬ify); 244 } 245 246 // suspend overlays 247 248 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 249 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 250 bitmap->Overlay()->Suspend(bitmap, false); 251 } 252 } 253 254 255 void 256 BitmapManager::ResumeOverlays() 257 { 258 BAutolock locker(fLock); 259 if (!locker.IsLocked()) 260 return; 261 262 // first, tell all applications owning an overlay that 263 // they can reacquire their locks 264 265 BObjectList<ServerApp> apps; 266 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 267 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 268 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 269 } 270 for (int32 i = 0; i < apps.CountItems(); i++) { 271 BMessage notify(B_RELEASE_OVERLAY_LOCK); 272 apps.ItemAt(i)->SendMessageToClient(¬ify); 273 } 274 275 // resume overlays 276 277 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 278 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 279 280 bitmap->Overlay()->Resume(bitmap); 281 } 282 } 283 284