now doing without a global dirty region, and it seems it gained a little speed too, should be easier now to make the multi locker work

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15231 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stephan Aßmus 2005-11-29 20:35:47 +00:00
parent 4dd89c6903
commit c63a78aafa
5 changed files with 67 additions and 101 deletions

View File

@ -22,7 +22,6 @@ Desktop::Desktop(DrawView* drawView)
fIs2ndButton(false),
fClippingLock("clipping lock"),
fDirtyRegion(),
fBackgroundRegion(),
fDrawView(drawView),
@ -102,33 +101,19 @@ Desktop::MouseDown(BPoint where, uint32 buttons)
fIs2ndButton = true;
} else if (buttons == B_TERTIARY_MOUSE_BUTTON) {
if (modifiers() & B_SHIFT_KEY) {
// render global dirty region
if (fDrawingEngine->Lock()) {
fDrawingEngine->SetHighColor(255, 0, 0);
fDrawingEngine->FillRegion(&fDirtyRegion);
fDrawingEngine->MarkDirty(&fDirtyRegion);
fDrawingEngine->Unlock();
}
} else {
// complete redraw
#if RUN_WITH_FRAME_BUFFER
if (fDrawingEngine->Lock()) {
fDirtyRegion.MakeEmpty();
if (fDrawingEngine->Lock()) {
BRegion region(fDrawingEngine->Bounds());
fDrawingEngine->Unlock();
BRegion region(fDrawingEngine->Bounds());
fDrawingEngine->Unlock();
MarkDirty(&region);
region = fBackgroundRegion;
fBackgroundRegion.MakeEmpty();
_SetBackground(&region);
}
#else
fDirtyRegion.MakeEmpty();
fDrawingEngine->MarkDirty();
#endif
MarkDirty(&region);
region = fBackgroundRegion;
fBackgroundRegion.MakeEmpty();
_SetBackground(&region);
}
#else
fDrawingEngine->MarkDirty();
#endif
}
}
@ -245,7 +230,7 @@ Desktop::MessageReceived(BMessage* message)
}
}
#pragma mark -
// #pragma mark -
// AddWindow
bool
@ -367,10 +352,6 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
if (LockClipping()) {
// the dirty region starts with the visible area of the window being moved
BRegion newDirtyRegion(window->VisibleRegion());
// we have to move along the part of the current dirty region
// that intersects with the window being moved
BRegion alreadyDirtyRegion(fDirtyRegion);
alreadyDirtyRegion.IntersectWith(&window->VisibleRegion());
window->MoveBy(x, y);
@ -394,15 +375,10 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
// could move by blitting
copyRegion.OffsetBy(x, y);
newDirtyRegion.Exclude(&copyRegion);
MarkClean(&copyRegion);
fDrawingEngine->MarkDirty(&copyRegion);
fDrawingEngine->Unlock();
}
// include the moved peviously dirty region
alreadyDirtyRegion.OffsetBy(x, y);
alreadyDirtyRegion.IntersectWith(&window->VisibleRegion());
newDirtyRegion.Include(&alreadyDirtyRegion);
MarkDirty(&newDirtyRegion);
_SetBackground(&background);
@ -531,7 +507,7 @@ Desktop::SetFocusWindow(WindowLayer* window)
#pragma mark -
// #pragma mark -
// MarkDirty
void
@ -540,28 +516,7 @@ Desktop::MarkDirty(BRegion* region)
if (region->CountRects() == 0)
return;
// NOTE: the idea is that for all dirty areas ever included
// in the culmulative dirty region, redraw messages have been
// sent to the windows affected by just the newly included
// area. Therefor, _TriggerWindowRedrawing() is not called
// with "fDirtyRegion", but with just the new "region" instead.
// Whenever a window is actually carrying out a redraw request,
// it is expected to remove the redrawn area from the dirty region.
if (LockClipping()) {
// add the new dirty region to the culmulative dirty region
fDirtyRegion.Include(region);
#if SHOW_GLOBAL_DIRTY_REGION
if (fDrawingEngine->Lock()) {
fDrawingEngine->SetHighColor(255, 0, 0);
fDrawingEngine->FillRegion(region);
fDrawingEngine->MarkDirty(region);
fDrawingEngine->Unlock();
snooze(100000);
}
#endif
// send redraw messages to all windows intersecting the dirty region
_TriggerWindowRedrawing(region);
@ -569,29 +524,7 @@ if (fDrawingEngine->Lock()) {
}
}
// MarkClean
void
Desktop::MarkClean(BRegion* region)
{
// NOTE: when a window owns the read lock for
// the clipping, it means the Desktop thread is currently
// not messing with the regions. Since a window is expected
// to only remove parts from the dirty region that intersect
// it's own visible region, it cannot remove the wrong parts
// of the dirty region (ie parts intersecting another window)
// writelocking would therefor not be needed, but of course
// BRegion is not threadsafe, and therefor, it would be cool
// if the dirty region was moved into each window again.
if (LockClipping()) {
// remove the clean region from the culmulative dirty region
fDirtyRegion.Exclude(region);
UnlockClipping();
}
}
#pragma mark -
// #pragma mark -
// _RebuildClippingForAllWindows
void
@ -629,7 +562,8 @@ Desktop::_TriggerWindowRedrawing(BRegion* newDirtyRegion)
for (int32 i = count - 1; i >= 0; i--) {
WindowLayer* window = WindowAtFast(i);
if (newDirtyRegion->Intersects(window->VisibleRegion().Frame()))
window->PostMessage(MSG_REDRAW);
// window->PostMessage(MSG_REDRAW);
window->ProcessDirtyRegion(newDirtyRegion);
}
}
@ -656,6 +590,5 @@ Desktop::_SetBackground(BRegion* background)
fDrawingEngine->Unlock();
}
MarkClean(&dirtyBackground);
}
}

View File

@ -91,11 +91,7 @@ class Desktop : public BLooper {
void UnlockClipping() { fClippingLock.Unlock(); }
#endif
void MarkDirty(BRegion* region);
void MarkClean(BRegion* region);
BRegion* DirtyRegion()
{ return &fDirtyRegion; }
DrawingEngine* GetDrawingEngine() const
{ return fDrawingEngine; }
@ -122,7 +118,6 @@ private:
#else
BLocker fClippingLock;
#endif
BRegion fDirtyRegion;
BRegion fBackgroundRegion;
DrawView* fDrawView;

View File

@ -375,7 +375,7 @@ ViewLayer::SetName(const char* string)
fName.SetTo(string);
}
#pragma mark -
// #pragma mark -
// MoveBy
void
@ -551,7 +551,7 @@ ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
InvalidateScreenClipping(true);
}
#pragma mark -
// #pragma mark -
// Draw
void
@ -617,7 +617,7 @@ ViewLayer::ClientDraw(DrawingEngine* drawingEngine, BRegion* effectiveClipping)
}
}
#pragma mark -
// #pragma mark -
// IsHidden
bool

View File

@ -30,6 +30,7 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
fVisibleRegion(),
fVisibleContentRegion(),
fDirtyRegion(),
fBorderRegion(),
fBorderRegionValid(false),
@ -93,6 +94,15 @@ WindowLayer::MessageReceived(BMessage* message)
_DrawBorder();
_TriggerContentRedraw();
// reset the dirty region, since
// we're fully clean. If the desktop
// thread wanted to mark something
// dirty in the mean time, it was
// blocking on the global region lock to
// get write access, since we held the
// read lock for the whole time.
fDirtyRegion.MakeEmpty();
fDesktop->ReadUnlockClipping();
} else {
//printf("%s MSG_REDRAW -> pending redraws\n", Name());
@ -225,6 +235,10 @@ WindowLayer::MoveBy(int32 x, int32 y)
fFrame.OffsetBy(x, y);
// take along the dirty region which have not
// processed yet
fDirtyRegion.OffsetBy(x, y);
if (fBorderRegionValid)
fBorderRegion.OffsetBy(x, y);
if (fContentRegionValid)
@ -315,6 +329,22 @@ WindowLayer::Show()
}
// ProcessDirtyRegion
void
WindowLayer::ProcessDirtyRegion(BRegion* region)
{
// this is exectuted in the desktop thread,
// and it means that the window thread currently
// blocks on the global region lock
if (fDirtyRegion.CountRects() == 0) {
// the window needs to be informed
// when the dirty region was empty
PostMessage(MSG_REDRAW, this);
}
// this is executed from the desktop thread
fDirtyRegion.Include(region);
}
// MarkDirty
void
WindowLayer::MarkDirty(BRegion* regionOnScreen)
@ -370,7 +400,7 @@ WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
// move along the already dirty regions that are common
// with the region that we could copy
_ShiftPartOfRegion(fDesktop->DirtyRegion(), region, xOffset, yOffset);
_ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
if (fCurrentUpdateSession)
_ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset);
if (fPendingUpdateSession)
@ -390,7 +420,7 @@ WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
}
}
# pragma mark -
// #pragma mark -
// _ShiftPartOfRegion
void
@ -415,7 +445,7 @@ WindowLayer::_TriggerContentRedraw()
{
//printf("%s - DrawContents()\n", Name());
BRegion dirtyContentRegion(fVisibleContentRegion);
dirtyContentRegion.IntersectWith(fDesktop->DirtyRegion());
dirtyContentRegion.IntersectWith(&fDirtyRegion);
if (dirtyContentRegion.CountRects() > 0) {
@ -431,8 +461,6 @@ snooze(100000);
// send UPDATE message to the client
_MarkContentDirty(&dirtyContentRegion);
fDesktop->MarkClean(&dirtyContentRegion);
#if DELAYED_BACKGROUND_CLEARING
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
&fVisibleContentRegion, false);
@ -505,10 +533,13 @@ WindowLayer::_DrawBorder()
// construct the region of the border that needs redrawing
BRegion dirtyBorderRegion;
GetBorderRegion(&dirtyBorderRegion);
// TODO: why is it not enough to only intersect with the dirty region?
// is it faster to intersect the dirty region with the visible when it
// is set in ProcessDirtyRegion()?
// intersect with our visible region
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
// intersect with the Desktop's dirty region
dirtyBorderRegion.IntersectWith(fDesktop->DirtyRegion());
// intersect with the dirty region
dirtyBorderRegion.IntersectWith(&fDirtyRegion);
if (dirtyBorderRegion.CountRects() > 0) {
if (fDrawingEngine->Lock()) {
@ -564,8 +595,6 @@ WindowLayer::_DrawBorder()
fDrawingEngine->MarkDirty(&dirtyBorderRegion);
fDrawingEngine->Unlock();
}
fDesktop->MarkClean(&dirtyBorderRegion);
}
}
@ -667,7 +696,7 @@ WindowLayer::_EndUpdate()
}
}
#pragma mark -
// #pragma mark -
// constructor
UpdateSession::UpdateSession(const BRegion& dirtyRegion)

View File

@ -71,6 +71,8 @@ class WindowLayer : public BLooper {
void MarkDirty(BRegion* regionOnScreen);
void MarkContentDirty(BRegion* regionOnScreen);
void ProcessDirtyRegion(BRegion* region);
DrawingEngine* GetDrawingEngine() const
{ return fDrawingEngine; }
@ -93,11 +95,18 @@ class WindowLayer : public BLooper {
BRect fFrame;
// the visible region is only recalculated from the
// Desktop thread, when using it, Desktop::LockClipping()
// Desktop thread, when using it, Desktop::ReadLockClipping()
// has to be called
BRegion fVisibleRegion;
BRegion fVisibleContentRegion;
// our part of the "global" dirty region
// it is calculated from the desktop thread,
// but we can write to it when we read locked
// the clipping, since it is local and the desktop
// thread is blocked
BRegion fDirtyRegion;
// caching local regions
BRegion fBorderRegion;