From ebe6011c58dbff7507ddca9e8dec7c05cffaf715 Mon Sep 17 00:00:00 2001 From: X512 Date: Sat, 12 Dec 2020 08:35:56 +0900 Subject: [PATCH] app_server: do not flush back buffer outside of clipping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce DrawTransaction that automatically hide/show floating overlays and flush back buffer. Fixes #15574. Change-Id: I30088b74fc66cfcd5b2b433b34141e7d496f68a1 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3496 Reviewed-by: Axel Dörfler --- src/servers/app/drawing/DrawingEngine.cpp | 480 ++++++++---------- src/servers/app/drawing/DrawingEngine.h | 4 +- src/servers/app/drawing/HWInterface.cpp | 2 +- src/servers/app/drawing/HWInterface.h | 2 +- .../interface/remote/RemoteHWInterface.cpp | 2 +- .../interface/remote/RemoteHWInterface.h | 2 +- 6 files changed, 229 insertions(+), 263 deletions(-) diff --git a/src/servers/app/drawing/DrawingEngine.cpp b/src/servers/app/drawing/DrawingEngine.cpp index ac31f87c62..fe61307121 100644 --- a/src/servers/app/drawing/DrawingEngine.cpp +++ b/src/servers/app/drawing/DrawingEngine.cpp @@ -97,6 +97,81 @@ class AutoFloatingOverlaysHider { }; +class DrawTransaction { +public: + DrawTransaction(DrawingEngine *engine, const BRect &bounds) + : + fEngine(engine), + fOverlaysHidden(false) + { + fDirty.Set(bounds); + fDirty.IntersectWith(fEngine->fPainter->ClippingRegion()); + if (fDirty.CountRects() == 0) + return; + fOverlaysHidden + = fEngine->fGraphicsCard->HideFloatingOverlays(fDirty.Frame()); + } + + DrawTransaction(DrawingEngine *engine) + : + fEngine(engine), + fOverlaysHidden(false) + { + fDirty = *fEngine->fPainter->ClippingRegion(); + if (fDirty.CountRects() == 0) + return; + fOverlaysHidden + = fEngine->fGraphicsCard->HideFloatingOverlays(fDirty.Frame()); + } + + DrawTransaction(DrawingEngine *engine, const BRegion ®ion) + : + fEngine(engine), + fOverlaysHidden(false) + { + // region is already clipped + fDirty = region; + if (fDirty.CountRects() == 0) + return; + fOverlaysHidden + = fEngine->fGraphicsCard->HideFloatingOverlays(fDirty.Frame()); + } + + ~DrawTransaction() + { + if (fEngine->fCopyToFront) + fEngine->fGraphicsCard->InvalidateRegion(fDirty); + if (fOverlaysHidden) + fEngine->fGraphicsCard->ShowFloatingOverlays(); + } + + bool IsDirty() const + { + return fDirty.CountRects() > 0; + } + + void SetDirty(const BRect &rect) + { + fDirty.Set(rect); + fDirty.IntersectWith(fEngine->fPainter->ClippingRegion()); + } + + const BRegion &DirtyRegion() const + { + return fDirty; + } + + bool WasOverlaysHidden() const + { + return fOverlaysHidden; + } + +private: + DrawingEngine *fEngine; + bool fOverlaysHidden; + BRegion fDirty; +}; + // #pragma mark - @@ -476,6 +551,7 @@ void DrawingEngine::CopyRegion(/*const*/ BRegion* region, int32 xOffset, int32 yOffset) { + // NOTE: region is already clipped ASSERT_PARALLEL_LOCKED(); BRect frame = region->Frame(); @@ -604,12 +680,10 @@ DrawingEngine::InvertRect(BRect r) make_rect_valid(r); // NOTE: Currently ignores view transformation, so no TransformAndClipRect() - r = fPainter->ClipRect(r); - if (!r.IsValid()) + DrawTransaction transaction(this, fPainter->ClipRect(r)); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider _(fGraphicsCard, r); - // try hardware optimized version first if (fAvailableHWAccleration & HW_ACC_INVERT_REGION) { BRegion region(r); @@ -618,8 +692,6 @@ DrawingEngine::InvertRect(BRect r) } else { fPainter->InvertRect(r); } - - _CopyToFront(r); } @@ -629,14 +701,9 @@ DrawingEngine::DrawBitmap(ServerBitmap* bitmap, const BRect& bitmapRect, { ASSERT_PARALLEL_LOCKED(); - BRect clipped = fPainter->TransformAndClipRect(viewRect); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - + DrawTransaction transaction(this, fPainter->TransformAndClipRect(viewRect)); + if (transaction.IsDirty()) fPainter->DrawBitmap(bitmap, bitmapRect, viewRect, options); - - _CopyToFront(clipped); - } } @@ -649,26 +716,22 @@ DrawingEngine::DrawArc(BRect r, const float& angle, const float& span, make_rect_valid(r); fPainter->AlignEllipseRect(&r, filled); + BRect clipped(r); if (!filled) - extend_by_stroke_width(r, fPainter->PenSize()); + extend_by_stroke_width(clipped, fPainter->PenSize()); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; - BRect clipped(fPainter->TransformAndClipRect(r)); + float xRadius = r.Width() / 2.0; + float yRadius = r.Height() / 2.0; + BPoint center(r.left + xRadius, + r.top + yRadius); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - - float xRadius = r.Width() / 2.0; - float yRadius = r.Height() / 2.0; - BPoint center(r.left + xRadius, - r.top + yRadius); - - if (filled) - fPainter->FillArc(center, xRadius, yRadius, angle, span); - else - fPainter->StrokeArc(center, xRadius, yRadius, angle, span); - - _CopyToFront(clipped); - } + if (filled) + fPainter->FillArc(center, xRadius, yRadius, angle, span); + else + fPainter->StrokeArc(center, xRadius, yRadius, angle, span); } @@ -680,20 +743,16 @@ DrawingEngine::FillArc(BRect r, const float& angle, const float& span, make_rect_valid(r); fPainter->AlignEllipseRect(&r, true); - BRect clipped(fPainter->TransformAndClipRect(r)); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(r)); + if (!transaction.IsDirty()) + return; - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + float xRadius = r.Width() / 2.0; + float yRadius = r.Height() / 2.0; + BPoint center(r.left + xRadius, + r.top + yRadius); - float xRadius = r.Width() / 2.0; - float yRadius = r.Height() / 2.0; - BPoint center(r.left + xRadius, - r.top + yRadius); - - fPainter->FillArc(center, xRadius, yRadius, angle, span, gradient); - - _CopyToFront(clipped); - } + fPainter->FillArc(center, xRadius, yRadius, angle, span, gradient); } @@ -703,11 +762,9 @@ DrawingEngine::DrawBezier(BPoint* pts, bool filled) ASSERT_PARALLEL_LOCKED(); // TODO: figure out bounds and hide cursor depending on that - AutoFloatingOverlaysHider _(fGraphicsCard); + DrawTransaction transaction(this); - BRect touched = fPainter->DrawBezier(pts, filled); - - _CopyToFront(touched); + transaction.SetDirty(fPainter->DrawBezier(pts, filled)); } @@ -717,11 +774,9 @@ DrawingEngine::FillBezier(BPoint* pts, const BGradient& gradient) ASSERT_PARALLEL_LOCKED(); // TODO: figure out bounds and hide cursor depending on that - AutoFloatingOverlaysHider _(fGraphicsCard); + DrawTransaction transaction(this); - BRect touched = fPainter->FillBezier(pts, gradient); - - _CopyToFront(touched); + transaction.SetDirty(fPainter->FillBezier(pts, gradient)); } @@ -742,15 +797,11 @@ DrawingEngine::DrawEllipse(BRect r, bool filled) clipped.right = ceilf(clipped.right); clipped.bottom = ceilf(clipped.bottom); - clipped = fPainter->TransformAndClipRect(clipped); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - - fPainter->DrawEllipse(r, filled); - - _CopyToFront(clipped); - } + fPainter->DrawEllipse(r, filled); } @@ -768,15 +819,11 @@ DrawingEngine::FillEllipse(BRect r, const BGradient& gradient) clipped.right = ceilf(clipped.right); clipped.bottom = ceilf(clipped.bottom); - clipped = fPainter->TransformAndClipRect(clipped); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - - fPainter->FillEllipse(r, gradient); - - _CopyToFront(clipped); - } + fPainter->FillEllipse(r, gradient); } @@ -789,14 +836,11 @@ DrawingEngine::DrawPolygon(BPoint* ptlist, int32 numpts, BRect bounds, make_rect_valid(bounds); if (!filled) extend_by_stroke_width(bounds, fPainter->PenSize()); - bounds = fPainter->TransformAndClipRect(bounds); - if (bounds.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, bounds); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(bounds)); + if (!transaction.IsDirty()) + return; - fPainter->DrawPolygon(ptlist, numpts, filled, closed); - - _CopyToFront(bounds); - } + fPainter->DrawPolygon(ptlist, numpts, filled, closed); } @@ -807,14 +851,11 @@ DrawingEngine::FillPolygon(BPoint* ptlist, int32 numpts, BRect bounds, ASSERT_PARALLEL_LOCKED(); make_rect_valid(bounds); - bounds = fPainter->TransformAndClipRect(bounds); - if (bounds.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, bounds); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(bounds)); + if (!transaction.IsDirty()) + return; - fPainter->FillPolygon(ptlist, numpts, gradient, closed); - - _CopyToFront(bounds); - } + fPainter->FillPolygon(ptlist, numpts, gradient, closed); } @@ -840,7 +881,7 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end, BRect touched(start, end); make_rect_valid(touched); touched = fPainter->ClipRect(touched); - AutoFloatingOverlaysHider _(fGraphicsCard, touched); + DrawTransaction transaction(this, touched); if (!fPainter->StraightLine(start, end, color)) { rgb_color previousColor = fPainter->HighColor(); @@ -853,8 +894,6 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end, fPainter->SetDrawingMode(previousMode); fPainter->SetHighColor(previousColor); } - - _CopyToFront(touched); } @@ -865,14 +904,11 @@ DrawingEngine::StrokeRect(BRect r, const rgb_color& color) ASSERT_PARALLEL_LOCKED(); make_rect_valid(r); - BRect clipped = fPainter->ClipRect(r); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, fPainter->ClipRect(r)); + if (!transaction.IsDirty()) + return; - fPainter->StrokeRect(r, color); - - _CopyToFront(clipped); - } + fPainter->StrokeRect(r, color); } @@ -886,22 +922,19 @@ DrawingEngine::FillRect(BRect r, const rgb_color& color) // gut feeling. make_rect_valid(r); r = fPainter->ClipRect(r); - if (!r.IsValid()) + DrawTransaction transaction(this, r); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, r); - // try hardware optimized version first if (fAvailableHWAccleration & HW_ACC_FILL_REGION) { BRegion region(r); region.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->FillRegion(region, color, - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); + fSuspendSyncLevel == 0 || transaction.WasOverlaysHidden()); } else { fPainter->FillRect(r, color); } - - _CopyToFront(r); } @@ -927,20 +960,18 @@ DrawingEngine::FillRegion(BRegion& r, const rgb_color& color) return; } - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, frame); + DrawTransaction transaction(this, r); // try hardware optimized version first if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0 && frame.Width() * frame.Height() > 100) { fGraphicsCard->FillRegion(r, color, fSuspendSyncLevel == 0 - || overlaysHider.WasHidden()); + || transaction.WasOverlaysHidden()); } else { int32 count = r.CountRects(); for (int32 i = 0; i < count; i++) fPainter->FillRectNoClipping(r.RectAtInt(i), color); } - - _CopyToFront(frame); } @@ -956,14 +987,11 @@ DrawingEngine::StrokeRect(BRect r) make_rect_valid(r); BRect clipped(r); extend_by_stroke_width(clipped, fPainter->PenSize()); - clipped = fPainter->TransformAndClipRect(clipped); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; - fPainter->StrokeRect(r); - - _CopyToFront(clipped); - } + fPainter->StrokeRect(r); } @@ -976,14 +1004,10 @@ DrawingEngine::FillRect(BRect r) r = fPainter->AlignRect(r); - BRect dirty = fPainter->TransformAndClipRect(r); - if (!dirty.IsValid()) + DrawTransaction transaction(this, fPainter->TransformAndClipRect(r)); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, dirty); - - bool doInSoftware = true; - if (fPainter->IsIdentityTransform()) { // TODO the accelerated code path may also be used for transforms that // only scale and translate (but don't shear or rotate). @@ -998,34 +1022,32 @@ DrawingEngine::FillRect(BRect r) BRegion region(r); region.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->FillRegion(region, fPainter->HighColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; + fSuspendSyncLevel == 0 + || transaction.WasOverlaysHidden()); + return; } else if (fPainter->Pattern() == B_SOLID_LOW && fPainter->DrawingMode() == B_OP_COPY) { BRegion region(r); region.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->FillRegion(region, fPainter->LowColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; + fSuspendSyncLevel == 0 + || transaction.WasOverlaysHidden()); + return; } } } - if (doInSoftware - && (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 + if ((fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 && fPainter->Pattern() == B_SOLID_HIGH && fPainter->DrawingMode() == B_OP_INVERT) { BRegion region(r); region.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->InvertRegion(region); - doInSoftware = false; + return; } } - if (doInSoftware) - fPainter->FillRect(r); - - _CopyToFront(dirty); + fPainter->FillRect(r); } @@ -1037,15 +1059,11 @@ DrawingEngine::FillRect(BRect r, const BGradient& gradient) make_rect_valid(r); r = fPainter->AlignRect(r); - BRect dirty = fPainter->TransformAndClipRect(r); - if (!dirty.IsValid()) + DrawTransaction transaction(this, fPainter->TransformAndClipRect(r)); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, dirty); - fPainter->FillRect(r, gradient); - - _CopyToFront(dirty); } @@ -1055,13 +1073,10 @@ DrawingEngine::FillRegion(BRegion& r) ASSERT_PARALLEL_LOCKED(); BRect clipped = fPainter->TransformAndClipRect(r.Frame()); - if (!clipped.IsValid()) + DrawTransaction transaction(this, clipped); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, clipped); - - bool doInSoftware = true; - if (fPainter->IsIdentityTransform()) { // try hardware optimized version first if ((fAvailableHWAccleration & HW_ACC_FILL_REGION) != 0) { @@ -1070,36 +1085,29 @@ DrawingEngine::FillRegion(BRegion& r) || fPainter->DrawingMode() == B_OP_OVER)) { r.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->FillRegion(r, fPainter->HighColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; + fSuspendSyncLevel == 0 || transaction.WasOverlaysHidden()); + return; } else if (fPainter->Pattern() == B_SOLID_LOW && fPainter->DrawingMode() == B_OP_COPY) { r.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->FillRegion(r, fPainter->LowColor(), - fSuspendSyncLevel == 0 || overlaysHider.WasHidden()); - doInSoftware = false; + fSuspendSyncLevel == 0 || transaction.WasOverlaysHidden()); + return; } } - if (doInSoftware - && (fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 + if ((fAvailableHWAccleration & HW_ACC_INVERT_REGION) != 0 && fPainter->Pattern() == B_SOLID_HIGH && fPainter->DrawingMode() == B_OP_INVERT) { r.IntersectWith(fPainter->ClippingRegion()); fGraphicsCard->InvertRegion(r); - doInSoftware = false; + return; } } - if (doInSoftware) { - BRect touched = fPainter->FillRect(r.RectAt(0)); - - int32 count = r.CountRects(); - for (int32 i = 1; i < count; i++) - touched = touched | fPainter->FillRect(r.RectAt(i)); - } - - _CopyToFront(r.Frame()); + int32 count = r.CountRects(); + for (int32 i = 0; i < count; i++) + fPainter->FillRect(r.RectAt(i)); } @@ -1109,18 +1117,13 @@ DrawingEngine::FillRegion(BRegion& r, const BGradient& gradient) ASSERT_PARALLEL_LOCKED(); BRect clipped = fPainter->TransformAndClipRect(r.Frame()); - if (!clipped.IsValid()) + DrawTransaction transaction(this, clipped); + if (!transaction.IsDirty()) return; - AutoFloatingOverlaysHider overlaysHider(fGraphicsCard, clipped); - - BRect touched = fPainter->FillRect(r.RectAt(0), gradient); - int32 count = r.CountRects(); - for (int32 i = 1; i < count; i++) - touched = touched | fPainter->FillRect(r.RectAt(i), gradient); - - _CopyToFront(r.Frame()); + for (int32 i = 0; i < count; i++) + fPainter->FillRect(r.RectAt(i), gradient); } @@ -1139,14 +1142,14 @@ DrawingEngine::DrawRoundRect(BRect r, float xrad, float yrad, bool filled) clipped.right = ceilf(clipped.right); clipped.bottom = ceilf(clipped.bottom); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, clipped); + if (!transaction.IsDirty()) + return; - BRect touched = filled ? fPainter->FillRoundRect(r, xrad, yrad) - : fPainter->StrokeRoundRect(r, xrad, yrad); - - _CopyToFront(touched); - } + if (filled) + fPainter->FillRoundRect(r, xrad, yrad); + else + fPainter->StrokeRoundRect(r, xrad, yrad); } @@ -1164,13 +1167,11 @@ DrawingEngine::FillRoundRect(BRect r, float xrad, float yrad, clipped.right = ceilf(clipped.right); clipped.bottom = ceilf(clipped.bottom); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, clipped); + if (!transaction.IsDirty()) + return; - BRect touched = fPainter->FillRoundRect(r, xrad, yrad, gradient); - - _CopyToFront(touched); - } + fPainter->FillRoundRect(r, xrad, yrad, gradient); } @@ -1192,16 +1193,13 @@ DrawingEngine::DrawShape(const BRect& bounds, int32 opCount, // clipped.right = ceilf(clipped.right); // clipped.bottom = ceilf(clipped.bottom); // -// if (!clipped.IsValid()) +// DrawTransaction transaction(this, clipped); +// if (!transaction.IsDirty()) // return; -// -// AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - AutoFloatingOverlaysHider _(fGraphicsCard); + DrawTransaction transaction(this); - BRect touched = fPainter->DrawShape(opCount, opList, ptCount, ptList, - filled, viewToScreenOffset, viewScale); - - _CopyToFront(touched); + transaction.SetDirty(fPainter->DrawShape(opCount, opList, ptCount, ptList, + filled, viewToScreenOffset, viewScale)); } @@ -1221,16 +1219,13 @@ DrawingEngine::FillShape(const BRect& bounds, int32 opCount, // clipped.right = ceilf(clipped.right); // clipped.bottom = ceilf(clipped.bottom); // -// if (!clipped.IsValid()) +// DrawTransaction transaction(this, clipped); +// if (!transaction.IsDirty()) // return; -// -// AutoFloatingOverlaysHider _(fGraphicsCard, clipped); - AutoFloatingOverlaysHider _(fGraphicsCard); + DrawTransaction transaction(this); - BRect touched = fPainter->FillShape(opCount, opList, ptCount, ptList, - gradient, viewToScreenOffset, viewScale); - - _CopyToFront(touched); + transaction.SetDirty(fPainter->FillShape(opCount, opList, ptCount, ptList, + gradient, viewToScreenOffset, viewScale)); } @@ -1242,17 +1237,14 @@ DrawingEngine::DrawTriangle(BPoint* pts, const BRect& bounds, bool filled) BRect clipped(bounds); if (!filled) extend_by_stroke_width(clipped, fPainter->PenSize()); - clipped = fPainter->TransformAndClipRect(clipped); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(clipped)); + if (!transaction.IsDirty()) + return; - if (filled) - fPainter->FillTriangle(pts[0], pts[1], pts[2]); - else - fPainter->StrokeTriangle(pts[0], pts[1], pts[2]); - - _CopyToFront(clipped); - } + if (filled) + fPainter->FillTriangle(pts[0], pts[1], pts[2]); + else + fPainter->StrokeTriangle(pts[0], pts[1], pts[2]); } @@ -1262,15 +1254,11 @@ DrawingEngine::FillTriangle(BPoint* pts, const BRect& bounds, { ASSERT_PARALLEL_LOCKED(); - BRect clipped(bounds); - clipped = fPainter->TransformAndClipRect(clipped); - if (clipped.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, clipped); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(bounds)); + if (!transaction.IsDirty()) + return; - fPainter->FillTriangle(pts[0], pts[1], pts[2], gradient); - - _CopyToFront(clipped); - } + fPainter->FillTriangle(pts[0], pts[1], pts[2], gradient); } @@ -1282,14 +1270,11 @@ DrawingEngine::StrokeLine(const BPoint& start, const BPoint& end) BRect touched(start, end); make_rect_valid(touched); extend_by_stroke_width(touched, fPainter->PenSize()); - touched = fPainter->TransformAndClipRect(touched); - if (touched.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, touched); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(touched)); + if (!transaction.IsDirty()) + return; - fPainter->StrokeLine(start, end); - - _CopyToFront(touched); - } + fPainter->StrokeLine(start, end); } @@ -1318,33 +1303,30 @@ DrawingEngine::StrokeLineArray(int32 numLines, touched = touched | box; } extend_by_stroke_width(touched, fPainter->PenSize()); - touched = fPainter->TransformAndClipRect(touched); - if (touched.IsValid()) { - AutoFloatingOverlaysHider _(fGraphicsCard, touched); + DrawTransaction transaction(this, fPainter->TransformAndClipRect(touched)); + if (!transaction.IsDirty()) + return; - data = (const ViewLineArrayInfo*)&(lineData[0]); + data = (const ViewLineArrayInfo*)&(lineData[0]); - // store current graphics state, we mess with the - // high color and pattern... - rgb_color oldColor = fPainter->HighColor(); - struct pattern pattern = fPainter->Pattern(); + // store current graphics state, we mess with the + // high color and pattern... + rgb_color oldColor = fPainter->HighColor(); + struct pattern pattern = fPainter->Pattern(); + fPainter->SetHighColor(data->color); + fPainter->SetPattern(B_SOLID_HIGH); + fPainter->StrokeLine(data->startPoint, data->endPoint); + + for (int32 i = 1; i < numLines; i++) { + data = (const ViewLineArrayInfo*)&(lineData[i]); fPainter->SetHighColor(data->color); - fPainter->SetPattern(B_SOLID_HIGH); fPainter->StrokeLine(data->startPoint, data->endPoint); - - for (int32 i = 1; i < numLines; i++) { - data = (const ViewLineArrayInfo*)&(lineData[i]); - fPainter->SetHighColor(data->color); - fPainter->StrokeLine(data->startPoint, data->endPoint); - } - - // restore correct drawing state highcolor and pattern - fPainter->SetHighColor(oldColor); - fPainter->SetPattern(pattern); - - _CopyToFront(touched); } + + // restore correct drawing state highcolor and pattern + fPainter->SetHighColor(oldColor); + fPainter->SetPattern(pattern); } @@ -1388,17 +1370,13 @@ DrawingEngine::DrawString(const char* string, int32 length, BRect b = fPainter->BoundingBox(string, length, pt, &penLocation, delta, &cacheReference); // stop here if we're supposed to render outside of the clipping - b = fPainter->ClipRect(b); - if (b.IsValid()) { + DrawTransaction transaction(this, fPainter->ClipRect(b)); + if (transaction.IsDirty()) { //printf("bounding box '%s': %lld µs\n", string, system_time() - now); - AutoFloatingOverlaysHider _(fGraphicsCard, b); //now = system_time(); - BRect touched = fPainter->DrawString(string, length, pt, delta, - &cacheReference); + fPainter->DrawString(string, length, pt, delta, &cacheReference); //printf("drawing string: %lld µs\n", system_time() - now); - - _CopyToFront(touched); } return penLocation; @@ -1419,17 +1397,13 @@ DrawingEngine::DrawString(const char* string, int32 length, BRect b = fPainter->BoundingBox(string, length, offsets, &penLocation, &cacheReference); // stop here if we're supposed to render outside of the clipping - b = fPainter->ClipRect(b); - if (b.IsValid()) { + DrawTransaction transaction(this, fPainter->ClipRect(b)); + if (transaction.IsDirty()) { //printf("bounding box '%s': %lld µs\n", string, system_time() - now); - AutoFloatingOverlaysHider _(fGraphicsCard, b); //now = system_time(); - BRect touched = fPainter->DrawString(string, length, offsets, - &cacheReference); + fPainter->DrawString(string, length, offsets, &cacheReference); //printf("drawing string: %lld µs\n", system_time() - now); - - _CopyToFront(touched); } return penLocation; @@ -1667,11 +1641,3 @@ DrawingEngine::_CopyRect(uint8* src, uint32 width, uint32 height, } } } - - -inline void -DrawingEngine::_CopyToFront(const BRect& frame) -{ - if (fCopyToFront) - fGraphicsCard->Invalidate(frame); -} diff --git a/src/servers/app/drawing/DrawingEngine.h b/src/servers/app/drawing/DrawingEngine.h index 6c1c62546d..4d87c40180 100644 --- a/src/servers/app/drawing/DrawingEngine.h +++ b/src/servers/app/drawing/DrawingEngine.h @@ -201,12 +201,12 @@ public: void SetRendererOffset(int32 offsetX, int32 offsetY); private: + friend class DrawTransaction; + void _CopyRect(uint8* bits, uint32 width, uint32 height, uint32 bytesPerRow, int32 xOffset, int32 yOffset) const; - inline void _CopyToFront(const BRect& frame); - ObjectDeleter fPainter; HWInterface* fGraphicsCard; diff --git a/src/servers/app/drawing/HWInterface.cpp b/src/servers/app/drawing/HWInterface.cpp index c449f13810..bb1d9c4119 100644 --- a/src/servers/app/drawing/HWInterface.cpp +++ b/src/servers/app/drawing/HWInterface.cpp @@ -317,7 +317,7 @@ HWInterface::IsDoubleBuffered() const /*! The object needs to be already locked! */ status_t -HWInterface::InvalidateRegion(BRegion& region) +HWInterface::InvalidateRegion(const BRegion& region) { int32 count = region.CountRects(); for (int32 i = 0; i < count; i++) { diff --git a/src/servers/app/drawing/HWInterface.h b/src/servers/app/drawing/HWInterface.h index a656ac089f..24c6618918 100644 --- a/src/servers/app/drawing/HWInterface.h +++ b/src/servers/app/drawing/HWInterface.h @@ -168,7 +168,7 @@ public: virtual bool IsDoubleBuffered() const; // Invalidate is used for scheduling an area for updating - virtual status_t InvalidateRegion(BRegion& region); + virtual status_t InvalidateRegion(const BRegion& region); virtual status_t Invalidate(const BRect& frame); // while as CopyBackToFront() actually performs the operation // either directly or asynchronously by the UpdateQueue thread diff --git a/src/servers/app/drawing/interface/remote/RemoteHWInterface.cpp b/src/servers/app/drawing/interface/remote/RemoteHWInterface.cpp index 290c9c0577..0362699f50 100644 --- a/src/servers/app/drawing/interface/remote/RemoteHWInterface.cpp +++ b/src/servers/app/drawing/interface/remote/RemoteHWInterface.cpp @@ -575,7 +575,7 @@ RemoteHWInterface::IsDoubleBuffered() const status_t -RemoteHWInterface::InvalidateRegion(BRegion& region) +RemoteHWInterface::InvalidateRegion(const BRegion& region) { RemoteMessage message(NULL, fSendBuffer.Get()); message.Start(RP_INVALIDATE_REGION); diff --git a/src/servers/app/drawing/interface/remote/RemoteHWInterface.h b/src/servers/app/drawing/interface/remote/RemoteHWInterface.h index e6aa514b49..6dedb5f7e4 100644 --- a/src/servers/app/drawing/interface/remote/RemoteHWInterface.h +++ b/src/servers/app/drawing/interface/remote/RemoteHWInterface.h @@ -76,7 +76,7 @@ virtual RenderingBuffer* FrontBuffer() const; virtual RenderingBuffer* BackBuffer() const; virtual bool IsDoubleBuffered() const; -virtual status_t InvalidateRegion(BRegion& region); +virtual status_t InvalidateRegion(const BRegion& region); virtual status_t Invalidate(const BRect& frame); virtual status_t CopyBackToFront(const BRect& frame);