vcl/inc/skia/gdiimpl.hxx | 1 vcl/skia/gdiimpl.cxx | 61 ++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 11 deletions(-)
New commits: commit b43255af2d8f9f7cc8c1e5ed15de398695b29048 Author: Luboš Luňák <l.lu...@collabora.com> AuthorDate: Wed Jan 15 11:26:49 2020 +0100 Commit: Luboš Luňák <l.lu...@collabora.com> CommitDate: Thu Jan 16 16:34:44 2020 +0100 limit the area where we manually do xor drawing in Skia Just in case. Without this vcldemo starts rather slowly, because it does xor drawing extensively (although I expect vcldemo is a rather unrealistic use case). Change-Id: Id6b0893d93f82d63863a3bbc520804e03b31cc0b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86834 Tested-by: Jenkins Reviewed-by: Luboš Luňák <l.lu...@collabora.com> diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index fd7cafc387db..f1ddc20bdf01 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -275,6 +275,7 @@ protected: bool mXorMode; SkBitmap mXorBitmap; std::unique_ptr<SkCanvas> mXorCanvas; + SkRect mXorExtents; // the area that needs updating for the xor operation (or empty for all) std::unique_ptr<SkiaFlushIdle> mFlush; }; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 7acd7e20e413..9e513290f959 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -307,17 +307,32 @@ void SkiaSalGraphicsImpl::destroySurface() void SkiaSalGraphicsImpl::DeInit() { destroySurface(); } -void SkiaSalGraphicsImpl::preDraw() { checkSurface(); } +void SkiaSalGraphicsImpl::preDraw() +{ + checkSurface(); + assert(mXorExtents.isEmpty()); // must be reset in postDraw() +} void SkiaSalGraphicsImpl::postDraw() { if (mXorMode) { // Apply the result from the temporary bitmap manually. This is indeed - // slow, but it doesn't seem to be needed often. It could be optimized - // by knowing the bounds of the xor operation, if needed. - SAL_INFO("vcl.skia", - "applyxor(" << this << "): " << Size(mSurface->width(), mSurface->height())); + // slow, but it doesn't seem to be needed often and can be optimized + // in each operation by setting mXorExtents to the area that should be + // updated. + if (mXorExtents.isEmpty()) + mXorExtents = SkRect::MakeXYWH(0, 0, mSurface->width(), mSurface->height()); + else + { + // Make slightly larger, just in case (rounding, antialiasing,...). + mXorExtents.outset(2, 2); + mXorExtents.intersect(SkRect::MakeXYWH(0, 0, mSurface->width(), mSurface->height())); + } + SAL_INFO("vcl.skia", "applyxor(" + << this << "): " + << tools::Rectangle(mXorExtents.left(), mXorExtents.top(), + mXorExtents.right(), mXorExtents.bottom())); // Copy the surface contents to another pixmap. SkBitmap surfaceBitmap; // Use unpremultiplied alpha format, so that we do not have to do the conversions to get @@ -328,17 +343,17 @@ void SkiaSalGraphicsImpl::postDraw() SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); // copy as is SkCanvas canvas(surfaceBitmap); - canvas.drawImage(mSurface->makeImageSnapshot(), 0, 0, &paint); + canvas.drawImageRect(mSurface->makeImageSnapshot(), mXorExtents, mXorExtents, &paint); // xor to surfaceBitmap assert(surfaceBitmap.info().alphaType() == kUnpremul_SkAlphaType); assert(mXorBitmap.info().alphaType() == kUnpremul_SkAlphaType); assert(surfaceBitmap.bytesPerPixel() == 4); assert(mXorBitmap.bytesPerPixel() == 4); - for (int y = 0; y < surfaceBitmap.height(); ++y) + for (int y = mXorExtents.top(); y < mXorExtents.bottom(); ++y) { - uint8_t* data = static_cast<uint8_t*>(surfaceBitmap.getAddr(0, y)); - const uint8_t* xordata = static_cast<uint8_t*>(mXorBitmap.getAddr(0, y)); - for (int x = 0; x < surfaceBitmap.width(); ++x) + uint8_t* data = static_cast<uint8_t*>(surfaceBitmap.getAddr(mXorExtents.x(), y)); + const uint8_t* xordata = static_cast<uint8_t*>(mXorBitmap.getAddr(mXorExtents.x(), y)); + for (int x = 0; x < mXorExtents.width(); ++x) { *data++ ^= *xordata++; *data++ ^= *xordata++; @@ -349,9 +364,10 @@ void SkiaSalGraphicsImpl::postDraw() } } surfaceBitmap.notifyPixelsChanged(); - mSurface->getCanvas()->drawBitmap(surfaceBitmap, 0, 0, &paint); + mSurface->getCanvas()->drawBitmapRect(surfaceBitmap, mXorExtents, mXorExtents, &paint); mXorCanvas.reset(); mXorBitmap.reset(); + mXorExtents.setEmpty(); } if (!isOffscreen()) { @@ -511,6 +527,8 @@ void SkiaSalGraphicsImpl::drawPixel(long nX, long nY, Color nColor) // Apparently drawPixel() is actually expected to set the pixel and not draw it. paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha getDrawCanvas()->drawPoint(toSkX(nX), toSkY(nY), paint); + if (mXorMode) // limit xor area update + mXorExtents = SkRect::MakeXYWH(nX, nY, 1, 1); postDraw(); } @@ -525,6 +543,8 @@ void SkiaSalGraphicsImpl::drawLine(long nX1, long nY1, long nX2, long nY2) paint.setColor(toSkColor(mLineColor)); paint.setAntiAlias(mParent.getAntiAliasB2DDraw()); getDrawCanvas()->drawLine(toSkX(nX1), toSkY(nY1), toSkX(nX2), toSkY(nY2), paint); + if (mXorMode) // limit xor area update + mXorExtents = SkRect::MakeLTRB(nX1, nY1, nX2 + 1, nY2 + 1); postDraw(); } @@ -550,6 +570,8 @@ void SkiaSalGraphicsImpl::privateDrawAlphaRect(long nX, long nY, long nWidth, lo paint.setStyle(SkPaint::kStroke_Style); canvas->drawIRect(SkIRect::MakeXYWH(nX, nY, nWidth - 1, nHeight - 1), paint); } + if (mXorMode) // limit xor area update + mXorExtents = SkRect::MakeXYWH(nX, nY, nWidth, nHeight); postDraw(); } @@ -640,6 +662,8 @@ bool SkiaSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectTo aPaint.setStyle(SkPaint::kStroke_Style); getDrawCanvas()->drawPath(aPath, aPaint); } + if (mXorMode) // limit xor area update + mXorExtents = aPath.getBounds(); postDraw(); return true; } @@ -726,6 +750,8 @@ bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDev // case as it seems to produce better results. aPath.offset(0.5, 0.5, nullptr); getDrawCanvas()->drawPath(aPath, aPaint); + if (mXorMode) // limit xor area update + mXorExtents = aPath.getBounds(); postDraw(); return true; @@ -765,6 +791,8 @@ void SkiaSalGraphicsImpl::copyArea(long nDestX, long nDestY, long nSrcX, long nS paint.setBlendMode(SkBlendMode::kSrc); // copy as is, including alpha getDrawCanvas()->drawImageRect(image, SkIRect::MakeXYWH(nSrcX, nSrcY, nSrcWidth, nSrcHeight), SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight), &paint); + if (mXorMode) // limit xor area update + mXorExtents = SkRect::MakeXYWH(nDestX, nDestY, nSrcWidth, nSrcHeight); postDraw(); } @@ -791,6 +819,9 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcG SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight), &paint); + if (mXorMode) // limit xor area update + mXorExtents = SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, + rPosAry.mnDestHeight); postDraw(); } @@ -951,6 +982,8 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl aPaint.setBlendMode(SkBlendMode::kDifference); getDrawCanvas()->drawPath(aPath, aPaint); + if (mXorMode) // limit xor area update + mXorExtents = aPath.getBounds(); } else { @@ -999,6 +1032,8 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl } getDrawCanvas()->drawPath(aPath, aPaint); + if (mXorMode) // limit xor area update + mXorExtents = aPath.getBounds(); } postDraw(); } @@ -1062,6 +1097,8 @@ void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_sp<SkIma preDraw(); SAL_INFO("vcl.skia", "drawimage(" << this << "): " << rPosAry << ":" << int(eBlendMode)); getDrawCanvas()->drawImageRect(aImage, aSourceRect, aDestinationRect, &aPaint); + if (mXorMode) // limit xor area update + mXorExtents = aDestinationRect; postDraw(); } @@ -1079,6 +1116,8 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkBitmap& preDraw(); SAL_INFO("vcl.skia", "drawbitmap(" << this << "): " << rPosAry << ":" << int(eBlendMode)); getDrawCanvas()->drawBitmapRect(aBitmap, aSourceRect, aDestinationRect, &aPaint); + if (mXorMode) // limit xor area update + mXorExtents = aDestinationRect; postDraw(); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits