diff --git a/src/tests/servers/app/newerClipping/Desktop.cpp b/src/tests/servers/app/newerClipping/Desktop.cpp index d902cac2ed..ced866f3b7 100644 --- a/src/tests/servers/app/newerClipping/Desktop.cpp +++ b/src/tests/servers/app/newerClipping/Desktop.cpp @@ -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); } } diff --git a/src/tests/servers/app/newerClipping/Desktop.h b/src/tests/servers/app/newerClipping/Desktop.h index 69fdead71d..d636bc3714 100644 --- a/src/tests/servers/app/newerClipping/Desktop.h +++ b/src/tests/servers/app/newerClipping/Desktop.h @@ -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; diff --git a/src/tests/servers/app/newerClipping/ViewLayer.cpp b/src/tests/servers/app/newerClipping/ViewLayer.cpp index 9b13785aee..5cb1ff82c6 100644 --- a/src/tests/servers/app/newerClipping/ViewLayer.cpp +++ b/src/tests/servers/app/newerClipping/ViewLayer.cpp @@ -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 diff --git a/src/tests/servers/app/newerClipping/WindowLayer.cpp b/src/tests/servers/app/newerClipping/WindowLayer.cpp index 879b39bdf4..eae6116d0f 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.cpp +++ b/src/tests/servers/app/newerClipping/WindowLayer.cpp @@ -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) diff --git a/src/tests/servers/app/newerClipping/WindowLayer.h b/src/tests/servers/app/newerClipping/WindowLayer.h index 9785016821..9add6daa9b 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.h +++ b/src/tests/servers/app/newerClipping/WindowLayer.h @@ -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;