From 581e67867c88e4dae51de5c30839eabd303cc0a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 9 Jun 2008 16:07:18 +0000 Subject: [PATCH] * Change the protocol for sending the affected view tokens during an update session to also include each view's individual update rect (in screen coords). Should actually not be mush slower than the old version, and hopefully makes it possible to have smarter BView::Draw() implementations which should make more than up for any potential speed loss. * Removed unused version of View::AddTokensForViewsInRegion(). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25879 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/interface/Window.cpp | 56 +++++++++++++++++++++++------------ src/servers/app/View.cpp | 44 ++++++++++++--------------- src/servers/app/View.h | 4 --- src/servers/app/Window.cpp | 2 -- 4 files changed, 56 insertions(+), 50 deletions(-) diff --git a/src/kits/interface/Window.cpp b/src/kits/interface/Window.cpp index 40248795a8..96028f0f5d 100644 --- a/src/kits/interface/Window.cpp +++ b/src/kits/interface/Window.cpp @@ -1154,7 +1154,6 @@ FrameMoved(origin); //bigtime_t now = system_time(); //bigtime_t drawTime = 0; STRACE(("info:BWindow handling _UPDATE_.\n")); - BRect updateRect; fLink->StartMessage(AS_BEGIN_UPDATE); fInTransaction = true; @@ -1189,36 +1188,55 @@ FrameMoved(origin); FrameResized(width, height); } - // read culmulated update rect (is in screen coords) - fLink->Read(&updateRect); - // read tokens for views that need to be drawn // NOTE: we need to read the tokens completely - // first, or other calls would likely mess up the - // data in the link. - BList tokens(20); - int32 token; - status_t error = fLink->Read(&token); - while (error >= B_OK && token != B_NULL_TOKEN) { - tokens.AddItem((void*)token); - error = fLink->Read(&token); + // first, we cannot draw views in between reading + // the tokens, since other communication would likely + // mess up the data in the link. + struct ViewUpdateInfo { + int32 token; + BRect updateRect; + }; + BList infos(20); + while (true) { + // read next token and create/add ViewUpdateInfo + int32 token; + status_t error = fLink->Read(&token); + if (error < B_OK || token == B_NULL_TOKEN) + break; + ViewUpdateInfo* info = new (nothrow) ViewUpdateInfo; + if (info == NULL || !infos.AddItem(info)) { + delete info; + break; + } + info->token = token; + // read culmulated update rect (is in screen coords) + error = fLink->Read(&(info->updateRect)); + if (error < B_OK) + break; } // draw - int32 count = tokens.CountItems(); + int32 count = infos.CountItems(); for (int32 i = 0; i < count; i++) { //bigtime_t drawStart = system_time(); - if (BView* view = _FindView((int32)tokens.ItemAtFast(i))) - view->_Draw(updateRect); + ViewUpdateInfo* info + = (ViewUpdateInfo*)infos.ItemAtFast(i); + if (BView* view = _FindView(info->token)) + view->_Draw(info->updateRect); else - printf("_UPDATE_ - didn't find view by token: %ld\n", (int32)tokens.ItemAtFast(i)); + printf("_UPDATE_ - didn't find view by token: %ld\n", + info->token); //drawTime += system_time() - drawStart; } // NOTE: The tokens are actually hirachically sorted, // so traversing the list in revers and calling - // child->DrawAfterChildren actually works correctly + // child->_DrawAfterChildren() actually works like intended. for (int32 i = count - 1; i >= 0; i--) { - if (BView* view = _FindView((int32)tokens.ItemAtFast(i))) - view->_DrawAfterChildren(updateRect); + ViewUpdateInfo* info + = (ViewUpdateInfo*)infos.ItemAtFast(i); + if (BView* view = _FindView(info->token)) + view->_DrawAfterChildren(info->updateRect); + delete info; } //printf(" %ld views drawn, total Draw() time: %lld\n", count, drawTime); diff --git a/src/servers/app/View.cpp b/src/servers/app/View.cpp index 8ff350c6dc..4a2a0837cc 100644 --- a/src/servers/app/View.cpp +++ b/src/servers/app/View.cpp @@ -1475,23 +1475,6 @@ View::MarkBackgroundDirty() } -void -View::AddTokensForViewsInRegion(BMessage* message, BRegion& region, - BRegion* windowContentClipping) -{ - if (!fVisible) - return; - - if (region.Intersects(_ScreenClipping(windowContentClipping).Frame())) - message->AddInt32("_token", fToken); - - for (View* child = FirstChild(); child; child = child->NextSibling()) { - child->AddTokensForViewsInRegion(message, region, - windowContentClipping); - } -} - - void View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, BRegion* windowContentClipping) @@ -1499,17 +1482,28 @@ View::AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, if (!fVisible) return; - IntRect screenBounds(Bounds()); - ConvertToScreen(&screenBounds); - if (!region.Intersects((clipping_rect)screenBounds)) - return; + { + // NOTE: use scope in order to reduce stack space requirements - if (region.Intersects(_ScreenClipping(windowContentClipping).Frame())) - link.Attach(fToken); + // This check will prevent descending the view hierarchy + // any further than necessary + IntRect screenBounds(Bounds()); + ConvertToScreen(&screenBounds); + if (!region.Intersects((clipping_rect)screenBounds)) + return; - for (View* child = FirstChild(); child; child = child->NextSibling()) { - child->AddTokensForViewsInRegion(link, region, windowContentClipping); + // Unfortunately, we intersecting another region, but otherwise + // we couldn't provide the exact update rect to the client + BRegion localDirty = _ScreenClipping(windowContentClipping); + localDirty.IntersectWith(®ion); + if (localDirty.CountRects() > 0) { + link.Attach(fToken); + link.Attach(localDirty.Frame()); + } } + + for (View* child = FirstChild(); child; child = child->NextSibling()) + child->AddTokensForViewsInRegion(link, region, windowContentClipping); } diff --git a/src/servers/app/View.h b/src/servers/app/View.h index f2157b6bb9..303f70c3e0 100644 --- a/src/servers/app/View.h +++ b/src/servers/app/View.h @@ -215,10 +215,6 @@ class View { bool IsDesktopBackground() const { return fIsDesktopBackground; } - void AddTokensForViewsInRegion(BMessage* message, - BRegion& region, - BRegion* windowContentClipping); - void AddTokensForViewsInRegion(BPrivate::PortLink& link, BRegion& region, BRegion* windowContentClipping); diff --git a/src/servers/app/Window.cpp b/src/servers/app/Window.cpp index 2ee518314b..9e9982491c 100644 --- a/src/servers/app/Window.cpp +++ b/src/servers/app/Window.cpp @@ -1915,8 +1915,6 @@ Window::BeginUpdate(BPrivate::PortLink& link) link.Attach(fFrame.LeftTop()); link.Attach(fFrame.Width()); link.Attach(fFrame.Height()); - // append he update rect in screen coords - link.Attach(dirty->Frame()); // find and attach all views that intersect with // the dirty region fTopView->AddTokensForViewsInRegion(link, *dirty, &fContentRegion);