From 21c8c925d834845b599781b72192b10befc68ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Sat, 22 Apr 2006 16:41:12 +0000 Subject: [PATCH] * With Rudolf's information about relocating overlays, I changed the way memory is managed for those bitmaps: - the shared client memory mechanism is used to allocate a small overlay_client_data structure that contains the actual buffer and a semaphore that you have acquire in order to access it. - LockBits()/UnlockBits() now have a function: you need to call them before accessing the overlay buffer, and you need to keep that lock until you're done with it. * The overlay cookie is now an extra member of the ServerBitmap class. * Removed fInitialized from ServerBitmap - IsValid() now just checks the buffer associated with the bitmap. * ViewLayer::Draw() will now handle overlay bitmaps specially and will draw the overlay color instead of any contents (this is currently in ugly pink, but will become some dark color later on). * All what's missing from actually being able to use overlays now is to configure them so that they are shown on screen. VLC will now show an empty pink window when overlay video is enabled. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17201 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/app/ServerProtocol.h | 10 +-- headers/private/interface/BitmapPrivate.h | 19 ++++ src/kits/interface/Bitmap.cpp | 83 +++++++++++------ src/servers/app/BitmapManager.cpp | 54 ++++++----- src/servers/app/BitmapManager.h | 2 +- src/servers/app/RGBColor.h | 8 +- src/servers/app/ServerApp.cpp | 18 ++-- src/servers/app/ServerBitmap.cpp | 104 ++++++++++++++-------- src/servers/app/ServerBitmap.h | 33 +++++-- src/servers/app/ServerCursor.cpp | 3 - src/servers/app/ViewLayer.cpp | 17 ++-- 11 files changed, 229 insertions(+), 122 deletions(-) create mode 100644 headers/private/interface/BitmapPrivate.h diff --git a/headers/private/app/ServerProtocol.h b/headers/private/app/ServerProtocol.h index 6b0b5d2c74..a5de756c55 100644 --- a/headers/private/app/ServerProtocol.h +++ b/headers/private/app/ServerProtocol.h @@ -332,12 +332,12 @@ enum cursor_which { B_CURSOR_INVALID }; -// bitmap allocation types +// bitmap allocation flags enum { - kAllocator, - kNewAllocatorArea, - kFramebuffer, - kHeap + kAllocator = 0x1, + kFramebuffer = 0x2, + kHeap = 0x4, + kNewAllocatorArea = 0x8, }; #endif // APP_SERVER_PROTOCOL_H diff --git a/headers/private/interface/BitmapPrivate.h b/headers/private/interface/BitmapPrivate.h new file mode 100644 index 0000000000..a91f76fe89 --- /dev/null +++ b/headers/private/interface/BitmapPrivate.h @@ -0,0 +1,19 @@ +/* + * Copyright 2006, Haiku, Inc. + * Distributed under the terms of the MIT License. + */ +#ifndef _BITMAP_PRIVATE_H +#define _BITMAP_PRIVATE_H + + +#include + + +// This structure is placed in the client/server shared memory area. + +struct overlay_client_data { + sem_id lock; + uint8* buffer; +}; + +#endif // _BITMAP_PRIVATE_H diff --git a/src/kits/interface/Bitmap.cpp b/src/kits/interface/Bitmap.cpp index 8b3c49ae8a..66035e3192 100644 --- a/src/kits/interface/Bitmap.cpp +++ b/src/kits/interface/Bitmap.cpp @@ -15,6 +15,7 @@ */ #include "ColorConversion.h" +#include "BitmapPrivate.h" #include #include @@ -360,23 +361,50 @@ BBitmap::IsValid() const return (InitCheck() == B_OK); } -// LockBits -/*! \brief ??? + +/*! + \brief Locks the bitmap bits so that they cannot be relocated. + + This is currently only used for overlay bitmaps - whenever you + need to access their Bits(), you have to lock them first. + On resolution change overlay bitmaps can be relocated in memory; + using this call prevents you from accessing an invalid pointer + and clobbering memory that doesn't belong you. */ status_t BBitmap::LockBits(uint32 *state) { + if (fFlags & B_BITMAP_WILL_OVERLAY) { + overlay_client_data* data = (overlay_client_data*)fBasePointer; + + status_t status; + do { + status = acquire_sem(data->lock); + } while (status == B_INTERRUPTED); + + return status; + } + // NOTE: maybe this is used to prevent the app_server from // drawing the bitmap yet? + // axeld: you mean for non overlays? + return B_ERROR; } -// UnlockBits -/*! \brief ??? + +/*! + \brief Unlocks the bitmap's buffer again. + Counterpart to LockBits(), see there for comments. */ void BBitmap::UnlockBits() { + if ((fFlags & B_BITMAP_WILL_OVERLAY) == 0) + return; + + overlay_client_data* data = (overlay_client_data*)fBasePointer; + release_sem(data->lock); } // Area @@ -390,7 +418,7 @@ BBitmap::Area() const return fArea; } -// Bits + /*! \brief Returns the pointer to the bitmap data. \return The pointer to the bitmap data. */ @@ -398,6 +426,12 @@ void * BBitmap::Bits() const { const_cast(this)->_AssertPointer(); + + if (fFlags & B_BITMAP_WILL_OVERLAY) { + overlay_client_data* data = (overlay_client_data*)fBasePointer; + return data->buffer; + } + return (void*)fBasePointer; } @@ -925,29 +959,26 @@ BBitmap::_InitObject(BRect bounds, color_space colorSpace, uint32 flags, // Get token link.Read(&fServerToken); - int8 allocationType; - link.Read(&allocationType); + uint8 allocationFlags; + link.Read(&allocationFlags); + link.Read(&fServerArea); + link.Read(&fAreaOffset); - if (allocationType == kFramebuffer) { - link.Read((addr_t*)&fBasePointer); + BPrivate::ServerMemoryAllocator* allocator + = BApplication::Private::ServerAllocator(); + + if (allocationFlags & kNewAllocatorArea) + error = allocator->AddArea(fServerArea, fArea, fBasePointer); + else { + error = allocator->AreaAndBaseFor(fServerArea, fArea, fBasePointer); + if (error == B_OK) + fBasePointer += fAreaOffset; + } + + if (allocationFlags & kFramebuffer) { + // the base pointer will now point to an overlay_client_data structure link.Read(&fBytesPerRow); - - fServerArea = B_ERROR; - fAreaOffset = 0; - } else { - link.Read(&fServerArea); - link.Read(&fAreaOffset); - - BPrivate::ServerMemoryAllocator* allocator - = BApplication::Private::ServerAllocator(); - - if (allocationType == kNewAllocatorArea) - error = allocator->AddArea(fServerArea, fArea, fBasePointer); - else { - error = allocator->AreaAndBaseFor(fServerArea, fArea, fBasePointer); - if (error == B_OK) - fBasePointer += fAreaOffset; - } + size = fBytesPerRow * (bounds.IntegerHeight() + 1); } if (fServerArea >= B_OK) { diff --git a/src/servers/app/BitmapManager.cpp b/src/servers/app/BitmapManager.cpp index fb11dffd9b..df2cadf93a 100644 --- a/src/servers/app/BitmapManager.cpp +++ b/src/servers/app/BitmapManager.cpp @@ -4,12 +4,10 @@ * * Authors: * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de */ /*! - Handler for allocating and freeing area memory for BBitmaps - on the server side. Utilizes the BGET pool allocator. - Whenever a ServerBitmap associated with a client-side BBitmap needs to be created or destroyed, the BitmapManager needs to handle it. It takes care of all memory management related to them. @@ -24,6 +22,7 @@ #include "ServerProtocol.h" #include "ServerTokenSpace.h" +#include #include #include @@ -79,7 +78,7 @@ BitmapManager::~BitmapManager() ServerBitmap* BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, HWInterface& hwInterface, BRect bounds, color_space space, int32 flags, int32 bytesPerRow, screen_id screen, - int8* _allocationType) + uint8* _allocationFlags) { BAutolock locker(fLock); @@ -113,60 +112,73 @@ BitmapManager::CreateBitmap(ClientMemoryAllocator* allocator, HWInterface& hwInt if (flags & B_BITMAP_WILL_OVERLAY) { OverlayCookie* overlayCookie = new (std::nothrow) OverlayCookie(hwInterface); - const overlay_buffer* overlayBuffer = NULL; - if (overlayCookie != NULL) { - overlayBuffer = hwInterface.AllocateOverlayBuffer(bitmap->Width(), - bitmap->Height(), space); + const overlay_buffer* overlayBuffer = NULL; + overlay_client_data* clientData = NULL; + bool newArea = false; + + if (overlayCookie != NULL && overlayCookie->InitCheck() == B_OK) { + // allocate client memory to communicate the overlay semaphore + // and buffer location to the BBitmap + cookie = allocator->Allocate(sizeof(overlay_client_data), + (void**)&clientData, newArea); + if (cookie != NULL) { + overlayBuffer = hwInterface.AllocateOverlayBuffer(bitmap->Width(), + bitmap->Height(), space); + } } if (overlayBuffer != NULL) { - overlayCookie->SetOverlayBuffer(overlayBuffer); - overlayCookie->SetOverlayToken(overlayToken); + overlayCookie->SetOverlayData(overlayBuffer, overlayToken, clientData); - bitmap->fAllocationCookie = overlayCookie; + bitmap->fAllocator = allocator; + bitmap->fAllocationCookie = cookie; + bitmap->SetOverlayCookie(overlayCookie); bitmap->fBytesPerRow = overlayBuffer->bytes_per_row; buffer = (uint8*)overlayBuffer->buffer; - if (_allocationType) - *_allocationType = kFramebuffer; + if (_allocationFlags) + *_allocationFlags = kFramebuffer | (newArea ? kNewAllocatorArea : 0); } else { hwInterface.ReleaseOverlayChannel(overlayToken); delete overlayCookie; + allocator->Free(cookie); } } else if (allocator != NULL) { + // standard bitmaps bool newArea; cookie = allocator->Allocate(bitmap->BitsLength(), (void**)&buffer, newArea); if (cookie != NULL) { bitmap->fAllocator = allocator; bitmap->fAllocationCookie = cookie; - if (_allocationType) - *_allocationType = newArea ? kNewAllocatorArea : kAllocator; + if (_allocationFlags) + *_allocationFlags = kAllocator | (newArea ? kNewAllocatorArea : 0); } } else { + // server side only bitmaps buffer = (uint8*)malloc(bitmap->BitsLength()); if (buffer != NULL) { bitmap->fAllocator = NULL; bitmap->fAllocationCookie = NULL; - if (_allocationType) - *_allocationType = kHeap; + if (_allocationFlags) + *_allocationFlags = kHeap; } } if (buffer && fBitmapList.AddItem(bitmap)) { bitmap->fBuffer = buffer; bitmap->fToken = gTokenSpace.NewToken(kBitmapToken, bitmap); - bitmap->fInitialized = true; if (flags & B_BITMAP_CLEAR_TO_WHITE) { - if (space == B_CMAP8) + if (space == B_CMAP8) { // "255" is the "transparent magic" index for B_CMAP8 bitmaps memset(bitmap->Bits(), 65, bitmap->BitsLength()); - else + } else { // should work for most colorspaces - memset(bitmap->Bits(), 255, bitmap->BitsLength()); + memset(bitmap->Bits(), 0xff, bitmap->BitsLength()); + } } } else { // Allocation failed for buffer or bitmap list diff --git a/src/servers/app/BitmapManager.h b/src/servers/app/BitmapManager.h index dc68e16562..62e0000da0 100644 --- a/src/servers/app/BitmapManager.h +++ b/src/servers/app/BitmapManager.h @@ -28,7 +28,7 @@ class BitmapManager { HWInterface& hwInterface, BRect bounds, color_space space, int32 flags, int32 bytesPerRow = -1, screen_id screen = B_MAIN_SCREEN_ID, - int8* _allocationType = NULL); + uint8* _allocationFlags = NULL); void DeleteBitmap(ServerBitmap* bitmap); protected: diff --git a/src/servers/app/RGBColor.h b/src/servers/app/RGBColor.h index 240757e2ae..7bcfeaa7d2 100644 --- a/src/servers/app/RGBColor.h +++ b/src/servers/app/RGBColor.h @@ -14,8 +14,8 @@ class RGBColor { public: - RGBColor(uint8 r, uint8 g, uint8 b, uint8 a=255); - RGBColor(int r, int g, int b, int a=255); + RGBColor(uint8 r, uint8 g, uint8 b, uint8 a = 255); + RGBColor(int r, int g, int b, int a = 255); RGBColor(const rgb_color &col); RGBColor(uint16 col); RGBColor(uint8 col); @@ -27,8 +27,8 @@ class RGBColor { uint16 GetColor16() const; rgb_color GetColor32() const; - void SetColor(uint8 r, uint8 g, uint8 b, uint8 a=255); - void SetColor(int r, int g, int b, int a=255); + void SetColor(uint8 r, uint8 g, uint8 b, uint8 a = 255); + void SetColor(int r, int g, int b, int a = 255); void SetColor(uint16 color16); void SetColor(uint8 color8); void SetColor(const rgb_color &color); diff --git a/src/servers/app/ServerApp.cpp b/src/servers/app/ServerApp.cpp index d68479e001..f618313e09 100644 --- a/src/servers/app/ServerApp.cpp +++ b/src/servers/app/ServerApp.cpp @@ -577,7 +577,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) // First, let's attempt to allocate the bitmap ServerBitmap *bitmap = NULL; - int8 allocationType = kAllocator; + uint8 allocationFlags = kAllocator; BRect frame; color_space colorSpace; @@ -592,24 +592,22 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver& link) // TODO: choose the right HWInterface with regards to the screenID bitmap = gBitmapManager->CreateBitmap(&fMemoryAllocator, *fDesktop->HWInterface(), frame, colorSpace, flags, bytesPerRow, - screenID, &allocationType); + screenID, &allocationFlags); } STRACE(("ServerApp %s: Create Bitmap (%.1fx%.1f)\n", - Signature(), frame.Width(), frame.Height())); + Signature(), frame.Width() + 1, frame.Height() + 1)); if (bitmap != NULL && fBitmapList.AddItem(bitmap)) { fLink.StartMessage(B_OK); fLink.Attach(bitmap->Token()); - fLink.Attach(allocationType); + fLink.Attach(allocationFlags); - if (allocationType == kFramebuffer) { - fLink.Attach((addr_t)bitmap->Bits()); + fLink.Attach(fMemoryAllocator.Area(bitmap->AllocationCookie())); + fLink.Attach(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie())); + + if (allocationFlags & kFramebuffer) fLink.Attach(bitmap->BytesPerRow()); - } else { - fLink.Attach(fMemoryAllocator.Area(bitmap->AllocationCookie())); - fLink.Attach(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie())); - } } else fLink.StartMessage(B_NO_MEMORY); diff --git a/src/servers/app/ServerBitmap.cpp b/src/servers/app/ServerBitmap.cpp index c4e3a0a14c..15576d0678 100644 --- a/src/servers/app/ServerBitmap.cpp +++ b/src/servers/app/ServerBitmap.cpp @@ -4,6 +4,7 @@ * * Authors: * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de */ @@ -12,6 +13,8 @@ #include "ColorConversion.h" #include "HWInterface.h" +#include + #include #include #include @@ -27,9 +30,9 @@ using std::nothrow; If a bitmap was allocated this way, both, the fAllocator and fAllocationCookie members are used. - For overlays, the creation speed is not crucial, that's why we can easily live - with the overhead of some heap allocations. The fAllocationCookie will point - to an OverlayCookie object that will also free the buffer upon destruction. + For overlays, the allocator only allocates a small piece of client memory + for use with the overlay_client_data structure - the actual buffer will be + placed in the graphics frame buffer and is allocated by the graphics driver. If the memory was allocated on the app_server heap, neither fAllocator, nor fAllocationCookie are used, and the buffer is just freed in that case when @@ -50,22 +53,23 @@ using std::nothrow; ServerBitmap::ServerBitmap(BRect rect, color_space space, int32 flags, int32 bytesPerRow, screen_id screen) - : fInitialized(false), - fAllocator(NULL), - fAllocationCookie(NULL), - fBuffer(NULL), - fReferenceCount(1), - // WARNING: '1' is added to the width and height. - // Same is done in FBBitmap subclass, so if you - // modify here make sure to do the same under - // FBBitmap::SetSize(...) - fWidth(rect.IntegerWidth() + 1), - fHeight(rect.IntegerHeight() + 1), - fBytesPerRow(0), - fSpace(space), - fFlags(flags), - fBitsPerPixel(0) - // fToken is initialized (if used) by the BitmapManager + : + fAllocator(NULL), + fAllocationCookie(NULL), + fOverlayCookie(NULL), + fBuffer(NULL), + fReferenceCount(1), + // WARNING: '1' is added to the width and height. + // Same is done in FBBitmap subclass, so if you + // modify here make sure to do the same under + // FBBitmap::SetSize(...) + fWidth(rect.IntegerWidth() + 1), + fHeight(rect.IntegerHeight() + 1), + fBytesPerRow(0), + fSpace(space), + fFlags(flags), + fBitsPerPixel(0) + // fToken is initialized (if used) by the BitmapManager { _HandleSpace(space, bytesPerRow); } @@ -73,14 +77,14 @@ ServerBitmap::ServerBitmap(BRect rect, color_space space, //! Copy constructor does not copy the buffer. ServerBitmap::ServerBitmap(const ServerBitmap* bmp) - : fInitialized(false), - fAllocator(NULL), - fAllocationCookie(NULL), - fBuffer(NULL), - fReferenceCount(1) + : + fAllocator(NULL), + fAllocationCookie(NULL), + fOverlayCookie(NULL), + fBuffer(NULL), + fReferenceCount(1) { if (bmp) { - fInitialized = bmp->fInitialized; fWidth = bmp->fWidth; fHeight = bmp->fHeight; fBytesPerRow = bmp->fBytesPerRow; @@ -102,11 +106,11 @@ ServerBitmap::~ServerBitmap() { if (fAllocator != NULL) fAllocator->Free(AllocationCookie()); - else if (fAllocationCookie != NULL) { - delete (OverlayCookie *)fAllocationCookie; - // deleting the cookie will also free the buffer - } else + else free(fBuffer); + + delete fOverlayCookie; + // deleting the cookie will also free the overlay buffer } @@ -140,7 +144,6 @@ ServerBitmap::_AllocateBuffer(void) if (length > 0) { delete[] fBuffer; fBuffer = new(nothrow) uint8[length]; - fInitialized = fBuffer != NULL; } } @@ -301,13 +304,17 @@ ServerBitmap::AreaOffset() const } -const overlay_buffer* -ServerBitmap::OverlayBuffer() const +void +ServerBitmap::SetOverlayCookie(::OverlayCookie* cookie) { - if (fAllocator != NULL || fAllocationCookie == NULL) - return NULL; + fOverlayCookie = cookie; +} - return ((OverlayCookie*)fAllocationCookie)->OverlayBuffer(); + +::OverlayCookie* +ServerBitmap::OverlayCookie() const +{ + return fOverlayCookie; } @@ -364,8 +371,12 @@ OverlayCookie::OverlayCookie(HWInterface& interface) : fHWInterface(interface), fOverlayBuffer(NULL), + fClientData(NULL), fOverlayToken(NULL) { + fSemaphore = create_sem(1, "overlay lock"); + fColor.SetColor(255, 0, 255); + // that color is just for testing, of course! } @@ -373,13 +384,28 @@ OverlayCookie::~OverlayCookie() { fHWInterface.ReleaseOverlayChannel(fOverlayToken); fHWInterface.FreeOverlayBuffer(fOverlayBuffer); + + delete_sem(fSemaphore); +} + + +status_t +OverlayCookie::InitCheck() const +{ + return fSemaphore >= B_OK ? B_OK : fSemaphore; } void -OverlayCookie::SetOverlayBuffer(const overlay_buffer* overlayBuffer) +OverlayCookie::SetOverlayData(const overlay_buffer* overlayBuffer, + overlay_token token, overlay_client_data* clientData) { fOverlayBuffer = overlayBuffer; + fOverlayToken = token; + + fClientData = clientData; + fClientData->lock = fSemaphore; + fClientData->buffer = (uint8*)fOverlayBuffer->buffer; } @@ -390,10 +416,10 @@ OverlayCookie::OverlayBuffer() const } -void -OverlayCookie::SetOverlayToken(overlay_token token) +overlay_client_data* +OverlayCookie::ClientData() const { - fOverlayToken = token; + return fClientData; } diff --git a/src/servers/app/ServerBitmap.h b/src/servers/app/ServerBitmap.h index 3c0ad6b2e7..7182718ee3 100644 --- a/src/servers/app/ServerBitmap.h +++ b/src/servers/app/ServerBitmap.h @@ -4,11 +4,14 @@ * * Authors: * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de */ #ifndef SERVER_BITMAP_H #define SERVER_BITMAP_H +#include "RGBColor.h" + #include #include #include @@ -19,6 +22,8 @@ class BitmapManager; class ClientMemoryAllocator; class HWInterface; +class OverlayCookie; +struct overlay_client_data; /*! \class ServerBitmap ServerBitmap.h @@ -31,7 +36,7 @@ class HWInterface; class ServerBitmap { public: inline bool IsValid() const - { return fInitialized; } + { return fBuffer != NULL; } void Acquire(); @@ -64,7 +69,8 @@ class ServerBitmap { area_id Area() const; uint32 AreaOffset() const; - const overlay_buffer* OverlayBuffer() const; + void SetOverlayCookie(::OverlayCookie* cookie); + ::OverlayCookie* OverlayCookie() const; //! Does a shallow copy of the bitmap passed to it inline void ShallowCopy(const ServerBitmap *from); @@ -101,9 +107,9 @@ protected: void _HandleSpace(color_space space, int32 bytesperline = -1); - bool fInitialized; ClientMemoryAllocator* fAllocator; void* fAllocationCookie; + ::OverlayCookie* fOverlayCookie; uint8* fBuffer; int32 fReferenceCount; @@ -140,26 +146,37 @@ class OverlayCookie { OverlayCookie(HWInterface& interface); ~OverlayCookie(); - void SetOverlayBuffer(const overlay_buffer* overlayBuffer); - const overlay_buffer* OverlayBuffer() const; + status_t InitCheck() const; - void SetOverlayToken(overlay_token token); + void SetOverlayData(const overlay_buffer* overlayBuffer, + overlay_token token, overlay_client_data* clientData); + + const overlay_buffer* OverlayBuffer() const; + overlay_client_data* ClientData() const; overlay_token OverlayToken() const; + sem_id Semaphore() const + { return fSemaphore; } + + const RGBColor& Color() const + { return fColor; } + private: HWInterface& fHWInterface; const overlay_buffer* fOverlayBuffer; + overlay_client_data* fClientData; overlay_token fOverlayToken; + sem_id fSemaphore; + RGBColor fColor; }; -// ShallowCopy +// ShallowCopy (only for server bitmaps) void ServerBitmap::ShallowCopy(const ServerBitmap* from) { if (!from) return; - fInitialized = from->fInitialized; fBuffer = from->fBuffer; fWidth = from->fWidth; fHeight = from->fHeight; diff --git a/src/servers/app/ServerCursor.cpp b/src/servers/app/ServerCursor.cpp index cc05e0236a..14ddcccaa9 100644 --- a/src/servers/app/ServerCursor.cpp +++ b/src/servers/app/ServerCursor.cpp @@ -78,8 +78,6 @@ ServerCursor::ServerCursor(const uint8* data) if (!buffer) return; - fInitialized = true; - uint16* cursorBits = (uint16*)(data + 4); uint16* transparencyBits = (uint16*)(data + 36); fHotSpot.Set(data[3], data[2]); @@ -160,7 +158,6 @@ ServerCursor::ServerCursor(const ServerCursor* cursor) _AllocateBuffer(); if (cursor) { - fInitialized = true; if (Bits() && cursor->Bits()) memcpy(Bits(), cursor->Bits(), BitsLength()); fHotSpot = cursor->fHotSpot; diff --git a/src/servers/app/ViewLayer.cpp b/src/servers/app/ViewLayer.cpp index 11e96a64f5..cac4ce53a5 100644 --- a/src/servers/app/ViewLayer.cpp +++ b/src/servers/app/ViewLayer.cpp @@ -978,7 +978,11 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, // add the current clipping redraw->IntersectWith(effectiveClipping); - if (fViewBitmap != NULL) { + OverlayCookie* overlayCookie = NULL; + if (fViewBitmap != NULL) + overlayCookie = fViewBitmap->OverlayCookie(); + + if (fViewBitmap != NULL && overlayCookie == NULL) { // draw view bitmap // TODO: support other options! BRect rect = fBitmapDestination; @@ -1009,6 +1013,7 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, if (fBitmapOptions & B_TILE_BITMAP) { // tile across entire view + float start = rect.left; while (rect.top < redraw->Frame().bottom) { while (rect.left < redraw->Frame().right) { @@ -1020,9 +1025,9 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, } // nothing left to be drawn redraw->MakeEmpty(); - } else if (fBitmapOptions & B_TILE_BITMAP_X) { // tile in x direction + while (rect.left < redraw->Frame().right) { drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource, rect, &defaultDrawState); @@ -1032,9 +1037,9 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, rect.left = redraw->Frame().left; rect.right = redraw->Frame().right; redraw->Exclude(rect); - } else if (fBitmapOptions & B_TILE_BITMAP_Y) { // tile in y direction + while (rect.top < redraw->Frame().bottom) { drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource, rect, &defaultDrawState); @@ -1044,9 +1049,9 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, rect.top = redraw->Frame().top; rect.bottom = redraw->Frame().bottom; redraw->Exclude(rect); - } else { // no tiling at all + drawingEngine->DrawBitmap(fViewBitmap, fBitmapSource, rect, &defaultDrawState); redraw->Exclude(rect); @@ -1059,7 +1064,9 @@ ViewLayer::Draw(DrawingEngine* drawingEngine, BRegion* effectiveClipping, } - if (!fViewColor.IsTransparentMagic()) { + if (overlayCookie != NULL) { + drawingEngine->FillRegion(*redraw, overlayCookie->Color()); + } else if (!fViewColor.IsTransparentMagic()) { // fill visible region with view color, // this version of FillRegion ignores any // clipping, that's why "redraw" needs to