1 /* 2 * Copyright 2001-2007, 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 #include "ServerBitmap.h" 12 13 #include <new> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include "ClientMemoryAllocator.h" 19 #include "ColorConversion.h" 20 #include "HWInterface.h" 21 #include "Overlay.h" 22 23 using std::nothrow; 24 25 /*! 26 A word about memory housekeeping and why it's implemented this way: 27 28 The reason why this looks so complicated is to optimize the most common 29 path (bitmap creation from the application), and don't cause any further 30 memory allocations for maintaining memory in that case. 31 If a bitmap was allocated this way, both, the fAllocator and fAllocationCookie 32 members are used. 33 34 For overlays, the allocator only allocates a small piece of client memory 35 for use with the overlay_client_data structure - the actual buffer will be 36 placed in the graphics frame buffer and is allocated by the graphics driver. 37 38 If the memory was allocated on the app_server heap, neither fAllocator, nor 39 fAllocationCookie are used, and the buffer is just freed in that case when 40 the bitmap is destructed. This method is mainly used for cursors. 41 */ 42 43 44 /*! 45 \brief Constructor called by the BitmapManager (only). 46 \param rect Size of the bitmap. 47 \param space Color space of the bitmap 48 \param flags Various bitmap flags to tweak the bitmap as defined in Bitmap.h 49 \param bytesperline Number of bytes in each row. -1 implies the default value. Any 50 value less than the the default will less than the default will be overridden, but any value 51 greater than the default will result in the number of bytes specified. 52 \param screen Screen assigned to the bitmap. 53 */ 54 ServerBitmap::ServerBitmap(BRect rect, color_space space, uint32 flags, 55 int32 bytesPerRow, screen_id screen) 56 : 57 fAllocator(NULL), 58 fAllocationCookie(NULL), 59 fOverlay(NULL), 60 fBuffer(NULL), 61 fReferenceCount(1), 62 // WARNING: '1' is added to the width and height. 63 // Same is done in FBBitmap subclass, so if you 64 // modify here make sure to do the same under 65 // FBBitmap::SetSize(...) 66 fWidth(rect.IntegerWidth() + 1), 67 fHeight(rect.IntegerHeight() + 1), 68 fBytesPerRow(0), 69 fSpace(space), 70 fFlags(flags), 71 fBitsPerPixel(0), 72 fOwner(NULL) 73 // fToken is initialized (if used) by the BitmapManager 74 { 75 _HandleSpace(space, bytesPerRow); 76 } 77 78 79 //! Copy constructor does not copy the buffer. 80 ServerBitmap::ServerBitmap(const ServerBitmap* bitmap) 81 : 82 fAllocator(NULL), 83 fAllocationCookie(NULL), 84 fOverlay(NULL), 85 fBuffer(NULL), 86 fReferenceCount(1) 87 { 88 if (bitmap) { 89 fWidth = bitmap->fWidth; 90 fHeight = bitmap->fHeight; 91 fBytesPerRow = bitmap->fBytesPerRow; 92 fSpace = bitmap->fSpace; 93 fFlags = bitmap->fFlags; 94 fBitsPerPixel = bitmap->fBitsPerPixel; 95 fOwner = bitmap->fOwner; 96 } else { 97 fWidth = 0; 98 fHeight = 0; 99 fBytesPerRow = 0; 100 fSpace = B_NO_COLOR_SPACE; 101 fFlags = 0; 102 fBitsPerPixel = 0; 103 fOwner = NULL; 104 } 105 } 106 107 108 ServerBitmap::~ServerBitmap() 109 { 110 if (fAllocator != NULL) 111 fAllocator->Free(AllocationCookie()); 112 else 113 free(fBuffer); 114 115 delete fOverlay; 116 // deleting the overlay will also free the overlay buffer 117 } 118 119 120 void 121 ServerBitmap::Acquire() 122 { 123 atomic_add(&fReferenceCount, 1); 124 } 125 126 127 bool 128 ServerBitmap::_Release() 129 { 130 if (atomic_add(&fReferenceCount, -1) == 1) 131 return true; 132 133 return false; 134 } 135 136 137 /*! 138 \brief Internal function used by subclasses 139 140 Subclasses should call this so the buffer can automagically 141 be allocated on the heap. 142 */ 143 void 144 ServerBitmap::_AllocateBuffer(void) 145 { 146 uint32 length = BitsLength(); 147 if (length > 0) { 148 delete[] fBuffer; 149 fBuffer = new(nothrow) uint8[length]; 150 } 151 } 152 153 154 /*! 155 \brief Internal function used to translate color space values to appropriate internal 156 values. 157 \param space Color space for the bitmap. 158 \param bytesPerRow Number of bytes per row to be used as an override. 159 */ 160 void 161 ServerBitmap::_HandleSpace(color_space space, int32 bytesPerRow) 162 { 163 // calculate the minimum bytes per row 164 // set fBitsPerPixel 165 int32 minBPR = 0; 166 switch(space) { 167 // 32-bit 168 case B_RGB32: 169 case B_RGBA32: 170 case B_RGB32_BIG: 171 case B_RGBA32_BIG: 172 case B_UVL32: 173 case B_UVLA32: 174 case B_LAB32: 175 case B_LABA32: 176 case B_HSI32: 177 case B_HSIA32: 178 case B_HSV32: 179 case B_HSVA32: 180 case B_HLS32: 181 case B_HLSA32: 182 case B_CMY32: 183 case B_CMYA32: 184 case B_CMYK32: 185 minBPR = fWidth * 4; 186 fBitsPerPixel = 32; 187 break; 188 189 // 24-bit 190 case B_RGB24_BIG: 191 case B_RGB24: 192 case B_LAB24: 193 case B_UVL24: 194 case B_HSI24: 195 case B_HSV24: 196 case B_HLS24: 197 case B_CMY24: 198 // TODO: These last two are calculated 199 // (width + 3) / 4 * 12 200 // in Bitmap.cpp, I don't understand why though. 201 case B_YCbCr444: 202 case B_YUV444: 203 minBPR = fWidth * 3; 204 fBitsPerPixel = 24; 205 break; 206 207 // 16-bit 208 case B_YUV9: 209 case B_YUV12: 210 case B_RGB15: 211 case B_RGBA15: 212 case B_RGB16: 213 case B_RGB16_BIG: 214 case B_RGB15_BIG: 215 case B_RGBA15_BIG: 216 minBPR = fWidth * 2; 217 fBitsPerPixel = 16; 218 break; 219 220 case B_YCbCr422: 221 case B_YUV422: 222 minBPR = (fWidth + 3) / 4 * 8; 223 // TODO: huh? why not simply fWidth * 2 ?!? 224 fBitsPerPixel = 16; 225 break; 226 227 // 8-bit 228 case B_CMAP8: 229 case B_GRAY8: 230 minBPR = fWidth; 231 fBitsPerPixel = 8; 232 break; 233 234 // 1-bit 235 case B_GRAY1: 236 minBPR = (fWidth + 7) / 8; 237 fBitsPerPixel = 1; 238 break; 239 240 // TODO: ??? get a clue what these mean 241 case B_YCbCr411: 242 case B_YUV411: 243 case B_YUV420: 244 case B_YCbCr420: 245 minBPR = (fWidth + 3) / 4 * 6; 246 fBitsPerPixel = 0; 247 break; 248 249 case B_NO_COLOR_SPACE: 250 default: 251 fBitsPerPixel = 0; 252 break; 253 } 254 if (minBPR > 0 || bytesPerRow > 0) { 255 // add the padding or use the provided bytesPerRow if sufficient 256 if (bytesPerRow >= minBPR) 257 fBytesPerRow = bytesPerRow; 258 else 259 fBytesPerRow = ((minBPR + 3) / 4) * 4; 260 } 261 } 262 263 264 status_t 265 ServerBitmap::ImportBits(const void *bits, int32 bitsLength, int32 bytesPerRow, 266 color_space colorSpace) 267 { 268 if (!bits || bitsLength < 0 || bytesPerRow <= 0) 269 return B_BAD_VALUE; 270 271 return BPrivate::ConvertBits(bits, fBuffer, bitsLength, BitsLength(), 272 bytesPerRow, fBytesPerRow, colorSpace, fSpace, fWidth, fHeight); 273 } 274 275 276 status_t 277 ServerBitmap::ImportBits(const void *bits, int32 bitsLength, int32 bytesPerRow, 278 color_space colorSpace, BPoint from, BPoint to, int32 width, int32 height) 279 { 280 if (!bits || bitsLength < 0 || bytesPerRow <= 0 || width < 0 || height < 0) 281 return B_BAD_VALUE; 282 283 return BPrivate::ConvertBits(bits, fBuffer, bitsLength, BitsLength(), 284 bytesPerRow, fBytesPerRow, colorSpace, fSpace, from, to, width, 285 height); 286 } 287 288 289 area_id 290 ServerBitmap::Area() const 291 { 292 if (fAllocator != NULL) 293 return fAllocator->Area(AllocationCookie()); 294 295 return B_ERROR; 296 } 297 298 299 uint32 300 ServerBitmap::AreaOffset() const 301 { 302 if (fAllocator != NULL) 303 return fAllocator->AreaOffset(AllocationCookie()); 304 305 return 0; 306 } 307 308 309 void 310 ServerBitmap::SetOverlay(::Overlay* overlay) 311 { 312 fOverlay = overlay; 313 } 314 315 316 ::Overlay* 317 ServerBitmap::Overlay() const 318 { 319 return fOverlay; 320 } 321 322 323 void 324 ServerBitmap::SetOwner(ServerApp* owner) 325 { 326 fOwner = owner; 327 } 328 329 330 ServerApp* 331 ServerBitmap::Owner() const 332 { 333 return fOwner; 334 } 335 336 337 void 338 ServerBitmap::PrintToStream() 339 { 340 printf("Bitmap@%p: (%ld:%ld), space %ld, bpr %ld, buffer %p\n", 341 this, fWidth, fHeight, (int32)fSpace, fBytesPerRow, fBuffer); 342 } 343 344 345 // #pragma mark - 346 347 348 UtilityBitmap::UtilityBitmap(BRect rect, color_space space, uint32 flags, 349 int32 bytesperline, screen_id screen) 350 : ServerBitmap(rect, space, flags, bytesperline, screen) 351 { 352 _AllocateBuffer(); 353 } 354 355 356 UtilityBitmap::UtilityBitmap(const ServerBitmap* bitmap) 357 : ServerBitmap(bitmap) 358 { 359 _AllocateBuffer(); 360 361 if (bitmap->Bits()) 362 memcpy(Bits(), bitmap->Bits(), bitmap->BitsLength()); 363 } 364 365 366 UtilityBitmap::UtilityBitmap(const uint8* alreadyPaddedData, uint32 width, 367 uint32 height, color_space format) 368 : ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0) 369 { 370 _AllocateBuffer(); 371 if (Bits()) 372 memcpy(Bits(), alreadyPaddedData, BitsLength()); 373 } 374 375 376 UtilityBitmap::~UtilityBitmap() 377 { 378 } 379