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