From 7fd1af6f040618119df7874f8be3a61641fc76c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Wed, 30 Nov 2005 20:35:47 +0000 Subject: [PATCH] I did some profiling using Daniel Reinholds ezprof, which is quite nice actually. I optimized a bit, without spending too much time on that yet, and now the clipping is on average 7 times faster than the current app_server (the time spend in the root layer thread) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15251 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../servers/app/newerClipping/Desktop.cpp | 6 +- .../app/newerClipping/DrawingEngine.cpp | 2 +- .../servers/app/newerClipping/WindowLayer.cpp | 106 +++++++++++------- .../servers/app/newerClipping/WindowLayer.h | 17 ++- src/tests/servers/app/newerClipping/main.cpp | 4 +- src/tests/servers/app/newerClipping/makefile | 5 +- 6 files changed, 90 insertions(+), 50 deletions(-) diff --git a/src/tests/servers/app/newerClipping/Desktop.cpp b/src/tests/servers/app/newerClipping/Desktop.cpp index ce15241923..797b6a7aa3 100644 --- a/src/tests/servers/app/newerClipping/Desktop.cpp +++ b/src/tests/servers/app/newerClipping/Desktop.cpp @@ -144,13 +144,13 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage) if (dx != 0 || dy != 0) { if (fClickedWindow) { -//bigtime_t now = system_time(); +bigtime_t now = system_time(); if (fResizing) { ResizeWindowBy(fClickedWindow, dx, dy); -//printf("resizing: %lld\n", system_time() - now); +printf("resizing: %lld\n", system_time() - now); } else { MoveWindowBy(fClickedWindow, dx, dy); -//printf("moving: %lld\n", system_time() - now); +printf("moving: %lld\n", system_time() - now); } } } diff --git a/src/tests/servers/app/newerClipping/DrawingEngine.cpp b/src/tests/servers/app/newerClipping/DrawingEngine.cpp index 29ccf337ad..de9b683f73 100644 --- a/src/tests/servers/app/newerClipping/DrawingEngine.cpp +++ b/src/tests/servers/app/newerClipping/DrawingEngine.cpp @@ -37,7 +37,7 @@ DrawingEngine::Unlock() #if RUN_WITH_FRAME_BUFFER Sync(); #else - Flush(); +// Flush(); #endif Window()->Unlock(); } diff --git a/src/tests/servers/app/newerClipping/WindowLayer.cpp b/src/tests/servers/app/newerClipping/WindowLayer.cpp index e033600f50..f56dc8d793 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(), + fVisibleContentRegionValid(false), fDirtyRegion(), fBorderRegion(), @@ -54,8 +55,8 @@ WindowLayer::WindowLayer(BRect frame, const char* name, fTokenViewMap(64), fClient(new ClientLooper(name, this)), - fCurrentUpdateSession(NULL), - fPendingUpdateSession(NULL), + fCurrentUpdateSession(), + fPendingUpdateSession(), fUpdateRequested(false), fInUpdate(false) { @@ -133,9 +134,7 @@ WindowLayer::SetClipping(BRegion* stillAvailableOnScreen) // clip to region still available on screen fVisibleRegion.IntersectWith(stillAvailableOnScreen); - GetContentRegion(&fVisibleContentRegion); - fVisibleContentRegion.IntersectWith(&fVisibleRegion); - + fVisibleContentRegionValid = false; fEffectiveDrawingRegionValid = false; } @@ -188,6 +187,18 @@ WindowLayer::GetContentRegion(BRegion* region) *region = fContentRegion; } +// VisibleContentRegion +BRegion& +WindowLayer::VisibleContentRegion() +{ + // regions expected to be locked + if (!fVisibleContentRegionValid) { + GetContentRegion(&fVisibleContentRegion); + fVisibleContentRegion.IntersectWith(&fVisibleRegion); + } + return fVisibleContentRegion; +} + // SetFocus void WindowLayer::SetFocus(bool focus) @@ -224,10 +235,10 @@ WindowLayer::MoveBy(int32 x, int32 y) if (fContentRegionValid) fContentRegion.OffsetBy(x, y); - if (fCurrentUpdateSession) - fCurrentUpdateSession->MoveBy(x, y); - if (fPendingUpdateSession) - fPendingUpdateSession->MoveBy(x, y); + if (fCurrentUpdateSession.IsUsed()) + fCurrentUpdateSession.MoveBy(x, y); + if (fPendingUpdateSession.IsUsed()) + fPendingUpdateSession.MoveBy(x, y); fEffectiveDrawingRegionValid = false; @@ -357,7 +368,7 @@ WindowLayer::MarkContentDirty(BRegion* regionOnScreen) // an update message is triggered if (fDesktop && fDesktop->ReadLockClipping()) { - regionOnScreen->IntersectWith(&fVisibleContentRegion); + regionOnScreen->IntersectWith(&VisibleContentRegion()); ProcessDirtyRegion(regionOnScreen); fDesktop->ReadUnlockClipping(); @@ -377,8 +388,10 @@ WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset) BRegion newDirty(*region); // clip the region to the visible contents at the - // source and destination location - region->IntersectWith(&fVisibleContentRegion); + // source and destination location (not that VisibleContentRegion() + // is used once to make sure it is valid, then fVisibleContentRegion + // is used directly) + region->IntersectWith(&VisibleContentRegion()); if (region->CountRects() > 0) { region->OffsetBy(xOffset, yOffset); region->IntersectWith(&fVisibleContentRegion); @@ -397,10 +410,10 @@ 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(&fDirtyRegion, region, xOffset, yOffset); - if (fCurrentUpdateSession) - _ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset); - if (fPendingUpdateSession) - _ShiftPartOfRegion(&fPendingUpdateSession->DirtyRegion(), region, xOffset, yOffset); + if (fCurrentUpdateSession.IsUsed()) + _ShiftPartOfRegion(&fCurrentUpdateSession.DirtyRegion(), region, xOffset, yOffset); + if (fPendingUpdateSession.IsUsed()) + _ShiftPartOfRegion(&fPendingUpdateSession.DirtyRegion(), region, xOffset, yOffset); } } @@ -444,7 +457,7 @@ void WindowLayer::_TriggerContentRedraw() { //printf("%s - DrawContents()\n", Name()); - BRegion dirtyContentRegion(fVisibleContentRegion); + BRegion dirtyContentRegion(VisibleContentRegion()); dirtyContentRegion.IntersectWith(&fDirtyRegion); if (dirtyContentRegion.CountRects() > 0) { @@ -490,10 +503,10 @@ WindowLayer::_DrawClient(int32 token) if (fDesktop->ReadLockClipping()) { if (!fEffectiveDrawingRegionValid) { - fEffectiveDrawingRegion = fVisibleContentRegion; + fEffectiveDrawingRegion = VisibleContentRegion(); if (fInUpdate) { // enforce the dirty region of the update session - fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession->DirtyRegion()); + fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession.DirtyRegion()); } else { printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token); } @@ -615,13 +628,9 @@ WindowLayer::_MarkContentDirty(BRegion* contentDirtyRegion) if (contentDirtyRegion->CountRects() <= 0) return; - if (!fPendingUpdateSession) { - // create new pending - fPendingUpdateSession = new UpdateSession(*contentDirtyRegion); - } else { - // add to pending - fPendingUpdateSession->Include(contentDirtyRegion); - } + // add to pending + fPendingUpdateSession.SetUsed(true); + fPendingUpdateSession.Include(contentDirtyRegion); // clip pending update session from current // update session, it makes no sense to draw stuff @@ -629,8 +638,8 @@ WindowLayer::_MarkContentDirty(BRegion* contentDirtyRegion) // this could be done smarter (clip layers from pending // that have not yet been redrawn in the current update // session) - if (fCurrentUpdateSession) { - fCurrentUpdateSession->Exclude(contentDirtyRegion); + if (fCurrentUpdateSession.IsUsed()) { + fCurrentUpdateSession.Exclude(contentDirtyRegion); fEffectiveDrawingRegionValid = false; } @@ -658,11 +667,14 @@ WindowLayer::_BeginUpdate() // at the same time. if (fDesktop->ReadLockClipping()) { - if (fUpdateRequested && !fCurrentUpdateSession) { - fCurrentUpdateSession = fPendingUpdateSession; - fPendingUpdateSession = NULL; - - if (fCurrentUpdateSession) { + if (fUpdateRequested && !fCurrentUpdateSession.IsUsed()) { + if (fPendingUpdateSession.IsUsed()) { + + // TODO: the toggling between the update sessions is too + // expensive, optimize with some pointer tricks + fCurrentUpdateSession = fPendingUpdateSession; + fPendingUpdateSession.SetUsed(false); + // all drawing command from the client // will have the dirty region from the update // session enforced @@ -671,7 +683,7 @@ WindowLayer::_BeginUpdate() fEffectiveDrawingRegionValid = false; } - fDesktop->ReadUnlockClipping(); + fDesktop->ReadUnlockClipping(); } } @@ -683,13 +695,12 @@ WindowLayer::_EndUpdate() if (fDesktop->ReadLockClipping()) { if (fInUpdate) { - delete fCurrentUpdateSession; - fCurrentUpdateSession = NULL; + fCurrentUpdateSession.SetUsed(false); fInUpdate = false; fEffectiveDrawingRegionValid = false; } - if (fPendingUpdateSession) { + if (fPendingUpdateSession.IsUsed()) { // send this to client fClient->PostMessage(MSG_UPDATE); fUpdateRequested = true; @@ -720,8 +731,9 @@ WindowLayer::_UpdateContentRegion() // #pragma mark - // constructor -UpdateSession::UpdateSession(const BRegion& dirtyRegion) - : fDirtyRegion(dirtyRegion) +UpdateSession::UpdateSession() + : fDirtyRegion(), + fInUse(false) { } @@ -751,6 +763,22 @@ UpdateSession::MoveBy(int32 x, int32 y) fDirtyRegion.OffsetBy(x, y); } +// SetUsed +void +UpdateSession::SetUsed(bool used) +{ + fInUse = used; + if (!fInUse) { + fDirtyRegion.MakeEmpty(); + } +} + +// operator= +UpdateSession& +UpdateSession::operator=(const UpdateSession& other) +{ + fDirtyRegion = other.fDirtyRegion; +} diff --git a/src/tests/servers/app/newerClipping/WindowLayer.h b/src/tests/servers/app/newerClipping/WindowLayer.h index 76f12b8b1c..3a3ddf76c0 100644 --- a/src/tests/servers/app/newerClipping/WindowLayer.h +++ b/src/tests/servers/app/newerClipping/WindowLayer.h @@ -23,7 +23,7 @@ enum { class UpdateSession { public: - UpdateSession(const BRegion& dirtyRegion); + UpdateSession(); virtual ~UpdateSession(); void Include(BRegion* additionalDirty); @@ -34,8 +34,15 @@ class UpdateSession { void MoveBy(int32 x, int32 y); + void SetUsed(bool used); + inline bool IsUsed() const + { return fInUse; } + + UpdateSession& operator=(const UpdateSession& other); + private: BRegion fDirtyRegion; + bool fInUse; }; class WindowLayer : public BLooper { @@ -49,9 +56,12 @@ class WindowLayer : public BLooper { inline BRect Frame() const { return fFrame; } + // setting and getting the "hard" clipping void SetClipping(BRegion* stillAvailableOnScreen); inline BRegion& VisibleRegion() { return fVisibleRegion; } + BRegion& VisibleContentRegion(); + void GetFullRegion(BRegion* region) const; void GetBorderRegion(BRegion* region); void GetContentRegion(BRegion* region); @@ -102,6 +112,7 @@ class WindowLayer : public BLooper { // has to be called BRegion fVisibleRegion; BRegion fVisibleContentRegion; + bool fVisibleContentRegionValid; // our part of the "global" dirty region // it is calculated from the desktop thread, // but we can write to it when we read locked @@ -142,8 +153,8 @@ class WindowLayer : public BLooper { // this is the current update session. All new // redraw requests from the root layer will go // into the pending update session. - UpdateSession* fCurrentUpdateSession; - UpdateSession* fPendingUpdateSession; + UpdateSession fCurrentUpdateSession; + UpdateSession fPendingUpdateSession; // these two flags are supposed to ensure a sane // and consistent update session bool fUpdateRequested; diff --git a/src/tests/servers/app/newerClipping/main.cpp b/src/tests/servers/app/newerClipping/main.cpp index cb6221bbc2..2eafcf1685 100644 --- a/src/tests/servers/app/newerClipping/main.cpp +++ b/src/tests/servers/app/newerClipping/main.cpp @@ -181,14 +181,14 @@ Window::Test() AddWindow(frame, name.String()); } -/* frame.Set(10, 80, 320, 290); + frame.Set(10, 80, 320, 290); for (int32 i = 20; i < 40; i++) { BString name("Window "); frame.OffsetBy(20, 15); name << i + 1; AddWindow(frame, name.String()); } - +/* frame.Set(20, 140, 330, 230); for (int32 i = 40; i < 60; i++) { BString name("Window "); diff --git a/src/tests/servers/app/newerClipping/makefile b/src/tests/servers/app/newerClipping/makefile index a8b13b4f8a..6f2f1b8bf4 100644 --- a/src/tests/servers/app/newerClipping/makefile +++ b/src/tests/servers/app/newerClipping/makefile @@ -36,7 +36,8 @@ SRCS= ClientLooper.cpp \ main.cpp \ MultiLocker.cpp \ ViewLayer.cpp \ - WindowLayer.cpp + WindowLayer.cpp \ +# trace.c # specify the resource files to use # full path or a relative path to the resource file can be used. @@ -105,7 +106,7 @@ SYMBOLS = DEBUGGER = # specify additional compiler flags for all files -COMPILER_FLAGS = +COMPILER_FLAGS = #-finstrument-functions # specify additional linker flags LINKER_FLAGS =