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