diff --git a/headers/os/interface/Bitmap.h b/headers/os/interface/Bitmap.h index 1800a622bc..872a30ec3b 100644 --- a/headers/os/interface/Bitmap.h +++ b/headers/os/interface/Bitmap.h @@ -56,6 +56,11 @@ public: BBitmap(const BBitmap* source, bool acceptsViews = false, bool needsContiguous = false); + BBitmap(area_id area, ptrdiff_t areaOffset, + BRect bounds, uint32 flags, + color_space colorSpace, + int32 bytesPerRow = B_ANY_BYTES_PER_ROW, + screen_id screenID = B_MAIN_SCREEN_ID); virtual ~BBitmap(); // Archiving @@ -133,7 +138,9 @@ private: int32 _ServerToken() const; void _InitObject(BRect bounds, color_space colorSpace, uint32 flags, - int32 bytesPerRow, screen_id screenID); + int32 bytesPerRow, screen_id screenID, + area_id area = -1, + ptrdiff_t areaOffset = 0); void _CleanUp(); void _AssertPointer(); diff --git a/src/kits/interface/Bitmap.cpp b/src/kits/interface/Bitmap.cpp index 7eeb685788..8f826daa9f 100644 --- a/src/kits/interface/Bitmap.cpp +++ b/src/kits/interface/Bitmap.cpp @@ -308,6 +308,28 @@ BBitmap::BBitmap(const BBitmap& source) } +BBitmap::BBitmap(area_id area, ptrdiff_t areaOffset, BRect bounds, + uint32 flags, color_space colorSpace, int32 bytesPerRow, + screen_id screenID) + : + fBasePointer(NULL), + fSize(0), + fColorSpace(B_NO_COLOR_SPACE), + fBounds(0, 0, -1, -1), + fBytesPerRow(0), + fWindow(NULL), + fServerToken(-1), + fAreaOffset(-1), + fArea(-1), + fServerArea(-1), + fFlags(0), + fInitError(B_NO_INIT) +{ + _InitObject(bounds, colorSpace, flags, + bytesPerRow, screenID, area, areaOffset); +} + + /*! \brief Frees all resources associated with this object. */ BBitmap::~BBitmap() @@ -1017,7 +1039,7 @@ BBitmap::_ServerToken() const */ void BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags, - int32 bytesPerRow, screen_id screenID) + int32 bytesPerRow, screen_id screenID, area_id area, ptrdiff_t areaOffset) { //printf("BBitmap::InitObject(bounds: BRect(%.1f, %.1f, %.1f, %.1f), format: %ld, flags: %ld, bpr: %ld\n", // bounds.left, bounds.top, bounds.right, bounds.bottom, colorSpace, flags, bytesPerRow); @@ -1070,63 +1092,104 @@ BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags, } else error = B_NO_MEMORY; } else { - // Ask the server (via our owning application) to create a bitmap. BPrivate::AppServerLink link; + + if (area >= B_OK) { + // Use area provided by client - // Attach Data: - // 1) BRect bounds - // 2) color_space space - // 3) int32 bitmap_flags - // 4) int32 bytes_per_row - // 5) int32 screen_id::id - link.StartMessage(AS_CREATE_BITMAP); - link.Attach(bounds); - link.Attach(colorSpace); - link.Attach(flags); - link.Attach(bytesPerRow); - link.Attach(screenID.id); + area_info info; + get_area_info(area, &info); - if (link.FlushWithReply(error) == B_OK && error == B_OK) { - // server side success - // Get token - link.Read(&fServerToken); - - uint8 allocationFlags; - link.Read(&allocationFlags); - link.Read(&fServerArea); - link.Read(&fAreaOffset); - - BPrivate::ServerMemoryAllocator* allocator - = BApplication::Private::ServerAllocator(); - - if ((allocationFlags & kNewAllocatorArea) != 0) { - error = allocator->AddArea(fServerArea, fArea, - fBasePointer, size); - } else { - error = allocator->AreaAndBaseFor(fServerArea, fArea, - fBasePointer); - if (error == B_OK) - fBasePointer += fAreaOffset; + // Area should be owned by current team. Client should clone area if needed. + if (info.team != getpid()) + error = B_BAD_VALUE; + else { + link.StartMessage(AS_RECONNECT_BITMAP); + link.Attach(bounds); + link.Attach(colorSpace); + link.Attach(flags); + link.Attach(bytesPerRow); + link.Attach(0); + link.Attach(area); + link.Attach(areaOffset); + + if (link.FlushWithReply(error) == B_OK && error == B_OK) { + link.Read(&fServerToken); + link.Read(&fServerArea); + + if (fServerArea >= B_OK) { + fSize = size; + fColorSpace = colorSpace; + fBounds = bounds; + fBytesPerRow = bytesPerRow; + fFlags = flags; + fArea = area; + fAreaOffset = areaOffset; + + fBasePointer = (uint8*)info.address + areaOffset; + } else + error = fServerArea; + } } + } else { + // Ask the server (via our owning application) to create a bitmap. - if ((allocationFlags & kFramebuffer) != 0) { - // The base pointer will now point to an overlay_client_data - // structure bytes per row might be modified to match - // hardware constraints - link.Read(&bytesPerRow); - size = bytesPerRow * (bounds.IntegerHeight() + 1); + // Attach Data: + // 1) BRect bounds + // 2) color_space space + // 3) int32 bitmap_flags + // 4) int32 bytes_per_row + // 5) int32 screen_id::id + link.StartMessage(AS_CREATE_BITMAP); + link.Attach(bounds); + link.Attach(colorSpace); + link.Attach(flags); + link.Attach(bytesPerRow); + link.Attach(screenID.id); + + if (link.FlushWithReply(error) == B_OK && error == B_OK) { + // server side success + // Get token + link.Read(&fServerToken); + + uint8 allocationFlags; + link.Read(&allocationFlags); + link.Read(&fServerArea); + link.Read(&fAreaOffset); + + BPrivate::ServerMemoryAllocator* allocator + = BApplication::Private::ServerAllocator(); + + if ((allocationFlags & kNewAllocatorArea) != 0) { + error = allocator->AddArea(fServerArea, fArea, + fBasePointer, size); + } else { + error = allocator->AreaAndBaseFor(fServerArea, fArea, + fBasePointer); + if (error == B_OK) + fBasePointer += fAreaOffset; + } + + if ((allocationFlags & kFramebuffer) != 0) { + // The base pointer will now point to an overlay_client_data + // structure bytes per row might be modified to match + // hardware constraints + link.Read(&bytesPerRow); + size = bytesPerRow * (bounds.IntegerHeight() + 1); + } + + if (fServerArea >= B_OK) { + fSize = size; + fColorSpace = colorSpace; + fBounds = bounds; + fBytesPerRow = bytesPerRow; + fFlags = flags; + } else + error = fServerArea; } - - if (fServerArea >= B_OK) { - fSize = size; - fColorSpace = colorSpace; - fBounds = bounds; - fBytesPerRow = bytesPerRow; - fFlags = flags; - } else - error = fServerArea; } + if (error < B_OK) { fBasePointer = NULL; fServerToken = -1;