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 (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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ DrawingEngine::Unlock()
|
||||
#if RUN_WITH_FRAME_BUFFER
|
||||
Sync();
|
||||
#else
|
||||
Flush();
|
||||
// Flush();
|
||||
#endif
|
||||
Window()->Unlock();
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 ");
|
||||
|
@ -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 =
|
||||
|
Loading…
Reference in New Issue
Block a user