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
This commit is contained in:
Stephan Aßmus 2005-11-30 20:35:47 +00:00
parent 5ca8477eca
commit 7fd1af6f04
6 changed files with 90 additions and 50 deletions

View File

@ -144,13 +144,13 @@ Desktop::MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
if (dx != 0 || dy != 0) { if (dx != 0 || dy != 0) {
if (fClickedWindow) { if (fClickedWindow) {
//bigtime_t now = system_time(); bigtime_t now = system_time();
if (fResizing) { if (fResizing) {
ResizeWindowBy(fClickedWindow, dx, dy); ResizeWindowBy(fClickedWindow, dx, dy);
//printf("resizing: %lld\n", system_time() - now); printf("resizing: %lld\n", system_time() - now);
} else { } else {
MoveWindowBy(fClickedWindow, dx, dy); MoveWindowBy(fClickedWindow, dx, dy);
//printf("moving: %lld\n", system_time() - now); printf("moving: %lld\n", system_time() - now);
} }
} }
} }

View File

@ -37,7 +37,7 @@ DrawingEngine::Unlock()
#if RUN_WITH_FRAME_BUFFER #if RUN_WITH_FRAME_BUFFER
Sync(); Sync();
#else #else
Flush(); // Flush();
#endif #endif
Window()->Unlock(); Window()->Unlock();
} }

View File

@ -30,6 +30,7 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
fVisibleRegion(), fVisibleRegion(),
fVisibleContentRegion(), fVisibleContentRegion(),
fVisibleContentRegionValid(false),
fDirtyRegion(), fDirtyRegion(),
fBorderRegion(), fBorderRegion(),
@ -54,8 +55,8 @@ WindowLayer::WindowLayer(BRect frame, const char* name,
fTokenViewMap(64), fTokenViewMap(64),
fClient(new ClientLooper(name, this)), fClient(new ClientLooper(name, this)),
fCurrentUpdateSession(NULL), fCurrentUpdateSession(),
fPendingUpdateSession(NULL), fPendingUpdateSession(),
fUpdateRequested(false), fUpdateRequested(false),
fInUpdate(false) fInUpdate(false)
{ {
@ -133,9 +134,7 @@ WindowLayer::SetClipping(BRegion* stillAvailableOnScreen)
// clip to region still available on screen // clip to region still available on screen
fVisibleRegion.IntersectWith(stillAvailableOnScreen); fVisibleRegion.IntersectWith(stillAvailableOnScreen);
GetContentRegion(&fVisibleContentRegion); fVisibleContentRegionValid = false;
fVisibleContentRegion.IntersectWith(&fVisibleRegion);
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
} }
@ -188,6 +187,18 @@ WindowLayer::GetContentRegion(BRegion* region)
*region = fContentRegion; *region = fContentRegion;
} }
// VisibleContentRegion
BRegion&
WindowLayer::VisibleContentRegion()
{
// regions expected to be locked
if (!fVisibleContentRegionValid) {
GetContentRegion(&fVisibleContentRegion);
fVisibleContentRegion.IntersectWith(&fVisibleRegion);
}
return fVisibleContentRegion;
}
// SetFocus // SetFocus
void void
WindowLayer::SetFocus(bool focus) WindowLayer::SetFocus(bool focus)
@ -224,10 +235,10 @@ WindowLayer::MoveBy(int32 x, int32 y)
if (fContentRegionValid) if (fContentRegionValid)
fContentRegion.OffsetBy(x, y); fContentRegion.OffsetBy(x, y);
if (fCurrentUpdateSession) if (fCurrentUpdateSession.IsUsed())
fCurrentUpdateSession->MoveBy(x, y); fCurrentUpdateSession.MoveBy(x, y);
if (fPendingUpdateSession) if (fPendingUpdateSession.IsUsed())
fPendingUpdateSession->MoveBy(x, y); fPendingUpdateSession.MoveBy(x, y);
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
@ -357,7 +368,7 @@ WindowLayer::MarkContentDirty(BRegion* regionOnScreen)
// an update message is triggered // an update message is triggered
if (fDesktop && fDesktop->ReadLockClipping()) { if (fDesktop && fDesktop->ReadLockClipping()) {
regionOnScreen->IntersectWith(&fVisibleContentRegion); regionOnScreen->IntersectWith(&VisibleContentRegion());
ProcessDirtyRegion(regionOnScreen); ProcessDirtyRegion(regionOnScreen);
fDesktop->ReadUnlockClipping(); fDesktop->ReadUnlockClipping();
@ -377,8 +388,10 @@ WindowLayer::CopyContents(BRegion* region, int32 xOffset, int32 yOffset)
BRegion newDirty(*region); BRegion newDirty(*region);
// clip the region to the visible contents at the // clip the region to the visible contents at the
// source and destination location // source and destination location (not that VisibleContentRegion()
region->IntersectWith(&fVisibleContentRegion); // is used once to make sure it is valid, then fVisibleContentRegion
// is used directly)
region->IntersectWith(&VisibleContentRegion());
if (region->CountRects() > 0) { if (region->CountRects() > 0) {
region->OffsetBy(xOffset, yOffset); region->OffsetBy(xOffset, yOffset);
region->IntersectWith(&fVisibleContentRegion); region->IntersectWith(&fVisibleContentRegion);
@ -397,10 +410,10 @@ 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(&fDirtyRegion, region, xOffset, yOffset); _ShiftPartOfRegion(&fDirtyRegion, region, xOffset, yOffset);
if (fCurrentUpdateSession) if (fCurrentUpdateSession.IsUsed())
_ShiftPartOfRegion(&fCurrentUpdateSession->DirtyRegion(), region, xOffset, yOffset); _ShiftPartOfRegion(&fCurrentUpdateSession.DirtyRegion(), region, xOffset, yOffset);
if (fPendingUpdateSession) if (fPendingUpdateSession.IsUsed())
_ShiftPartOfRegion(&fPendingUpdateSession->DirtyRegion(), region, xOffset, yOffset); _ShiftPartOfRegion(&fPendingUpdateSession.DirtyRegion(), region, xOffset, yOffset);
} }
} }
@ -444,7 +457,7 @@ void
WindowLayer::_TriggerContentRedraw() WindowLayer::_TriggerContentRedraw()
{ {
//printf("%s - DrawContents()\n", Name()); //printf("%s - DrawContents()\n", Name());
BRegion dirtyContentRegion(fVisibleContentRegion); BRegion dirtyContentRegion(VisibleContentRegion());
dirtyContentRegion.IntersectWith(&fDirtyRegion); dirtyContentRegion.IntersectWith(&fDirtyRegion);
if (dirtyContentRegion.CountRects() > 0) { if (dirtyContentRegion.CountRects() > 0) {
@ -490,10 +503,10 @@ WindowLayer::_DrawClient(int32 token)
if (fDesktop->ReadLockClipping()) { if (fDesktop->ReadLockClipping()) {
if (!fEffectiveDrawingRegionValid) { if (!fEffectiveDrawingRegionValid) {
fEffectiveDrawingRegion = fVisibleContentRegion; fEffectiveDrawingRegion = VisibleContentRegion();
if (fInUpdate) { if (fInUpdate) {
// enforce the dirty region of the update session // enforce the dirty region of the update session
fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession->DirtyRegion()); fEffectiveDrawingRegion.IntersectWith(&fCurrentUpdateSession.DirtyRegion());
} else { } else {
printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token); printf("%s - _DrawClient(token: %ld) - not in update\n", Name(), token);
} }
@ -615,13 +628,9 @@ WindowLayer::_MarkContentDirty(BRegion* contentDirtyRegion)
if (contentDirtyRegion->CountRects() <= 0) if (contentDirtyRegion->CountRects() <= 0)
return; return;
if (!fPendingUpdateSession) { // add to pending
// create new pending fPendingUpdateSession.SetUsed(true);
fPendingUpdateSession = new UpdateSession(*contentDirtyRegion); fPendingUpdateSession.Include(contentDirtyRegion);
} else {
// add to pending
fPendingUpdateSession->Include(contentDirtyRegion);
}
// clip pending update session from current // clip pending update session from current
// update session, it makes no sense to draw stuff // 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 // this could be done smarter (clip layers from pending
// that have not yet been redrawn in the current update // that have not yet been redrawn in the current update
// session) // session)
if (fCurrentUpdateSession) { if (fCurrentUpdateSession.IsUsed()) {
fCurrentUpdateSession->Exclude(contentDirtyRegion); fCurrentUpdateSession.Exclude(contentDirtyRegion);
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
} }
@ -658,11 +667,14 @@ WindowLayer::_BeginUpdate()
// at the same time. // at the same time.
if (fDesktop->ReadLockClipping()) { if (fDesktop->ReadLockClipping()) {
if (fUpdateRequested && !fCurrentUpdateSession) { if (fUpdateRequested && !fCurrentUpdateSession.IsUsed()) {
fCurrentUpdateSession = fPendingUpdateSession; if (fPendingUpdateSession.IsUsed()) {
fPendingUpdateSession = NULL;
// TODO: the toggling between the update sessions is too
if (fCurrentUpdateSession) { // expensive, optimize with some pointer tricks
fCurrentUpdateSession = fPendingUpdateSession;
fPendingUpdateSession.SetUsed(false);
// all drawing command from the client // all drawing command from the client
// will have the dirty region from the update // will have the dirty region from the update
// session enforced // session enforced
@ -671,7 +683,7 @@ WindowLayer::_BeginUpdate()
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
} }
fDesktop->ReadUnlockClipping(); fDesktop->ReadUnlockClipping();
} }
} }
@ -683,13 +695,12 @@ WindowLayer::_EndUpdate()
if (fDesktop->ReadLockClipping()) { if (fDesktop->ReadLockClipping()) {
if (fInUpdate) { if (fInUpdate) {
delete fCurrentUpdateSession; fCurrentUpdateSession.SetUsed(false);
fCurrentUpdateSession = NULL;
fInUpdate = false; fInUpdate = false;
fEffectiveDrawingRegionValid = false; fEffectiveDrawingRegionValid = false;
} }
if (fPendingUpdateSession) { if (fPendingUpdateSession.IsUsed()) {
// send this to client // send this to client
fClient->PostMessage(MSG_UPDATE); fClient->PostMessage(MSG_UPDATE);
fUpdateRequested = true; fUpdateRequested = true;
@ -720,8 +731,9 @@ WindowLayer::_UpdateContentRegion()
// #pragma mark - // #pragma mark -
// constructor // constructor
UpdateSession::UpdateSession(const BRegion& dirtyRegion) UpdateSession::UpdateSession()
: fDirtyRegion(dirtyRegion) : fDirtyRegion(),
fInUse(false)
{ {
} }
@ -751,6 +763,22 @@ UpdateSession::MoveBy(int32 x, int32 y)
fDirtyRegion.OffsetBy(x, 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;
}

View File

@ -23,7 +23,7 @@ enum {
class UpdateSession { class UpdateSession {
public: public:
UpdateSession(const BRegion& dirtyRegion); UpdateSession();
virtual ~UpdateSession(); virtual ~UpdateSession();
void Include(BRegion* additionalDirty); void Include(BRegion* additionalDirty);
@ -34,8 +34,15 @@ class UpdateSession {
void MoveBy(int32 x, int32 y); void MoveBy(int32 x, int32 y);
void SetUsed(bool used);
inline bool IsUsed() const
{ return fInUse; }
UpdateSession& operator=(const UpdateSession& other);
private: private:
BRegion fDirtyRegion; BRegion fDirtyRegion;
bool fInUse;
}; };
class WindowLayer : public BLooper { class WindowLayer : public BLooper {
@ -49,9 +56,12 @@ class WindowLayer : public BLooper {
inline BRect Frame() const inline BRect Frame() const
{ return fFrame; } { return fFrame; }
// setting and getting the "hard" clipping
void SetClipping(BRegion* stillAvailableOnScreen); void SetClipping(BRegion* stillAvailableOnScreen);
inline BRegion& VisibleRegion() inline BRegion& VisibleRegion()
{ return fVisibleRegion; } { return fVisibleRegion; }
BRegion& VisibleContentRegion();
void GetFullRegion(BRegion* region) const; void GetFullRegion(BRegion* region) const;
void GetBorderRegion(BRegion* region); void GetBorderRegion(BRegion* region);
void GetContentRegion(BRegion* region); void GetContentRegion(BRegion* region);
@ -102,6 +112,7 @@ class WindowLayer : public BLooper {
// has to be called // has to be called
BRegion fVisibleRegion; BRegion fVisibleRegion;
BRegion fVisibleContentRegion; BRegion fVisibleContentRegion;
bool fVisibleContentRegionValid;
// our part of the "global" dirty region // our part of the "global" dirty region
// it is calculated from the desktop thread, // it is calculated from the desktop thread,
// but we can write to it when we read locked // 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 // this is the current update session. All new
// redraw requests from the root layer will go // redraw requests from the root layer will go
// into the pending update session. // into the pending update session.
UpdateSession* fCurrentUpdateSession; UpdateSession fCurrentUpdateSession;
UpdateSession* fPendingUpdateSession; UpdateSession fPendingUpdateSession;
// these two flags are supposed to ensure a sane // these two flags are supposed to ensure a sane
// and consistent update session // and consistent update session
bool fUpdateRequested; bool fUpdateRequested;

View File

@ -181,14 +181,14 @@ Window::Test()
AddWindow(frame, name.String()); AddWindow(frame, name.String());
} }
/* frame.Set(10, 80, 320, 290); frame.Set(10, 80, 320, 290);
for (int32 i = 20; i < 40; i++) { for (int32 i = 20; i < 40; i++) {
BString name("Window "); BString name("Window ");
frame.OffsetBy(20, 15); frame.OffsetBy(20, 15);
name << i + 1; name << i + 1;
AddWindow(frame, name.String()); AddWindow(frame, name.String());
} }
/*
frame.Set(20, 140, 330, 230); frame.Set(20, 140, 330, 230);
for (int32 i = 40; i < 60; i++) { for (int32 i = 40; i < 60; i++) {
BString name("Window "); BString name("Window ");

View File

@ -36,7 +36,8 @@ SRCS= ClientLooper.cpp \
main.cpp \ main.cpp \
MultiLocker.cpp \ MultiLocker.cpp \
ViewLayer.cpp \ ViewLayer.cpp \
WindowLayer.cpp WindowLayer.cpp \
# trace.c
# specify the resource files to use # specify the resource files to use
# full path or a relative path to the resource file can be used. # full path or a relative path to the resource file can be used.
@ -105,7 +106,7 @@ SYMBOLS =
DEBUGGER = DEBUGGER =
# specify additional compiler flags for all files # specify additional compiler flags for all files
COMPILER_FLAGS = COMPILER_FLAGS = #-finstrument-functions
# specify additional linker flags # specify additional linker flags
LINKER_FLAGS = LINKER_FLAGS =