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:
@@ -22,7 +22,6 @@ Desktop::Desktop(DrawView* drawView)
|
|||||||
fIs2ndButton(false),
|
fIs2ndButton(false),
|
||||||
|
|
||||||
fClippingLock("clipping lock"),
|
fClippingLock("clipping lock"),
|
||||||
fDirtyRegion(),
|
|
||||||
fBackgroundRegion(),
|
fBackgroundRegion(),
|
||||||
|
|
||||||
fDrawView(drawView),
|
fDrawView(drawView),
|
||||||
@@ -102,33 +101,19 @@ Desktop::MouseDown(BPoint where, uint32 buttons)
|
|||||||
|
|
||||||
fIs2ndButton = true;
|
fIs2ndButton = true;
|
||||||
} else if (buttons == B_TERTIARY_MOUSE_BUTTON) {
|
} 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 RUN_WITH_FRAME_BUFFER
|
||||||
if (fDrawingEngine->Lock()) {
|
if (fDrawingEngine->Lock()) {
|
||||||
fDirtyRegion.MakeEmpty();
|
BRegion region(fDrawingEngine->Bounds());
|
||||||
|
fDrawingEngine->Unlock();
|
||||||
|
|
||||||
BRegion region(fDrawingEngine->Bounds());
|
MarkDirty(®ion);
|
||||||
fDrawingEngine->Unlock();
|
region = fBackgroundRegion;
|
||||||
|
fBackgroundRegion.MakeEmpty();
|
||||||
MarkDirty(®ion);
|
_SetBackground(®ion);
|
||||||
region = fBackgroundRegion;
|
|
||||||
fBackgroundRegion.MakeEmpty();
|
|
||||||
_SetBackground(®ion);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
fDirtyRegion.MakeEmpty();
|
|
||||||
fDrawingEngine->MarkDirty();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
fDrawingEngine->MarkDirty();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,7 +230,7 @@ Desktop::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// AddWindow
|
// AddWindow
|
||||||
bool
|
bool
|
||||||
@@ -367,10 +352,6 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
|
|||||||
if (LockClipping()) {
|
if (LockClipping()) {
|
||||||
// the dirty region starts with the visible area of the window being moved
|
// the dirty region starts with the visible area of the window being moved
|
||||||
BRegion newDirtyRegion(window->VisibleRegion());
|
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);
|
window->MoveBy(x, y);
|
||||||
|
|
||||||
@@ -394,15 +375,10 @@ Desktop::MoveWindowBy(WindowLayer* window, int32 x, int32 y)
|
|||||||
// could move by blitting
|
// could move by blitting
|
||||||
copyRegion.OffsetBy(x, y);
|
copyRegion.OffsetBy(x, y);
|
||||||
newDirtyRegion.Exclude(©Region);
|
newDirtyRegion.Exclude(©Region);
|
||||||
MarkClean(©Region);
|
|
||||||
fDrawingEngine->MarkDirty(©Region);
|
fDrawingEngine->MarkDirty(©Region);
|
||||||
|
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
// include the moved peviously dirty region
|
|
||||||
alreadyDirtyRegion.OffsetBy(x, y);
|
|
||||||
alreadyDirtyRegion.IntersectWith(&window->VisibleRegion());
|
|
||||||
newDirtyRegion.Include(&alreadyDirtyRegion);
|
|
||||||
|
|
||||||
MarkDirty(&newDirtyRegion);
|
MarkDirty(&newDirtyRegion);
|
||||||
_SetBackground(&background);
|
_SetBackground(&background);
|
||||||
@@ -531,7 +507,7 @@ Desktop::SetFocusWindow(WindowLayer* window)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// MarkDirty
|
// MarkDirty
|
||||||
void
|
void
|
||||||
@@ -540,28 +516,7 @@ Desktop::MarkDirty(BRegion* region)
|
|||||||
if (region->CountRects() == 0)
|
if (region->CountRects() == 0)
|
||||||
return;
|
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()) {
|
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
|
// send redraw messages to all windows intersecting the dirty region
|
||||||
_TriggerWindowRedrawing(region);
|
_TriggerWindowRedrawing(region);
|
||||||
|
|
||||||
@@ -569,29 +524,7 @@ if (fDrawingEngine->Lock()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarkClean
|
// #pragma mark -
|
||||||
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 -
|
|
||||||
|
|
||||||
// _RebuildClippingForAllWindows
|
// _RebuildClippingForAllWindows
|
||||||
void
|
void
|
||||||
@@ -629,7 +562,8 @@ Desktop::_TriggerWindowRedrawing(BRegion* newDirtyRegion)
|
|||||||
for (int32 i = count - 1; i >= 0; i--) {
|
for (int32 i = count - 1; i >= 0; i--) {
|
||||||
WindowLayer* window = WindowAtFast(i);
|
WindowLayer* window = WindowAtFast(i);
|
||||||
if (newDirtyRegion->Intersects(window->VisibleRegion().Frame()))
|
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();
|
fDrawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
MarkClean(&dirtyBackground);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,11 +91,7 @@ class Desktop : public BLooper {
|
|||||||
void UnlockClipping() { fClippingLock.Unlock(); }
|
void UnlockClipping() { fClippingLock.Unlock(); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void MarkDirty(BRegion* region);
|
void MarkDirty(BRegion* region);
|
||||||
void MarkClean(BRegion* region);
|
|
||||||
BRegion* DirtyRegion()
|
|
||||||
{ return &fDirtyRegion; }
|
|
||||||
|
|
||||||
DrawingEngine* GetDrawingEngine() const
|
DrawingEngine* GetDrawingEngine() const
|
||||||
{ return fDrawingEngine; }
|
{ return fDrawingEngine; }
|
||||||
@@ -122,7 +118,6 @@ private:
|
|||||||
#else
|
#else
|
||||||
BLocker fClippingLock;
|
BLocker fClippingLock;
|
||||||
#endif
|
#endif
|
||||||
BRegion fDirtyRegion;
|
|
||||||
BRegion fBackgroundRegion;
|
BRegion fBackgroundRegion;
|
||||||
|
|
||||||
DrawView* fDrawView;
|
DrawView* fDrawView;
|
||||||
|
|||||||
@@ -375,7 +375,7 @@ ViewLayer::SetName(const char* string)
|
|||||||
fName.SetTo(string);
|
fName.SetTo(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// MoveBy
|
// MoveBy
|
||||||
void
|
void
|
||||||
@@ -551,7 +551,7 @@ ViewLayer::ScrollBy(int32 x, int32 y, BRegion* dirtyRegion)
|
|||||||
InvalidateScreenClipping(true);
|
InvalidateScreenClipping(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
void
|
void
|
||||||
@@ -617,7 +617,7 @@ ViewLayer::ClientDraw(DrawingEngine* drawingEngine, BRegion* effectiveClipping)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// IsHidden
|
// IsHidden
|
||||||
bool
|
bool
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
|
|||||||
|
|
||||||
fVisibleRegion(),
|
fVisibleRegion(),
|
||||||
fVisibleContentRegion(),
|
fVisibleContentRegion(),
|
||||||
|
fDirtyRegion(),
|
||||||
|
|
||||||
fBorderRegion(),
|
fBorderRegion(),
|
||||||
fBorderRegionValid(false),
|
fBorderRegionValid(false),
|
||||||
@@ -93,6 +94,15 @@ WindowLayer::MessageReceived(BMessage* message)
|
|||||||
_DrawBorder();
|
_DrawBorder();
|
||||||
_TriggerContentRedraw();
|
_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();
|
fDesktop->ReadUnlockClipping();
|
||||||
} else {
|
} else {
|
||||||
//printf("%s MSG_REDRAW -> pending redraws\n", Name());
|
//printf("%s MSG_REDRAW -> pending redraws\n", Name());
|
||||||
@@ -225,6 +235,10 @@ WindowLayer::MoveBy(int32 x, int32 y)
|
|||||||
|
|
||||||
fFrame.OffsetBy(x, y);
|
fFrame.OffsetBy(x, y);
|
||||||
|
|
||||||
|
// take along the dirty region which have not
|
||||||
|
// processed yet
|
||||||
|
fDirtyRegion.OffsetBy(x, y);
|
||||||
|
|
||||||
if (fBorderRegionValid)
|
if (fBorderRegionValid)
|
||||||
fBorderRegion.OffsetBy(x, y);
|
fBorderRegion.OffsetBy(x, y);
|
||||||
if (fContentRegionValid)
|
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
|
// MarkDirty
|
||||||
void
|
void
|
||||||
WindowLayer::MarkDirty(BRegion* regionOnScreen)
|
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
|
// move along the already dirty regions that are common
|
||||||
// with the region that we could copy
|
// with the region that we could copy
|
||||||
_ShiftPartOfRegion(fDesktop->DirtyRegion(), region, xOffset, yOffset);
|
_ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
|
||||||
if (fCurrentUpdateSession)
|
if (fCurrentUpdateSession)
|
||||||
_ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset);
|
_ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset);
|
||||||
if (fPendingUpdateSession)
|
if (fPendingUpdateSession)
|
||||||
@@ -390,7 +420,7 @@ WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// _ShiftPartOfRegion
|
// _ShiftPartOfRegion
|
||||||
void
|
void
|
||||||
@@ -415,7 +445,7 @@ WindowLayer::_TriggerContentRedraw()
|
|||||||
{
|
{
|
||||||
//printf("%s - DrawContents()\n", Name());
|
//printf("%s - DrawContents()\n", Name());
|
||||||
BRegion dirtyContentRegion(fVisibleContentRegion);
|
BRegion dirtyContentRegion(fVisibleContentRegion);
|
||||||
dirtyContentRegion.IntersectWith(fDesktop->DirtyRegion());
|
dirtyContentRegion.IntersectWith(&fDirtyRegion);
|
||||||
|
|
||||||
if (dirtyContentRegion.CountRects() > 0) {
|
if (dirtyContentRegion.CountRects() > 0) {
|
||||||
|
|
||||||
@@ -431,8 +461,6 @@ snooze(100000);
|
|||||||
// send UPDATE message to the client
|
// send UPDATE message to the client
|
||||||
_MarkContentDirty(&dirtyContentRegion);
|
_MarkContentDirty(&dirtyContentRegion);
|
||||||
|
|
||||||
fDesktop->MarkClean(&dirtyContentRegion);
|
|
||||||
|
|
||||||
#if DELAYED_BACKGROUND_CLEARING
|
#if DELAYED_BACKGROUND_CLEARING
|
||||||
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
fTopLayer->Draw(fDrawingEngine, &dirtyContentRegion,
|
||||||
&fVisibleContentRegion, false);
|
&fVisibleContentRegion, false);
|
||||||
@@ -505,10 +533,13 @@ WindowLayer::_DrawBorder()
|
|||||||
// construct the region of the border that needs redrawing
|
// construct the region of the border that needs redrawing
|
||||||
BRegion dirtyBorderRegion;
|
BRegion dirtyBorderRegion;
|
||||||
GetBorderRegion(&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
|
// intersect with our visible region
|
||||||
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
|
dirtyBorderRegion.IntersectWith(&fVisibleRegion);
|
||||||
// intersect with the Desktop's dirty region
|
// intersect with the dirty region
|
||||||
dirtyBorderRegion.IntersectWith(fDesktop->DirtyRegion());
|
dirtyBorderRegion.IntersectWith(&fDirtyRegion);
|
||||||
|
|
||||||
if (dirtyBorderRegion.CountRects() > 0) {
|
if (dirtyBorderRegion.CountRects() > 0) {
|
||||||
if (fDrawingEngine->Lock()) {
|
if (fDrawingEngine->Lock()) {
|
||||||
@@ -564,8 +595,6 @@ WindowLayer::_DrawBorder()
|
|||||||
fDrawingEngine->MarkDirty(&dirtyBorderRegion);
|
fDrawingEngine->MarkDirty(&dirtyBorderRegion);
|
||||||
fDrawingEngine->Unlock();
|
fDrawingEngine->Unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
fDesktop->MarkClean(&dirtyBorderRegion);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -667,7 +696,7 @@ WindowLayer::_EndUpdate()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
UpdateSession::UpdateSession(const BRegion& dirtyRegion)
|
UpdateSession::UpdateSession(const BRegion& dirtyRegion)
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ class WindowLayer : public BLooper {
|
|||||||
void MarkDirty(BRegion* regionOnScreen);
|
void MarkDirty(BRegion* regionOnScreen);
|
||||||
void MarkContentDirty(BRegion* regionOnScreen);
|
void MarkContentDirty(BRegion* regionOnScreen);
|
||||||
|
|
||||||
|
void ProcessDirtyRegion(BRegion* region);
|
||||||
|
|
||||||
DrawingEngine* GetDrawingEngine() const
|
DrawingEngine* GetDrawingEngine() const
|
||||||
{ return fDrawingEngine; }
|
{ return fDrawingEngine; }
|
||||||
|
|
||||||
@@ -93,11 +95,18 @@ class WindowLayer : public BLooper {
|
|||||||
|
|
||||||
|
|
||||||
BRect fFrame;
|
BRect fFrame;
|
||||||
|
|
||||||
// the visible region is only recalculated from the
|
// 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
|
// has to be called
|
||||||
BRegion fVisibleRegion;
|
BRegion fVisibleRegion;
|
||||||
BRegion fVisibleContentRegion;
|
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
|
// caching local regions
|
||||||
BRegion fBorderRegion;
|
BRegion fBorderRegion;
|
||||||
|
|||||||
Reference in New Issue
Block a user