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 free(buffer); 197 delete bitmap; 198 bitmap = NULL; 199 } 200 201 return bitmap; 202 } 203 204 205 /*! \brief Called when a ServerBitmap is deleted. 206 */ 207 void 208 BitmapManager::BitmapRemoved(ServerBitmap* bitmap) 209 { 210 BAutolock locker(fLock); 211 if (!locker.IsLocked()) 212 return; 213 214 if (bitmap->Overlay() != NULL) 215 fOverlays.RemoveItem(bitmap); 216 217 fBitmapList.RemoveItem(bitmap); 218 } 219 220 221 void 222 BitmapManager::SuspendOverlays() 223 { 224 BAutolock locker(fLock); 225 if (!locker.IsLocked()) 226 return; 227 228 // first, tell all applications owning an overlay to release their locks 229 230 BObjectList<ServerApp> apps; 231 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 232 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 233 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 234 } 235 for (int32 i = 0; i < apps.CountItems(); i++) { 236 BMessage notify(B_RELEASE_OVERLAY_LOCK); 237 apps.ItemAt(i)->SendMessageToClient(¬ify); 238 } 239 240 // suspend overlays 241 242 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 243 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 244 bitmap->Overlay()->Suspend(bitmap, false); 245 } 246 } 247 248 249 void 250 BitmapManager::ResumeOverlays() 251 { 252 BAutolock locker(fLock); 253 if (!locker.IsLocked()) 254 return; 255 256 // first, tell all applications owning an overlay that 257 // they can reacquire their locks 258 259 BObjectList<ServerApp> apps; 260 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 261 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 262 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 263 } 264 for (int32 i = 0; i < apps.CountItems(); i++) { 265 BMessage notify(B_RELEASE_OVERLAY_LOCK); 266 apps.ItemAt(i)->SendMessageToClient(¬ify); 267 } 268 269 // resume overlays 270 271 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 272 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 273 274 bitmap->Overlay()->Resume(bitmap); 275 } 276 } 277 278