* 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
This commit is contained in:
Axel Dörfler 2006-04-22 16:41:12 +00:00
parent 704c03b9e6
commit 21c8c925d8
11 changed files with 229 additions and 122 deletions

View File

@ -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

View File

@ -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 <OS.h>
// This structure is placed in the client/server shared memory area.
struct overlay_client_data {
sem_id lock;
uint8* buffer;
};
#endif // _BITMAP_PRIVATE_H

View File

@ -15,6 +15,7 @@
*/
#include "ColorConversion.h"
#include "BitmapPrivate.h"
#include <Application.h>
#include <Bitmap.h>
@ -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<BBitmap *>(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<int32>(&fServerToken);
int8 allocationType;
link.Read<int8>(&allocationType);
uint8 allocationFlags;
link.Read<uint8>(&allocationFlags);
link.Read<area_id>(&fServerArea);
link.Read<int32>(&fAreaOffset);
if (allocationType == kFramebuffer) {
link.Read<addr_t>((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<int32>(&fBytesPerRow);
fServerArea = B_ERROR;
fAreaOffset = 0;
} else {
link.Read<area_id>(&fServerArea);
link.Read<int32>(&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) {

View File

@ -4,12 +4,10 @@
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* 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 <BitmapPrivate.h>
#include <video_overlay.h>
#include <Autolock.h>
@ -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

View File

@ -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:

View File

@ -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);

View File

@ -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<int32>(bitmap->Token());
fLink.Attach<int8>(allocationType);
fLink.Attach<uint8>(allocationFlags);
if (allocationType == kFramebuffer) {
fLink.Attach<addr_t>((addr_t)bitmap->Bits());
fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie()));
fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
if (allocationFlags & kFramebuffer)
fLink.Attach<int32>(bitmap->BytesPerRow());
} else {
fLink.Attach<area_id>(fMemoryAllocator.Area(bitmap->AllocationCookie()));
fLink.Attach<int32>(fMemoryAllocator.AreaOffset(bitmap->AllocationCookie()));
}
} else
fLink.StartMessage(B_NO_MEMORY);

View File

@ -4,6 +4,7 @@
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
@ -12,6 +13,8 @@
#include "ColorConversion.h"
#include "HWInterface.h"
#include <BitmapPrivate.h>
#include <new>
#include <stdio.h>
#include <string.h>
@ -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;
}

View File

@ -4,11 +4,14 @@
*
* Authors:
* DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de
*/
#ifndef SERVER_BITMAP_H
#define SERVER_BITMAP_H
#include "RGBColor.h"
#include <GraphicsDefs.h>
#include <Rect.h>
#include <OS.h>
@ -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;

View File

@ -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;

View File

@ -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