* 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
This commit is contained in:
Stephan Aßmus 2008-06-09 16:07:18 +00:00
parent 50d3d63701
commit 581e67867c
4 changed files with 56 additions and 50 deletions

View File

@ -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<BRect>(&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<int32>(&token);
while (error >= B_OK && token != B_NULL_TOKEN) {
tokens.AddItem((void*)token);
error = fLink->Read<int32>(&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<int32>(&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<BRect>(&(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);

View File

@ -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<int32>(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(&region);
if (localDirty.CountRects() > 0) {
link.Attach<int32>(fToken);
link.Attach<BRect>(localDirty.Frame());
}
}
for (View* child = FirstChild(); child; child = child->NextSibling())
child->AddTokensForViewsInRegion(link, region, windowContentClipping);
}

View File

@ -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);

View File

@ -1915,8 +1915,6 @@ Window::BeginUpdate(BPrivate::PortLink& link)
link.Attach<BPoint>(fFrame.LeftTop());
link.Attach<float>(fFrame.Width());
link.Attach<float>(fFrame.Height());
// append he update rect in screen coords
link.Attach<BRect>(dirty->Frame());
// find and attach all views that intersect with
// the dirty region
fTopView->AddTokensForViewsInRegion(link, *dirty, &fContentRegion);