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