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 gTokenSpace.RemoveToken(bitmap->Token()); 232 233 if (bitmap->Overlay() != NULL) 234 fOverlays.RemoveItem(bitmap); 235 236 fBitmapList.RemoveItem(bitmap); 237 } 238 239 240 void 241 BitmapManager::SuspendOverlays() 242 { 243 BAutolock locker(fLock); 244 if (!locker.IsLocked()) 245 return; 246 247 // first, tell all applications owning an overlay to release their locks 248 249 BObjectList<ServerApp> apps; 250 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 251 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 252 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 253 } 254 for (int32 i = 0; i < apps.CountItems(); i++) { 255 BMessage notify(B_RELEASE_OVERLAY_LOCK); 256 apps.ItemAt(i)->SendMessageToClient(¬ify); 257 } 258 259 // suspend overlays 260 261 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 262 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 263 bitmap->Overlay()->Suspend(bitmap, false); 264 } 265 } 266 267 268 void 269 BitmapManager::ResumeOverlays() 270 { 271 BAutolock locker(fLock); 272 if (!locker.IsLocked()) 273 return; 274 275 // first, tell all applications owning an overlay that 276 // they can reacquire their locks 277 278 BObjectList<ServerApp> apps; 279 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 280 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 281 apps.BinaryInsert(bitmap->Owner(), &compare_app_pointer); 282 } 283 for (int32 i = 0; i < apps.CountItems(); i++) { 284 BMessage notify(B_RELEASE_OVERLAY_LOCK); 285 apps.ItemAt(i)->SendMessageToClient(¬ify); 286 } 287 288 // resume overlays 289 290 for (int32 i = 0; i < fOverlays.CountItems(); i++) { 291 ServerBitmap* bitmap = (ServerBitmap*)fOverlays.ItemAt(i); 292 293 bitmap->Overlay()->Resume(bitmap); 294 } 295 } 296 297