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