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:
parent
5ca8477eca
commit
7fd1af6f04
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 ");
|
||||||
|
@ -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 =
|
||||||
|
Loading…
Reference in New Issue
Block a user