From 97ee7d0a557283d65918c9eb9e4c2958d0f1928d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Mon, 12 May 2008 21:10:05 +0000 Subject: [PATCH] When drawing is double buffered, there is no excuse for a flickering cursor (including any drag bitmap). HWInterface::HideFloatingOverlays() was plain stupid, I know it did check double buffering at one point, but I must have removed that when messing with it. But copying anything from back to front buffer is now not overwriting the cursor area anymore, which is painted immediatly afterwards. Also moving the cursor invalidates only one rect if old and new cursor area overlap. All these changes should save some cycles too. Added TODO with regard to caching the on-the-fly cursor compositing buffer. If you have * a more recent computer * a decent VESA BIOS which supports your native resolution * don't need video overlays ... I recommend using the VESA driver. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25479 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/servers/app/drawing/HWInterface.cpp | 36 ++++++++++++++++--------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index 64ae40681e..ab0bc387a7 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -226,7 +226,7 @@ HWInterface::MoveCursorTo(const float& x, const float& y) if (fCursorObscured) { SetCursorVisible(true); } - BRect oldFrame = _CursorFrame(); + IntRect oldFrame = _CursorFrame(); fCursorLocation = p; if (fCursorVisible) { // Invalidate and _DrawCursor would not draw @@ -238,8 +238,13 @@ HWInterface::MoveCursorTo(const float& x, const float& y) _RestoreCursorArea(); _DrawCursor(_CursorFrame()); } - Invalidate(oldFrame); - Invalidate(_CursorFrame()); + IntRect newFrame = _CursorFrame(); + if (newFrame.Intersects(oldFrame)) + Invalidate(oldFrame | newFrame); + else { + Invalidate(oldFrame); + Invalidate(newFrame); + } } } fFloatingOverlaysLock.Unlock(); @@ -334,16 +339,18 @@ HWInterface::CopyBackToFront(const BRect& frame) uint32 srcBPR = backBuffer->BytesPerRow(); uint8* src = (uint8*)backBuffer->Bits(); - // convert to integer coordinates - int32 left = (int32)floorf(area.left); - int32 top = (int32)floorf(area.top); - int32 right = (int32)ceilf(area.right); - int32 bottom = (int32)ceilf(area.bottom); + BRegion region((BRect)area); + if (IsDoubleBuffered()) + region.Exclude((clipping_rect)_CursorFrame()); + + int32 count = region.CountRects(); + for (int32 i = 0; i < count; i++) { + clipping_rect r = region.RectAtInt(i); + // offset to left top pixel in source buffer (always B_RGBA32) + uint8* srcOffset = src + r.top * srcBPR + r.left * 4; + _CopyToFront(srcOffset, srcBPR, r.left, r.top, r.right, r.bottom); + } - // offset to left top pixel in source buffer (always B_RGBA32) - src += top * srcBPR + left * 4; - - _CopyToFront(src, srcBPR, left, top, right, bottom); _DrawCursor(area); return B_OK; @@ -415,6 +422,8 @@ HWInterface::HideOverlay(Overlay* overlay) bool HWInterface::HideFloatingOverlays(const BRect& area) { + if (IsDoubleBuffered()) + return false; if (!fFloatingOverlaysLock.Lock()) return false; if (fCursorAreaBackup && !fCursorAreaBackup->cursor_hidden) { @@ -436,6 +445,8 @@ HWInterface::HideFloatingOverlays(const BRect& area) bool HWInterface::HideFloatingOverlays() { + if (IsDoubleBuffered()) + return false; if (!fFloatingOverlaysLock.Lock()) return false; @@ -505,6 +516,7 @@ HWInterface::_DrawCursor(IntRect area) const // blending buffer uint8* buffer = new uint8[width * height * 4]; + // TODO: cache this buffer // offset into back buffer uint8* src = (uint8*)backBuffer->Bits();