Used the new mechanism/options in the DrawingEngine with regard to
back to front copies in Window for updates. When in an update session, any back to front copies are turned off. When the update session ends, the whole region is copied at once. This has two effects: For once, it avoids a lot of unnecessary copies (for example, rendering text copied the background and then the same area for the text again). But even more effective, it changes the entire drawing of any Haiku app to be completely flicker free. Provided it happens in the normal Invalidate()/Draw() cycle. And of course all this only works for double buffering mode, ie VESA. Potentially, I might have overlooked something, so that this patch could result in some drawing glitches, but in my testing, I have seen none yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24354 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
18212e76cc
commit
ffac272e35
@ -1739,12 +1739,15 @@ Window::_TriggerContentRedraw(BRegion& dirtyContentRegion)
|
||||
}
|
||||
|
||||
if (fDrawingEngine->LockParallelAccess()) {
|
||||
bool copyToFrontEnabled = fDrawingEngine->CopyToFrontEnabled();
|
||||
fDrawingEngine->SetCopyToFrontEnabled(true);
|
||||
fDrawingEngine->SuspendAutoSync();
|
||||
|
||||
fTopView->Draw(fDrawingEngine, backgroundClearingRegion,
|
||||
&fContentRegion, true);
|
||||
|
||||
fDrawingEngine->Sync();
|
||||
fDrawingEngine->SetCopyToFrontEnabled(copyToFrontEnabled);
|
||||
fDrawingEngine->UnlockParallelAccess();
|
||||
}
|
||||
}
|
||||
@ -1775,8 +1778,13 @@ Window::_DrawBorder()
|
||||
DrawingEngine* engine = fDecorator->GetDrawingEngine();
|
||||
if (dirtyBorderRegion->CountRects() > 0 && engine->LockParallelAccess()) {
|
||||
engine->ConstrainClippingRegion(dirtyBorderRegion);
|
||||
bool copyToFrontEnabled = engine->CopyToFrontEnabled();
|
||||
engine->SetCopyToFrontEnabled(true);
|
||||
|
||||
fDecorator->Draw(dirtyBorderRegion->Frame());
|
||||
|
||||
engine->SetCopyToFrontEnabled(copyToFrontEnabled);
|
||||
|
||||
// TODO: remove this once the DrawState stuff is handled
|
||||
// more cleanly. The reason why this is needed is that
|
||||
// when the decorator draws strings, a draw state is set
|
||||
@ -1815,23 +1823,6 @@ Window::_TransferToUpdateSession(BRegion* contentDirtyRegion)
|
||||
fPendingUpdateSession->AddCause(fDirtyCause);
|
||||
fPendingUpdateSession->Include(contentDirtyRegion);
|
||||
|
||||
// clip pending update session from current
|
||||
// update session, it makes no sense to draw stuff
|
||||
// already needing a redraw anyways. Theoretically,
|
||||
// this could be done smarter (clip views from pending
|
||||
// that have not yet been redrawn in the current update
|
||||
// session)
|
||||
// NOTE: appearently the R5 app_server does not do that, it just
|
||||
// keeps drawing until the screen is valid, without caring much
|
||||
// for a consistent display while it does so, it just keeps drawing
|
||||
// until everything settles down. Potentially, this could even give
|
||||
// the impression of faster updates, even though they might look
|
||||
// wrong when looked at closer, but will fix themselves shortly later
|
||||
// if (fCurrentUpdateSession->IsUsed() && fCurrentUpdateSession->IsExpose()) {
|
||||
// fCurrentUpdateSession->Exclude(contentDirtyRegion);
|
||||
// fEffectiveDrawingRegionValid = false;
|
||||
// }
|
||||
|
||||
if (!fUpdateRequested) {
|
||||
// send this to client
|
||||
_SendUpdateMessage();
|
||||
@ -1867,36 +1858,42 @@ Window::BeginUpdate(BPrivate::PortLink& link)
|
||||
// dirty regions are not messed with from the Desktop thread
|
||||
// and ServerWindow thread at the same time.
|
||||
|
||||
if (fUpdateRequested) {
|
||||
// make the pending update session the current update session
|
||||
// (toggle the pointers)
|
||||
UpdateSession* temp = fCurrentUpdateSession;
|
||||
fCurrentUpdateSession = fPendingUpdateSession;
|
||||
fPendingUpdateSession = temp;
|
||||
fPendingUpdateSession->SetUsed(false);
|
||||
// all drawing command from the client
|
||||
// will have the dirty region from the update
|
||||
// session enforced
|
||||
fInUpdate = true;
|
||||
fEffectiveDrawingRegionValid = false;
|
||||
if (!fUpdateRequested) {
|
||||
link.StartMessage(B_ERROR);
|
||||
link.Flush();
|
||||
fprintf(stderr, "Window::BeginUpdate() - no update requested!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: each view could be drawn individually
|
||||
// right before carrying out the first drawing
|
||||
// command from the client during an update
|
||||
// (View::IsBackgroundDirty() can be used
|
||||
// for this)
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
// make the pending update session the current update session
|
||||
// (toggle the pointers)
|
||||
UpdateSession* temp = fCurrentUpdateSession;
|
||||
fCurrentUpdateSession = fPendingUpdateSession;
|
||||
fPendingUpdateSession = temp;
|
||||
fPendingUpdateSession->SetUsed(false);
|
||||
// all drawing command from the client
|
||||
// will have the dirty region from the update
|
||||
// session enforced
|
||||
fInUpdate = true;
|
||||
fEffectiveDrawingRegionValid = false;
|
||||
|
||||
BRegion* dirty = fRegionPool.GetRegion(
|
||||
fCurrentUpdateSession->DirtyRegion());
|
||||
if (!dirty) {
|
||||
link.StartMessage(B_ERROR);
|
||||
link.Flush();
|
||||
return;
|
||||
}
|
||||
// TODO: each view could be drawn individually
|
||||
// right before carrying out the first drawing
|
||||
// command from the client during an update
|
||||
// (View::IsBackgroundDirty() can be used
|
||||
// for this)
|
||||
if (!fContentRegionValid)
|
||||
_UpdateContentRegion();
|
||||
|
||||
dirty->IntersectWith(&VisibleContentRegion());
|
||||
BRegion* dirty = fRegionPool.GetRegion(
|
||||
fCurrentUpdateSession->DirtyRegion());
|
||||
if (!dirty) {
|
||||
link.StartMessage(B_ERROR);
|
||||
link.Flush();
|
||||
return;
|
||||
}
|
||||
|
||||
dirty->IntersectWith(&VisibleContentRegion());
|
||||
|
||||
//sCurrentColor.red = rand() % 255;
|
||||
//sCurrentColor.green = rand() % 255;
|
||||
@ -1907,39 +1904,35 @@ Window::BeginUpdate(BPrivate::PortLink& link)
|
||||
//fDrawingEngine->FillRegion(*dirty, sCurrentColor);
|
||||
//snooze(10000);
|
||||
|
||||
link.StartMessage(B_OK);
|
||||
// append the current window geometry to the
|
||||
// message, the client will need it
|
||||
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);
|
||||
// mark the end of the token "list"
|
||||
link.Attach<int32>(B_NULL_TOKEN);
|
||||
link.Flush();
|
||||
link.StartMessage(B_OK);
|
||||
// append the current window geometry to the
|
||||
// message, the client will need it
|
||||
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);
|
||||
// mark the end of the token "list"
|
||||
link.Attach<int32>(B_NULL_TOKEN);
|
||||
link.Flush();
|
||||
|
||||
if (!fCurrentUpdateSession->IsExpose() && fDrawingEngine->LockParallelAccess()) {
|
||||
// supress back to front buffer copies in the drawing engine
|
||||
fDrawingEngine->SetCopyToFrontEnabled(false);
|
||||
|
||||
if (!fCurrentUpdateSession->IsExpose() && fDrawingEngine->LockParallelAccess()) {
|
||||
//fDrawingEngine->FillRegion(dirty, (rgb_color){ 255, 0, 0, 255 });
|
||||
fDrawingEngine->SuspendAutoSync();
|
||||
fDrawingEngine->SuspendAutoSync();
|
||||
|
||||
fTopView->Draw(fDrawingEngine, dirty, &fContentRegion, true);
|
||||
fTopView->Draw(fDrawingEngine, dirty, &fContentRegion, true);
|
||||
|
||||
fDrawingEngine->Sync();
|
||||
fDrawingEngine->UnlockParallelAccess();
|
||||
} // else the background was cleared already
|
||||
fDrawingEngine->Sync();
|
||||
fDrawingEngine->UnlockParallelAccess();
|
||||
} // else the background was cleared already
|
||||
|
||||
fRegionPool.Recycle(dirty);
|
||||
|
||||
} else {
|
||||
printf("BeginUpdate() but no update requested!!\n");
|
||||
link.StartMessage(B_ERROR);
|
||||
link.Flush();
|
||||
fprintf(stderr, "Window::BeginUpdate() - no update requested!\n");
|
||||
}
|
||||
fRegionPool.Recycle(dirty);
|
||||
}
|
||||
|
||||
|
||||
@ -1949,6 +1942,19 @@ Window::EndUpdate()
|
||||
// NOTE: see comment in _BeginUpdate()
|
||||
|
||||
if (fInUpdate) {
|
||||
// reenable copy to front
|
||||
fDrawingEngine->SetCopyToFrontEnabled(true);
|
||||
|
||||
BRegion* dirty = fRegionPool.GetRegion(
|
||||
fCurrentUpdateSession->DirtyRegion());
|
||||
|
||||
if (dirty) {
|
||||
dirty->IntersectWith(&VisibleContentRegion());
|
||||
|
||||
fDrawingEngine->CopyToFront(*dirty);
|
||||
fRegionPool.Recycle(dirty);
|
||||
}
|
||||
|
||||
fCurrentUpdateSession->SetUsed(false);
|
||||
|
||||
fInUpdate = false;
|
||||
|
Loading…
Reference in New Issue
Block a user