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:
parent
4dd89c6903
commit
c63a78aafa
@ -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(®ion);
|
||||
region = fBackgroundRegion;
|
||||
fBackgroundRegion.MakeEmpty();
|
||||
_SetBackground(®ion);
|
||||
}
|
||||
#else
|
||||
fDirtyRegion.MakeEmpty();
|
||||
fDrawingEngine->MarkDirty();
|
||||
#endif
|
||||
MarkDirty(®ion);
|
||||
region = fBackgroundRegion;
|
||||
fBackgroundRegion.MakeEmpty();
|
||||
_SetBackground(®ion);
|
||||
}
|
||||
#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(©Region);
|
||||
MarkClean(©Region);
|
||||
fDrawingEngine->MarkDirty(©Region);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user