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)b - (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 if (ServerBitmap* bitmap = (ServerBitmap*)fBitmapList.ItemAt(i)) { 73 if (bitmap->AllocationCookie() != NULL) 74 debugger("We're not supposed to keep our cookies..."); 75 76 delete bitmap; 77 } 78 } 79 } 80 81 82 /*! \brief Allocates a new ServerBitmap. 83 84 \param bounds Size of the bitmap 85 \param space Color space of the bitmap 86 \param flags Bitmap flags as defined in Bitmap.h 87 \param bytesPerRow Number of bytes per row. 88 \param screen Screen id of the screen associated with it. Unused. 89 \return A new ServerBitmap or NULL if unable to allocate one. 90 */ 91 ServerBitmap* 92 BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, 93 HWInterface& hwInterface, BRect bounds, color_space space, uint32 flags, 94 int32 bytesPerRow, int32 screen, uint8* _allocationFlags) 95 { 96 BAutolock locker(fLock); 97 98 if (!locker.IsLocked()) 99 return NULL; 100 101 overlay_token overlayToken = NULL; 102 103 if (flags & B_BITMAP_WILL_OVERLAY) { 104 if (!hwInterface.CheckOverlayRestrictions(bounds.IntegerWidth() + 1, 105 bounds.IntegerHeight() + 1, space)) 106 return NULL; 107 108 if (flags & B_BITMAP_RESERVE_OVERLAY_CHANNEL) { 109 overlayToken = hwInterface.AcquireOverlayChannel(); 110 if (overlayToken == NULL) 111 return NULL; 112 } 113 } 114 115 ServerBitmap* bitmap = new(nothrow) ServerBitmap(bounds, space, flags, 116 bytesPerRow); 117 if (bitmap == NULL) { 118 if (overlayToken != NULL) 119 hwInterface.ReleaseOverlayChannel(overlayToken); 120 121 return NULL; 122 } 123 124 void* cookie = NULL; 125 uint8* buffer = NULL; 126 127 if (flags & B_BITMAP_WILL_OVERLAY) { 128 Overlay* overlay = new (std::nothrow) Overlay(hwInterface, bitmap, 129 overlayToken); 130 131 overlay_client_data* clientData = NULL; 132 bool newArea = false; 133 134 if (overlay != NULL && overlay->InitCheck() == B_OK) { 135 // allocate client memory to communicate the overlay semaphore 136 // and buffer location to the BBitmap 137 cookie = allocator->Allocate(sizeof(overlay_client_data), 138 (void**)&clientData, newArea); 139 } 140 141 if (cookie != NULL) { 142 overlay->SetClientData(clientData); 143 144 bitmap->fAllocator = allocator; 145 bitmap->fAllocationCookie = cookie; 146 bitmap->SetOverlay(overlay); 147 bitmap->fBytesPerRow = overlay->OverlayBuffer()->bytes_per_row; 148 149 buffer = (uint8*)overlay->OverlayBuffer()->buffer; 150 if (_allocationFlags) 151 *_allocationFlags = kFramebuffer | (newArea ? kNewAllocatorArea : 0); 152 } else { 153 delete overlay; 154 allocator->Free(cookie); 155 } 156 } else if (allocator != NULL) { 157 // standard bitmaps 158 bool newArea; 159 cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea); 160 if (cookie != NULL) { 161 bitmap->fAllocator = allocator; 162 bitmap->fAllocationCookie = cookie; 163 164 if (_allocationFlags) 165 *_allocationFlags = kAllocator | (newArea ? kNewAllocatorArea : 0); 166 } 167 } else { 168 // server side only bitmaps 169 buffer = (uint8*)malloc(bitmap->BitsLength()); 170 if (buffer != NULL) { 171 bitmap->fAllocator = NULL; 172 bitmap->fAllocationCookie = NULL; 173 174 if (_allocationFlags) 175 *_allocationFlags = kHeap; 176 } 177 } 178 179 bool success = false; 180 if (buffer != NULL) { 181 success = fBitmapList.AddItem(bitmap); 182 if (success && bitmap->Overlay() != NULL) { 183 success = fOverlays.AddItem(bitmap); 184 if (!success) 185 fBitmapList.RemoveItem(bitmap); 186 } 187 } 188 189 if (success) { 190 bitmap->fBuffer = buffer; 191 bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap); 192 // NOTE: the client handles clearing to white in case the flags 193 // indicate this is needed 194 } else { 195 // Allocation failed for buffer or bitmap list 196 delete bitmap; 197 bitmap = NULL; 198 } 199 200 return bitmap; 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 212 // it yet 213 return; 214 } 215 216 BAutolock locker(fLock); 217 if (!locker.IsLocked()) 218 return; 219 220 if (bitmap->Overlay() != NULL) 221 fOverlays.RemoveItem(bitmap); 222 223 if (fBitmapList.RemoveItem(bitmap)) 224 delete bitmap; 225 } 226 227 228 void 229 BitmapManager::SuspendOverlays() 230 { 231 BAutolock locker(fLock); 232 if (!locker.IsLocked()) 233 return; 234 235 // first, tell all applications owning an overlay to release their locks 236 237 BObjectList<ServerApp> apps; 238 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 239 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 240 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 241 } 242 for (int32 i = 0; i < apps.CountItems(); i++) { 243 BMessage notify(B_RELEASE_OVERLAY_LOCK); 244 apps.ItemAt(i)->SendMessageToClient(¬ify); 245 } 246 247 // suspend overlays 248 249 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 250 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 251 bitmap->Overlay()->Suspend(bitmap, false); 252 } 253 } 254 255 256 void 257 BitmapManager::ResumeOverlays() 258 { 259 BAutolock locker(fLock); 260 if (!locker.IsLocked()) 261 return; 262 263 // first, tell all applications owning an overlay that 264 // they can reacquire their locks 265 266 BObjectList<ServerApp> apps; 267 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 268 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 269 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 270 } 271 for (int32 i = 0; i < apps.CountItems(); i++) { 272 BMessage notify(B_RELEASE_OVERLAY_LOCK); 273 apps.ItemAt(i)->SendMessageToClient(¬ify); 274 } 275 276 // resume overlays 277 278 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 279 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 280 281 bitmap->Overlay()->Resume(bitmap); 282 } 283 } 284 285