[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |1 + vcl/skia/salbmp.cxx | 39 +++ 2 files changed, 32 insertions(+), 8 deletions(-) New commits: commit 5baac4e53128d3c0fc73b9918dc9a9c2777ace08 Author: Patrick Luby AuthorDate: Fri Aug 18 15:14:18 2023 -0400 Commit: Patrick Luby CommitDate: Sat Aug 19 15:59:14 2023 +0200 Reimplement fix for tdf#156629 and tdf#156630 Reimplement fix in commit 926c5246b6694d469a6caed5d7ea4c3a68648468 in an attempt to reduce the fix's performance hit. Instead of invoking EnsureBitmapData() and converting the SkImage to a memory buffer, any pending scaling on alpha masks is handled by creating a new, scaled SkImage. Note that in commit 926c5246b6694d469a6caed5d7ea4c3a68648468, EnsureBitmapData() was invoked which converted the SkImage to a memory buffer. That in turn would make Invert() a noop which fixed the related bug where an image has been opened and, before it has been printed or run in a slideshow, the alpha mask would unexpectedly be inverted. So keep this immutable behavior without calling EnsureBitmapData() by adding a new mutability flag. Change-Id: I99dc272b40c53664ea49333402a6a637b1548a5f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155850 Tested-by: Jenkins Reviewed-by: Patrick Luby diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 3c8b1a964806..c42aa30f4654 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -211,6 +211,7 @@ private: boost::shared_ptr mBuffer; int mScanlineSize; // size of one row in mBuffer (based on mPixelsSize) sk_sp mImage; // possibly GPU-backed +bool mImageImmutable = false; sk_sp mAlphaImage; // cached contents as alpha image, possibly GPU-backed // Actual scaling triggered by scale() is done on-demand. This is the size of the pixel // data in mBuffer, if it differs from mSize, then there is a scaling operation pending. diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index eac913671384..2aa9a0a69cee 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -164,6 +164,7 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, vcl::PixelFormat eNewPixelF ResetAllData(); const SkiaSalBitmap& src = static_cast(rSalBmp); mImage = src.mImage; +mImageImmutable = src.mImageImmutable; mAlphaImage = src.mAlphaImage; mBuffer = src.mBuffer; mPalette = src.mPalette; @@ -224,7 +225,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) assert(!mEraseColorSet); break; case BitmapAccessMode::Info: -// Related tdf#156630 and tdf#156629 force snapshot of alpha mask +// Related tdf#156629 and tdf#156630 force snapshot of alpha mask // On macOS, with Skia/Metal or Skia/Raster with a Retina display // (i.e. 2.0 window scale), the alpha mask gets upscaled in certain // cases. @@ -236,9 +237,24 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) // fail: // https://bugs.documentfoundation.org/attachment.cgi?id=188792 static const bool bForceHiDPIScaling = getenv("SAL_FORCE_HIDPI_SCALING") != nullptr; -if (mPixelsSize != mSize || (bForceHiDPIScaling && mImage)) -EnsureBitmapData(); -assert(mPixelsSize == mSize); +if (mImage && !mImageImmutable && mBitCount == 8 && mPalette.IsGreyPalette8Bit() +&& (mPixelsSize != mSize || bForceHiDPIScaling)) +{ +ResetToSkImage(GetSkImage()); +ResetPendingScaling(); +assert(mPixelsSize == mSize); + +// When many of the images affected by tdf#156629 and +// tdf#156630 are exported to PDF the first time after the +// image has been opened and before it has been printed or run +// in a slideshow, the alpha mask will unexpectedly be +// inverted. Fix that by marking this alpha mask as immutable +// so that when Invert() is called on this alpha mask, it will +// be a noop. Invert() is a noop after EnsureBitmapData() is +// called but we don't want to call that due to performance +// so set a flag instead. +mImageImmutable = true; +} break; } #ifdef DBG_UTIL @@ -653,17 +669,18 @@ bool SkiaSalBitmap::Invert() // Normally this would need to convert contents of mBuffer for all possible formats, // so just let the VCL algorithm do it. // Avoid the costly SkImage->buffer->SkImage conversion. -if (!mBuffer && mImage && !mEraseColorSet) +if (!mBuffer && mImage && !mImageImmutable && !mEraseColorSet) { // This is 8-bit bitmap serving as alpha/transparency/mask, so the image
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source
vcl/inc/salbmp.hxx|5 + vcl/inc/skia/salbmp.hxx |1 + vcl/skia/salbmp.cxx | 25 + vcl/source/bitmap/bitmappaint.cxx |2 +- 4 files changed, 32 insertions(+), 1 deletion(-) New commits: commit 72f2de04a23680fcb75cf5bc89b3422f9e89cdef Author: Noel Grandin AuthorDate: Fri Jun 30 15:02:16 2023 +0200 Commit: Noel Grandin CommitDate: Sun Jul 2 16:57:46 2023 +0200 optimised Skia Invert() operation which is not that important right now, but my upcoming transparency->alpha patch will make more heavy use of Invert(), and this change will reduce the cost of that Change-Id: I53d8dfbf153f16f4d94022527c71d70d08392dfc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/153857 Tested-by: Jenkins Reviewed-by: Noel Grandin diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx index 2b93fb4d..3f9dafab15dc 100644 --- a/vcl/inc/salbmp.hxx +++ b/vcl/inc/salbmp.hxx @@ -104,6 +104,11 @@ public: return false; } +virtual boolInvert() +{ +return false; +} + #if defined MACOSX || defined IOS // Related: tdf#146842 Eliminate temporary copies of SkiaSalBitmap when // printing diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 8a974f08566c..3c8b1a964806 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -64,6 +64,7 @@ public: virtual bool ConvertToGreyscale() override; virtual bool Erase(const Color& color) override; virtual bool AlphaBlendWith(const SalBitmap& rSalBmp) override; +virtual bool Invert() override; #if defined MACOSX || defined IOS virtual CGImageRef CreateWithMask(const SalBitmap& rMask, int nX, int nY, int nWidth, int nHeight) const override; diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 57cea14316c5..1ce85dd0e837 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -623,6 +623,31 @@ bool SkiaSalBitmap::AlphaBlendWith(const SalBitmap& rSalBmp) return true; } +bool SkiaSalBitmap::Invert() +{ +#ifdef DBG_UTIL +assert(mWriteAccessCount == 0); +#endif +// Normally this would need to convert contents of mBuffer for all possible formats, +// so just let the VCL algorithm do it. +// Avoid the costly SkImage->buffer->SkImage conversion. +if (!mBuffer && mImage && !mEraseColorSet) +{ +// This is 8-bit bitmap serving as alpha/transparency/mask, so the image itself needs no alpha. +sk_sp surface = createSkSurface(mSize, kOpaque_SkAlphaType); +surface->getCanvas()->clear(SK_ColorWHITE); +SkPaint paint; +paint.setBlendMode(SkBlendMode::kDifference); +surface->getCanvas()->drawImage( +mImage, 0, 0, SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), ); +ResetToSkImage(makeCheckedImageSnapshot(surface)); +DataChanged(); +SAL_INFO("vcl.skia.trace", "invert(" << this << ")"); +return true; +} +return false; +} + SkBitmap SkiaSalBitmap::GetAsSkBitmap() const { #ifdef DBG_UTIL diff --git a/vcl/source/bitmap/bitmappaint.cxx b/vcl/source/bitmap/bitmappaint.cxx index f454aa97affa..7701af429ef6 100644 --- a/vcl/source/bitmap/bitmappaint.cxx +++ b/vcl/source/bitmap/bitmappaint.cxx @@ -77,7 +77,7 @@ bool Bitmap::Invert() pAcc->SetPalette(aBmpPal); } -else +else if (!mxSalBmp->Invert()) // try optimised call first { const tools::Long nWidth = pAcc->Width(); const tools::Long nHeight = pAcc->Height();
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/win
vcl/inc/skia/win/gdiimpl.hxx |2 +- vcl/inc/win/DWriteTextRenderer.hxx |2 +- vcl/inc/win/salgdi.h |3 +++ vcl/skia/win/gdiimpl.cxx | 33 +++-- vcl/win/gdi/DWriteTextRenderer.cxx | 26 -- vcl/win/gdi/salfont.cxx| 28 6 files changed, 56 insertions(+), 38 deletions(-) New commits: commit a80239ede3236c84d7a05d0fbc0f299811fee6c0 Author: Khaled Hosny AuthorDate: Sat Nov 19 03:03:15 2022 +0200 Commit: خالد حسني CommitDate: Sat Nov 19 12:44:10 2022 +0100 vcl: move creating DWFontFace to WinFontFace Change-Id: Ie0e94787d962eaec7753ae50d548ad8655dbc209 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142957 Tested-by: Jenkins Reviewed-by: خالد حسني diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 92f873ca7d43..c5b12d08811a 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -63,7 +63,7 @@ public: protected: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -static sk_sp createDirectWriteTypeface(HDC hdc, HFONT hfont); +static sk_sp createDirectWriteTypeface(const WinFontInstance* pWinFont); static void initFontInfo(); inline static sal::systools::COMReference dwriteFontSetBuilder; inline static sal::systools::COMReference dwritePrivateCollection; diff --git a/vcl/inc/win/DWriteTextRenderer.hxx b/vcl/inc/win/DWriteTextRenderer.hxx index 5f0dc35ddd58..b2d685b20365 100644 --- a/vcl/inc/win/DWriteTextRenderer.hxx +++ b/vcl/inc/win/DWriteTextRenderer.hxx @@ -60,7 +60,7 @@ private: D2DWriteTextOutRenderer(const D2DWriteTextOutRenderer &) = delete; D2DWriteTextOutRenderer & operator = (const D2DWriteTextOutRenderer &) = delete; -bool GetDWriteFaceFromHDC(HDC hDC, IDWriteFontFace ** ppFontFace, float * lfSize) const; +IDWriteFontFace* GetDWriteFace(const WinFontInstance& rWinFont, float * lfSize) const; bool performRender(GenericSalLayout const , SalGraphics , HDC hDC, bool& bRetry, bool bRenderingModeNatural); ID2D1Factory* mpD2DFactory; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index db00ff03455a..c21c36db2dec 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -72,6 +72,8 @@ public: BYTEGetCharSet() const { return meWinCharSet; } BYTEGetPitchAndFamily() const { return mnPitchAndFamily; } +IDWriteFontFace*GetDWFontFace() const; + virtual hb_blob_t* GetHbTable(hb_tag_t nTag) const override; private: @@ -80,6 +82,7 @@ private: BYTEmeWinCharSet; BYTEmnPitchAndFamily; LOGFONTWmaLogFont; +mutable sal::systools::COMReference mxDWFontFace; }; /** Class that creates (and destroys) a compatible Device Context. diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 74bc3cce5ec5..a9df26cb53a1 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -121,12 +121,12 @@ bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, C return true; } -sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFONT hfont) try +sk_sp +WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const WinFontInstance* pWinFont) try { using sal::systools::ThrowIfFailed; IDWriteFactory* dwriteFactory; -IDWriteGdiInterop* dwriteGdiInterop; -WinSalGraphics::getDWriteFactory(, ); +WinSalGraphics::getDWriteFactory(); if (!dwriteDone) { dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory); @@ -135,30 +135,20 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO if (!dwriteFontMgr) return nullptr; -// tdf#137122: We need to get the exact same font as HFONT refers to, -// since VCL core computes things like glyph ids based on that, and getting -// a different font could lead to mismatches (e.g. if there's a slightly -// different version of the same font installed system-wide). -// For that CreateFromFaceFromHdc() is necessary. The simpler -// CreateFontFromLOGFONT() seems to search for the best matching font, -// which may not be the exact font. -sal::systools::COMReference fontFace; -{ -comphelper::ScopeGuard g( -[ hdc, oldFont(SelectFont(hdc, hfont)) ] { SelectFont(hdc, oldFont); }); -ThrowIfFailed(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, ), SAL_WHERE); -} +IDWriteFontFace* fontFace = pWinFont->GetFontFace()->GetDWFontFace(); +if (!fontFace) +return nullptr; sal::systools::COMReference collection; ThrowIfFailed(dwriteFactory->GetSystemFontCollection(), SAL_WHERE); sal::systools::COMReference font; // As said above, this fails for our fonts. -if
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/win
vcl/inc/skia/win/gdiimpl.hxx |2 -- vcl/inc/win/salgdi.h |7 +++ vcl/skia/win/gdiimpl.cxx | 11 --- vcl/win/gdi/DWriteTextRenderer.cxx | 13 ++--- vcl/win/gdi/salgdi.cxx | 32 5 files changed, 45 insertions(+), 20 deletions(-) New commits: commit 042473d4b162c87a27a55e9b9f076b5fc479a55a Author: Khaled Hosny AuthorDate: Sat Nov 19 00:30:15 2022 +0200 Commit: خالد حسني CommitDate: Sat Nov 19 12:43:51 2022 +0100 vcl: move creating DWriteFactory to a centeral place We already have code in two places to create it, and I will need it in yet another place. Change-Id: I12dee85347a3894045c345b0ec9d5e02c493c218 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142956 Tested-by: Jenkins Reviewed-by: خالد حسني diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 1977e7152080..92f873ca7d43 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -65,8 +65,6 @@ protected: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; static sk_sp createDirectWriteTypeface(HDC hdc, HFONT hfont); static void initFontInfo(); -inline static sal::systools::COMReference dwriteFactory; -inline static sal::systools::COMReference dwriteGdiInterop; inline static sal::systools::COMReference dwriteFontSetBuilder; inline static sal::systools::COMReference dwritePrivateCollection; inline static sk_sp dwriteFontMgr; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index 35d723b0bc90..db00ff03455a 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -161,6 +162,10 @@ private: RGNDATA*mpStdClipRgnData; // Cache Standard-ClipRegion-Data int mnPenWidth; // line width +inline static sal::systools::COMReference mxDWriteFactory; +inline static sal::systools::COMReference mxDWriteGdiInterop; +inline static bool bDWriteDone = false; + // just call both from setHDC! void InitGraphics(); void DeInitGraphics(); @@ -189,6 +194,8 @@ public: SCREEN }; +static void getDWriteFactory(IDWriteFactory** pFactory, IDWriteGdiInterop** pInterop = nullptr); + public: HWND gethWnd(); diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 692ad36b9eb2..74bc3cce5ec5 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -124,13 +124,12 @@ bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, C sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFONT hfont) try { using sal::systools::ThrowIfFailed; +IDWriteFactory* dwriteFactory; +IDWriteGdiInterop* dwriteGdiInterop; +WinSalGraphics::getDWriteFactory(, ); if (!dwriteDone) { -ThrowIfFailed(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), - reinterpret_cast()), - SAL_WHERE); -ThrowIfFailed(dwriteFactory->GetGdiInterop(), SAL_WHERE); -dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory.get()); +dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory); dwriteDone = true; } if (!dwriteFontMgr) @@ -343,8 +342,6 @@ void WinSkiaSalGraphicsImpl::ClearDevFontCache() dwriteFontMgr.reset(); dwriteFontSetBuilder.clear(); dwritePrivateCollection.clear(); -dwriteFactory.clear(); -dwriteGdiInterop.clear(); dwriteDone = false; initFontInfo(); // get font info again, just in case } diff --git a/vcl/win/gdi/DWriteTextRenderer.cxx b/vcl/win/gdi/DWriteTextRenderer.cxx index 64d49696b102..1e44d95ad2cb 100644 --- a/vcl/win/gdi/DWriteTextRenderer.cxx +++ b/vcl/win/gdi/DWriteTextRenderer.cxx @@ -101,8 +101,6 @@ HRESULT checkResult(HRESULT hr, const char* file, size_t line) D2DWriteTextOutRenderer::D2DWriteTextOutRenderer(bool bRenderingModeNatural) : mpD2DFactory(nullptr), -mpDWriteFactory(nullptr), -mpGdiInterop(nullptr), mpRT(nullptr), mRTProps(D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED), @@ -110,14 +108,11 @@ D2DWriteTextOutRenderer::D2DWriteTextOutRenderer(bool bRenderingModeNatural) mbRenderingModeNatural(bRenderingModeNatural), meTextAntiAliasMode(D2DTextAntiAliasMode::Default) { +WinSalGraphics::getDWriteFactory(, ); HRESULT hr = S_OK; hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory), nullptr, reinterpret_cast()); -hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast()); if (SUCCEEDED(hr)) -{ -
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |2 +- vcl/skia/salbmp.cxx | 30 +++--- 2 files changed, 20 insertions(+), 12 deletions(-) New commits: commit 20de4e3ca38e177ea61e818b32d82008758b8caa Author: Luboš Luňák AuthorDate: Tue Sep 13 18:15:17 2022 +0200 Commit: Luboš Luňák CommitDate: Wed Sep 14 08:05:18 2022 +0200 do not check and refcount Info access to Skia bitmaps (tdf#150817) VclCanvasBitmap keeps one around for no good reason, and I don't feel like digging into it. Since there's no pixel data involved in that case, let's assume the reader knows that the info about the bitmap will not change. Making this difference is actually what I suggested in 0e5b473a63409da2cdae4f4c60a91fcc93755ba5. Change-Id: I302a9c2c63c8b9474a541a963928933e223f4b45 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139873 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 05e489643f88..e79fb1cc101d 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -211,7 +211,7 @@ private: // Erase() is delayed, just sets these two instead of filling the buffer. bool mEraseColorSet = false; Color mEraseColor; -int mAnyAccessCount = 0; // number of any kind of AcquireAccess() that have not been released +int mReadAccessCount = 0; // number of read AcquireAccess() that have not been released #ifdef DBG_UTIL int mWriteAccessCount = 0; // number of write AcquireAccess() that have not been released #endif diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index df3536b4de91..57cea14316c5 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -68,7 +68,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) #endif mSize = mPixelsSize = Size(image->width(), image->height()); ComputeScanlineSize(); -mAnyAccessCount = 0; +mReadAccessCount = 0; #ifdef DBG_UTIL mWriteAccessCount = 0; #endif @@ -78,7 +78,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) bool SkiaSalBitmap::Create(const Size& rSize, vcl::PixelFormat ePixelFormat, const BitmapPalette& rPal) { -assert(mAnyAccessCount == 0); +assert(mReadAccessCount == 0); ResetAllData(); if (ePixelFormat == vcl::PixelFormat::INVALID) return false; @@ -157,7 +157,7 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, SalGraphics* pGraphics) bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, vcl::PixelFormat eNewPixelFormat) { -assert(mAnyAccessCount == 0); +assert(mReadAccessCount == 0); assert( != this); ResetAllData(); const SkiaSalBitmap& src = static_cast(rSalBmp); @@ -195,7 +195,7 @@ void SkiaSalBitmap::Destroy() #ifdef DBG_UTIL assert(mWriteAccessCount == 0); #endif -assert(mAnyAccessCount == 0); +assert(mReadAccessCount == 0); ResetAllData(); } @@ -274,7 +274,12 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) abort(); } buffer->mnFormat |= ScanlineFormat::TopDown; -++mAnyAccessCount; +// Refcount all read/write accesses, to catch problems with existing accesses while +// a bitmap changes, and also to detect when we can free mBuffer if wanted. +// Write mode implies also reading. It would be probably a good idea to count even +// Info accesses, but VclCanvasBitmap keeps one around pointlessly, causing tdf#150817. +if (nMode == BitmapAccessMode::Read || nMode == BitmapAccessMode::Write) +++mReadAccessCount; #ifdef DBG_UTIL if (nMode == BitmapAccessMode::Write) ++mWriteAccessCount; @@ -300,8 +305,11 @@ void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode, ResetToBuffer(); DataChanged(); } -assert(mAnyAccessCount > 0); ---mAnyAccessCount; +if (nMode == BitmapAccessMode::Read || nMode == BitmapAccessMode::Write) +{ +assert(mReadAccessCount > 0); +--mReadAccessCount; +} // Are there any more ground movements underneath us ? assert(pBuffer->mnWidth == mSize.Width()); assert(pBuffer->mnHeight == mSize.Height()); @@ -812,7 +820,7 @@ const sk_sp& SkiaSalBitmap::GetSkImage(DirectImage direct) const thisPtr->mImage = image; // The data is now stored both in the SkImage and in our mBuffer, so drop the buffer // if conserving memory. It'll be converted back by EnsureBitmapData() if needed. -if (ConserveMemory() && mAnyAccessCount == 0) +if (ConserveMemory() && mReadAccessCount == 0) { SAL_INFO("vcl.skia.trace", "getskimage(" << this << "): dropping buffer"); thisPtr->ResetToSkImage(mImage); @@ -968,7 +976,7 @@ const sk_sp& SkiaSalBitmap::GetAlphaSkImage(DirectImage direct) const // The data is now stored both in the SkImage and in our mBuffer, so drop the buffer // if conserving memory and the conversion back
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/unx
vcl/inc/unx/glyphcache.hxx |6 vcl/skia/x11/textrender.cxx|3 -- vcl/unx/generic/gdi/cairotextrender.cxx|2 - vcl/unx/generic/glyphs/freetype_glyphcache.cxx | 34 - 4 files changed, 45 deletions(-) New commits: commit ba9c6ad27d76de2cc4bc43cc2836a9680a3e1a9b Author: Caolán McNamara AuthorDate: Fri Aug 26 14:59:26 2022 +0100 Commit: Caolán McNamara CommitDate: Fri Aug 26 18:11:51 2022 +0200 freetype 2.9 was relesed in Jan 2018, drop workaround for <= 2.8 Change-Id: Iaf95faa15d56e8f26ed57cb4744b039a18223c5c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138877 Tested-by: Jenkins Reviewed-by: Caolán McNamara diff --git a/vcl/inc/unx/glyphcache.hxx b/vcl/inc/unx/glyphcache.hxx index b54e10bdb20b..27ddd6cb32b5 100644 --- a/vcl/inc/unx/glyphcache.hxx +++ b/vcl/inc/unx/glyphcache.hxx @@ -134,12 +134,6 @@ public: voidSetFontVariationsOnHBFont(hb_font_t* pHbFace) const; -// tdf#127189 FreeType <= 2.8 will fail to render stretched horizontal brace glyphs -// in starmath at a fairly low stretch ratio. This appears fixed in 2.9 with -// https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=91015cb41d8f56777f93394f5a60914bc0c0f330 -// "Improve complex rendering at high ppem" -static bool AlmostHorizontalDrainsRenderingPool(int nRatio, const vcl::font::FontSelectPattern& rFSD); - private: friend class FreetypeFontInstance; friend class FreetypeManager; diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx index 3548dc61683e..7be518e96c92 100644 --- a/vcl/skia/x11/textrender.cxx +++ b/vcl/skia/x11/textrender.cxx @@ -40,9 +40,6 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGr if (nWidth == 0 || nHeight == 0) return; -if (FreetypeFont::AlmostHorizontalDrainsRenderingPool(nWidth * 10 / nHeight, rFSD)) -return; - if (!fontManager) { // Get the global FcConfig that our VCL fontconfig code uses, and refcount it. diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx b/vcl/unx/generic/gdi/cairotextrender.cxx index 006ea2ce8d4a..5ddee651d70e 100644 --- a/vcl/unx/generic/gdi/cairotextrender.cxx +++ b/vcl/unx/generic/gdi/cairotextrender.cxx @@ -205,8 +205,6 @@ void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalG } int nRatio = nWidth * 10 / nHeight; -if (FreetypeFont::AlmostHorizontalDrainsRenderingPool(nRatio, rFSD)) -return; /* * It might be ideal to cache surface and cairo context between calls and diff --git a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx index 848405169cd2..c9c471144bd3 100644 --- a/vcl/unx/generic/glyphs/freetype_glyphcache.cxx +++ b/vcl/unx/generic/glyphs/freetype_glyphcache.cxx @@ -313,40 +313,6 @@ void FreetypeManager::InitFreetype() nDefaultPrioAntiAlias = pEnv[0] - '0'; } -namespace -{ -bool DoesAlmostHorizontalDrainRenderingPool() -{ -FT_Int nMajor, nMinor, nPatch; -FT_Library_Version(aLibFT, , , ); -if (nMajor > 2) -return false; -if (nMajor == 2 && nMinor <= 8) -return true; -return false; -} -} - -bool FreetypeFont::AlmostHorizontalDrainsRenderingPool(int nRatio, const vcl::font::FontSelectPattern& rFSD) -{ -static bool bAlmostHorizontalDrainsRenderingPool = DoesAlmostHorizontalDrainRenderingPool(); -if (nRatio > 100 && rFSD.maTargetName == "OpenSymbol" && bAlmostHorizontalDrainsRenderingPool) -{ -// tdf#127189 FreeType <= 2.8 will fail to render stretched horizontal -// brace glyphs in starmath at a fairly low stretch ratio. The failure -// will set CAIRO_STATUS_FREETYPE_ERROR on the surface which cannot be -// cleared, so all further painting to the surface fails. - -// This appears fixed in >= freetype 2.9 - -// Restrict this bodge to a stretch ratio > ~10 of the OpenSymbol font -// where it has been seen in practice. -SAL_WARN("vcl", "rendering text would fail with stretch ratio of: " << nRatio << ", with FreeType <= 2.8"); -return true; -} -return false; -} - FT_Face FreetypeFont::GetFtFace() const { FT_Activate_Size( maSizeFT );
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/win
vcl/inc/skia/win/gdiimpl.hxx |1 vcl/inc/win/wingdiimpl.hxx|2 vcl/skia/win/gdiimpl.cxx |6 ++ vcl/win/gdi/salnativewidgets-luna.cxx | 95 +- 4 files changed, 58 insertions(+), 46 deletions(-) New commits: commit 3eecde27009b74a7f3bf75809109a2367e262b09 Author: Caolán McNamara AuthorDate: Mon Mar 14 23:25:12 2022 + Commit: Caolán McNamara CommitDate: Wed Mar 16 16:17:08 2022 +0100 throw away skia control cache on theme change Change-Id: Idd21e966cf2c9b246c7484ba6c118c872a3dbac3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131568 Tested-by: Jenkins Tested-by: Caolán McNamara Reviewed-by: Caolán McNamara diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index a8897d0d7c20..1977e7152080 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -54,6 +54,7 @@ public: virtual bool DrawTextLayout(const GenericSalLayout& layout) override; virtual void ClearDevFontCache() override; +virtual void ClearNativeControlCache() override; virtual void freeResources() override; virtual void Flush() override; diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx index 5abf86e6e36f..d9616292b950 100644 --- a/vcl/inc/win/wingdiimpl.hxx +++ b/vcl/inc/win/wingdiimpl.hxx @@ -42,6 +42,8 @@ public: // Implementation for WinSalGraphics::DrawTextLayout(). // Returns true if handled, if false, then WinSalGraphics will handle it itself. virtual bool DrawTextLayout(const GenericSalLayout&) { return false; } + +virtual void ClearNativeControlCache() {} }; #endif // INCLUDED_VCL_INC_WIN_WINGDIIMPL_HXX diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index f2f0d82a9047..586b4e1fdd97 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -428,4 +428,10 @@ void WinSkiaSalGraphicsImpl::prepareSkia() SkiaHelper::prepareSkia(createVulkanWindowContext); } +void WinSkiaSalGraphicsImpl::ClearNativeControlCache() +{ +SalData* data = GetSalData(); +data->m_pSkiaControlsCache.reset(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/gdi/salnativewidgets-luna.cxx b/vcl/win/gdi/salnativewidgets-luna.cxx index 6a21a3d6d394..8e754d129580 100644 --- a/vcl/win/gdi/salnativewidgets-luna.cxx +++ b/vcl/win/gdi/salnativewidgets-luna.cxx @@ -78,12 +78,15 @@ void SalData::deInitNWF() aThemeMap.clear(); } -static HTHEME getThemeHandle( HWND hWnd, LPCWSTR name ) +static HTHEME getThemeHandle(HWND hWnd, LPCWSTR name, SalGraphicsImpl* pGraphicsImpl) { if( GetSalData()->mbThemeChanged ) { // throw away invalid theme handles SalData::deInitNWF(); +// throw away native control cache +if (WinSalGraphicsImplBase* pImpl = dynamic_cast(pGraphicsImpl)) +pImpl->ClearNativeControlCache(); GetSalData()->mbThemeChanged = false; } @@ -107,33 +110,33 @@ bool WinSalGraphics::isNativeControlSupported( ControlType nType, ControlPart nP case ControlType::Radiobutton: case ControlType::Checkbox: if( nPart == ControlPart::Entire ) -hTheme = getThemeHandle( mhWnd, L"Button"); +hTheme = getThemeHandle(mhWnd, L"Button", mpImpl.get()); break; case ControlType::Scrollbar: if( nPart == ControlPart::DrawBackgroundHorz || nPart == ControlPart::DrawBackgroundVert ) return false; // no background painting needed if( nPart == ControlPart::Entire ) -hTheme = getThemeHandle( mhWnd, L"Scrollbar"); +hTheme = getThemeHandle(mhWnd, L"Scrollbar", mpImpl.get()); break; case ControlType::Combobox: if( nPart == ControlPart::HasBackgroundTexture ) return false; // we do not paint the inner part (ie the selection background/focus indication) if( nPart == ControlPart::Entire ) -hTheme = getThemeHandle( mhWnd, L"Edit"); +hTheme = getThemeHandle(mhWnd, L"Edit", mpImpl.get()); else if( nPart == ControlPart::ButtonDown ) -hTheme = getThemeHandle( mhWnd, L"Combobox"); +hTheme = getThemeHandle(mhWnd, L"Combobox", mpImpl.get()); break; case ControlType::Spinbox: if( nPart == ControlPart::Entire ) -hTheme = getThemeHandle( mhWnd, L"Edit"); +hTheme = getThemeHandle(mhWnd, L"Edit", mpImpl.get()); else if( nPart == ControlPart::AllButtons || nPart == ControlPart::ButtonUp || nPart == ControlPart::ButtonDown || nPart == ControlPart::ButtonLeft|| nPart == ControlPart::ButtonRight ) -hTheme = getThemeHandle( mhWnd, L"Spin"); +hTheme = getThemeHandle(mhWnd, L"Spin",
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |2 +- vcl/skia/gdiimpl.cxx | 28 ++-- vcl/skia/osx/gdiimpl.cxx |2 +- 3 files changed, 8 insertions(+), 24 deletions(-) New commits: commit 9cb34aa3c98ac6254b7e70e26e92f3e2ba881fab Author: Luboš Luňák AuthorDate: Thu Jan 6 18:33:04 2022 +0100 Commit: Luboš Luňák CommitDate: Wed Jan 12 13:27:37 2022 +0100 reduce explicit Skia flushing The docs say that Skia handles this itself, and with Vulkan excessive flushing may show up in profiling in some cases, as it's apparently a non-trivial operation in GPU mode. Remove even the two workarounds, I cannot reproduce the problems anymore, so let's assume it's been fixed in Skia. But still keep the flushing after a certain number of operations, as too many pending operations still may overload Skia (or Vulkan?), besides tdf#136369 I can also reproduce it while loading bsc#1183308 which does a large number of tiny VirtualDevice's and does GetBitmap() on them. Also change the counter to be global, as we use just one Skia drawing context. Change-Id: I48b96c2a59f8e1eeef3da154dbe373a37857c4be Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128293 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index b5144a249207..b2814b2a6463 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -368,7 +368,7 @@ protected: double transparency; }; LastPolyPolygonInfo mLastPolyPolygonInfo; -int mPendingOperationsToFlush; +inline static int pendingOperationsToFlush = 0; int mScaling; // The scale factor for HiDPI screens. }; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 593e2ffb57e4..362508a5cdbe 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -265,7 +265,6 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvid , mFillColor(SALCOLOR_NONE) , mXorMode(XorMode::None) , mFlush(new SkiaFlushIdle(this)) -, mPendingOperationsToFlush(0) , mScaling(1) { } @@ -362,15 +361,6 @@ void SkiaSalGraphicsImpl::destroySurface() // if this fails, something forgot to use SkAutoCanvasRestore assert(mSurface->getCanvas()->getTotalMatrix() == SkMatrix::Scale(mScaling, mScaling)); } -// If we use e.g. Vulkan, we must destroy the surface before the context, -// otherwise destroying the surface will reference the context. This is -// handled by calling destroySurface() before destroying the context. -// However we also need to flush the surface before destroying it, -// otherwise when destroying the context later there still could be queued -// commands referring to the surface data. This is probably a Skia bug, -// but work around it here. -if (mSurface) -mSurface->flushAndSubmit(); mSurface.reset(); mWindowContext.reset(); mIsGPU = false; @@ -439,10 +429,12 @@ void SkiaSalGraphicsImpl::postDraw() // But tdf#136369 leads to creating and queueing many tiny bitmaps, which makes // Skia slow, and may make it even run out of memory. So force a flush if such // a problematic operation has been performed too many times without a flush. -if (mPendingOperationsToFlush > 1000) +// Note that the counter is a static variable, as all drawing shares the same Skia drawing +// context (and so the flush here will also flush all drawing). +if (pendingOperationsToFlush > 1000) { mSurface->flushAndSubmit(); -mPendingOperationsToFlush = 0; +pendingOperationsToFlush = 0; } SkiaZone::leave(); // matched in preDraw() // If there's a problem with the GPU context, abort. @@ -540,8 +532,7 @@ void SkiaSalGraphicsImpl::flushDrawing() if (!mSurface) return; checkPendingDrawing(); -mSurface->flushAndSubmit(); -mPendingOperationsToFlush = 0; +++pendingOperationsToFlush; } void SkiaSalGraphicsImpl::setCanvasScalingAndClipping() @@ -901,13 +892,6 @@ void SkiaSalGraphicsImpl::performDrawPolyPolygon(const basegfx::B2DPolyPolygon& getDrawCanvas()->drawPath(polygonPath, aPaint); } postDraw(); -#if defined LINUX -// WORKAROUND: The logo in the about dialog has drawing errors. This seems to happen -// only on Linux (not Windows on the same machine), with both AMDGPU and Mesa, -// and only when antialiasing is enabled. Flushing seems to avoid the problem. -if (useAA && getVendor() == DriverBlocklist::VendorAMD) -mSurface->flushAndSubmit(); -#endif } namespace @@ -1786,7 +1770,7 @@ void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_spdrawImageRect(aImage, aSourceRect, aDestinationRect, makeSamplingOptions(rPosAry, mScaling, srcScaling), ,
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |4 ++ vcl/skia/win/gdiimpl.cxx | 70 +++ 2 files changed, 68 insertions(+), 6 deletions(-) New commits: commit 68818db0ec0e9c308c8a0772d46af551f439b32c Author: Caolán McNamara AuthorDate: Sun Jan 2 21:55:10 2022 + Commit: Caolán McNamara CommitDate: Tue Jan 11 18:11:23 2022 +0100 build a IDWriteFontCollection1 of our FR_PRIVATE fonts so we don't need to fallback to gdi in skia for those we build it incrementally as GetFontFromFontFace fails in the system font set Change-Id: I2ac6d151657b9b720eed46dd7bcee0e9682e462a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127877 Tested-by: Jenkins Reviewed-by: Caolán McNamara diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 58043e5f6a83..a8897d0d7c20 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -25,6 +25,8 @@ #include #include +#include + class SkTypeface; class ControlCacheKey; @@ -64,6 +66,8 @@ protected: static void initFontInfo(); inline static sal::systools::COMReference dwriteFactory; inline static sal::systools::COMReference dwriteGdiInterop; +inline static sal::systools::COMReference dwriteFontSetBuilder; +inline static sal::systools::COMReference dwritePrivateCollection; inline static sk_sp dwriteFontMgr; inline static bool dwriteDone = false; static SkFont::Edging fontEdging; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index a10351888eac..6686ecd0e8ed 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -163,11 +163,7 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO // different version of the same font installed system-wide). // For that CreateFromFaceFromHdc() is necessary. The simpler // CreateFontFromLOGFONT() seems to search for the best matching font, -// which may not be the exact font. Our private fonts are installed -// using AddFontResourceExW( FR_PRIVATE ) and that apparently does -// not make them available to DirectWrite (at least, they are not -// included the DWrite system font collection). For such cases, we'll -// need to fall back to Skia's GDI-based font rendering. +// which may not be the exact font. HFONT oldFont = SelectFont(hdc, hfont); sal::systools::COMReference fontFace; if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, @@ -175,6 +171,7 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO SelectFont(hdc, oldFont); return nullptr; } + SelectFont(hdc, oldFont); sal::systools::COMReference collection; if (FAILED(CHECKHR(dwriteFactory->GetSystemFontCollection( @@ -182,7 +179,66 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO sal::systools::COMReference font; // Do not use CHECKHR() here, as said above, this fails for our fonts. if (FAILED(collection->GetFontFromFontFace(fontFace.get(), ))) -return nullptr; +{ +// If not found in system collection, try our private font collection. +// If that's not possible we'll fall back to Skia's GDI-based font rendering. +if (!dwritePrivateCollection +|| FAILED(dwritePrivateCollection->GetFontFromFontFace(fontFace.get(), ))) +{ +// Our private fonts are installed using AddFontResourceExW( FR_PRIVATE ) +// and that does not make them available to the DWrite system font +// collection. For such cases attempt to update a collection of +// private fonts with this newly used font. + +sal::systools::COMReference dwriteFactory3; +if (FAILED(dwriteFactory->QueryInterface())) +return nullptr; + +if (!dwriteFontSetBuilder +&& FAILED(dwriteFactory3->CreateFontSetBuilder())) +return nullptr; + +UINT32 numberOfFiles; +if (FAILED(fontFace->GetFiles(, nullptr)) || numberOfFiles != 1) +return nullptr; + +sal::systools::COMReference fontFile; +if (FAILED(fontFace->GetFiles(, ))) +return nullptr; + +BOOL isSupported; +DWRITE_FONT_FILE_TYPE fileType; +UINT32 numberOfFonts; +if (FAILED(fontFile->Analyze(, , nullptr, )) +|| !isSupported) +return nullptr; + +// For each font within the font file, get a font face reference and add to the builder. +for (UINT32 fontIndex = 0; fontIndex < numberOfFonts; ++fontIndex) +{ +sal::systools::COMReference fontFaceReference; +if (FAILED(dwriteFactory3->CreateFontFaceReference(fontFile.get(), fontIndex, +
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx | 11 +++ vcl/inc/skia/utils.hxx | 26 +- vcl/skia/gdiimpl.cxx | 10 +- 3 files changed, 33 insertions(+), 14 deletions(-) New commits: commit 0a596fbd94e1750e9d1f5cdab624c719b33c3ab4 Author: Luboš Luňák AuthorDate: Fri Dec 3 16:48:47 2021 +0100 Commit: Luboš Luňák CommitDate: Sat Dec 4 11:30:52 2021 +0100 only bilinear+mipmap for Skia/raster to-screen drawing (tdf#146024) The code already tries to hide the cost of the high-quality bicubic scaling by caching, but there are still cases where there's too much scaling done. Since this is only drawing to screen, use only bilinear+mipmap scaling in raster mode, which should be good enough (it's what the "super" scaling VCL algorithm for BmpScaleFlag::Default does as well). Change-Id: I75c86932e097411422dc1ef5e0534059dbf11ff8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126326 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 2473d0918284..b5144a249207 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -296,6 +296,17 @@ protected: void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency, bool useAA); +BmpScaleFlag goodScalingQuality() const { return SkiaHelper::goodScalingQuality(isGPU()); } +SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor, + int srcScalingFactor = 1) +{ +return SkiaHelper::makeSamplingOptions(rPosAry, scalingFactor, srcScalingFactor, isGPU()); +} +SkSamplingOptions makeSamplingOptions(const SkMatrix& matrix, int scalingFactor) +{ +return SkiaHelper::makeSamplingOptions(goodScalingQuality(), matrix, scalingFactor); +} + // Create SkPaint to use when drawing to the surface. It is not to be used // when doing internal drawing such as when merging two bitmaps together. // This may apply some default settings to the paint as necessary. diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index c4d671ed6b7e..35180c016e24 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -135,6 +135,16 @@ inline bool isUnitTestRunning(const char* name = nullptr) return testname != nullptr && std::string_view(name) == testname; } +// Scaling done on the GPU is fast, but bicubic done in raster mode can be slow +// if done too much, and it generally shouldn't be needed for to-screen drawing. +// In that case use only BmpScaleFlag::Default, which is bilinear+mipmap, +// which should be good enough (and that's what the "super" bitmap scaling +// algorithm done by VCL does as well). +inline BmpScaleFlag goodScalingQuality(bool isGPU) +{ +return isGPU ? BmpScaleFlag::BestQuality : BmpScaleFlag::Default; +} + // Normal scaling algorithms have a poor quality when downscaling a lot. // https://bugs.chromium.org/p/skia/issues/detail?id=11810 suggests to use mipmaps // in such a case, which is annoying to do explicitly instead of Skia deciding which @@ -156,7 +166,9 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, SkMatrix return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); return SkSamplingOptions(SkCubicResampler::Mitchell()); case BmpScaleFlag::Default: -return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone); +// Use SkMipmapMode::kNearest for better quality when downscaling. SkMipmapMode::kLinear +// would be even better, but it is not specially optimized in raster mode. +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest); case BmpScaleFlag::Fast: case BmpScaleFlag::NearestNeighbor: return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone); @@ -179,7 +191,8 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, const Siz return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); return SkSamplingOptions(SkCubicResampler::Mitchell()); case BmpScaleFlag::Default: -return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone); +// As in the first overload, use kNearest. +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNearest); case BmpScaleFlag::Fast: case BmpScaleFlag::NearestNeighbor: return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone); @@ -190,7 +203,7 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scalingType, const Siz } inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry, int scalingFactor, - int
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |3 --- vcl/skia/SkiaHelper.cxx | 34 -- vcl/skia/gdiimpl.cxx|7 --- 3 files changed, 4 insertions(+), 40 deletions(-) New commits: commit 4a11c85baeb4998e12bc2ab45b0c23d7203bd5b0 Author: Luboš Luňák AuthorDate: Thu Nov 25 22:38:55 2021 +0100 Commit: Luboš Luňák CommitDate: Mon Nov 29 21:48:53 2021 +0100 remove Skia kDifference workaround I thought it was a driver problem, but now I'm actually not sure, as I cannot reproduce it anymore and I don't know if it was a driver update or Skia update. Either way, this works now. Also switch to kExclusion, because the end result is the same, but this formula is simpler (to understand primarily, the performance is going to be probably the same). Change-Id: I6ced098ca4a3361cf98d3f9b32968c128eb9f299 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126050 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 0583e9ceb624..ac8a185e711e 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -103,9 +103,6 @@ enum DirectImage No }; -// Do 'paint->setBlendMode(SkBlendMode::kDifference)' (workaround for buggy drivers). -void setBlendModeDifference(SkPaint* paint); - // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 631e5b64fe52..d082b6799129 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -644,45 +644,11 @@ tools::Long maxImageCacheSize() return officecfg::Office::Common::Cache::Skia::ImageCacheSize::get(); } -static sk_sp differenceBlender; - -void setBlendModeDifference(SkPaint* paint) -{ -// This should normally do 'paint->setBlendMode(SkBlendMode::kDifference);'. -// But some drivers have a problem with this, namely currently AMD on Windows -// (e.g. 'Vulkan API version: 1.2.170, driver version: 2.0.179, vendor: 0x1002 (AMD), -// device: 0x15dd, type: integrated, name: AMD Radeon(TM) Vega 8 Graphics') -// simply crashes when kDifference is used. -// Intel also had repaint problems with kDifference (tdf#130430), but it seems -// those do not(?) exist anymore. -// Interestingly, explicitly writing a shader that does exactly the same works fine, -// so do that. -if (!differenceBlender) -{ -const char* const diff = R"( -vec4 main( vec4 src, vec4 dst ) -{ -return vec4(abs( src.r - dst.r ), abs( src.g - dst.g ), abs( src.b - dst.b ), dst.a ); -} -)"; -auto effect = SkRuntimeEffect::MakeForBlender(SkString(diff)); -if (!effect.effect) -{ -SAL_WARN("vcl.skia", - "SKRuntimeEffect::MakeForBlender failed: " << effect.errorText.c_str()); -abort(); -} -differenceBlender = effect.effect->makeBlender(nullptr); -} -paint->setBlender(differenceBlender); -} - void cleanup() { sharedWindowContext.reset(); imageCache.clear(); imageCacheSize = 0; -differenceBlender.reset(); } static SkSurfaceProps commonSurfaceProps; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 3d7697c4dcfa..63d588aa913e 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1507,7 +1507,10 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl addUpdateRegion(aPath.getBounds()); SkAutoCanvasRestore autoRestore(getDrawCanvas(), true); SkPaint aPaint; -setBlendModeDifference(); +// There's no blend mode for inverting as such, but kExclusion is 's + d - 2*s*d', +// so with d = 1.0 (all channels) it becomes effectively '1 - s', i.e. inverted color. +aPaint.setBlendMode(SkBlendMode::kExclusion); +aPaint.setColor(SkColorSetARGB(255, 255, 255, 255)); // TrackFrame just inverts a dashed path around the polygon if (eFlags == SalInvert::TrackFrame) { @@ -1519,11 +1522,9 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl constexpr float intervals[] = { 4.0f, 4.0f }; aPaint.setStyle(SkPaint::kStroke_Style); aPaint.setPathEffect(SkDashPathEffect::Make(intervals, SK_ARRAY_COUNT(intervals), 0)); -aPaint.setColor(SkColorSetARGB(255, 255, 255, 255)); } else { -aPaint.setColor(SkColorSetARGB(255, 255, 255, 255)); aPaint.setStyle(SkPaint::kFill_Style); // N50 inverts in checker pattern
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |3 +-- vcl/inc/skia/salbmp.hxx |3 +-- vcl/inc/skia/utils.hxx |3 ++- vcl/skia/README |3 ++- vcl/skia/SkiaHelper.cxx | 31 +++ vcl/skia/gdiimpl.cxx |2 -- vcl/skia/salbmp.cxx |3 +-- 7 files changed, 22 insertions(+), 26 deletions(-) New commits: commit f33b76b4e675818deae244427cef84c576a1a1f8 Author: Luboš Luňák AuthorDate: Sat Nov 13 08:30:36 2021 +0100 Commit: Luboš Luňák CommitDate: Tue Nov 16 18:37:06 2021 +0100 make SkiaHelper::dump() available also in non-dbgutil builds They are just a set of small functions, and I sometimes need to debug optimized builds too. Change-Id: I6350476e8c7fef85460a88b9e3d56d02213764ea Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125310 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 942567fec0f6..abfa89ca8bfa 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -198,9 +198,8 @@ public: virtual bool supportsOperation(OutDevSupportType eType) const override; -#ifdef DBG_UTIL +// Dump contents to a file for debugging. void dump(const char* file) const; -#endif // Default blend mode for SkPaint is SkBlendMode::kSrcOver void drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBitmap& bitmap, diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index b2f452c82979..aa8d245ce741 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -88,9 +88,8 @@ public: // Alpha type best suitable for the content. SkAlphaType alphaType() const; -#ifdef DBG_UTIL +// Dump contents to a file for debugging. void dump(const char* file) const; -#endif // These are to be used only by unittests. bool unittestHasBuffer() const { return mBuffer.get(); } diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index ed404f7cc3eb..0a17ee81bc4d 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -194,10 +194,11 @@ inline SkIRect scaleRect(const SkIRect& rect, int scaling) #ifdef DBG_UTIL void prefillSurface(const sk_sp& surface); +#endif + VCL_DLLPUBLIC void dump(const SkBitmap& bitmap, const char* file); VCL_DLLPUBLIC void dump(const sk_sp& image, const char* file); VCL_DLLPUBLIC void dump(const sk_sp& surface, const char* file); -#endif VCL_DLLPUBLIC extern uint32_t vendorId; diff --git a/vcl/skia/README b/vcl/skia/README index f2903d97fdd7..63f6073bac87 100644 --- a/vcl/skia/README +++ b/vcl/skia/README @@ -31,7 +31,8 @@ Debugging: Both SkiaSalBitmap and SkiaSalGraphicsImpl have a dump() method that writes a PNG with the current contents. There is also SkiaHelper::dump() for dumping contents -of SkBitmap, SkImage and SkSurface. +of SkBitmap, SkImage and SkSurface. You can use these in a debugger too, for example +'p SkiaHelper::dump(image, "/tmp/a.png")'. If there is a drawing problem, you can use something like the following piece of code to dump an image after each relevant operation (or do it in postDraw() if you don't diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 57bde5abf919..cc9303af39f5 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -704,6 +704,21 @@ void prepareSkia(std::unique_ptr (*createGpuWindowContext skiaSupportedByBackend = true; } +void dump(const SkBitmap& bitmap, const char* file) { dump(SkImage::MakeFromBitmap(bitmap), file); } + +void dump(const sk_sp& surface, const char* file) +{ +surface->getCanvas()->flush(); +dump(makeCheckedImageSnapshot(surface), file); +} + +void dump(const sk_sp& image, const char* file) +{ +sk_sp data = image->encodeToData(SkEncodedImageFormat::kPNG, 1); +std::ofstream ostream(file, std::ios::binary); +ostream.write(static_cast(data->data()), data->size()); +} + #ifdef DBG_UTIL void prefillSurface(const sk_sp& surface) { @@ -724,22 +739,6 @@ void prefillSurface(const sk_sp& surface) bitmap.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions())); surface->getCanvas()->drawPaint(paint); } - -void dump(const SkBitmap& bitmap, const char* file) { dump(SkImage::MakeFromBitmap(bitmap), file); } - -void dump(const sk_sp& surface, const char* file) -{ -surface->getCanvas()->flush(); -dump(makeCheckedImageSnapshot(surface), file); -} - -void dump(const sk_sp& image, const char* file) -{ -sk_sp data = image->encodeToData(SkEncodedImageFormat::kPNG, 1); -std::ofstream ostream(file, std::ios::binary); -ostream.write(static_cast(data->data()), data->size()); -} - #endif } // namespace diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 4019c436d51d..f532e48528a9 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2213,12 +2213,10 @@ int SkiaSalGraphicsImpl::getWindowScaling() const return scaling; } -#ifdef DBG_UTIL void
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |4 +-- vcl/skia/gdiimpl.cxx | 61 +-- 2 files changed, 40 insertions(+), 25 deletions(-) New commits: commit 6792e6e5e49d11a54256b75c4c5a476bb2f10b4a Author: Luboš Luňák AuthorDate: Mon Nov 15 18:19:27 2021 +0100 Commit: Luboš Luňák CommitDate: Tue Nov 16 10:39:43 2021 +0100 when caching bitmaps in skia, take into account HiDPI Since the image will be actually eventually drawn twice as big, cache an image that is twice as big. Change-Id: Iea0340cd92c102e453330723c797659c742feb63 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125263 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 70bbcf5c4dcc..942567fec0f6 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -206,7 +206,7 @@ public: void drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBitmap& bitmap, SkBlendMode blendMode = SkBlendMode::kSrcOver); -void drawImage(const SalTwoRect& rPosAry, const sk_sp& aImage, +void drawImage(const SalTwoRect& rPosAry, const sk_sp& aImage, int srcScaling = 1, SkBlendMode eBlendMode = SkBlendMode::kSrcOver); void drawShader(const SalTwoRect& rPosAry, const sk_sp& shader, @@ -284,7 +284,7 @@ protected: void resetCanvasScalingAndClipping(); static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region); sk_sp mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap, - const Size targetSize); + const Size& targetSize); // Skia uses floating point coordinates, so when we use integer coordinates, sometimes // rounding results in off-by-one errors (down), especially when drawing using GPU, diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index ebd1389c5970..de1e8c47cb12 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1604,9 +1604,8 @@ bool SkiaSalGraphicsImpl::drawEPS(tools::Long, tools::Long, tools::Long, tools:: // Especially in raster mode scaling and alpha blending may be expensive if done repeatedly. sk_sp SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap, - const Size targetSize) + const Size& targetSize) { -// TODO This should take into account mScaling!=1, and callers should use that too. sk_sp image; if (targetSize.IsEmpty()) return image; @@ -1631,7 +1630,7 @@ sk_sp SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma // In some cases (tdf#134237) the target size may be very large. In that case it's // better to rely on Skia to clip and draw only the necessary, rather than prepare // a very large image only to not use most of it. -const Size drawAreaSize = mClipRegion.GetBoundRect().GetSize(); +const Size drawAreaSize = mClipRegion.GetBoundRect().GetSize() * mScaling; if (targetSize.Width() > drawAreaSize.Width() || targetSize.Height() > drawAreaSize.Height()) { // This is a bit tricky. The condition above just checks that at least a part of the resulting @@ -1727,9 +1726,10 @@ bool SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBi imagePosAry.mnSrcHeight = imagePosAry.mnDestHeight; imageSize = Size(imagePosAry.mnSrcWidth, imagePosAry.mnSrcHeight); } -sk_sp image = mergeCacheBitmaps(rSkiaSourceBitmap, , imageSize); +sk_sp image += mergeCacheBitmaps(rSkiaSourceBitmap, , imageSize * mScaling); if (image) -drawImage(imagePosAry, image); +drawImage(imagePosAry, image, mScaling); else if (rSkiaAlphaBitmap.IsFullyOpaqueAsAlpha()) // alpha can be ignored drawBitmap(rPosAry, rSkiaSourceBitmap); else @@ -1763,18 +1763,20 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBit imagePosAry.mnSrcHeight = imagePosAry.mnDestHeight; imageSize = Size(imagePosAry.mnSrcWidth, imagePosAry.mnSrcHeight); } -sk_sp image = mergeCacheBitmaps(bitmap, nullptr, imageSize); +sk_sp image = mergeCacheBitmaps(bitmap, nullptr, imageSize * mScaling); if (image) -drawImage(imagePosAry, image, blendMode); +drawImage(imagePosAry, image, mScaling, blendMode); else -drawImage(rPosAry, bitmap.GetSkImage(), blendMode); +drawImage(rPosAry, bitmap.GetSkImage(), 1, blendMode); } void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_sp& aImage, -SkBlendMode eBlendMode) +int srcScaling, SkBlendMode eBlendMode) {
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |3 +++ vcl/skia/SkiaHelper.cxx | 35 +++ vcl/skia/gdiimpl.cxx| 35 ++- 3 files changed, 40 insertions(+), 33 deletions(-) New commits: commit 110fa313628c55fef1d35830358aea7e27c1e3ee Author: Luboš Luňák AuthorDate: Thu Nov 11 20:51:55 2021 +0100 Commit: Luboš Luňák CommitDate: Fri Nov 12 18:49:39 2021 +0100 get rid of Skia's 'rasterhack' for Invert() It seems that manually writing a shader that does the same as SkBlendMode::kDifference works fine even though the blend mode crashes e.g. on Windows/AMD. So get rid of the memory<->GPU conversions and use the shader as a workaround. Change-Id: I971deeeb98f40e5ffa90f6a8dd7b0b21ec491c1a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125101 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 0bcc5989493e..ba479c58f234 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -71,6 +71,9 @@ VCL_DLLPUBLIC sk_sp makeCheckedImageSnapshot(sk_sp surface, inline Size imageSize(const sk_sp& image) { return Size(image->width(), image->height()); } +// Do 'paint->setBlendMode(SkBlendMode::kDifference)' (workaround for buggy drivers). +void setBlendModeDifference(SkPaint* paint); + // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 458f415befa4..ed04e5f20ec0 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -42,6 +42,7 @@ bool isVCLSkiaEnabled() { return false; } #include #include #include +#include #include #include #include @@ -645,11 +646,45 @@ tools::Long maxImageCacheSize() return officecfg::Office::Common::Cache::Skia::ImageCacheSize::get(); } +static sk_sp differenceBlender; + +void setBlendModeDifference(SkPaint* paint) +{ +// This should normally do 'paint->setBlendMode(SkBlendMode::kDifference);'. +// But some drivers have a problem with this, namely currently AMD on Windows +// (e.g. 'Vulkan API version: 1.2.170, driver version: 2.0.179, vendor: 0x1002 (AMD), +// device: 0x15dd, type: integrated, name: AMD Radeon(TM) Vega 8 Graphics') +// simply crashes when kDifference is used. +// Intel also had repaint problems with kDifference (tdf#130430), but it seems +// those do not(?) exist anymore. +// Interestingly, explicitly writing a shader that does exactly the same works fine, +// so do that. +if (!differenceBlender) +{ +const char* diff = R"( +vec4 main( vec4 src, vec4 dst ) +{ +return vec4(abs( src.r - dst.r ), abs( src.g - dst.g ), abs( src.b - dst.b ), dst.a ); +} +)"; +auto effect = SkRuntimeEffect::MakeForBlender(SkString(diff)); +if (!effect.effect) +{ +SAL_WARN("vcl.skia", + "SKRuntimeEffect::MakeForBlender failed: " << effect.errorText.c_str()); +abort(); +} +differenceBlender = effect.effect->makeBlender(nullptr); +} +paint->setBlender(differenceBlender); +} + void cleanup() { sharedWindowContext.reset(); imageCache.clear(); imageCacheSize = 0; +differenceBlender.reset(); } static SkSurfaceProps commonSurfaceProps; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 9e2da70323de..fd86928c24c9 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1412,16 +1412,6 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl preDraw(); SAL_INFO("vcl.skia.trace", "invert(" << this << "): " << rPoly << ":" << int(eFlags)); assert(!mXorMode); -// Intel Vulkan drivers (up to current 0.401.3889) have a problem -// with SkBlendMode::kDifference(?) and surfaces wider than 1024 pixels, resulting -// in drawing errors. Work that around by fetching the relevant part of the surface -// and drawing using CPU. -bool rasterHack = (isGPU() && getVendor() == DriverBlocklist::VendorIntel && !mXorMode); -// BackendTest::testDrawInvertTrackFrameWithRectangle() also has a problem -// with SkBlendMode::kDifference on AMD, leading to crashes or even -// driver instability. Also work around by drawing using CPU. -if (isGPU() && getVendor() == DriverBlocklist::VendorAMD && !mXorMode) -rasterHack = true; SkPath aPath; aPath.incReserve(rPoly.count()); addPolygonToPath(rPoly, aPath); @@ -1429,6 +1419,7 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon const& rPoly, SalInvert eFl addUpdateRegion(aPath.getBounds()); SkAutoCanvasRestore autoRestore(getDrawCanvas(), true); SkPaint aPaint; +setBlendModeDifference(); // TrackFrame just inverts a dashed path around the
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |4 ++-- vcl/inc/skia/osx/gdiimpl.hxx |4 ++-- vcl/inc/skia/win/gdiimpl.hxx |1 - vcl/inc/skia/x11/gdiimpl.hxx |1 - vcl/skia/gdiimpl.cxx | 16 ++-- vcl/skia/osx/gdiimpl.cxx | 41 + vcl/skia/win/gdiimpl.cxx | 12 vcl/skia/x11/gdiimpl.cxx | 13 - 8 files changed, 35 insertions(+), 57 deletions(-) New commits: commit 234ed4bcd5c4b5b41467890b82c6efa08dec559d Author: Luboš Luňák AuthorDate: Mon Aug 30 21:02:29 2021 +0200 Commit: Luboš Luňák CommitDate: Tue Aug 31 11:37:53 2021 +0200 reduce code duplication Change-Id: I31ee84be7ebee7f1644d7fd43bbc951abd2842d6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121328 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index c914c26752cc..03a4d5cf0413 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -235,7 +235,7 @@ protected: void createWindowSurface(bool forceRaster = false); virtual void createWindowSurfaceInternal(bool forceRaster = false) = 0; void createOffscreenSurface(); -void flushSurfaceToWindowContext(const SkIRect& rect); +virtual void flushSurfaceToWindowContext(); void privateDrawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, double nTransparency, bool blockAA = false); @@ -248,7 +248,7 @@ protected: void invert(basegfx::B2DPolygon const& rPoly, SalInvert eFlags); // Called by SkiaFlushIdle. -virtual void performFlush() = 0; +void performFlush(); void scheduleFlush(); friend class SkiaFlushIdle; diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx index 4ffac5985edb..c4892ab45b43 100644 --- a/vcl/inc/skia/osx/gdiimpl.hxx +++ b/vcl/inc/skia/osx/gdiimpl.hxx @@ -45,8 +45,8 @@ public: private: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -virtual void performFlush() override; -void flushSurfaceToScreenCG(const SkIRect& rect); +virtual void flushSurfaceToWindowContext() override; +void flushSurfaceToScreenCG(); static inline sk_sp fontManager; }; diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 7e3f37ce435c..58043e5f6a83 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -60,7 +60,6 @@ public: protected: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -virtual void performFlush() override; static sk_sp createDirectWriteTypeface(HDC hdc, HFONT hfont); static void initFontInfo(); inline static sal::systools::COMReference dwriteFactory; diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx index d85c7dc0e5c7..b7e9fe2615e0 100644 --- a/vcl/inc/skia/x11/gdiimpl.hxx +++ b/vcl/inc/skia/x11/gdiimpl.hxx @@ -33,7 +33,6 @@ public: private: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -virtual void performFlush() override; virtual bool avoidRecreateByResize() const override; static std::unique_ptr createWindowContext(Display* display, Drawable drawable, const XVisualInfo* visual, int width, diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 97a34bb3f66f..433663eadd55 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -391,7 +391,19 @@ void SkiaSalGraphicsImpl::destroySurface() mIsGPU = false; } -void SkiaSalGraphicsImpl::flushSurfaceToWindowContext(const SkIRect& rect) +void SkiaSalGraphicsImpl::performFlush() +{ +SkiaZone zone; +flushDrawing(); +if (mWindowContext) +{ +if (mDirtyRect.intersect(SkIRect::MakeWH(GetWidth(), GetHeight( +flushSurfaceToWindowContext(); +mDirtyRect.setEmpty(); +} +} + +void SkiaSalGraphicsImpl::flushSurfaceToWindowContext() { sk_sp screenSurface = mWindowContext->getBackbufferSurface(); if (screenSurface != mSurface) @@ -415,7 +427,7 @@ void SkiaSalGraphicsImpl::flushSurfaceToWindowContext(const SkIRect& rect) // getBackbufferSurface() repeatedly. Using our own surface would duplicate // memory and cost time copying pixels around. assert(!isGPU()); -mWindowContext->swapBuffers(); +mWindowContext->swapBuffers(); } } diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx index 1be661629741..43fe07d5391a 100644 --- a/vcl/skia/osx/gdiimpl.cxx +++ b/vcl/skia/osx/gdiimpl.cxx @@ -84,21 +84,12 @@ void AquaSkiaSalGraphicsImpl::Flush() { performFlush(); } void AquaSkiaSalGraphicsImpl::Flush(const tools::Rectangle&) { performFlush(); } -void AquaSkiaSalGraphicsImpl::performFlush() +void AquaSkiaSalGraphicsImpl::flushSurfaceToWindowContext() { -SkiaZone zone; -flushDrawing(); -if (mSurface) -{ -
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx | 12 +++--- vcl/inc/skia/osx/gdiimpl.hxx |8 -- vcl/inc/skia/win/gdiimpl.hxx |7 -- vcl/inc/skia/x11/gdiimpl.hxx |5 vcl/skia/gdiimpl.cxx | 37 +-- vcl/skia/osx/gdiimpl.cxx | 50 ++- vcl/skia/win/gdiimpl.cxx | 22 -- vcl/skia/x11/gdiimpl.cxx | 28 8 files changed, 67 insertions(+), 102 deletions(-) New commits: commit 148ac7de372d0af3c3d20a5c94c12ca0b9cfd4ab Author: Luboš Luňák AuthorDate: Tue Aug 24 21:32:20 2021 +0200 Commit: Luboš Luňák CommitDate: Wed Aug 25 11:36:59 2021 +0200 use our own Skia surface when using GPU screen drawing Previously the code called window context's getBackbufferSurface() once, and the repeatedly used it for drawing and then did swapBuffers(). This worked until version chrome/m91, now Skia requires that a screen drawing pass is calling getBackbufferSurface(), drawing to it and calling swapBuffers(). Since we do not always draw full window content and instead keep previous content, use a separate offscreen surface for that and for actual screen drawing just blit that to the screen surface. Change-Id: I36a5b3bb23a085936f4473a0e00d8e04c6b40dab Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120966 Tested-by: Luboš Luňák Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index a7ba10c3273b..c914c26752cc 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -25,13 +25,7 @@ #include #include -#include -#include -#include -#include - -#include -#include +#include class SkiaFlushIdle; class GenericSalLayout; @@ -240,8 +234,8 @@ protected: virtual bool avoidRecreateByResize() const; void createWindowSurface(bool forceRaster = false); virtual void createWindowSurfaceInternal(bool forceRaster = false) = 0; -virtual void destroyWindowSurfaceInternal() = 0; void createOffscreenSurface(); +void flushSurfaceToWindowContext(const SkIRect& rect); void privateDrawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, double nTransparency, bool blockAA = false); @@ -321,6 +315,8 @@ protected: SalGeometryProvider* mProvider; // The Skia surface that is target of all the rendering. sk_sp mSurface; +// Note that mSurface may be a proxy surface and not the one from the window context. +std::unique_ptr mWindowContext; bool mIsGPU; // whether the surface is GPU-backed SkIRect mDirtyRect; // the area that has been changed since the last performFlush() vcl::Region mClipRegion; diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx index b9adccb370ea..4ffac5985edb 100644 --- a/vcl/inc/skia/osx/gdiimpl.hxx +++ b/vcl/inc/skia/osx/gdiimpl.hxx @@ -26,9 +26,7 @@ public: AquaSkiaSalGraphicsImpl(AquaSalGraphics& rParent, AquaSharedAttributes& rShared); virtual ~AquaSkiaSalGraphicsImpl() override; -virtual void DeInit() override; virtual void freeResources() override; -//virtual void Flush() override; virtual void UpdateGeometryProvider(SalGeometryProvider* provider) override { @@ -47,13 +45,9 @@ public: private: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -virtual void destroyWindowSurfaceInternal() override; virtual void performFlush() override; -void flushToScreenRaster(const SkIRect& rect); -void flushToScreenMetal(const SkIRect& rect); +void flushSurfaceToScreenCG(const SkIRect& rect); static inline sk_sp fontManager; -// This one is used only for Metal, and only indirectly. -std::unique_ptr mWindowContext; }; #endif // INCLUDED_VCL_INC_SKIA_OSX_GDIIMPL_HXX diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 2f85a9e3cf66..7e3f37ce435c 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -43,10 +43,6 @@ private: public: WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, SalGeometryProvider* mpProvider); -virtual ~WinSkiaSalGraphicsImpl() override; - -virtual void DeInit() override; -virtual void freeResources() override; virtual bool UseRenderNativeControl() const override { return true; } virtual bool TryRenderCachedNativeControl(ControlCacheKey const& rControlCacheKey, int nX, @@ -57,13 +53,13 @@ public: virtual bool DrawTextLayout(const GenericSalLayout& layout) override; virtual void ClearDevFontCache() override; +virtual void freeResources() override; virtual void Flush() override; static void prepareSkia(); protected: virtual void createWindowSurfaceInternal(bool forceRaster = false) override; -virtual void destroyWindowSurfaceInternal() override;
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/osx/gdiimpl.hxx |1 vcl/skia/osx/gdiimpl.cxx | 47 +-- 2 files changed, 46 insertions(+), 2 deletions(-) New commits: commit 830abb2437e3f150e1369816f491fb12a3db0c16 Author: Luboš Luňák AuthorDate: Fri Aug 13 07:35:00 2021 +0200 Commit: Luboš Luňák CommitDate: Mon Aug 23 14:59:42 2021 +0200 implement blitting to screen for skia on mac Change-Id: I01fdb57815dc3dff6d2c5757b55445f16825ed20 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120807 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/osx/gdiimpl.hxx b/vcl/inc/skia/osx/gdiimpl.hxx index eabea4483c2d..2850b92110e6 100644 --- a/vcl/inc/skia/osx/gdiimpl.hxx +++ b/vcl/inc/skia/osx/gdiimpl.hxx @@ -37,6 +37,7 @@ public: private: virtual void createWindowContext(bool forceRaster = false) override; virtual void performFlush() override; +void flushToScreen(const SkIRect& rect); friend std::unique_ptr createVulkanWindowContext(bool); }; diff --git a/vcl/skia/osx/gdiimpl.cxx b/vcl/skia/osx/gdiimpl.cxx index 399f8d024f0a..c815fc1ebe9d 100644 --- a/vcl/skia/osx/gdiimpl.cxx +++ b/vcl/skia/osx/gdiimpl.cxx @@ -56,7 +56,7 @@ void AquaSkiaSalGraphicsImpl::createWindowContext(bool forceRaster) switch (renderMethod) { case RenderRaster: -displayParams.fColorType = kBGRA__SkColorType; // TODO +displayParams.fColorType = kRGBA__SkColorType; // TODO mWindowContext.reset( new AquaSkiaWindowContextRaster(GetWidth(), GetHeight(), displayParams)); break; @@ -75,11 +75,54 @@ void AquaSkiaSalGraphicsImpl::performFlush() if (mWindowContext) { if (mDirtyRect.intersect(SkIRect::MakeWH(GetWidth(), GetHeight( -mWindowContext->swapBuffers(); // TODO +flushToScreen(mDirtyRect); mDirtyRect.setEmpty(); } } +void AquaSkiaSalGraphicsImpl::flushToScreen(const SkIRect& rect) +{ +// Based on AquaGraphicsBackend::drawBitmap(). +if (!mrShared.checkContext()) +return; + +assert(mSurface.get()); +// Do not use sub-rect, it creates copies of the data. +sk_sp image = makeCheckedImageSnapshot(mSurface); +SkPixmap pixmap; +if (!image->peekPixels()) +abort(); +// This creates the bitmap context from the cropped part, writable_addr32() will get +// the first pixel of rect.topLeft(), and using pixmap.rowBytes() ensures the following +// pixel lines will be read from correct positions. +CGContextRef context += CGBitmapContextCreate(pixmap.writable_addr32(rect.left(), rect.top()), rect.width(), +rect.height(), 8, pixmap.rowBytes(), // TODO +GetSalData()->mxRGBSpace, kCGImageAlphaNoneSkipLast); // TODO +assert(context); // TODO +CGImageRef screenImage = CGBitmapContextCreateImage(context); +assert(screenImage); // TODO +if (mrShared.isFlipped()) +{ +const CGRect screenRect = CGRectMake(rect.left(), GetHeight() - rect.top() - rect.height(), + rect.width(), rect.height()); +mrShared.maContextHolder.saveState(); +CGContextTranslateCTM(mrShared.maContextHolder.get(), 0, pixmap.height()); +CGContextScaleCTM(mrShared.maContextHolder.get(), 1, -1); +CGContextDrawImage(mrShared.maContextHolder.get(), screenRect, screenImage); +mrShared.maContextHolder.restoreState(); +} +else +{ +const CGRect screenRect = CGRectMake(rect.left(), rect.top(), rect.width(), rect.height()); +CGContextDrawImage(mrShared.maContextHolder.get(), screenRect, screenImage); +} + +CGImageRelease(screenImage); +CGContextRelease(context); +mrShared.refreshRect(rect.left(), rect.top(), rect.width(), rect.height()); +} + std::unique_ptr createVulkanWindowContext(bool /*temporary*/) { return nullptr;
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx|7 +-- vcl/skia/gdiimpl.cxx| 16 ++-- vcl/skia/win/gdiimpl.cxx| 42 ++ vcl/skia/x11/textrender.cxx |3 +-- 4 files changed, 38 insertions(+), 30 deletions(-) New commits: commit b60cf6c7a85d2fa8ea5b17851407417be7a6 Author: Luboš Luňák AuthorDate: Fri May 14 13:48:37 2021 + Commit: Luboš Luňák CommitDate: Mon May 24 11:01:31 2021 +0200 fix Skia Windows text rendering This is quite some trial and error, but now it seems all CJK text rendering works properly. I tested tdf#136081, tdf#137907, tdf#103785, tdf#106295, tdf#114209 and tdf#141715. Change-Id: I40e893f66281b0a1a0e814feec3f782ceeb0c535 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115620 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 08d9f6ee64cc..14fa5df6012b 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -217,13 +217,8 @@ public: void drawShader(const SalTwoRect& rPosAry, const sk_sp& shader, SkBlendMode blendMode = SkBlendMode::kSrcOver); -enum class GlyphOrientation -{ -Apply, -Ignore -}; void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font, - const SkFont& verticalFont, GlyphOrientation glyphOrientation); + const SkFont& verticalFont); protected: // To be called before any drawing. diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index b559231cd906..fbc77b4112ae 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2060,8 +2060,7 @@ static double toCos(Degree10 degree10th) { return SkScalarCos(toRadian(degree10t static double toSin(Degree10 degree10th) { return SkScalarSin(toRadian(degree10th)); } void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Color textColor, -const SkFont& font, const SkFont& verticalFont, -GlyphOrientation glyphOrientation) +const SkFont& font, const SkFont& verticalFont) { SkiaZone zone; std::vector glyphIds; @@ -2076,13 +2075,9 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo while (layout.GetNextGlyph(, aPos, nStart)) { glyphIds.push_back(pGlyph->glyphId()); -Degree10 angle(0); // 10th of degree -if (glyphOrientation == GlyphOrientation::Apply) -{ -angle = layout.GetOrientation(); -if (pGlyph->IsVertical()) -angle += 900_deg10; // 90 degree -} +Degree10 angle = layout.GetOrientation(); +if (pGlyph->IsVertical()) +angle += 900_deg10; SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.X(), aPos.Y()); glyphForms.emplace_back(std::move(form)); verticals.emplace_back(pGlyph->IsVertical()); @@ -2099,7 +2094,8 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo SAL_INFO("vcl.skia.trace", "drawtextblob(" << this << "): " << getBoundRect() << ", " << glyphIds.size() << " glyphs, " << textColor); -// Vertical glyphs need a different font, so each run draw only consecutive horizontal or vertical glyphs. +// Vertical glyphs need a different font, so split drawing into runs that each +// draw only consecutive horizontal or vertical glyphs. std::vector::const_iterator pos = verticals.cbegin(); std::vector::const_iterator end = verticals.cend(); while (pos != end) diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index e245f488433a..2e0e7fc8ee12 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -203,6 +203,7 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) const SkiaWinFontInstance* pWinFont = static_cast(()); const HFONT hLayoutFont = pWinFont->GetHFONT(); +double hScale = pWinFont->getHScale(); LOGFONTW logFont; if (GetObjectW(hLayoutFont, sizeof(logFont), ) == 0) { @@ -216,34 +217,51 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) bool dwrite = true; if (!typeface) // fall back to GDI text rendering { -// If lfWidth is kept, then with fHScale != 1 characters get too wide, presumably +// If lfWidth is kept, then with hScale != 1 characters get too wide, presumably // because the horizontal scaling gets applied twice if GDI is used for drawing (tdf#141715). -// Using lfWidth /= fHScale gives slightly incorrect sizes, for a reason I don't understand. +// Using lfWidth /=
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx|2 +- vcl/skia/gdiimpl.cxx| 42 -- vcl/skia/win/gdiimpl.cxx|2 +- vcl/skia/x11/textrender.cxx | 10 -- 4 files changed, 42 insertions(+), 14 deletions(-) New commits: commit d3772e26c077686fc5ca0a8ba526df7d104ada5c Author: Luboš Luňák AuthorDate: Wed May 5 18:21:21 2021 +0200 Commit: Luboš Luňák CommitDate: Mon May 24 10:58:18 2021 +0200 fix font scale width handling for Skia/X11 (tdf#136081) We get width+height, for vertical text width is the font "height". This means we need to use two different fonts, one for "normal" glyphs and one for vertical glyphs. Change-Id: I9d190fc28286055a18c3d5c3ec75515c7c1d4373 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115618 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 2eb2ffd26136..08d9f6ee64cc 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -223,7 +223,7 @@ public: Ignore }; void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font, - GlyphOrientation glyphOrientation); + const SkFont& verticalFont, GlyphOrientation glyphOrientation); protected: // To be called before any drawing. diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 2e15d8dbb45f..b559231cd906 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -2060,13 +2060,16 @@ static double toCos(Degree10 degree10th) { return SkScalarCos(toRadian(degree10t static double toSin(Degree10 degree10th) { return SkScalarSin(toRadian(degree10th)); } void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Color textColor, -const SkFont& font, GlyphOrientation glyphOrientation) +const SkFont& font, const SkFont& verticalFont, +GlyphOrientation glyphOrientation) { SkiaZone zone; std::vector glyphIds; std::vector glyphForms; +std::vector verticals; glyphIds.reserve(256); glyphForms.reserve(256); +verticals.reserve(256); Point aPos; const GlyphItem* pGlyph; int nStart = 0; @@ -2082,19 +2085,38 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo } SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.X(), aPos.Y()); glyphForms.emplace_back(std::move(form)); +verticals.emplace_back(pGlyph->IsVertical()); } if (glyphIds.empty()) return; -sk_sp textBlob -= SkTextBlob::MakeFromRSXform(glyphIds.data(), glyphIds.size() * sizeof(SkGlyphID), - glyphForms.data(), font, SkTextEncoding::kGlyphID); + preDraw(); -SAL_INFO("vcl.skia.trace", - "drawtextblob(" << this << "): " << textBlob->bounds() << ":" << textColor); -addUpdateRegion(textBlob->bounds()); -SkPaint paint; -paint.setColor(toSkColor(textColor)); -getDrawCanvas()->drawTextBlob(textBlob, 0, 0, paint); +auto getBoundRect = []() { +tools::Rectangle rect; +layout.GetBoundRect(rect); +return rect; +}; +SAL_INFO("vcl.skia.trace", "drawtextblob(" << this << "): " << getBoundRect() << ", " + << glyphIds.size() << " glyphs, " << textColor); + +// Vertical glyphs need a different font, so each run draw only consecutive horizontal or vertical glyphs. +std::vector::const_iterator pos = verticals.cbegin(); +std::vector::const_iterator end = verticals.cend(); +while (pos != end) +{ +bool verticalRun = *pos; +std::vector::const_iterator rangeEnd = std::find(pos + 1, end, !verticalRun); +size_t index = pos - verticals.cbegin(); +size_t count = rangeEnd - pos; +sk_sp textBlob = SkTextBlob::MakeFromRSXform( +glyphIds.data() + index, count * sizeof(SkGlyphID), glyphForms.data() + index, +verticalRun ? verticalFont : font, SkTextEncoding::kGlyphID); +addUpdateRegion(textBlob->bounds()); +SkPaint paint; +paint.setColor(toSkColor(textColor)); +getDrawCanvas()->drawTextBlob(textBlob, 0, 0, paint); +pos = rangeEnd; +} postDraw(); } diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 5f7e1fe3538a..24daf1fc8b7c 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -240,7 +240,7 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) SkiaSalGraphicsImpl* impl = static_cast(mWinParent.GetImpl()); COLORREF color = ::GetTextColor(mWinParent.getHDC()); Color salColor(GetRValue(color), GetGValue(color), GetBValue(color)); -
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx | 38 +- vcl/skia/gdiimpl.cxx |6 +++--- vcl/skia/salbmp.cxx| 13 - 3 files changed, 48 insertions(+), 9 deletions(-) New commits: commit 8043fe3e45c8999c8eaf475ba46d50b125e38b93 Author: Luboš Luňák AuthorDate: Thu Apr 8 22:20:53 2021 +0200 Commit: Luboš Luňák CommitDate: Mon Apr 12 15:05:49 2021 +0200 use Skia linear+mipmap for quality large downscaling (tdf#140129) This is what https://bugs.chromium.org/p/skia/issues/detail?id=11810#c1 suggests (although I consider it to be an annoyance having to do this explicitly). Change-Id: I3df80374492c7b208ebaf819c0b4794ba535aa53 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113979 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 716bd3e2471c..e53a17c7d934 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -85,11 +85,42 @@ VCL_DLLPUBLIC const SkSurfaceProps* surfaceProps(); // Set pixel geometry to be used by SkSurfaceProps. VCL_DLLPUBLIC void setPixelGeometry(SkPixelGeometry pixelGeometry); -inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scaling) +// Normal scaling algorithms have a poor quality when downscaling a lot. +// https://bugs.chromium.org/p/skia/issues/detail?id=11810 suggests to use mipmaps +// in such a case, which is annoying to do explicitly instead of Skia deciding which +// algorithm would be the best, but now with Skia removing SkFilterQuality and requiring +// explicitly being told what algorithm to use this appears to be the best we can do. +// Anything scaled down at least this ratio will use linear+mipmaps. +constexpr int downscaleRatioThreshold = 4; + +inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scaling, const SkMatrix& matrix) { switch (scaling) { case BmpScaleFlag::BestQuality: +if (matrix.getScaleX() <= 1.0 / downscaleRatioThreshold +|| matrix.getScaleY() <= 1.0 / downscaleRatioThreshold) +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); +return SkSamplingOptions(SkCubicResampler::Mitchell()); +case BmpScaleFlag::Default: +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone); +case BmpScaleFlag::Fast: +return SkSamplingOptions(SkFilterMode::kNearest, SkMipmapMode::kNone); +default: +assert(false); +return SkSamplingOptions(); +} +} + +inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scaling, const Size& srcSize, + const Size& destSize) +{ +switch (scaling) +{ +case BmpScaleFlag::BestQuality: +if (srcSize.Width() / destSize.Width() >= downscaleRatioThreshold +|| srcSize.Height() / destSize.Height() >= downscaleRatioThreshold) +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); return SkSamplingOptions(SkCubicResampler::Mitchell()); case BmpScaleFlag::Default: return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone); @@ -104,7 +135,12 @@ inline SkSamplingOptions makeSamplingOptions(BmpScaleFlag scaling) inline SkSamplingOptions makeSamplingOptions(const SalTwoRect& rPosAry) { if (rPosAry.mnSrcWidth != rPosAry.mnDestWidth || rPosAry.mnSrcHeight != rPosAry.mnDestHeight) +{ +if (rPosAry.mnSrcWidth / rPosAry.mnDestWidth >= downscaleRatioThreshold +|| rPosAry.mnSrcHeight / rPosAry.mnDestHeight >= downscaleRatioThreshold) +return SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear); return SkSamplingOptions(SkCubicResampler::Mitchell()); // best +} return SkSamplingOptions(); // none } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 828b7959244b..fd4f64e930cf 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1652,7 +1652,7 @@ sk_sp SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma matrix.set(SkMatrix::kMScaleX, 1.0 * targetSize.Width() / bitmap.GetSize().Width()); matrix.set(SkMatrix::kMScaleY, 1.0 * targetSize.Height() / bitmap.GetSize().Height()); canvas->concat(matrix); -samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality); +samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, matrix); } if (alphaBitmap != nullptr) { @@ -1884,7 +1884,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const basegfx::B2DPoint& rNull, canvas->concat(matrix); SkSamplingOptions samplingOptions; if (matrixNeedsHighQuality(matrix)) -samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality); +samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, matrix);
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/win
vcl/inc/skia/win/font.hxx | 41 + vcl/skia/win/gdiimpl.cxx | 33 +++-- vcl/win/gdi/salfont.cxx |9 + 3 files changed, 69 insertions(+), 14 deletions(-) New commits: commit 43bcc236d8253dff80b0911836fe73504b561f9a Author: Luboš Luňák AuthorDate: Wed Apr 7 12:48:35 2021 + Commit: Luboš Luňák CommitDate: Wed Apr 7 17:01:40 2021 +0200 cache Skia font The conversion costs a little bit and it was done for each drawing. Change-Id: Ifaad42308213f15839d9277beb837d21535bfc25 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/113735 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/font.hxx b/vcl/inc/skia/win/font.hxx new file mode 100644 index ..4dc0bdf047d5 --- /dev/null +++ b/vcl/inc/skia/win/font.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#ifndef INCLUDED_VCL_INC_SKIA_WIN_FONT_HXX +#define INCLUDED_VCL_INC_SKIA_WIN_FONT_HXX + +#include + +#include + +// This class only adds SkTypeface in order to allow its caching. +class SkiaWinFontInstance : public WinFontInstance +{ +friend rtl::Reference +WinFontFace::CreateFontInstance(const FontSelectPattern&) const; + +public: +sk_sp GetSkiaTypeface() const { return m_skiaTypeface; } +bool GetSkiaDWrite() const { return m_skiaDWrite; } +void SetSkiaTypeface(const sk_sp& typeface, bool dwrite) +{ +m_skiaTypeface = typeface; +m_skiaDWrite = dwrite; +} + +private: +using WinFontInstance::WinFontInstance; +sk_sp m_skiaTypeface; +bool m_skiaDWrite; +}; + +#endif // INCLUDED_VCL_INC_SKIA_WIN_FONT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 6b09375c4138..94162bb55fbe 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -199,11 +199,9 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFO bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) { -const WinFontInstance& rWinFont = static_cast(rLayout.GetFont()); -float fHScale = rWinFont.getHScale(); - -assert(dynamic_cast(())); -const WinFontInstance* pWinFont = static_cast(()); +assert(dynamic_cast(())); +const SkiaWinFontInstance* pWinFont += static_cast(()); const HFONT hLayoutFont = pWinFont->GetHFONT(); LOGFONTW logFont; if (GetObjectW(hLayoutFont, sizeof(logFont), ) == 0) @@ -211,12 +209,18 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) assert(false); return false; } -sk_sp typeface = createDirectWriteTypeface(mWinParent.getHDC(), hLayoutFont); -GlyphOrientation glyphOrientation = GlyphOrientation::Apply; -if (!typeface) // fall back to GDI text rendering +sk_sp typeface = pWinFont->GetSkiaTypeface(); +if (!typeface) { -typeface.reset(SkCreateTypefaceFromLOGFONT(logFont)); -glyphOrientation = GlyphOrientation::Ignore; +typeface = createDirectWriteTypeface(mWinParent.getHDC(), hLayoutFont); +bool dwrite = true; +if (!typeface) // fall back to GDI text rendering +{ +typeface.reset(SkCreateTypefaceFromLOGFONT(logFont)); +dwrite = false; +} +// Cache the typeface. +const_cast(pWinFont)->SetSkiaTypeface(typeface, dwrite); } // lfHeight actually depends on DPI, so it's not really font height as such, // but for LOGFONT-based typefaces Skia simply sets lfHeight back to this value @@ -224,14 +228,15 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) double fontHeight = logFont.lfHeight; if (fontHeight < 0) fontHeight = -fontHeight; -SkFont font(typeface, fontHeight, fHScale, 0); +SkFont font(typeface, fontHeight, pWinFont->getHScale(), 0); font.setEdging(fontEdging); assert(dynamic_cast(mWinParent.GetImpl())); SkiaSalGraphicsImpl* impl = static_cast(mWinParent.GetImpl()); COLORREF color = ::GetTextColor(mWinParent.getHDC()); Color salColor(GetRValue(color), GetGValue(color), GetBValue(color)); -// The font already is set up to have glyphs rotated as needed. -impl->drawGenericLayout(rLayout, salColor, font, glyphOrientation); +impl->drawGenericLayout(rLayout, salColor, font, +pWinFont->GetSkiaDWrite() ? GlyphOrientation::Apply +
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |2 ++ vcl/skia/salbmp.cxx| 10 ++ 2 files changed, 12 insertions(+) New commits: commit 96007832dd3d800ca781c9ef12904b178adb61f1 Author: Luboš Luňák AuthorDate: Mon Mar 15 16:56:07 2021 +0100 Commit: Luboš Luňák CommitDate: Tue Mar 16 12:55:33 2021 +0100 don't repeatedly create (alpha)SkImage on mEraseColorSet Change-Id: Iac42ead2bfd5a2b7f245cc44634f675a559d86ee Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112543 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 3baa749adb8b..716bd3e2471c 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -67,6 +67,8 @@ VCL_DLLPUBLIC sk_sp makeCheckedImageSnapshot(sk_sp surface); VCL_DLLPUBLIC sk_sp makeCheckedImageSnapshot(sk_sp surface, const SkIRect& bounds); +inline Size imageSize(const sk_sp& image) { return Size(image->width(), image->height()); } + // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 0fa95deb39db..83dd16950eaa 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -730,6 +730,11 @@ const sk_sp& SkiaSalBitmap::GetSkImage() const #endif if (mEraseColorSet) { +if (mImage) +{ +assert(imageSize(mImage) == mSize); +return mImage; +} SkiaZone zone; sk_sp surface = createSkSurface( mSize, mEraseColor.IsTransparent() ? kPremul_SkAlphaType : kOpaque_SkAlphaType); @@ -801,6 +806,11 @@ const sk_sp& SkiaSalBitmap::GetAlphaSkImage() const #endif if (mEraseColorSet) { +if (mAlphaImage) +{ +assert(imageSize(mAlphaImage) == mSize); +return mAlphaImage; +} SkiaZone zone; sk_sp surface = createSkSurface(mSize, kAlpha_8_SkColorType); assert(surface); ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |4 ++ vcl/skia/salbmp.cxx | 68 +--- 2 files changed, 69 insertions(+), 3 deletions(-) New commits: commit 3c9936a9b77fe18396d048de2f97b9e8eb66a787 Author: Luboš Luňák AuthorDate: Wed Mar 3 11:29:49 2021 +0100 Commit: Luboš Luňák CommitDate: Wed Mar 3 19:06:42 2021 +0100 try to avoid skia alpha blending with fully opaque bitmaps E.g. the document in tdf#140753 has a PNG which technically has an alpha channel, but it's actually completely opaque. Doing this avoids having the pixel data for the separate alpha bitmap, and it also avoids the pointless (somewhat costly in the raster case) alpha blending. Change-Id: I0916962e5894a111002c667a2f98782765aacb1f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111893 Tested-by: Luboš Luňák Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 2a1d309a7fec..0509ed3381b6 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -123,6 +123,10 @@ private: void EraseInternal(const Color& color); // Sets pixels to the erase color. void PerformErase(); +// Try to find out if the content is completely black. Used for optimizations, +// not guaranteed to always return true for such bitmaps. +bool IsAllBlack() const; +void ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode, bool dontChangeToErase); SkBitmap GetAsSkBitmap() const; bool ConserveMemory() const; void verify() const diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index c8d8f1a766b2..68d2f9a76964 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -278,6 +278,12 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) } void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) +{ +ReleaseBuffer(pBuffer, nMode, false); +} + +void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode, + bool dontChangeToErase) { if (nMode == BitmapAccessMode::Write) { @@ -298,6 +304,62 @@ void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) assert(pBuffer->mpBits == mBuffer.get() || nMode == BitmapAccessMode::Info); verify(); delete pBuffer; +if (nMode == BitmapAccessMode::Write && !dontChangeToErase) +{ +// This saves memory and is also used by IsFullyOpaqueAsAlpha() to avoid unnecessary +// alpha blending. +if (IsAllBlack()) +{ +SAL_INFO("vcl.skia.trace", "releasebuffer(" << this << "): erasing to black"); +EraseInternal(COL_BLACK); +} +} +} + +static bool isAllZero(const sal_uInt8* data, size_t size) +{ // For performance, check in larger data chunks. +#ifdef UINT64_MAX +const int64_t* d = reinterpret_cast(data); +#else +const int32_t* d = reinterpret_cast(data); +#endif +constexpr size_t step = sizeof(*d) * 8; +for (size_t i = 0; i < size / step; ++i) +{ // Unrolled loop. +if (d[0] != 0) +return false; +if (d[1] != 0) +return false; +if (d[2] != 0) +return false; +if (d[3] != 0) +return false; +if (d[4] != 0) +return false; +if (d[5] != 0) +return false; +if (d[6] != 0) +return false; +if (d[7] != 0) +return false; +d += 8; +} +for (size_t i = size / step * step; i < size; ++i) +if (data[i] != 0) +return false; +return true; +} + +bool SkiaSalBitmap::IsAllBlack() const +{ +if (mBitCount % 8 != 0 || (!!mPalette && mPalette[0] != COL_BLACK)) +return false; // Don't bother. +if (mSize.Width() * mBitCount / 8 == mScanlineSize) +return isAllZero(mBuffer.get(), mScanlineSize * mSize.Height()); +for (tools::Long y = 0; y < mSize.Height(); ++y) +if (!isAllZero(mBuffer.get() + mScanlineSize * y, mSize.Width() * mBitCount / 8)) +return false; +return true; } bool SkiaSalBitmap::GetSystemData(BitmapSystemData&) @@ -899,8 +961,8 @@ sk_sp SkiaSalBitmap::GetAlphaSkShader(const SkSamplingOptions& samplin bool SkiaSalBitmap::IsFullyOpaqueAsAlpha() const { -if (!mEraseColorSet) -return false; // don't bother figuring it out from the pixels +if (!mEraseColorSet) // Set from Erase() or ReleaseBuffer(). +return false; // If the erase color is set so that this bitmap used as alpha would // mean a fully opaque alpha mask (= noop), we can skip using it. // Note that for alpha bitmaps we use the VCL "transparency" convention, @@ -943,7 +1005,7 @@ void SkiaSalBitmap::PerformErase() memcpy(scanline + y * bitmapBuffer->mnScanlineSize, scanline, bitmapBuffer->mnScanlineSize); } -
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |9 + vcl/skia/win/gdiimpl.cxx | 40 ++-- 2 files changed, 35 insertions(+), 14 deletions(-) New commits: commit 13f53741dabc33c5ac12ae26538a2803c6ba1073 Author: Luboš Luňák AuthorDate: Thu Feb 25 10:05:36 2021 + Commit: Luboš Luňák CommitDate: Mon Mar 1 15:56:46 2021 +0100 make sure Skia DWrite matches the given HFONT exactly (tdf#137122) The problem appears to be that we use our private copy of the Dejavu Sans fonts, installed using AddFontResourceExW( FR_PRIVATE ), but that's not for whatever reason available for DirectWrite, which made CreateFontFromLOGFONT() find the system-installed Dejavu Sans, and if there was a difference between the two, then incorrect glyph ids were used. Use CreateFontFaceFromHdc(), which seems to match exactly. For private fonts this later fails the check with GetSystemFontCollection(), which would be nice to handle somehow, but I don't know how to get a font collection containing those fonts other than modifying SalFont to use DirectWrite API to install the fonts. Change-Id: I10d8fcb618f3b4decbb0198274331d7beaf843d6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111522 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 277c076323c8..594d4bad4b8c 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -11,8 +11,9 @@ #define INCLUDED_VCL_INC_SKIA_WIN_GDIIMPL_HXX #include -#include +#include +#include #include #include #include @@ -61,10 +62,10 @@ public: protected: virtual void createWindowContext(bool forceRaster = false) override; virtual void performFlush() override; -sk_sp createDirectWriteTypeface(const LOGFONTW& logFont); +sk_sp createDirectWriteTypeface(HDC hdc, HFONT hfont); static void initFontInfo(); -inline static IDWriteFactory* dwriteFactory; -inline static IDWriteGdiInterop* dwriteGdiInterop; +inline static sal::systools::COMReference dwriteFactory; +inline static sal::systools::COMReference dwriteGdiInterop; inline static sk_sp dwriteFontMgr; inline static bool dwriteDone = false; static SkFont::Edging fontEdging; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 6d47f34ed84d..d296747936f5 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -144,7 +144,7 @@ static HRESULT checkResult(HRESULT hr, const char* file, size_t line) #define CHECKHR(funct) (funct) #endif -sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const LOGFONTW& logFont) +sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(HDC hdc, HFONT hfont) { if (!dwriteDone) { @@ -153,25 +153,43 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const LOGFON reinterpret_cast() { if (SUCCEEDED(CHECKHR(dwriteFactory->GetGdiInterop( -dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory); +dwriteFontMgr = SkFontMgr_New_DirectWrite(dwriteFactory.get()); else -dwriteFactory->Release(); +dwriteFactory.clear(); } dwriteDone = true; } if (!dwriteFontMgr) return nullptr; -IDWriteFont* font = nullptr; -IDWriteFontFace* fontFace; -IDWriteFontFamily* fontFamily; -if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFromLOGFONT(, + +// tdf#137122: We need to get the exact same font as HFONT refers to, +// since VCL core computes things like glyph ids based on that, and getting +// a different font could lead to mismatches (e.g. if there's a slightly +// different version of the same font installed system-wide). +// For that CreateFromFaceFromHdc() is necessary. The simpler +// CreateFontFromLOGFONT() seems to search for the best matching font, +// which may not be the exact font. Our private fonts are installed +// using AddFontResourceExW( FR_PRIVATE ) and that apparently does +// not make them available to DirectWrite (at least, they are not +// included the DWrite system font collection). For such cases, we'll +// need to fall back to Skia's GDI-based font rendering. +HFONT oldFont = SelectFont(hdc, hfont); +auto restoreFont = [hdc, oldFont]() { SelectFont(hdc, oldFont); }; +sal::systools::COMReference fontFace; +if (FAILED(CHECKHR(dwriteGdiInterop->CreateFontFaceFromHdc(hdc, +return nullptr; +sal::systools::COMReference collection; +if (FAILED(CHECKHR(dwriteFactory->GetSystemFontCollection( return nullptr; -if (FAILED(CHECKHR(font->CreateFontFace( +sal::systools::COMReference font; +// Do not use CHECKHR() here, as said above, this fails for our fonts. +if
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx| 10 +- vcl/inc/skia/x11/textrender.hxx |2 +- vcl/skia/win/gdiimpl.cxx|2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) New commits: commit 9cd95b10936450b5d1d60319192c25c4aea05fa3 Author: Luboš Luňák AuthorDate: Wed Feb 24 12:45:32 2021 + Commit: Luboš Luňák CommitDate: Mon Mar 1 15:56:25 2021 +0100 it's enough to have one Skia font manager Change-Id: I5dd29178e1a1ec1081820912f49fd387eb3f822b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111521 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index fd39ca273609..277c076323c8 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -21,9 +21,9 @@ #include #include +#include class SkTypeface; -class SkFontMgr; class ControlCacheKey; class SkiaCompatibleDC : public CompatibleDC @@ -63,10 +63,10 @@ protected: virtual void performFlush() override; sk_sp createDirectWriteTypeface(const LOGFONTW& logFont); static void initFontInfo(); -IDWriteFactory* dwriteFactory; -IDWriteGdiInterop* dwriteGdiInterop; -sk_sp dwriteFontMgr; -bool dwriteDone = false; +inline static IDWriteFactory* dwriteFactory; +inline static IDWriteGdiInterop* dwriteGdiInterop; +inline static sk_sp dwriteFontMgr; +inline static bool dwriteDone = false; static SkFont::Edging fontEdging; }; diff --git a/vcl/inc/skia/x11/textrender.hxx b/vcl/inc/skia/x11/textrender.hxx index d6eda9a048ea..6943ab4ce416 100644 --- a/vcl/inc/skia/x11/textrender.hxx +++ b/vcl/inc/skia/x11/textrender.hxx @@ -32,7 +32,7 @@ public: virtual void ClearDevFontCache() override; private: -sk_sp fontManager; +static inline sk_sp fontManager; }; #endif diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 8467b1d80765..6d47f34ed84d 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -159,6 +159,8 @@ sk_sp WinSkiaSalGraphicsImpl::createDirectWriteTypeface(const LOGFON } dwriteDone = true; } +if (!dwriteFontMgr) +return nullptr; IDWriteFont* font = nullptr; IDWriteFontFace* fontFace; IDWriteFontFamily* fontFamily; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |4 ++-- vcl/skia/gdiimpl.cxx | 34 +- vcl/skia/win/gdiimpl.cxx |1 + vcl/skia/x11/gdiimpl.cxx |2 ++ 4 files changed, 26 insertions(+), 15 deletions(-) New commits: commit 9d8c04d2d5529626d649af3fcebb6d4b65193b28 Author: Luboš Luňák AuthorDate: Thu Feb 25 11:37:54 2021 + Commit: Luboš Luňák CommitDate: Mon Mar 1 15:53:55 2021 +0100 generic Skia workaround for VCL sending empty size (tdf#140288) There have already been commits to handle this, but the case of getting the wrong size the first was still broken (or was fixed in the past and got broken again). Try to be generic by forcing these to be always considered to be offscreen and force non-zero size there. Change-Id: Ie366a296f7f6645333630fa31e9fe18d54c7fba8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111528 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 64707e35d134..2eb2ffd26136 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -241,7 +241,7 @@ protected: void checkSurface(); void destroySurface(); // Reimplemented for X11. -virtual bool avoidRecreateByResize() const { return false; } +virtual bool avoidRecreateByResize() const; void createWindowSurface(bool forceRaster = false); virtual void createWindowContext(bool forceRaster = false) = 0; void createOffscreenSurface(); @@ -251,7 +251,7 @@ protected: void setProvider(SalGeometryProvider* provider) { mProvider = provider; } -bool isOffscreen() const { return mProvider == nullptr || mProvider->IsOffScreen(); } +bool isOffscreen() const; bool isGPU() const { return mIsGPU; } void invert(basegfx::B2DPolygon const& rPoly, SalInvert eFlags); diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 950010183cb1..d8ddf48536c0 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -334,14 +334,24 @@ void SkiaSalGraphicsImpl::createWindowSurface(bool forceRaster) #endif } +bool SkiaSalGraphicsImpl::isOffscreen() const +{ +if (mProvider == nullptr || mProvider->IsOffScreen()) +return true; +// HACK: Sometimes (tdf#131939, tdf#138022, tdf#140288) VCL passes us a zero-sized window, +// and zero size is invalid for Skia, so force offscreen surface, where we handle this. +if (GetWidth() <= 0 || GetHeight() <= 0) +return true; +return false; +} + void SkiaSalGraphicsImpl::createOffscreenSurface() { SkiaZone zone; assert(isOffscreen()); assert(!mSurface); assert(!mWindowContext); -// When created (especially on Windows), Init() gets called with size (0,0), which is invalid size -// for Skia. May happen also in rare cases such as shutting down (tdf#131939). +// HACK: See isOffscreen(). int width = std::max(1, GetWidth()); int height = std::max(1, GetHeight()); switch (SkiaHelper::renderMethodToUse()) @@ -460,17 +470,7 @@ void SkiaSalGraphicsImpl::checkSurface() } else if (GetWidth() != mSurface->width() || GetHeight() != mSurface->height()) { -if (avoidRecreateByResize()) -return; - -if (!GetWidth() || !GetHeight()) -{ -SAL_WARN("vcl.skia", "recreate(" << this << "): can't create empty surface " - << Size(GetWidth(), GetHeight()) - << " => keeping old one!"); -return; -} - +if (!avoidRecreateByResize()) { Size oldSize(mSurface->width(), mSurface->height()); // Recreating a surface means that the old SkSurface contents will be lost. @@ -503,6 +503,14 @@ void SkiaSalGraphicsImpl::checkSurface() } } +bool SkiaSalGraphicsImpl::avoidRecreateByResize() const +{ +// Keep the old surface if VCL sends us a broken size (see isOffscreen()). +if (GetWidth() == 0 || GetHeight() == 0) +return true; +return false; +} + void SkiaSalGraphicsImpl::flushDrawing() { if (!mSurface) diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 054555ca6e41..8467b1d80765 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -38,6 +38,7 @@ void WinSkiaSalGraphicsImpl::createWindowContext(bool forceRaster) { SkiaZone zone; sk_app::DisplayParams displayParams; +assert(GetWidth() > 0 && GetHeight() > 0); displayParams.fSurfaceProps = *SkiaHelper::surfaceProps(); switch (forceRaster ? SkiaHelper::RenderRaster : SkiaHelper::renderMethodToUse()) { diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx index 29fb15d27140..2ef186ad78d0 100644 --- a/vcl/skia/x11/gdiimpl.cxx +++ b/vcl/skia/x11/gdiimpl.cxx @@ -108,6 +108,8 @@ X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable, bool
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |1 + vcl/skia/salbmp.cxx | 35 +-- 2 files changed, 26 insertions(+), 10 deletions(-) New commits: commit 0e5b473a63409da2cdae4f4c60a91fcc93755ba5 Author: Luboš Luňák AuthorDate: Tue Dec 15 12:59:25 2020 +0100 Commit: Luboš Luňák CommitDate: Tue Dec 15 16:03:27 2020 +0100 do not free SkiaSalBitmap buffer if a read access points to it When conserving memory in raster mode, SkiaSalBitmap may decide to drop the pixel buffer if SkImage is created from it, since having both wastes memory and converting between them is cheap. But if there is still a Bitmap::ScopedReadAccess existing for the bitmap (e.g. VclCanvasBitmap keeps it as a member), then dropping the pixel buffer would make the data pointed to by the read access invalid. Technically this patch should distinguish between info and read accesses, as info accesses do not point to pixels, but this is simpler and hopefully doesn't make a difference in practice. Change-Id: I307170ad4651b849feda0cf224976ca5a87e5207 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107752 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 9edb1d620e3a..ec8d4f3c7b82 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -177,6 +177,7 @@ private: // Erase() is delayed, just sets these two instead of filling the buffer. bool mEraseColorSet = false; Color mEraseColor; +int mAnyAccessCount = 0; // number of any kind of AcquireAccess() that have not been released #ifdef DBG_UTIL int mWriteAccessCount = 0; // number of write AcquireAccess() that have not been released #endif diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 096a667e9382..119f4acda526 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -68,6 +68,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) mBitCount = 32; mSize = mPixelsSize = Size(image->width(), image->height()); ComputeScanlineSize(); +mAnyAccessCount = 0; #ifdef DBG_UTIL mWriteAccessCount = 0; #endif @@ -76,15 +77,13 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal) { +assert(mAnyAccessCount == 0); ResetAllData(); if (!isValidBitCount(nBitCount)) return false; mPalette = rPal; mBitCount = nBitCount; mSize = mPixelsSize = rSize; -#ifdef DBG_UTIL -mWriteAccessCount = 0; -#endif if (!ComputeScanlineSize()) { mBitCount = 0; @@ -150,6 +149,7 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, SalGraphics* pGraphics) bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) { +assert(mAnyAccessCount == 0); const SkiaSalBitmap& src = static_cast(rSalBmp); mImage = src.mImage; mAlphaImage = src.mAlphaImage; @@ -162,9 +162,6 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) mScaleQuality = src.mScaleQuality; mEraseColorSet = src.mEraseColorSet; mEraseColor = src.mEraseColor; -#ifdef DBG_UTIL -mWriteAccessCount = 0; -#endif if (nNewBitCount != src.GetBitCount()) { // This appears to be unused(?). Implement this just in case, but be lazy @@ -188,6 +185,7 @@ void SkiaSalBitmap::Destroy() #ifdef DBG_UTIL assert(mWriteAccessCount == 0); #endif +assert(mAnyAccessCount == 0); ResetAllData(); } @@ -226,7 +224,10 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) buffer->mnHeight = mSize.Height(); buffer->mnBitCount = mBitCount; buffer->maPalette = mPalette; -buffer->mpBits = mBuffer.get(); +if (nMode != BitmapAccessMode::Info) +buffer->mpBits = mBuffer.get(); +else +buffer->mpBits = nullptr; if (mPixelsSize == mSize) buffer->mnScanlineSize = mScanlineSize; else @@ -266,6 +267,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) abort(); } buffer->mnFormat |= ScanlineFormat::TopDown; +++mAnyAccessCount; #ifdef DBG_UTIL if (nMode == BitmapAccessMode::Write) ++mWriteAccessCount; @@ -285,11 +287,13 @@ void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) ResetToBuffer(); InvalidateChecksum(); } +assert(mAnyAccessCount > 0); +--mAnyAccessCount; // Are there any more ground movements underneath us ? assert(pBuffer->mnWidth == mSize.Width()); assert(pBuffer->mnHeight == mSize.Height()); assert(pBuffer->mnBitCount == mBitCount); -assert(pBuffer->mpBits == mBuffer.get()); +assert(pBuffer->mpBits == mBuffer.get() || nMode == BitmapAccessMode::Info); verify(); delete pBuffer; } @@ -456,6 +460,9 @@ bool SkiaSalBitmap::InterpretAs8Bit() bool
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/win
vcl/inc/skia/win/gdiimpl.hxx | 14 - vcl/inc/win/saldata.hxx |2 vcl/inc/win/salgdi.h | 17 -- vcl/inc/win/wingdiimpl.hxx | 14 - vcl/inc/win/winlayout.hxx| 88 vcl/skia/win/gdiimpl.cxx | 67 - vcl/win/gdi/winlayout.cxx| 312 --- 7 files changed, 3 insertions(+), 511 deletions(-) New commits: commit daa0e2629e13883da0cb41c29fccbcff48b930c5 Author: Luboš Luňák AuthorDate: Fri Dec 4 20:25:06 2020 + Commit: Luboš Luňák CommitDate: Mon Dec 7 20:47:18 2020 +0100 remove WinGlyphCache and related code The code for separately rendering glyphs was used only by OpenGL code (and temporarily by Skia code). Change-Id: I8eee764045273705c108f3734b330a2237de15f7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/107291 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 167b57147bf3..fd39ca273609 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -31,21 +31,7 @@ class SkiaCompatibleDC : public CompatibleDC public: SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int width, int height); -virtual std::unique_ptr getAsMaskTexture() const override; - -sk_sp getAsImage() const; -sk_sp getAsMaskImage() const; sk_sp getAsImageDiff(const SkiaCompatibleDC& white) const; - -struct Texture; -}; - -struct SkiaCompatibleDC::Texture : public CompatibleDC::Texture -{ -sk_sp image; -virtual bool isValid() const { return image.get(); } -virtual int GetWidth() const { return image->width(); } -virtual int GetHeight() const { return image->height(); } }; class WinSkiaSalGraphicsImpl : public SkiaSalGraphicsImpl, public WinSalGraphicsImplBase diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx index 8d2935216d87..80286d87d347 100644 --- a/vcl/inc/win/saldata.hxx +++ b/vcl/inc/win/saldata.hxx @@ -42,7 +42,6 @@ class WinSalFrame; class WinSalVirtualDevice; class WinSalPrinter; namespace vcl { class Font; } -struct GlobalWinGlyphCache; struct HDCCache; struct TempFontItem; class TextOutRenderer; @@ -128,7 +127,6 @@ public: std::unique_ptr m_pD2DWriteTextOutRenderer; // tdf#107205 need 2 instances because D2DWrite can't rotate text std::unique_ptr m_pExTextOutRenderer; -std::unique_ptr m_pGlobalWinGlyphCache; #if HAVE_FEATURE_SKIA std::unique_ptr m_pSkiaControlsCache; #endif diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index c01e9794160b..52b04aaf26b9 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -135,20 +135,6 @@ public: /// Reset the DC with the defined color. void fill(sal_uInt32 color); - -/// Base texture class (OpenGL and Skia will provide their implementations). -struct Texture; - -/// Obtain the texture in format for WinSalGraphicsImplBase::DrawTextMask(). -virtual std::unique_ptr getAsMaskTexture() const { abort(); }; -}; - -struct CompatibleDC::Texture -{ -virtual ~Texture() {}; -virtual bool isValid() const = 0; -virtual int GetWidth() const = 0; -virtual int GetHeight() const = 0; }; class WinSalGraphics : public SalGraphics @@ -179,9 +165,6 @@ private: RGNDATA*mpStdClipRgnData; // Cache Standard-ClipRegion-Data int mnPenWidth; // line width -bool CacheGlyphs(const GenericSalLayout& rLayout); -bool DrawCachedGlyphs(const GenericSalLayout& rLayout); - public: HFONT ImplDoSetFont(FontSelectPattern const & i_rFont, const PhysicalFontFace * i_pFontFace, HFONT& o_rOldFont); diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx index 2b1355cae9bf..6fc08f0a355a 100644 --- a/vcl/inc/win/wingdiimpl.hxx +++ b/vcl/inc/win/wingdiimpl.hxx @@ -42,20 +42,6 @@ public: // Implementation for WinSalGraphics::DrawTextLayout(). // Returns true if handled, if false, then WinSalGraphics will handle it itself. virtual bool DrawTextLayout(const GenericSalLayout&) { return false; } -// If true is returned, the following functions are used for text rendering. -virtual bool UseTextDraw() const { return false; } -virtual void PreDrawText() {} -virtual void PostDrawText() {} -virtual void DrawTextMask(CompatibleDC::Texture* /*rTexture*/, Color /*nMaskColor*/, - const SalTwoRect& /*rPosAry*/) -{ -abort(); -}; -virtual void DeferredTextDraw(const CompatibleDC::Texture* /*pTexture*/, Color /*nMaskColor*/, - const SalTwoRect& /*rPosAry*/) -{ -abort(); -}; }; #endif // INCLUDED_VCL_INC_WIN_WINGDIIMPL_HXX diff --git a/vcl/inc/win/winlayout.hxx b/vcl/inc/win/winlayout.hxx index 35a855a3722e..b4e51d8dc4bb 100644 --- a/vcl/inc/win/winlayout.hxx +++ b/vcl/inc/win/winlayout.hxx @@ -27,90 +27,6 @@ #include
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |1 - vcl/skia/gdiimpl.cxx | 23 +++ 2 files changed, 15 insertions(+), 9 deletions(-) New commits: commit 42e30c24615402c49351f80cc8a47d61d47267c6 Author: Jan-Marek Glogowski AuthorDate: Mon Nov 16 22:43:51 2020 +0100 Commit: Luboš Luňák CommitDate: Tue Nov 17 11:33:32 2020 +0100 tdf#138022 Skia don't recreate empty surfaces Skia can't create empty surfaces, so the recreation will hit the std::abort() in SkiaSalGraphicsImpl::createWindowSurface. Origin of the backtrace is some queued Resize event, which will hit this a few times via SkiaSalGraphicsImpl::checkSurface. This feels a bit like tdf#130831, where VCL tried to track damange for an empty Qt image... Change-Id: I75e22c987ba633e7a403541db8d580df33c68964 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105963 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 8e14df458a23..6b60f63ae405 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -237,7 +237,6 @@ protected: // Call to ensure that mSurface is valid. If mSurface is going to be modified, // use preDraw() instead of this. void checkSurface(); -void recreateSurface(); void destroySurface(); // Reimplemented for X11. virtual bool avoidRecreateByResize() const { return false; } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index e339171d9d80..d89ec093a964 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -277,12 +277,6 @@ SkiaSalGraphicsImpl::~SkiaSalGraphicsImpl() void SkiaSalGraphicsImpl::Init() {} -void SkiaSalGraphicsImpl::recreateSurface() -{ -destroySurface(); -createSurface(); -} - void SkiaSalGraphicsImpl::createSurface() { SkiaZone zone; @@ -453,7 +447,17 @@ void SkiaSalGraphicsImpl::checkSurface() } else if (GetWidth() != mSurface->width() || GetHeight() != mSurface->height()) { -if (!avoidRecreateByResize()) +if (avoidRecreateByResize()) +return; + +if (!GetWidth() || !GetHeight()) +{ +SAL_WARN("vcl.skia", "recreate(" << this << "): can't create empty surface " + << Size(GetWidth(), GetHeight()) + << " => keeping old one!"); +return; +} + { Size oldSize(mSurface->width(), mSurface->height()); // Recreating a surface means that the old SkSurface contents will be lost. @@ -468,7 +472,10 @@ void SkiaSalGraphicsImpl::checkSurface() flushDrawing(); snapshot = SkiaHelper::makeCheckedImageSnapshot(mSurface); } -recreateSurface(); + +destroySurface(); +createSurface(); + if (snapshot) { SkPaint paint; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |5 + vcl/inc/skia/win/gdiimpl.hxx |5 + vcl/skia/SkiaHelper.cxx | 22 +++--- vcl/skia/gdiimpl.cxx |6 -- vcl/skia/win/gdiimpl.cxx | 29 ++--- 5 files changed, 35 insertions(+), 32 deletions(-) New commits: commit 1724b7a2cb16336b2c6e066504708396b8ecfa32 Author: Luboš Luňák AuthorDate: Mon Nov 16 11:14:33 2020 + Commit: Luboš Luňák CommitDate: Tue Nov 17 10:55:19 2020 +0100 set Skia pixel geometry for every surface Skia update chrome/m88 removed the possibility to call SkFontLCDConfig::SetSubpixelOrder() to set subpixel setup for all surfaces. So I guess now we have to explicitly pass SkSurfaceProps to every single SkSurface we create. Change-Id: I15be37ba9301c92d0cb109e88f3d1396a7223208 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105922 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 00feccedfdae..03e01d2e5d8b 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -75,6 +75,11 @@ sk_sp findCachedImage(const OString& key); void removeCachedImage(sk_sp image); constexpr int MAX_CACHE_SIZE = 4 * 2000 * 2000 * 4; // 4x 2000px 32bpp images, 64MiB +// SkSurfaceProps to be used by all Skia surfaces. +VCL_DLLPUBLIC const SkSurfaceProps* surfaceProps(); +// Set pixel geometry to be used by SkSurfaceProps. +VCL_DLLPUBLIC void setPixelGeometry(SkPixelGeometry pixelGeometry); + #ifdef DBG_UTIL void prefillSurface(const sk_sp& surface); VCL_DLLPUBLIC void dump(const SkBitmap& bitmap, const char* file); diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 26ca29eaee7b..167b57147bf3 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -76,15 +76,12 @@ protected: virtual void createWindowContext(bool forceRaster = false) override; virtual void performFlush() override; sk_sp createDirectWriteTypeface(const LOGFONTW& logFont); -SkFont::Edging getFontEdging(); -void initFontInfo(); +static void initFontInfo(); IDWriteFactory* dwriteFactory; IDWriteGdiInterop* dwriteGdiInterop; sk_sp dwriteFontMgr; bool dwriteDone = false; static SkFont::Edging fontEdging; -static SkPixelGeometry pixelGeometry; -static bool fontInfoDone; }; typedef std::pair> SkiaControlCachePair; diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 3adef6a9afd2..b3aa5a1d1cbc 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -392,9 +392,9 @@ sk_sp createSkSurface(int width, int height, SkColorType type, SkAlph { if (GrDirectContext* grDirectContext = getSharedGrDirectContext()) { -surface -= SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo, - SkImageInfo::Make(width, height, type, alpha)); +surface = SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo, + SkImageInfo::Make(width, height, type, alpha), + 0, surfaceProps()); if (surface) { #ifdef DBG_UTIL @@ -411,7 +411,7 @@ sk_sp createSkSurface(int width, int height, SkColorType type, SkAlph break; } // Create raster surface as a fallback. -surface = SkSurface::MakeRaster(SkImageInfo::Make(width, height, type, alpha)); +surface = SkSurface::MakeRaster(SkImageInfo::Make(width, height, type, alpha), surfaceProps()); assert(surface); if (surface) { @@ -435,9 +435,9 @@ sk_sp createSkImage(const SkBitmap& bitmap) { if (GrDirectContext* grDirectContext = getSharedGrDirectContext()) { -sk_sp surface -= SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo, - bitmap.info().makeAlphaType(kPremul_SkAlphaType)); +sk_sp surface = SkSurface::MakeRenderTarget( +grDirectContext, SkBudgeted::kNo, +bitmap.info().makeAlphaType(kPremul_SkAlphaType), 0, surfaceProps()); if (surface) { SkPaint paint; @@ -563,6 +563,14 @@ void cleanup() imageCacheSize = 0; } +static SkSurfaceProps commonSurfaceProps; +const SkSurfaceProps* surfaceProps() { return } + +void setPixelGeometry(SkPixelGeometry pixelGeometry) +{ +commonSurfaceProps = SkSurfaceProps(commonSurfaceProps.flags(), pixelGeometry); +} + // Skia should not be used from VCL backends that do not actually support it, as there will be setup missing. // The code here (that is in the vcl lib) needs a function for creating Vulkan context that is // usually available
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |2 ++ vcl/inc/skia/utils.hxx | 18 +++--- vcl/skia/SkiaHelper.cxx | 10 +- vcl/skia/gdiimpl.cxx|3 ++- vcl/skia/salbmp.cxx | 31 --- 5 files changed, 44 insertions(+), 20 deletions(-) New commits: commit 3f359a03308493e59e0c29572fff7b0194c4aea1 Author: Luboš Luňák AuthorDate: Tue Oct 6 22:56:40 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Oct 7 16:18:16 2020 +0200 try more to match Skia's alpha type for source and destination This is an extension of the other recent commit, matching alpha type is faster, and knowing the content is opaque should also allow more optimizations. Change-Id: I632d3f50e3f4729a64403c3c3ed1b79d63f0c5dd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104046 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 0cd48c8c46c2..49aabcf69a7f 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -82,6 +82,8 @@ public: // Returns true if it is known that this bitmap can be ignored if it's to be used // as an alpha bitmap. An optimization, not guaranteed to return true for all such cases. bool IsFullyOpaqueAsAlpha() const; +// Alpha type best suitable for the content. +SkAlphaType alphaType() const; #ifdef DBG_UTIL void dump(const char* file) const; diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index b3a2045eea96..00feccedfdae 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -37,11 +37,23 @@ void disableRenderMethod(RenderMethod method); // Create SkSurface, GPU-backed if possible. VCL_DLLPUBLIC sk_sp createSkSurface(int width, int height, - SkColorType type = kN32_SkColorType); + SkColorType type = kN32_SkColorType, + SkAlphaType alpha = kPremul_SkAlphaType); -inline sk_sp createSkSurface(const Size& size, SkColorType type = kN32_SkColorType) +inline sk_sp createSkSurface(const Size& size, SkColorType type = kN32_SkColorType, +SkAlphaType alpha = kPremul_SkAlphaType) { -return createSkSurface(size.Width(), size.Height(), type); +return createSkSurface(size.Width(), size.Height(), type, alpha); +} + +inline sk_sp createSkSurface(int width, int height, SkAlphaType alpha) +{ +return createSkSurface(width, height, kN32_SkColorType, alpha); +} + +inline sk_sp createSkSurface(const Size& size, SkAlphaType alpha) +{ +return createSkSurface(size.Width(), size.Height(), kN32_SkColorType, alpha); } // Create SkImage, GPU-backed if possible. diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 2d185bab149b..3adef6a9afd2 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -381,7 +381,7 @@ static sk_app::VulkanWindowContext::SharedGrDirectContext getTemporaryGrDirectCo return sk_app::VulkanWindowContext::getSharedGrDirectContext(); } -sk_sp createSkSurface(int width, int height, SkColorType type) +sk_sp createSkSurface(int width, int height, SkColorType type, SkAlphaType alpha) { SkiaZone zone; assert(type == kN32_SkColorType || type == kAlpha_8_SkColorType); @@ -392,9 +392,9 @@ sk_sp createSkSurface(int width, int height, SkColorType type) { if (GrDirectContext* grDirectContext = getSharedGrDirectContext()) { -surface = SkSurface::MakeRenderTarget( -grDirectContext, SkBudgeted::kNo, -SkImageInfo::Make(width, height, type, kPremul_SkAlphaType)); +surface += SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo, + SkImageInfo::Make(width, height, type, alpha)); if (surface) { #ifdef DBG_UTIL @@ -411,7 +411,7 @@ sk_sp createSkSurface(int width, int height, SkColorType type) break; } // Create raster surface as a fallback. -surface = SkSurface::MakeRaster(SkImageInfo::Make(width, height, type, kPremul_SkAlphaType)); +surface = SkSurface::MakeRaster(SkImageInfo::Make(width, height, type, alpha)); assert(surface); if (surface) { diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index f0076d9a90f9..fa29ab32d0ac 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1540,7 +1540,8 @@ sk_sp SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma assert(image->width() == targetSize.Width() && image->height() == targetSize.Height()); return image; } -sk_sp tmpSurface = SkiaHelper::createSkSurface(targetSize); +sk_sp tmpSurface = SkiaHelper::createSkSurface( +targetSize, alphaBitmap ? kPremul_SkAlphaType :
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |9 ++--- vcl/skia/salbmp.cxx | 38 +- 2 files changed, 35 insertions(+), 12 deletions(-) New commits: commit 16fc984bda55febdbc54bae7b34c5dc07dca7b41 Author: Luboš Luňák AuthorDate: Fri Oct 2 18:50:08 2020 +0200 Commit: Luboš Luňák CommitDate: Sun Oct 4 11:11:33 2020 +0200 clean up handling of erased state in SkiaSalBitmap So that e.g. ResetToSkImage() does not keep the erase state. Change-Id: I67e15c7f26c804437b15c394bf1aa4bbc38dfed1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103887 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 00cd76ffd10e..6f74ac04b6f9 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -93,8 +93,8 @@ public: bool unittestHasEraseColor() const { return mEraseColorSet; } private: -// Reset the cached images allocated in GetSkImage()/GetAlphaSkImage(). -void ResetCachedData(); +// Reset the state to pixel data (resets cached images allocated in GetSkImage()/GetAlphaSkImage()). +void ResetToBuffer(); // Sets the data only as SkImage (will be converted as needed). void ResetToSkImage(sk_sp image); // Resets all data that does not match mSize. @@ -111,7 +111,10 @@ private: void CreateBitmapData(); // Should be called whenever mPixelsSize or mBitCount is set/changed. bool ComputeScanlineSize(); -void EraseInternal(); +// Sets bitmap to be erased on demand. +void EraseInternal(const Color& color); +// Sets pixels to the erase color. +void PerformErase(); SkBitmap GetAsSkBitmap() const; bool ConserveMemory() const; void verify() const diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index e8f67b0585ed..7bce30b6b637 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -282,7 +282,7 @@ void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) --mWriteAccessCount; #endif mPalette = pBuffer->maPalette; -ResetCachedData(); +ResetToBuffer(); InvalidateChecksum(); } // Are there any more ground movements underneath us ? @@ -316,6 +316,13 @@ bool SkiaSalBitmap::Scale(const double& rScaleX, const double& rScaleY, BmpScale SAL_INFO("vcl.skia.trace", "scale(" << this << "): " << mSize << "/" << mBitCount << "->" << newSize << ":" << static_cast(nScaleFlag)); +if (mEraseColorSet) +{ // Simple. +mSize = mPixelsSize = newSize; +EraseInternal(mEraseColor); +return true; +} + // The idea here is that the actual scaling will be delayed until the result // is actually needed. Usually the scaled bitmap will be drawn somewhere, // so delaying will mean the scaling can be done as a part of GetSkImage(). @@ -355,8 +362,10 @@ bool SkiaSalBitmap::Scale(const double& rScaleX, const double& rScaleY, BmpScale // by mSize != mPixelsSize mSize = newSize; // Do not reset cached data if mImage is possibly the only data we have. -if (mBuffer) -ResetCachedData(); +if (mImage) +ResetToSkImage(mImage); +else +ResetToBuffer(); // The rest will be handled when the scaled bitmap is actually needed, // such as in EnsureBitmapData() or GetSkImage(). return true; @@ -417,6 +426,7 @@ bool SkiaSalBitmap::InterpretAs8Bit() mBitCount = 8; ComputeScanlineSize(); mPalette = Bitmap::GetGreyPalette(256); +EraseInternal(mEraseColor); SAL_INFO("vcl.skia.trace", "interpretas8bit(" << this << ") with erase color"); return true; } @@ -447,10 +457,16 @@ bool SkiaSalBitmap::Erase(const Color& color) // Optimized variant, just remember the color and apply it when needed, // which may save having to do format conversions (e.g. GetSkImage() // may directly erase the SkImage). +EraseInternal(color); +SAL_INFO("vcl.skia.trace", "erase(" << this << ")"); +return true; +} + +void SkiaSalBitmap::EraseInternal(const Color& color) +{ ResetAllData(); mEraseColorSet = true; mEraseColor = color; -return true; } SkBitmap SkiaSalBitmap::GetAsSkBitmap() const @@ -810,7 +826,7 @@ bool SkiaSalBitmap::IsFullyOpaqueAsAlpha() const return SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)) == 0; } -void SkiaSalBitmap::EraseInternal() +void SkiaSalBitmap::PerformErase() { if (mPixelsSize.IsEmpty()) return; @@ -851,7 +867,7 @@ void SkiaSalBitmap::EnsureBitmapData() CreateBitmapData(); // Unset now, so that repeated call will return mBuffer. mEraseColorSet = false; -EraseInternal(); +PerformErase(); verify(); SAL_INFO("vcl.skia.trace", "ensurebitmapdata(" << this << ") from erase color " <<
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/unx vcl/win
vcl/inc/skia/win/gdiimpl.hxx|2 ++ vcl/inc/skia/x11/gdiimpl.hxx|1 + vcl/inc/unx/salgdi.h|2 ++ vcl/inc/unx/x11/x11gdiimpl.h|1 + vcl/inc/win/salgdi.h|1 + vcl/inc/win/wingdiimpl.hxx |2 ++ vcl/skia/win/gdiimpl.cxx|2 ++ vcl/skia/x11/gdiimpl.cxx|2 ++ vcl/unx/generic/gdi/salgdi.cxx |6 ++ vcl/unx/generic/window/salframe.cxx |2 ++ vcl/win/gdi/salgdi.cxx |6 ++ vcl/win/window/salframe.cxx |4 12 files changed, 31 insertions(+) New commits: commit 2217c3fa74fb3c910566ef1de1e05da5c5a120ff Author: Luboš Luňák AuthorDate: Wed Sep 30 10:05:53 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Sep 30 16:47:14 2020 +0200 make OutputDevice::Flush() also flush Skia Skia uses an idle timer to flush buffered Skia drawing. This has the problem that if there's a lot to do, the actual drawing to the screen may become starved and not update. Fortunately there's OutputDevice::Flush() that is called e.g. during Impress animations, so make that also work for Skia, which should make things somewhat smoother. Change-Id: Ia8629e63dc7d7a2d7200c033bc2dc2c51f6caf0b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103675 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 564fcd7e9614..bcdf6874f4d5 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -68,6 +68,8 @@ public: virtual bool DrawTextLayout(const GenericSalLayout& layout) override; virtual void ClearDevFontCache() override; +virtual void Flush() override; + static void prepareSkia(); protected: diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx index d131d54bfe8e..10c6c5fcb972 100644 --- a/vcl/inc/skia/x11/gdiimpl.hxx +++ b/vcl/inc/skia/x11/gdiimpl.hxx @@ -30,6 +30,7 @@ public: virtual void Init() override; virtual void DeInit() override; virtual void freeResources() override; +virtual void Flush() override; static void prepareSkia(); diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index eac9dad95bb8..6e5e260f1185 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -98,6 +98,8 @@ public: const SalX11Screen& GetScreenNumber() const { return m_nXScreen; } +voidFlush(); + // override all pure virtual methods virtual voidGetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) override; virtual sal_uInt16 GetBitCount() const override; diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h index 2e41e87c860d..342da0907517 100644 --- a/vcl/inc/unx/x11/x11gdiimpl.h +++ b/vcl/inc/unx/x11/x11gdiimpl.h @@ -18,6 +18,7 @@ class X11GraphicsImpl { public: virtual ~X11GraphicsImpl() {}; +virtual void Flush() {}; }; #endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index f2560f3ade59..a717286737c0 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -222,6 +222,7 @@ public: bool isScreen() const; void setHWND(HWND hWnd); +void Flush(); protected: virtual boolsetClipRegion( const vcl::Region& ) override; diff --git a/vcl/inc/win/wingdiimpl.hxx b/vcl/inc/win/wingdiimpl.hxx index 679be2c36588..2b1355cae9bf 100644 --- a/vcl/inc/win/wingdiimpl.hxx +++ b/vcl/inc/win/wingdiimpl.hxx @@ -37,6 +37,8 @@ public: virtual void ClearDevFontCache(){}; +virtual void Flush(){}; + // Implementation for WinSalGraphics::DrawTextLayout(). // Returns true if handled, if false, then WinSalGraphics will handle it itself. virtual bool DrawTextLayout(const GenericSalLayout&) { return false; } diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index ce67db42914b..819f024fa5cd 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -61,6 +61,8 @@ void WinSkiaSalGraphicsImpl::DeInit() void WinSkiaSalGraphicsImpl::freeResources() {} +void WinSkiaSalGraphicsImpl::Flush() { performFlush(); } + void WinSkiaSalGraphicsImpl::performFlush() { SkiaZone zone; diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx index 68571ccb73e7..635beb1edb09 100644 --- a/vcl/skia/x11/gdiimpl.cxx +++ b/vcl/skia/x11/gdiimpl.cxx @@ -129,6 +129,8 @@ void X11SkiaSalGraphicsImpl::DeInit() void X11SkiaSalGraphicsImpl::freeResources() {} +void X11SkiaSalGraphicsImpl::Flush() { performFlush(); } + void X11SkiaSalGraphicsImpl::performFlush() { SkiaZone zone; diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index eeae83132781..6da291c91bea 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -500,6 +500,12 @@ SystemGraphicsData
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |2 +- vcl/skia/x11/gdiimpl.cxx |7 +++ 2 files changed, 8 insertions(+), 1 deletion(-) New commits: commit 614d310751d1a32baec85c11637fb3813a9dd749 Author: Luboš Luňák AuthorDate: Mon Sep 28 15:13:08 2020 +0200 Commit: Luboš Luňák CommitDate: Tue Sep 29 09:58:16 2020 +0200 disable VSync for Skia/Vulkan on Linux/nVidia It causes freezes. This can be changed later to a blacklist of older drivers once fixed drivers are actually available. Change-Id: I6cc996aee2ae69d5c8fdd9eb5f9f336683350485 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103554 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index ed9ae0eaf100..222a413b511e 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -70,7 +70,7 @@ VCL_DLLPUBLIC void dump(const sk_sp& image, const char* file); VCL_DLLPUBLIC void dump(const sk_sp& surface, const char* file); #endif -extern uint32_t vendorId; +VCL_DLLPUBLIC extern uint32_t vendorId; inline DriverBlocklist::DeviceVendor getVendor() { diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx index 7a55415ee55a..68571ccb73e7 100644 --- a/vcl/skia/x11/gdiimpl.cxx +++ b/vcl/skia/x11/gdiimpl.cxx @@ -57,6 +57,13 @@ X11SkiaSalGraphicsImpl::createWindowContext(Display* display, Drawable drawable, SkiaZone zone; sk_app::DisplayParams displayParams; displayParams.fColorType = kN32_SkColorType; +#if defined LINUX +// WORKAROUND: VSync causes freezes that can even temporarily freeze the entire desktop. +// This happens even with the latest 450.66 drivers despite them claiming a fix for vsync. +// https://forums.developer.nvidia.com/t/hangs-freezes-when-vulkan-v-sync-vk-present-mode-fifo-khr-is-enabled/67751 +if (SkiaHelper::getVendor() == DriverBlocklist::VendorNVIDIA) +displayParams.fDisableVsync = true; +#endif sk_app::window_context_factory::XlibWindowInfo winInfo; assert(display); winInfo.fDisplay = display; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/zone.hxx |3 +++ vcl/skia/README |9 + 2 files changed, 12 insertions(+) New commits: commit 7c1dc527837a65b77f7624e18a575271cb46afba Author: Luboš Luňák AuthorDate: Thu Sep 10 20:20:25 2020 +0200 Commit: Luboš Luňák CommitDate: Tue Sep 29 09:56:49 2020 +0200 ensure SolarMutex is held for SkiaZone This is simply being lazy and requiring the mutex held for all Skia operations. With the effort to verify things it'd presumably be possible to make the code thread-safe. Change-Id: I748dbf2d5af66dcd140b5a9d6d57e9d848babf0e Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103564 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/zone.hxx b/vcl/inc/skia/zone.hxx index 1f6bbb0dddca..6d503e7eb803 100644 --- a/vcl/inc/skia/zone.hxx +++ b/vcl/inc/skia/zone.hxx @@ -14,10 +14,13 @@ #include +#include + // Used around calls to Skia code to detect crashes in drivers. class VCL_DLLPUBLIC SkiaZone : public CrashZone { public: +SkiaZone() { assert(comphelper::SolarMutex::get()->IsCurrentThread()); } static void hardDisable(); static void relaxWatchdogTimings(); static const CrashWatchdogTimingsValues& getCrashWatchdogTimingsValues(); diff --git a/vcl/skia/README b/vcl/skia/README index f178ef8f3b76..c508beb33cea 100644 --- a/vcl/skia/README +++ b/vcl/skia/README @@ -59,6 +59,15 @@ You can also use 'visualbackendtest' to visually check some operations. Use some SAL_SKIA=raster SAL_ENABLESKIA=1 SAL_USE_VCLPLUGIN=gen [srcdir]/bin/run visualbackendtest +Thread safety: +== + +SolarMutex must be held for most operations (asserted in SkiaSalGraphicsImpl::preDraw() and +in SkiaZone constructor). The reason for this is that this restriction does not appear to be +a problem, so there's no need to verify thread safety of the code (including the Skia library). +There's probably no fundamental reason why the code couldn't be made thread-safe. + + GrDirectContext sharing: ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |2 ++ vcl/skia/salbmp.cxx | 19 --- 2 files changed, 14 insertions(+), 7 deletions(-) New commits: commit b5e023a7ef21c2ce546035b99ead7caf4e9b5343 Author: Luboš Luňák AuthorDate: Thu Sep 24 12:56:46 2020 +0200 Commit: Luboš Luňák CommitDate: Fri Sep 25 09:51:16 2020 +0200 simplify clearing all data in SkiaSalBitmap Change-Id: I5e53b70bca651493a5bf449ca41a568e2a72b683 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103304 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 6e325b9c6a62..0f1a8b235164 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -93,6 +93,8 @@ private: void ResetToSkImage(sk_sp image); // Resets all data that does not match mSize. void ResetCachedDataBySize(); +// Resets all data (buffer and images). +void ResetAllData(); // Call to ensure mBuffer has data (will convert from mImage if necessary). void EnsureBitmapData(); void EnsureBitmapData() const { return const_cast(this)->EnsureBitmapData(); } diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 379f53bb032d..2128511247bc 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -62,8 +62,7 @@ static bool isValidBitCount(sal_uInt16 nBitCount) SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) { -ResetCachedData(); -mBuffer.reset(); +ResetAllData(); mImage = image; mPalette = BitmapPalette(); mBitCount = 32; @@ -77,7 +76,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal) { -ResetCachedData(); +ResetAllData(); mBuffer.reset(); if (!isValidBitCount(nBitCount)) return false; @@ -190,8 +189,7 @@ void SkiaSalBitmap::Destroy() #ifdef DBG_UTIL assert(mWriteAccessCount == 0); #endif -ResetCachedData(); -mBuffer.reset(); +ResetAllData(); } Size SkiaSalBitmap::GetSize() const { return mSize; } @@ -441,8 +439,7 @@ bool SkiaSalBitmap::Erase(const Color& color) // Optimized variant, just remember the color and apply it when needed, // which may save having to do format conversions (e.g. GetSkImage() // may directly erase the SkImage). -ResetCachedData(); -mBuffer.reset(); +ResetAllData(); mEraseColorSet = true; mEraseColor = color; return true; @@ -1069,6 +1066,14 @@ void SkiaSalBitmap::ResetToSkImage(sk_sp image) mAlphaImage.reset(); } +void SkiaSalBitmap::ResetAllData() +{ +SkiaZone zone; +mBuffer.reset(); +mImage.reset(); +mAlphaImage.reset(); +} + void SkiaSalBitmap::ResetCachedDataBySize() { SkiaZone zone; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |5 + vcl/skia/SkiaHelper.cxx | 32 vcl/skia/gdiimpl.cxx | 27 --- vcl/skia/salbmp.cxx | 12 ++-- vcl/skia/win/gdiimpl.cxx |4 ++-- 5 files changed, 57 insertions(+), 23 deletions(-) New commits: commit 797315f220f82682748efaf80a29844a93f04f48 Author: Luboš Luňák AuthorDate: Tue Sep 22 13:42:02 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Sep 23 08:46:10 2020 +0200 detect and fail immediately on failed Skia allocations (tdf#135952) The problem with tdf#135952 is that the PNG export dialog can lead to requesting an absurdly large image, which leads to allocation failures. Some VCL backends such as headless try to cope with this and bail out, but they often crash anyway, since at higher levels of LO code nothing checks for these corner cases anyway. And even if nothing would crash, this can lead to silently losing data. So I've decided to directly detect such cases and fail hard and early. Change-Id: I5277a65c794116206de8280faf22ff897daa2f56 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103171 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index fc2567ac4e32..ed9ae0eaf100 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -47,6 +47,11 @@ inline sk_sp createSkSurface(const Size& size, SkColorType type = kN3 // Create SkImage, GPU-backed if possible. VCL_DLLPUBLIC sk_sp createSkImage(const SkBitmap& bitmap); +// Call surface->makeImageSnapshot() and abort on failure. +VCL_DLLPUBLIC sk_sp makeCheckedImageSnapshot(sk_sp surface); +VCL_DLLPUBLIC sk_sp makeCheckedImageSnapshot(sk_sp surface, + const SkIRect& bounds); + // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index e029a9137429..f9b231d87ce6 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -413,10 +413,16 @@ sk_sp createSkSurface(int width, int height, SkColorType type) // Create raster surface as a fallback. surface = SkSurface::MakeRaster(SkImageInfo::Make(width, height, type, kPremul_SkAlphaType)); assert(surface); +if (surface) +{ #ifdef DBG_UTIL -prefillSurface(surface); +prefillSurface(surface); #endif -return surface; +return surface; +} +// In non-debug builds we could return SkSurface::MakeNull() and try to cope with the situation, +// but that can lead to unnoticed data loss, so better fail clearly. +abort(); } sk_sp createSkImage(const SkBitmap& bitmap) @@ -437,7 +443,7 @@ sk_sp createSkImage(const SkBitmap& bitmap) SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha surface->getCanvas()->drawBitmap(bitmap, 0, 0, ); -return surface->makeImageSnapshot(); +return makeCheckedImageSnapshot(surface); } // Try to fall back in non-debug builds. SAL_WARN("vcl.skia", @@ -454,6 +460,24 @@ sk_sp createSkImage(const SkBitmap& bitmap) return image; } +sk_sp makeCheckedImageSnapshot(sk_sp surface) +{ +sk_sp ret = surface->makeImageSnapshot(); +assert(ret); +if (ret) +return ret; +abort(); +} + +sk_sp makeCheckedImageSnapshot(sk_sp surface, const SkIRect& bounds) +{ +sk_sp ret = surface->makeImageSnapshot(bounds); +assert(ret); +if (ret) +return ret; +abort(); +} + namespace { // Image cache, for saving results of complex operations such as drawTransformedBitmap(). @@ -573,7 +597,7 @@ void dump(const SkBitmap& bitmap, const char* file) { dump(SkImage::MakeFromBitm void dump(const sk_sp& surface, const char* file) { surface->getCanvas()->flush(); -dump(surface->makeImageSnapshot(), file); +dump(makeCheckedImageSnapshot(surface), file); } void dump(const sk_sp& image, const char* file) diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 1821f48a7cce..698d20730751 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -308,7 +308,7 @@ void SkiaSalGraphicsImpl::createWindowSurface(bool forceRaster) destroySurface(); // destroys also WindowContext return createWindowSurface(true); // try again case SkiaHelper::RenderRaster: -abort(); // this should not really happen +abort(); // This should not really happen, do not even try to cope with it. } } mIsGPU = mSurface->getCanvas()->getGrContext() != nullptr; @@ -438,7 +438,7 @@ void SkiaSalGraphicsImpl::checkSurface() if (!isOffscreen()) {
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |4 ++-- vcl/inc/skia/win/gdiimpl.hxx |2 +- vcl/inc/skia/x11/gdiimpl.hxx |2 +- vcl/skia/SkiaHelper.cxx | 25 + vcl/skia/gdiimpl.cxx | 35 ++- vcl/skia/win/gdiimpl.cxx |6 ++ vcl/skia/x11/gdiimpl.cxx | 13 + 7 files changed, 46 insertions(+), 41 deletions(-) New commits: commit 19365e6e2b3311bacb2ae2abb70be5cfaf843776 Author: Luboš Luňák AuthorDate: Tue Sep 22 12:48:10 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Sep 23 08:45:47 2020 +0200 if allocating Vulkan surface fails, fall back to Skia raster surface Occassionally there may be very large surfaces, such as in tdf#135952. Try to fall back to raster, which is more likely to succeed, given that it uses system RAM instead of video RAM. Change-Id: I81994b174e5e52066eacc5f8778e9469b042f9c8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/103170 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 9405bc39ade2..2d8086639a08 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -235,8 +235,8 @@ protected: void destroySurface(); // Reimplemented for X11. virtual bool avoidRecreateByResize() const { return false; } -void createWindowSurface(); -virtual void createWindowContext() = 0; +void createWindowSurface(bool forceRaster = false); +virtual void createWindowContext(bool forceRaster = false) = 0; void createOffscreenSurface(); void privateDrawAlphaRect(long nX, long nY, long nWidth, long nHeight, double nTransparency, diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index cdb6977e5bd2..564fcd7e9614 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -71,7 +71,7 @@ public: static void prepareSkia(); protected: -virtual void createWindowContext() override; +virtual void createWindowContext(bool forceRaster = false) override; virtual void performFlush() override; sk_sp createDirectWriteTypeface(const LOGFONTW& logFont); SkFont::Edging getFontEdging(); diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx index 0f86f0907dcd..d131d54bfe8e 100644 --- a/vcl/inc/skia/x11/gdiimpl.hxx +++ b/vcl/inc/skia/x11/gdiimpl.hxx @@ -34,7 +34,7 @@ public: static void prepareSkia(); private: -virtual void createWindowContext() override; +virtual void createWindowContext(bool forceRaster = false) override; virtual void performFlush() override; virtual bool avoidRecreateByResize() const override; static std::unique_ptr diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 72944a946c71..e029a9137429 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -395,11 +395,15 @@ sk_sp createSkSurface(int width, int height, SkColorType type) surface = SkSurface::MakeRenderTarget( grDirectContext, SkBudgeted::kNo, SkImageInfo::Make(width, height, type, kPremul_SkAlphaType)); -assert(surface); +if (surface) +{ #ifdef DBG_UTIL -prefillSurface(surface); +prefillSurface(surface); #endif -return surface; +return surface; +} +SAL_WARN("vcl.skia", + "cannot create Vulkan GPU offscreen surface, falling back to Raster"); } break; } @@ -428,11 +432,16 @@ sk_sp createSkImage(const SkBitmap& bitmap) sk_sp surface = SkSurface::MakeRenderTarget(grDirectContext, SkBudgeted::kNo, bitmap.info().makeAlphaType(kPremul_SkAlphaType)); -assert(surface); -SkPaint paint; -paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha -surface->getCanvas()->drawBitmap(bitmap, 0, 0, ); -return surface->makeImageSnapshot(); +if (surface) +{ +SkPaint paint; +paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha +surface->getCanvas()->drawBitmap(bitmap, 0, 0, ); +return surface->makeImageSnapshot(); +} +// Try to fall back in non-debug builds. +SAL_WARN("vcl.skia", + "cannot create Vulkan GPU offscreen surface, falling back to Raster"); } break; } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 8f73db8411fa..1821f48a7cce 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -289,13 +289,13 @@ void
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |1 vcl/skia/salbmp.cxx | 107 2 files changed, 91 insertions(+), 17 deletions(-) New commits: commit 6caa412d911e806f805633f1296ddc5908eab868 Author: Luboš Luňák AuthorDate: Mon Sep 7 22:38:34 2020 +0200 Commit: Luboš Luňák CommitDate: Tue Sep 8 09:57:58 2020 +0200 try harder to not duplicate large memory usage in SkiaSalBitmap This is an extension of a9f68d9d9ae8d7c8f79152055795044993b252ea. Try also to drop the image if converting back to buffer, and also try to do the same with the alpha image if the conversion is simple. Change-Id: I88f6f9d37a1e527c2d6c083ee9744959571534ab Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102209 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 0a6ed6f1b874..6e325b9c6a62 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -105,6 +105,7 @@ private: bool ComputeScanlineSize(); void EraseInternal(); SkBitmap GetAsSkBitmap() const; +bool ConserveMemory() const; void verify() const #ifdef DBG_UTIL ; diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 0c855ef79ebf..c77b80e39bc1 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -578,6 +578,29 @@ static SkColor fromEraseColorToAlphaImageColor(Color color) return SkColorSetARGB(color.GetBlue(), 0, 0, 0); } +// SkiaSalBitmap can store data in both the SkImage and our mBuffer, which with large +// images can waste quite a lot of memory. Ideally we should store the data in Skia's +// SkBitmap, but LO wants us to support data formats that Skia doesn't support. +// So try to conserve memory by keeping the data only once in that was the most +// recently wanted storage, and drop the other one. Usually the other one won't be needed +// for a long time, and especially with raster the conversion is usually fast. +// Do this only with raster, to avoid GPU->CPU transfer in GPU mode (exception is 32bit +// builds, where memory is more important). Also don't do this with paletted bitmaps, +// where EnsureBitmapData() would be expensive. +// Ideally SalBitmap should be able to say which bitmap formats it supports +// and VCL code should oblige, which would allow reusing the same data. +bool SkiaSalBitmap::ConserveMemory() const +{ +static bool keepBitmapBuffer = getenv("SAL_SKIA_KEEP_BITMAP_BUFFER") != nullptr; +constexpr bool is32Bit = sizeof(void*) == 4; +// 16MiB bitmap data at least (set to 0 for easy testing). +constexpr long maxBufferSize = 2000 * 2000 * 4; +return !keepBitmapBuffer + && (SkiaHelper::renderMethodToUse() == SkiaHelper::RenderRaster || is32Bit) + && mPixelsSize.Height() * mScanlineSize > maxBufferSize + && (mBitCount > 8 || (mBitCount == 8 && mPalette.IsGreyPalette8Bit())); +} + const sk_sp& SkiaSalBitmap::GetSkImage() const { #ifdef DBG_UTIL @@ -639,24 +662,13 @@ const sk_sp& SkiaSalBitmap::GetSkImage() const assert(image); SkiaSalBitmap* thisPtr = const_cast(this); thisPtr->mImage = image; -// The data is now stored both in the SkImage and in our mBuffer, which with large -// images can waste quite a lot of memory. Ideally we should store the data in Skia's -// SkBitmap, but LO wants us to support data formats that Skia doesn't support. -// So just drop our buffer, it usually won't be needed anyway, and it'll be converted -// back by EnsureBitmapData() if yes. Do this only with raster, to avoid GPU->CPU -// transfer in GPU mode. Also don't do this with paletted bitmaps, where EnsureBitmapData() -// would be expensive. -// Ideally SalBitmap should be able to say which bitmap formats it supports -// and VCL code should oblige, which would allow reusing the same data. -static bool keepBitmapBuffer = getenv("SAL_SKIA_KEEP_BITMAP_BUFFER") != nullptr; -// 32bit builds have limited address space, so try to conserve memory as well. -constexpr bool is32Bit = sizeof(void*) == 4; -constexpr long maxBufferSize = 2000 * 2000 * 4; -if (!keepBitmapBuffer -&& (SkiaHelper::renderMethodToUse() == SkiaHelper::RenderRaster || is32Bit) -&& mPixelsSize.Height() * mScanlineSize > maxBufferSize -&& (mBitCount > 8 || (mBitCount == 8 && mPalette.IsGreyPalette8Bit( +// The data is now stored both in the SkImage and in our mBuffer, so drop the buffer +// if conserving memory. It'll be converted back by EnsureBitmapData() if needed. +if (ConserveMemory()) +{ +SAL_INFO("vcl.skia.trace", "getskimage(" << this << "): dropping buffer"); thisPtr->ResetToSkImage(mImage); +} SAL_INFO("vcl.skia.trace", "getskimage(" << this << ")"); return mImage; } @@ -714,6 +726,9 @@ const sk_sp& SkiaSalBitmap::GetAlphaSkImage() const
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source
vcl/inc/driverblocklist.hxx |4 +++- vcl/skia/SkiaHelper.cxx |3 ++- vcl/source/helper/driverblocklist.cxx | 12 ++-- 3 files changed, 11 insertions(+), 8 deletions(-) New commits: commit 9db379b0b7dded5e9a4523ce48dac928979aab70 Author: Stephan Bergmann AuthorDate: Mon Sep 7 22:21:36 2020 +0200 Commit: Stephan Bergmann CommitDate: Tue Sep 8 07:33:19 2020 +0200 Simplify GetVendorNameFromId, returning std::string_view Change-Id: Ida709a432a1892494a767da3979afdc3ee4477b2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102206 Tested-by: Jenkins Reviewed-by: Stephan Bergmann diff --git a/vcl/inc/driverblocklist.hxx b/vcl/inc/driverblocklist.hxx index f28dc418383a..a417d19ff543 100644 --- a/vcl/inc/driverblocklist.hxx +++ b/vcl/inc/driverblocklist.hxx @@ -12,6 +12,8 @@ #include #include + +#include #include namespace DriverBlocklist @@ -36,7 +38,7 @@ const int DeviceVendorMax = VendorMicrosoft + 1; /// Returns vendor for the given vendor ID, or VendorAll if not known. VCL_DLLPUBLIC DeviceVendor GetVendorFromId(uint32_t id); -VCL_DLLPUBLIC OUStringLiteral GetVendorNameFromId(uint32_t id); +VCL_DLLPUBLIC std::string_view GetVendorNameFromId(uint32_t id); // The rest should be private (only for the unittest). diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 8ba1e06f2463..5bf8c04cff6a 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -32,6 +32,7 @@ bool isVCLSkiaEnabled() { return false; } #include #include #include +#include #include #include @@ -64,7 +65,7 @@ static OUString versionAsString(uint32_t version) + OUString::number(version & 0xfff); } -static OUStringLiteral vendorAsString(uint32_t vendor) +static std::string_view vendorAsString(uint32_t vendor) { return DriverBlocklist::GetVendorNameFromId(vendor); } diff --git a/vcl/source/helper/driverblocklist.cxx b/vcl/source/helper/driverblocklist.cxx index 8b2ca1ffa0c1..6bcee982015f 100644 --- a/vcl/source/helper/driverblocklist.cxx +++ b/vcl/source/helper/driverblocklist.cxx @@ -157,20 +157,20 @@ DeviceVendor GetVendorFromId(uint32_t id) } } -OUStringLiteral GetVendorNameFromId(uint32_t id) +std::string_view GetVendorNameFromId(uint32_t id) { switch (id) { case 0x8086: -return u"Intel"; +return "Intel"; case 0x10de: -return u"Nvidia"; +return "Nvidia"; case 0x1002: -return u"AMD"; +return "AMD"; case 0x1414: -return u"Microsoft"; +return "Microsoft"; default: -return u"?"; +return "?"; } } ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx | 12 vcl/skia/salbmp.cxx |2 ++ 2 files changed, 10 insertions(+), 4 deletions(-) New commits: commit 76babdeaf2e419d2aa21d674160a4575691a536a Author: Luboš Luňák AuthorDate: Sat Sep 5 14:11:43 2020 +0200 Commit: Luboš Luňák CommitDate: Mon Sep 7 15:22:11 2020 +0200 improve debug for erased SkiaSalBitmap Change-Id: I1e1edafc7b9daf5748e22846ca5807613f779b2d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102167 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index f834478be51a..d2599d3e98b5 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -121,10 +121,14 @@ private: return stream << "(null)"; // I/i - has SkImage (on GPU/CPU), // A/a - has alpha SkImage (on GPU/CPU) -return stream << static_cast(bitmap) << " " << bitmap->GetSize() << "/" - << (bitmap->mImage ? (bitmap->mImage->isTextureBacked() ? "I" : "i") : "") - << (bitmap->mAlphaImage ? (bitmap->mAlphaImage->isTextureBacked() ? "A" : "a") - : ""); +stream << static_cast(bitmap) << " " << bitmap->GetSize() << "/"; +if (bitmap->mImage) +stream << (bitmap->mImage->isTextureBacked() ? "I" : "i"); +if (bitmap->mAlphaImage) +stream << (bitmap->mAlphaImage->isTextureBacked() ? "A" : "a"); +if (bitmap->mEraseColorSet) +stream << "E" << bitmap->mEraseColor; +return stream; } BitmapPalette mPalette; diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index ec91417cdf1b..83b807e87b15 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -204,12 +204,14 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) if (!mBuffer) return nullptr; assert(mPixelsSize == mSize); +assert(!mEraseColorSet); break; case BitmapAccessMode::Read: EnsureBitmapData(); if (!mBuffer) return nullptr; assert(mPixelsSize == mSize); +assert(!mEraseColorSet); break; case BitmapAccessMode::Info: break; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |1 + vcl/skia/gdiimpl.cxx | 12 2 files changed, 13 insertions(+) New commits: commit acb47f7aaaec14baccc0f3233670044e72342d29 Author: Luboš Luňák AuthorDate: Sat Sep 5 10:59:25 2020 +0200 Commit: Luboš Luňák CommitDate: Mon Sep 7 15:21:41 2020 +0200 do not queue up too many Skia image drawing operations (tdf#136369) The document tries to draw a larger number of tiny bitmaps, which results in Skia trying to allocate many tiny GPU images, which slows it down (something quadratic there?) and it may eventually run out of memory. So force a flush if there are too many such operations unflushed. This is somewhat similar to what was done in the past by ad3580df085b3a3d66eb73cae997ea5ca178ccc1 . Change-Id: Ib0309ea9c7ac6c80d69ceed2922e885a2aa7f2d8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102166 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 32beae036d5f..9405bc39ade2 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -325,6 +325,7 @@ protected: double transparency; }; LastPolyPolygonInfo mLastPolyPolygonInfo; +int mPendingOperationsToFlush; }; #endif diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index cb0f9b47ecf8..17fcbf092335 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -255,6 +255,7 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvid , mFillColor(SALCOLOR_NONE) , mXorMode(false) , mFlush(new SkiaFlushIdle(this)) +, mPendingOperationsToFlush(0) { } @@ -389,6 +390,15 @@ void SkiaSalGraphicsImpl::preDraw() void SkiaSalGraphicsImpl::postDraw() { scheduleFlush(); +// Skia (at least when using Vulkan) queues drawing commands and executes them only later. +// But tdf#136369 leads to creating and queueing many tiny bitmaps, which makes +// Skia slow, and may make it even run out of memory. So force a flush if such +// a problematic operation has been performed too many times without a flush. +if (mPendingOperationsToFlush > 1000) +{ +mSurface->flushAndSubmit(); +mPendingOperationsToFlush = 0; +} SkiaZone::leave(); // matched in preDraw() } @@ -454,6 +464,7 @@ void SkiaSalGraphicsImpl::flushDrawing() if (mXorMode) applyXor(); mSurface->flushAndSubmit(); +mPendingOperationsToFlush = 0; } bool SkiaSalGraphicsImpl::setClipRegion(const vcl::Region& region) @@ -1550,6 +1561,7 @@ void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& rPosAry, const sk_spdrawImageRect(aImage, aSourceRect, aDestinationRect, ); addXorRegion(aDestinationRect); +++mPendingOperationsToFlush; // tdf#136369 postDraw(); } ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |1 + vcl/skia/SkiaHelper.cxx |5 ++--- vcl/skia/gdiimpl.cxx|3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) New commits: commit a8a7df6de6b48a03589ac9b66b490875eab19b75 Author: Luboš Luňák AuthorDate: Sat Sep 5 09:10:40 2020 +0200 Commit: Luboš Luňák CommitDate: Mon Sep 7 15:19:55 2020 +0200 increase Skia image cache size to 64MiB (tdf#136244) 16MiB was enough to hold just one 2000x2000 image, which is almost the usual screen size. Change-Id: I8fd02101cd2a18ddb89500d555d5c2f051fdb81f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102069 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 8a104e066090..fc2567ac4e32 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -56,6 +56,7 @@ VCL_DLLPUBLIC void void addCachedImage(const OString& key, sk_sp image); sk_sp findCachedImage(const OString& key); void removeCachedImage(sk_sp image); +constexpr int MAX_CACHE_SIZE = 4 * 2000 * 2000 * 4; // 4x 2000px 32bpp images, 64MiB #ifdef DBG_UTIL void prefillSurface(sk_sp& surface); diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index de0fd94be79c..8ba1e06f2463 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -472,13 +472,12 @@ void addCachedImage(const OString& key, sk_sp image) imageCache->push_front({ key, image, size }); imageCacheSize += size; SAL_INFO("vcl.skia.trace", "addcachedimage " << image << " :" << size << "/" << imageCacheSize); -const int MAX_CACHE_SIZE = 4 * 1000 * 1000 * 4; // 4x 1000px 32bpp images, 16MiB while (imageCacheSize > MAX_CACHE_SIZE) { assert(!imageCache->empty()); imageCacheSize -= imageCache->back().size; -SAL_INFO("vcl.skia.trace", - "least used removal " << image << ":" << imageCache->back().size); +SAL_INFO("vcl.skia.trace", "least used removal " << imageCache->back().image << ":" + << imageCache->back().size); imageCache->pop_back(); } } diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 652fea88f38e..f5374b773028 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1436,6 +1436,9 @@ sk_sp SkiaSalGraphicsImpl::mergeCacheBitmaps(const SkiaSalBitmap& bitma return image; } } +// Do not cache the result if it would take most of the cache and thus get evicted soon. +if (targetSize.Width() * targetSize.Height() * 4 > SkiaHelper::MAX_CACHE_SIZE * 0.7) +return image; OString key; OStringBuffer keyBuf; keyBuf.append(targetSize.Width()) ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |5 +++-- vcl/skia/gdiimpl.cxx | 41 - 2 files changed, 19 insertions(+), 27 deletions(-) New commits: commit 4f6551d24279aab31b23f4dd668f42d6e3d15348 Author: Luboš Luňák AuthorDate: Wed Aug 26 10:44:48 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Aug 26 11:47:46 2020 +0200 optimize polygon merging in Skia (tdf#136139) basegfx::utils::mergeToSinglePolyPolygon() can be an expensive operation when many polygons are involved, and the code was calling it for every new polygon, which is actually not needed. Simply merge all the collected polygons just once before they need to be drawn. Change-Id: Id29d5dd5647d262b2cdfe9963f8d4e2ace844b66 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101384 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 7413c781409b..32beae036d5f 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -286,7 +286,7 @@ protected: // and anything that means the next operation cannot be another one in a series (e.g. // changing colors). void checkPendingDrawing(); -bool mergePolyPolygonToPrevious(const basegfx::B2DPolyPolygon& polygon, double transparency); +bool delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency); void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double transparency, bool useAA); @@ -320,7 +320,8 @@ protected: // Info about pending polygons to draw (we try to merge adjacent polygons into one). struct LastPolyPolygonInfo { -basegfx::B2DPolyPolygon polygon; +basegfx::B2DPolyPolygonVector polygons; +basegfx::B2DRange bounds; double transparency; }; LastPolyPolygonInfo mLastPolyPolygonInfo; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 25decef1c0ed..b80fcc301d8a 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -735,7 +735,7 @@ bool SkiaSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectTo SAL_INFO("vcl.skia.trace", "drawpolypolygon(" << this << "): " << aPolyPolygon << ":" << mLineColor << ":" << mFillColor); -if (mergePolyPolygonToPrevious(aPolyPolygon, fTransparency)) +if (delayDrawPolyPolygon(aPolyPolygon, fTransparency)) { scheduleFlush(); return true; @@ -790,8 +790,8 @@ void SkiaSalGraphicsImpl::performDrawPolyPolygon(const basegfx::B2DPolyPolygon& #endif } -bool SkiaSalGraphicsImpl::mergePolyPolygonToPrevious(const basegfx::B2DPolyPolygon& aPolyPolygon, - double fTransparency) +bool SkiaSalGraphicsImpl::delayDrawPolyPolygon(const basegfx::B2DPolyPolygon& aPolyPolygon, + double fTransparency) { // There is some code that needlessly subdivides areas into adjacent rectangles, // but Skia doesn't line them up perfectly if AA is enabled (e.g. Cairo, Qt5 do, @@ -819,39 +819,30 @@ bool SkiaSalGraphicsImpl::mergePolyPolygonToPrevious(const basegfx::B2DPolyPolyg if (aPolyPolygon.count() != 1) return false; -if (mLastPolyPolygonInfo.polygon.count() != 0 +if (mLastPolyPolygonInfo.polygons.size() != 0 && (mLastPolyPolygonInfo.transparency != fTransparency -|| !mLastPolyPolygonInfo.polygon.getB2DRange().overlaps(aPolyPolygon.getB2DRange( +|| !mLastPolyPolygonInfo.bounds.overlaps(aPolyPolygon.getB2DRange( { checkPendingDrawing(); // Cannot be parts of the same larger polygon, draw the last and reset. } -if (mLastPolyPolygonInfo.polygon.count() == 0) -{ -mLastPolyPolygonInfo.polygon = aPolyPolygon; -mLastPolyPolygonInfo.transparency = fTransparency; -return true; -} -basegfx::B2DPolyPolygon merged -= basegfx::utils::mergeToSinglePolyPolygon({ mLastPolyPolygonInfo.polygon, aPolyPolygon }); -if (merged.count() == 0) // it wasn't actually merged -{ -checkPendingDrawing(); -mLastPolyPolygonInfo.polygon = aPolyPolygon; -mLastPolyPolygonInfo.transparency = fTransparency; -return true; -} -mLastPolyPolygonInfo.polygon = std::move(merged); +// Collect the polygons that can be possibly merged. Do the merging only once at the end, +// because it's not a cheap operation. +mLastPolyPolygonInfo.polygons.push_back(aPolyPolygon); +mLastPolyPolygonInfo.bounds.expand(aPolyPolygon.getB2DRange()); +mLastPolyPolygonInfo.transparency = fTransparency; return true; } void SkiaSalGraphicsImpl::checkPendingDrawing() { -if (mLastPolyPolygonInfo.polygon.count() != 0) +if (mLastPolyPolygonInfo.polygons.size() != 0) { // Flush any pending
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |6 ++-- vcl/skia/salbmp.cxx | 69 +++- 2 files changed, 55 insertions(+), 20 deletions(-) New commits: commit 65f9d384fdc0ed4a3c9c6aa57af526fe818b311e Author: Luboš Luňák AuthorDate: Mon Jul 27 15:47:17 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Jul 29 15:47:53 2020 +0200 allocate bitmap data buffer on demand in SkiaSalBitmap And also make sure mScanlineSize is always correct, which it seems like it possibly might not have been the case (the delayed scaling makes it a bit complicated, as the internal scanline size is based on the internal bitmap size mPixelsSize, not the externally reported bitmap size mSize). Change-Id: I0d6cc2fca27ffa1c3accc13b38c8c01b5ffc8ba0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/99680 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 4ee6e4908ee7..3725c9f9a8ec 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -96,7 +96,9 @@ private: // Call before changing the data. void EnsureBitmapUniqueData(); // Allocate mBuffer (with uninitialized contents). -bool CreateBitmapData(); +void CreateBitmapData(); +// Should be called whenever mPixelsSize or mBitCount is set/changed. +bool ComputeScanlineSize(); void EraseInternal(); SkBitmap GetAsSkBitmap() const; #ifdef DBG_UTIL @@ -131,7 +133,7 @@ private: // is reset by ResetCachedImage(). But sometimes only mImage will be set and in that case // mBuffer must be filled from it on demand if necessary by EnsureBitmapData(). boost::shared_ptr mBuffer; -int mScanlineSize; // size of one row in mBuffer +int mScanlineSize; // size of one row in mBuffer (based on mPixelsSize) sk_sp mImage; // possibly GPU-backed sk_sp mAlphaImage; // cached contents as alpha image, possibly GPU-backed // Actual scaling triggered by scale() is done on-demand. This is the size of the pixel diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index ed66eddbc3c5..7f8fa50aced3 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -65,6 +65,7 @@ SkiaSalBitmap::SkiaSalBitmap(const sk_sp& image) mPalette = BitmapPalette(); mBitCount = 32; mSize = mPixelsSize = Size(image->width(), image->height()); +ComputeScanlineSize(); #ifdef DBG_UTIL mWriteAccessCount = 0; #endif @@ -83,10 +84,11 @@ bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const Bitmap #ifdef DBG_UTIL mWriteAccessCount = 0; #endif -if (!CreateBitmapData()) +if (!ComputeScanlineSize()) { mBitCount = 0; mSize = mPixelsSize = Size(); +mScanlineSize = 0; mPalette = BitmapPalette(); return false; } @@ -94,9 +96,23 @@ bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const Bitmap return true; } -bool SkiaSalBitmap::CreateBitmapData() +bool SkiaSalBitmap::ComputeScanlineSize() +{ +int bitScanlineWidth; +if (o3tl::checked_multiply(mPixelsSize.Width(), mBitCount, bitScanlineWidth)) +{ +SAL_WARN("vcl.skia", "checked multiply failed"); +return false; +} +mScanlineSize = AlignedWidth4Bytes(bitScanlineWidth); +return true; +} + +void SkiaSalBitmap::CreateBitmapData() { assert(!mBuffer); +// Make sure code has not missed calling ComputeScanlineSize(). +assert(mScanlineSize == int(AlignedWidth4Bytes(mPixelsSize.Width() * mBitCount))); // The pixels could be stored in SkBitmap, but Skia only supports 8bit gray, 16bit and 32bit formats // (e.g. 24bpp is actually stored as 32bpp). But some of our code accessing the bitmap assumes that // when it asked for 24bpp, the format really will be 24bpp (e.g. the png loader), so we cannot use @@ -104,16 +120,9 @@ bool SkiaSalBitmap::CreateBitmapData() // and a VCL bitmap can change its grayscale status simply by changing the palette. // Moreover creating SkImage from SkBitmap does a data copy unless the bitmap is immutable. // So just always store pixels in our buffer and convert as necessary. -int bitScanlineWidth; -if (o3tl::checked_multiply(mSize.Width(), mBitCount, bitScanlineWidth)) -{ -SAL_WARN("vcl.skia", "checked multiply failed"); -return false; -} -mScanlineSize = AlignedWidth4Bytes(bitScanlineWidth); -if (mScanlineSize != 0 && mSize.Height() != 0) +if (mScanlineSize != 0 && mPixelsSize.Height() != 0) { -size_t allocate = mScanlineSize * mSize.Height(); +size_t allocate = mScanlineSize * mPixelsSize.Height(); #ifdef DBG_UTIL allocate += sizeof(CANARY); #endif @@ -126,7 +135,6 @@ bool SkiaSalBitmap::CreateBitmapData() memcpy(buffer + allocate - sizeof(CANARY), CANARY, sizeof(CANARY)); #endif } -return true; } bool
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx | 12 +++- vcl/skia/gdiimpl.cxx | 28 2 files changed, 19 insertions(+), 21 deletions(-) New commits: commit 4bb931a488b8fe7a0b4961956252f667b683a630 Author: Luboš Luňák AuthorDate: Tue Jul 14 16:12:36 2020 +0200 Commit: Luboš Luňák CommitDate: Thu Jul 16 11:56:18 2020 +0200 use consistent Skia pixel position adjustments (tdf#134346) What happens in tdf#134346 is that the same shape was drawn twice, once using drawPolyPolygon() and once as an outline using drawPolyLine(). Those had different offsets, so with AA enabled the tiny difference could be actually visible. Be more consistent with how the pixels are positioned in float coordinates. Change-Id: Id852fef70e7bd829ff0108a86d1ebee29c300e3a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98745 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index c98038807287..344509fe301e 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -272,12 +272,14 @@ protected: sk_sp mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap, const Size targetSize); -// When drawing using GPU, rounding errors may result in off-by-one errors, +// Skia uses floating point coordinates, so when we use integer coordinates, sometimes +// rounding results in off-by-one errors (down), especially when drawing using GPU, // see https://bugs.chromium.org/p/skia/issues/detail?id=9611 . Compensate for -// it by using centers of pixels (Skia uses float coordinates). In raster case -// it seems better to not do this though. -SkScalar toSkX(long x) const { return mIsGPU ? x + 0.5 : x; } -SkScalar toSkY(long y) const { return mIsGPU ? y + 0.5 : y; } +// it by using centers of pixels. Using 0.5 may sometimes round up, so go with 0.495 . +static constexpr SkScalar toSkX(long x) { return x + 0.495; } +static constexpr SkScalar toSkY(long y) { return y + 0.495; } +// Value to add to be exactly in the middle of the pixel. +static constexpr SkScalar toSkXYFix = SkScalar(0.005); template friend inline std::basic_ostream& diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index bb837b03493b..09dd924b6a2c 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -597,11 +597,7 @@ void SkiaSalGraphicsImpl::drawLine(long nX1, long nY1, long nX2, long nY2) SkPaint paint; paint.setColor(toSkColor(mLineColor)); paint.setAntiAlias(mParent.getAntiAliasB2DDraw()); -// Raster has better results if shifted by 0.25 (unlike the 0.5 done by toSkX/toSkY). -if (!isGPU()) -getDrawCanvas()->drawLine(nX1 + 0.25, nY1 + 0.25, nX2 + 0.25, nY2 + 0.25, paint); -else -getDrawCanvas()->drawLine(toSkX(nX1), toSkY(nY1), toSkX(nX2), toSkY(nY2), paint); +getDrawCanvas()->drawLine(toSkX(nX1), toSkY(nY1), toSkX(nX2), toSkY(nY2), paint); addXorRegion(SkRect::MakeLTRB(nX1, nY1, nX2 + 1, nY2 + 1)); postDraw(); } @@ -708,19 +704,21 @@ bool SkiaSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectTo SkPaint aPaint; aPaint.setAntiAlias(mParent.getAntiAliasB2DDraw()); +// We normally use pixel at their center positions, but slightly off (see toSkX/Y()). +// With AA lines that "slightly off" causes tiny changes of color, making some tests +// fail. Since moving AA-ed line slightly to a side doesn't cause any real visual +// difference, just place exactly at the center. tdf#134346 +const SkScalar posFix = mParent.getAntiAliasB2DDraw() ? toSkXYFix : 0; if (mFillColor != SALCOLOR_NONE) { aPaint.setColor(toSkColorWithTransparency(mFillColor, fTransparency)); aPaint.setStyle(SkPaint::kFill_Style); +aPath.offset(toSkX(0) + posFix, toSkY(0) + posFix, nullptr); getDrawCanvas()->drawPath(aPath, aPaint); } if (mLineColor != SALCOLOR_NONE) { -// Raster has better results if shifted by 0.25 (unlike the 0.5 done by toSkX/toSkY). -if (!isGPU()) -aPath.offset(0.25, 0.25, nullptr); -else // Apply the same adjustment as toSkX()/toSkY() do. -aPath.offset(0.5, 0.5, nullptr); +aPath.offset(toSkX(0) + posFix, toSkY(0) + posFix, nullptr); aPaint.setColor(toSkColorWithTransparency(mLineColor, fTransparency)); aPaint.setStyle(SkPaint::kStroke_Style); getDrawCanvas()->drawPath(aPath, aPaint); @@ -811,6 +809,8 @@ bool SkiaSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDev aPaint.setStrokeMiter(fMiterLimit); aPaint.setStrokeWidth(fLineWidth); aPaint.setAntiAlias(mParent.getAntiAliasB2DDraw()); +// See the tdf#134346 comment above. +const SkScalar posFix = mParent.getAntiAliasB2DDraw() ? toSkXYFix : 0;
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source
vcl/inc/salbmp.hxx|5 + vcl/inc/skia/gdiimpl.hxx |6 + vcl/inc/skia/salbmp.hxx | 15 vcl/skia/gdiimpl.cxx | 87 +--- vcl/skia/salbmp.cxx | 134 +- vcl/source/bitmap/bitmappaint.cxx | 13 +++ 6 files changed, 231 insertions(+), 29 deletions(-) New commits: commit d1fcc9053f98cc4afb52498b40a836884bb5ec6f Author: Luboš Luňák AuthorDate: Tue Jun 30 10:19:34 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Jul 1 07:36:39 2020 +0200 optimize Bitmap::Erase() for Skia by delaying the erase (tdf#134363) Tdf#134363 causes OutputDevice::DrawTransformBitmapExDirect() to create a huge 1bpp bitmap as mask, and Skia code then tries to convert all the bits to a format Skia would understand. Which is wasteful, as SkShader with the color given will do the same task much more efficiently. Change-Id: If0bba16f56fed9c3720be801b25a1e703054ed8d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97488 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx index 4244ae1a376f..ab16b317d7eb 100644 --- a/vcl/inc/salbmp.hxx +++ b/vcl/inc/salbmp.hxx @@ -86,6 +86,11 @@ public: return false; } +virtual boolErase( const Color& /*color*/ ) +{ +return false; +} + void GetChecksum(BitmapChecksum& rChecksum) const { updateChecksum(); diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 73fbee394072..c98038807287 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -200,10 +200,14 @@ public: #endif // Default blend mode for SkPaint is SkBlendMode::kSrcOver +void drawBitmap(const SalTwoRect& rPosAry, const SkiaSalBitmap& bitmap, +SkBlendMode blendMode = SkBlendMode::kSrcOver); + void drawImage(const SalTwoRect& rPosAry, const sk_sp& aImage, SkBlendMode eBlendMode = SkBlendMode::kSrcOver); -void drawShader(const SalTwoRect& rPosAry, const sk_sp& shader); +void drawShader(const SalTwoRect& rPosAry, const sk_sp& shader, +SkBlendMode blendMode = SkBlendMode::kSrcOver); enum class GlyphOrientation { diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index d5491e367700..4ee6e4908ee7 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -59,13 +59,24 @@ public: sal_uInt8 nTol) override; virtual bool InterpretAs8Bit() override; virtual bool ConvertToGreyscale() override; +virtual bool Erase(const Color& color) override; const BitmapPalette& Palette() const { return mPalette; } + +// True if GetSkShader() should be preferred to GetSkImage() (or the Alpha variants). +bool PreferSkShader() const; + // Returns the contents as SkImage (possibly GPU-backed). const sk_sp& GetSkImage() const; +sk_sp GetSkShader() const; // Returns the contents as alpha SkImage (possibly GPU-backed) const sk_sp& GetAlphaSkImage() const; +sk_sp GetAlphaSkShader() const; + +// Key for caching/hashing. +OString GetImageKey() const; +OString GetAlphaImageKey() const; #ifdef DBG_UTIL void dump(const char* file) const; @@ -86,6 +97,7 @@ private: void EnsureBitmapUniqueData(); // Allocate mBuffer (with uninitialized contents). bool CreateBitmapData(); +void EraseInternal(); SkBitmap GetAsSkBitmap() const; #ifdef DBG_UTIL void verify() const; @@ -126,6 +138,9 @@ private: // data in mBuffer, if it differs from mSize, then there is a scaling operation pending. Size mPixelsSize; SkFilterQuality mScaleQuality = kHigh_SkFilterQuality; // quality for on-demand scaling +// Erase() is delayed, just sets these two instead of filling the buffer. +bool mEraseColorSet = false; +Color mEraseColor; #ifdef DBG_UTIL int mWriteAccessCount = 0; // number of write AcquireAccess() that have not been released #endif diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index b00b74d24647..c11705486926 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1009,7 +1009,7 @@ bool SkiaSalGraphicsImpl::blendBitmap(const SalTwoRect& rPosAry, const SalBitmap // combinedTextureFragmentShader.glsl, the layer is not even alpha values but // simply yes-or-no mask. // See also blendAlphaBitmap(). -drawImage(rPosAry, rSkiaBitmap.GetSkImage(), SkBlendMode::kMultiply); +drawBitmap(rPosAry, rSkiaBitmap, SkBlendMode::kMultiply); return true; } @@ -1040,11 +1040,11 @@ bool SkiaSalGraphicsImpl::blendAlphaBitmap(const SalTwoRect& rPosAry, // First do the "( 1 - alpha ) * mask" // (no idea how to do "floor", but hopefully not needed in practice). sk_sp shaderAlpha -= SkShaders::Blend(SkBlendMode::kDstOut,
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |1 vcl/skia/salbmp.cxx | 54 +++- 2 files changed, 13 insertions(+), 42 deletions(-) New commits: commit e318e4cea37f6adb20cffc913655c0e6dbabe45a Author: Luboš Luňák AuthorDate: Sat Jun 27 09:39:56 2020 +0200 Commit: Luboš Luňák CommitDate: Sat Jun 27 10:43:54 2020 +0200 do not use VCL scaling algorithm from Skia The only threaded one is "Super" (i.e. the default one), and Skia at a comparable quality seems to perform better. And the code is simpler too. Change-Id: I366197fe1a033c1f7a5f5c7f9fdcc00bff74dc11 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97278 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 2bd729683bde..d5491e367700 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -126,7 +126,6 @@ private: // data in mBuffer, if it differs from mSize, then there is a scaling operation pending. Size mPixelsSize; SkFilterQuality mScaleQuality = kHigh_SkFilterQuality; // quality for on-demand scaling -bool mDisableScale = false; // used to block our scale() #ifdef DBG_UTIL int mWriteAccessCount = 0; // number of write AcquireAccess() that have not been released #endif diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 428592f44808..2ac221fdba19 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -279,7 +279,7 @@ bool SkiaSalBitmap::GetSystemData(BitmapSystemData&) return false; } -bool SkiaSalBitmap::ScalingSupported() const { return !mDisableScale; } +bool SkiaSalBitmap::ScalingSupported() const { return true; } bool SkiaSalBitmap::Scale(const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag) { @@ -618,46 +618,18 @@ void SkiaSalBitmap::EnsureBitmapData() { if (mBuffer) { -if (mSize != mPixelsSize) // pending scaling? -{ -// This will be pixel->pixel scaling, use VCL algorithm, it should be faster than Skia -// (no need to possibly convert bpp, it's multithreaded,...). -std::shared_ptr src = std::make_shared(); -if (!src->Create(*this)) -abort(); -// force 'src' to use VCL's scaling -src->mDisableScale = true; -src->mSize = src->mPixelsSize; -Bitmap bitmap(src); -BmpScaleFlag scaleFlag; -switch (mScaleQuality) -{ -case kNone_SkFilterQuality: -scaleFlag = BmpScaleFlag::Fast; -break; -case kMedium_SkFilterQuality: -scaleFlag = BmpScaleFlag::Default; -break; -case kHigh_SkFilterQuality: -scaleFlag = BmpScaleFlag::BestQuality; -break; -default: -abort(); -} -bitmap.Scale(mSize, scaleFlag); -assert(dynamic_cast(bitmap.ImplGetSalBitmap().get())); -const SkiaSalBitmap* dest -= static_cast(bitmap.ImplGetSalBitmap().get()); -assert(dest->mSize == dest->mPixelsSize); -assert(dest->mSize == mSize); -SAL_INFO("vcl.skia.trace", "ensurebitmapdata(" << this << "): pixels scaled " - << mPixelsSize << "->" << mSize << ":" - << static_cast(mScaleQuality)); -Destroy(); -Create(*dest); -mDisableScale = false; -} -return; +if (mSize == mPixelsSize) +return; +// Pending scaling. Create raster SkImage from the bitmap data +// at the pixel size and then the code below will scale at the correct +// bpp from the image. +SAL_INFO("vcl.skia.trace", "ensurebitmapdata(" << this << "): pixels to be scaled " + << mPixelsSize << "->" << mSize << ":" + << static_cast(mScaleQuality)); +Size savedSize = mSize; +mSize = mPixelsSize; +ResetToSkImage(SkImage::MakeFromBitmap(GetAsSkBitmap())); +mSize = savedSize; } // Try to fill mBuffer from mImage. if (!mImage) ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |7 - vcl/skia/gdiimpl.cxx | 249 +++ 2 files changed, 150 insertions(+), 106 deletions(-) New commits: commit 3d37d591377fe532fc0d32e9fbc8e57b8ded6768 Author: Luboš Luňák AuthorDate: Fri Jun 26 15:45:20 2020 +0200 Commit: Luboš Luňák CommitDate: Fri Jun 26 17:42:22 2020 +0200 use Skia's SkShader for blending bitmaps It turns out it's sometimes more efficient to use SkCanvas::drawPaint() with SkShader::Blend() used to blend bitmaps together, rather than manually creating temporary SkImage for the blending. This way it saves memory and it also performs faster e.g. for tdf#134237, where when zoomed it processes only relevant parts of the images instead of blending a whole enlarged image). Sadly in raster mode it is sometimes still faster to cache the image (e.g. with tdf#134160), so keep the caching there as well, for when useful. Change-Id: I887ae330907100c21a0d152783fcd7e8ef230355 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97238 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index 12a2366bce51..73fbee394072 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -35,6 +35,7 @@ class SkiaFlushIdle; class GenericSalLayout; class SkFont; +class SkiaSalBitmap; class VCL_DLLPUBLIC SkiaSalGraphicsImpl : public SalGraphicsImpl { @@ -202,6 +203,8 @@ public: void drawImage(const SalTwoRect& rPosAry, const sk_sp& aImage, SkBlendMode eBlendMode = SkBlendMode::kSrcOver); +void drawShader(const SalTwoRect& rPosAry, const sk_sp& shader); + enum class GlyphOrientation { Apply, @@ -251,8 +254,6 @@ protected: // get the height of the device int GetHeight() const { return mProvider ? mProvider->GetHeight() : 1; } -void drawMask(const SalTwoRect& rPosAry, const sk_sp& rImage, Color nMaskColor); - SkCanvas* getXorCanvas(); void applyXor(); void addXorRegion(const SkRect& rect) @@ -264,6 +265,8 @@ protected: } } static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region); +sk_sp mergeCacheBitmaps(const SkiaSalBitmap& bitmap, const SkiaSalBitmap* alphaBitmap, + const Size targetSize); // When drawing using GPU, rounding errors may result in off-by-one errors, // see https://bugs.chromium.org/p/skia/issues/detail?id=9611 . Compensate for diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 6dd6a5d35bd7..9304246e439e 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1024,11 +1024,6 @@ bool SkiaSalGraphicsImpl::blendAlphaBitmap(const SalTwoRect& rPosAry, assert(dynamic_cast()); assert(dynamic_cast()); assert(dynamic_cast()); - -sk_sp tmpSurface = SkiaHelper::createSkSurface(rSourceBitmap.GetSize()); -if (!tmpSurface) -return false; - const SkiaSalBitmap& rSkiaSourceBitmap = static_cast(rSourceBitmap); const SkiaSalBitmap& rSkiaMaskBitmap = static_cast(rMaskBitmap); const SkiaSalBitmap& rSkiaAlphaBitmap = static_cast(rAlphaBitmap); @@ -1041,20 +1036,16 @@ bool SkiaSalGraphicsImpl::blendAlphaBitmap(const SalTwoRect& rPosAry, // in opengl's combinedTextureFragmentShader.glsl is // "result_alpha = 1.0 - (1.0 - floor(alpha)) * mask". // See also blendBitmap(). -SkCanvas* aCanvas = tmpSurface->getCanvas(); -aCanvas->clear(SK_ColorTRANSPARENT); -SkPaint aPaint; -// First copy the mask as is. -aPaint.setBlendMode(SkBlendMode::kSrc); -aCanvas->drawImage(rSkiaMaskBitmap.GetAlphaSkImage(), 0, 0, ); -// Do the "1 - alpha" (no idea how to do "floor", but hopefully not needed in practice). -aPaint.setBlendMode(SkBlendMode::kDstOut); -aCanvas->drawImage(rSkiaAlphaBitmap.GetAlphaSkImage(), 0, 0, ); -// And now draw the bitmap with "1 - x", where x is the "( 1 - alpha ) * mask". -aPaint.setBlendMode(SkBlendMode::kSrcOut); -aCanvas->drawImage(rSkiaSourceBitmap.GetSkImage(), 0, 0, ); -drawImage(rPosAry, tmpSurface->makeImageSnapshot()); +// First do the "( 1 - alpha ) * mask" +// (no idea how to do "floor", but hopefully not needed in practice). +sk_sp shaderAlpha += SkShaders::Blend(SkBlendMode::kDstOut, rSkiaMaskBitmap.GetAlphaSkImage()->makeShader(), + rSkiaAlphaBitmap.GetAlphaSkImage()->makeShader()); +// And now draw the bitmap with "1 - x", where x is the "( 1 - alpha ) * mask". +sk_sp shader = SkShaders::Blend(SkBlendMode::kSrcOut, shaderAlpha, + rSkiaSourceBitmap.GetSkImage()->makeShader()); +drawShader(rPosAry, shader); return true; } @@ -1079,24 +1070,11 @@ void SkiaSalGraphicsImpl::drawMask(const SalTwoRect& rPosAry, const SalBitmap& r
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |7 ++- vcl/skia/salbmp.cxx | 42 ++ 2 files changed, 16 insertions(+), 33 deletions(-) New commits: commit 2ce4b01d935b8df878e0c9995f51264398fa5264 Author: Luboš Luňák AuthorDate: Thu May 14 16:08:50 2020 +0200 Commit: Luboš Luňák CommitDate: Fri May 15 19:32:23 2020 +0200 do not cache SkBitmap in SkiaSalBitmap It doesn't make much sense anymore to keep it around, it's now used only by GetAsSkImage(), which is only called from GetSkImage() and GetSkAlphaImage(), and it's unlikely one SkiaSalBitmap would be used both as a bitmap and an alpha mask. In Vulkan mode this should save the memory (in raster mode the memory is shared by the SkImage). Change-Id: I5818a462aca85906f2e82cd951b6241d954723c6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94228 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index d13e765d63cd..7eb2a8eb72a6 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -71,8 +71,7 @@ public: #endif private: -// Reset the cached images allocated in GetSkImage()/GetAlphaSkImage(), -// and also the SkBitmap allocated in GetAsSkBitmap(). +// Reset the cached images allocated in GetSkImage()/GetAlphaSkImage(). void ResetCachedData(); // Sets the data only as SkImage (will be converted as needed). void ResetToSkImage(sk_sp image); @@ -97,10 +96,9 @@ private: friend inline std::basic_ostream& operator<<(std::basic_ostream& stream, const SkiaSalBitmap* bitmap) { -// B - has SkBitmap, I/i - has SkImage (on GPU/CPU), +// I/i - has SkImage (on GPU/CPU), // A/a - has alpha SkImage (on GPU/CPU) return stream << static_cast(bitmap) << " " << bitmap->GetSize() << "/" - << bitmap->mBitCount << (!bitmap->mBitmap.isNull() ? "B" : "") << (bitmap->mImage ? (bitmap->mImage->isTextureBacked() ? "I" : "i") : "") << (bitmap->mAlphaImage ? (bitmap->mAlphaImage->isTextureBacked() ? "A" : "a") : ""); @@ -119,7 +117,6 @@ private: // mBuffer must be filled from it on demand if necessary by EnsureBitmapData(). boost::shared_ptr mBuffer; int mScanlineSize; // size of one row in mBuffer -SkBitmap mBitmap; // cached mBuffer, if needed sk_sp mImage; // possibly GPU-backed sk_sp mAlphaImage; // cached contents as alpha image, possibly GPU-backed // Actual scaling triggered by scale() is done on-demand. This is the size of the pixel diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index d48e67c4e904..1bf0f77bfc2a 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -93,7 +93,6 @@ bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const Bitmap bool SkiaSalBitmap::CreateBitmapData() { -assert(mBitmap.isNull()); assert(!mBuffer); // The pixels could be stored in SkBitmap, but Skia only supports 8bit gray, 16bit and 32bit formats // (e.g. 24bpp is actually stored as 32bpp). But some of our code accessing the bitmap assumes that @@ -140,9 +139,6 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, SalGraphics* pGraphics) bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) { const SkiaSalBitmap& src = static_cast(rSalBmp); -mBitmap = src.mBitmap; -// SkBitmap shares pixels on copy. -assert(mBitmap.getPixels() == src.mBitmap.getPixels()); mImage = src.mImage; mAlphaImage = src.mAlphaImage; mBuffer = src.mBuffer; @@ -389,7 +385,7 @@ bool SkiaSalBitmap::InterpretAs8Bit() // the content as an alpha channel. This is often used // by the horrible separate-alpha-outdev hack, where the bitmap comes // from SkiaSalGraphicsImpl::GetBitmap(), so only mImage is set, -// and that is followed by a later call to GetAlphaSkBitmap(). +// and that is followed by a later call to GetAlphaSkImage(). // Avoid the costly SkImage->buffer->SkImage conversion and simply // just treat the SkImage as being for 8bit bitmap. EnsureBitmapData() // will do the conversion if needed, but the normal case will be @@ -410,8 +406,6 @@ SkBitmap SkiaSalBitmap::GetAsSkBitmap() const #ifdef DBG_UTIL assert(mWriteAccessCount == 0); #endif -if (!mBitmap.isNull()) -return mBitmap; EnsureBitmapData(); assert(mSize == mPixelsSize); // data has already been scaled if needed SkiaZone zone; @@ -479,8 +473,7 @@ SkBitmap SkiaSalBitmap::GetAsSkBitmap() const bitmap.setImmutable(); } } -const_cast(mBitmap) = bitmap; -return mBitmap; +return bitmap; } const sk_sp& SkiaSalBitmap::GetSkImage() const @@ -491,7 +484,7 @@ const sk_sp& SkiaSalBitmap::GetSkImage() const if (mPixelsSize != mSize && !mImage
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |2 ++ vcl/skia/salbmp.cxx | 20 ++-- 2 files changed, 20 insertions(+), 2 deletions(-) New commits: commit 31b00fe0f469c1bda8e523441e20f6e36bc17fd1 Author: Luboš Luňák AuthorDate: Fri Apr 24 12:26:10 2020 +0200 Commit: Luboš Luňák CommitDate: Fri Apr 24 16:06:45 2020 +0200 make SkiaSalBitmap discard cached data of incorrect size (tdf#132367) Performing the delayed scaling for the bitmap data could keep around cached mImage with a different size. Which theoretically could be kept around and resized later, but the bitmap data scaling finishes the delayed scaling by discarding all the data about it (scaling quality), so the later resizing wouldn't know how. Change-Id: I6a817d87becd44214f0f4db0755731b6e4ae1409 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92846 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index cfdb9d3d2347..d13e765d63cd 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -76,6 +76,8 @@ private: void ResetCachedData(); // Sets the data only as SkImage (will be converted as needed). void ResetToSkImage(sk_sp image); +// Resets all data that does not match mSize. +void ResetCachedDataBySize(); // Call to ensure mBuffer has data (will convert from mImage if necessary). void EnsureBitmapData(); void EnsureBitmapData() const { return const_cast(this)->EnsureBitmapData(); } diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 1f91b5d90a86..52808b38939e 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -679,6 +679,9 @@ void SkiaSalBitmap::EnsureBitmapData() << static_cast(mScaleQuality)); mPixelsSize = mSize; mScaleQuality = kNone_SkFilterQuality; +// Information about the pending scaling has been discarded, so make sure we do not +// keep around any cached images would still need scaling. +ResetCachedDataBySize(); } else canvas.drawImage(mImage, 0, 0, ); @@ -767,8 +770,8 @@ void SkiaSalBitmap::ResetCachedData() // mBuffer from it if needed, in that case ResetToSkImage() should be used. assert(mBuffer.get() || !mImage); mBitmap.reset(); -mAlphaImage.reset(); mImage.reset(); +mAlphaImage.reset(); } void SkiaSalBitmap::ResetToSkImage(sk_sp image) @@ -776,8 +779,21 @@ void SkiaSalBitmap::ResetToSkImage(sk_sp image) SkiaZone zone; mBuffer.reset(); mBitmap.reset(); -mAlphaImage.reset(); mImage = image; +mAlphaImage.reset(); +} + +void SkiaSalBitmap::ResetCachedDataBySize() +{ +SkiaZone zone; +assert(!mBitmap.isNull()); +assert(mBitmap.width() == mSize.getWidth() && mBitmap.height() == mSize.getHeight()); +assert(mSize == mPixelsSize); +if (mImage && (mImage->width() != mSize.getWidth() || mImage->height() != mSize.getHeight())) +mImage.reset(); +if (mAlphaImage +&& (mAlphaImage->width() != mSize.getWidth() || mAlphaImage->height() != mSize.getHeight())) +mAlphaImage.reset(); } #ifdef DBG_UTIL ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx | 14 +++ vcl/inc/skia/utils.hxx | 37 + vcl/skia/gdiimpl.cxx | 189 +++ 3 files changed, 146 insertions(+), 94 deletions(-) New commits: commit 3974dfee554bda82fdfb89cd4a2ea8926eb31243 Author: Luboš Luňák AuthorDate: Mon Apr 20 12:43:39 2020 +0200 Commit: Luboš Luňák CommitDate: Mon Apr 20 15:06:35 2020 +0200 batch Skia xor drawing (tdf#132241) The code previously applied the xor operation after each drawing, but the bugdoc draws a large number of polygons in xor mode, so the xor drawing was done repeatedly. Do the xor drawing just once when leaving the xor mode. Change-Id: I6c8d1c2f01688dc957a0af75232ee9fb69fe5d1b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92558 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index a99bb9ae4ce1..904053200d0a 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -219,6 +220,8 @@ protected: void postDraw(); // The canvas to draw to. Will be diverted to a temporary for Xor mode. SkCanvas* getDrawCanvas() { return mXorMode ? getXorCanvas() : mSurface->getCanvas(); } +// Call before makeImageSnapshot(), ensures the content is up to date. +void flushDrawing(); virtual void createSurface(); // Call to ensure that mSurface is valid. If mSurface is going to be modified, @@ -254,6 +257,15 @@ protected: void drawMask(const SalTwoRect& rPosAry, const sk_sp& rImage, Color nMaskColor); SkCanvas* getXorCanvas(); +void applyXor(); +void addXorRegion(const SkRect& rect) +{ +if (mXorMode) +{ +// Make slightly larger, just in case (rounding, antialiasing,...). +mXorRegion.op(rect.makeOutset(2, 2).round(), SkRegion::kUnion_Op); +} +} static void setCanvasClipRegion(SkCanvas* canvas, const vcl::Region& region); // When drawing using GPU, rounding errors may result in off-by-one errors, @@ -286,7 +298,7 @@ protected: bool mXorMode; SkBitmap mXorBitmap; std::unique_ptr mXorCanvas; -SkRect mXorExtents; // the area that needs updating for the xor operation (or empty for all) +SkRegion mXorRegion; // the area that needs updating for the xor operation std::unique_ptr mFlush; int mPendingPixelsToFlush; }; diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 16e5addd6909..942b5c3b88ef 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -25,6 +25,7 @@ #include #include +#include #include namespace SkiaHelper @@ -67,6 +68,42 @@ inline DriverBlocklist::DeviceVendor getVendor() } // namespace +template +inline std::basic_ostream& operator<<(std::basic_ostream& stream, + const SkRect& rectangle) +{ +if (rectangle.isEmpty()) +return stream << "EMPTY"; +else +return stream << rectangle.width() << 'x' << rectangle.height() << "@(" << rectangle.x() + << ',' << rectangle.y() << ")"; +} + +template +inline std::basic_ostream& operator<<(std::basic_ostream& stream, + const SkIRect& rectangle) +{ +if (rectangle.isEmpty()) +return stream << "EMPTY"; +else +return stream << rectangle.width() << 'x' << rectangle.height() << "@(" << rectangle.x() + << ',' << rectangle.y() << ")"; +} + +template +inline std::basic_ostream& operator<<(std::basic_ostream& stream, + const SkRegion& region) +{ +if (region.isEmpty()) +return stream << "EMPTY"; +stream << "("; +SkRegion::Iterator it(region); +for (int i = 0; !it.done(); it.next(), ++i) +stream << "[" << i << "] " << it.rect(); +stream << ")"; +return stream; +} + #endif // INCLUDED_VCL_INC_SKIA_UTILS_H /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index b4bda610e1b6..1937115e1c23 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -327,71 +327,10 @@ void SkiaSalGraphicsImpl::preDraw() assert(comphelper::SolarMutex::get()->IsCurrentThread()); SkiaZone::enter(); // matched in postDraw() checkSurface(); -assert(!mXorMode || 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 and can be optimized -// in each operation by setting mXorExtents to the area that should be -// updated. -if (mXorExtents.isEmpty()) -mXorExtents =
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source
vcl/inc/driverblocklist.hxx |2 vcl/skia/SkiaHelper.cxx | 103 +- vcl/source/helper/driverblocklist.cxx | 17 + 3 files changed, 109 insertions(+), 13 deletions(-) New commits: commit e3f5e49ac3aff3db9491b57e001579729f21bd56 Author: Luboš Luňák AuthorDate: Thu Apr 9 15:47:34 2020 +0200 Commit: Luboš Luňák CommitDate: Fri Apr 10 21:15:33 2020 +0200 dump info about Skia and Vulkan drivers to a log file Apparently it's hard for users to find out the actual Vulkan driver version (as compared to the marketing version), which is needed for blacklisting. And raster performance is noticeably better if Skia is compiled using Clang. So just dump the info to /skia.log (where on Windows the should be AppData\Roaming\LibreOffice\4\cache). Change-Id: Iafbc32637579b831275c60554f064479a326b917 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91980 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/driverblocklist.hxx b/vcl/inc/driverblocklist.hxx index c9b83b3f365e..8c1747be472f 100644 --- a/vcl/inc/driverblocklist.hxx +++ b/vcl/inc/driverblocklist.hxx @@ -36,6 +36,8 @@ const int DeviceVendorMax = VendorMicrosoft + 1; /// Returns vendor for the given vendor ID, or VendorAll if not known. VCL_DLLPUBLIC DeviceVendor GetVendorFromId(uint32_t id); +VCL_DLLPUBLIC OUStringLiteral GetVendorNameFromId(uint32_t id); + // The rest should be private (only for the unittest). struct InvalidFileException diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 356570706f59..f0d2559d376f 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -29,6 +29,8 @@ bool isVCLSkiaEnabled() { return false; } #include #include #include +#include +#include #include #include @@ -40,8 +42,6 @@ bool isVCLSkiaEnabled() { return false; } namespace SkiaHelper { -uint32_t vendorId = 0; - static OUString getBlacklistFile() { OUString url("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER); @@ -50,25 +50,98 @@ static OUString getBlacklistFile() return url + "/skia/skia_blacklist_vulkan.xml"; } +static uint32_t driverVersion = 0; +uint32_t vendorId = 0; + +static OUString versionAsString(uint32_t version) +{ +return OUString::number(version >> 22) + "." + OUString::number((version >> 12) & 0x3ff) + "." + + OUString::number(version & 0xfff); +} + +static OUStringLiteral vendorAsString(uint32_t vendor) +{ +return DriverBlocklist::GetVendorNameFromId(vendor); +} + +static OUString getCacheFolder() +{ +OUString url("${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER + "/" SAL_CONFIGFILE("bootstrap") ":UserInstallation}/cache/"); +rtl::Bootstrap::expandMacros(url); +osl::Directory::create(url); +return url; +} + +static void writeToLog(SvStream& stream, const char* key, const char* value) +{ +stream.WriteCharPtr(key); +stream.WriteCharPtr(": "); +stream.WriteCharPtr(value); +stream.WriteChar('\n'); +} + +static void writeToLog(SvStream& stream, const char* key, const OUString& value) +{ +writeToLog(stream, key, OUStringToOString(value, RTL_TEXTENCODING_UTF8).getStr()); +} + +// Note that this function also logs system information about Vulkan. static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props) { static const char* const types[] = { "other", "integrated", "discrete", "virtual", "cpu", "??" }; // VkPhysicalDeviceType -OUString driverVersion = OUString::number(props.driverVersion >> 22) + "." - + OUString::number((props.driverVersion >> 12) & 0x3ff) + "." - + OUString::number(props.driverVersion & 0xfff); +driverVersion = props.driverVersion; vendorId = props.vendorID; OUString vendorIdStr = "0x" + OUString::number(props.vendorID, 16); OUString deviceIdStr = "0x" + OUString::number(props.deviceID, 16); +OUString driverVersionString = versionAsString(driverVersion); +OUString apiVersion = versionAsString(props.apiVersion); +const char* deviceType = types[std::min(props.deviceType, SAL_N_ELEMENTS(types) - 1)]; + +CrashReporter::addKeyValue("VulkanVendor", vendorIdStr, CrashReporter::AddItem); +CrashReporter::addKeyValue("VulkanDevice", deviceIdStr, CrashReporter::AddItem); +CrashReporter::addKeyValue("VulkanAPI", apiVersion, CrashReporter::AddItem); +CrashReporter::addKeyValue("VulkanDriver", driverVersionString, CrashReporter::AddItem); +CrashReporter::addKeyValue("VulkanDeviceType", OUString::createFromAscii(deviceType), + CrashReporter::AddItem); +CrashReporter::addKeyValue("VulkanDeviceName", OUString::createFromAscii(props.deviceName), + CrashReporter::Write); + +SvFileStream logFile(getCacheFolder() + "/skia.log", StreamMode::WRITE); +writeToLog(logFile, "RenderMethod",
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |2 +- vcl/skia/gdiimpl.cxx | 33 ++--- 2 files changed, 31 insertions(+), 4 deletions(-) New commits: commit 738a563a0512bf7f28f15160f0be271bcef4f59e Author: Luboš Luňák AuthorDate: Tue Apr 7 16:48:07 2020 +0200 Commit: Luboš Luňák CommitDate: Wed Apr 8 11:56:03 2020 +0200 fix/improve Skia debug messages CopyBits() wasn't reporting 'src' if it was different from 'this'. Put the 'O' for offscreen after 'G' or 'R', so that it doesn't look like 0 being part of the size. Add pointer value to the Idle instances debug name. Change-Id: I001f4265696ff2b15e0273b3ae0c3857b39e2a0a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91835 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index a145e001850d..a99bb9ae4ce1 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -269,7 +269,7 @@ protected: { // O - offscreen, G - GPU-based, R - raster return stream << static_cast(graphics) << " " << Size(graphics->GetWidth(), graphics->GetHeight()) - << (graphics->isOffscreen() ? "O" : "") << (graphics->isGPU() ? "G" : "R"); + << (graphics->isGPU() ? "G" : "R") << (graphics->isOffscreen() ? "O" : ""); } SalGraphics& mParent; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 8b484ea124c7..b9d6d3575c85 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -156,15 +156,31 @@ bool checkInvalidSourceOrDestination(SalTwoRect const& rPosAry) class SkiaFlushIdle : public Idle { SkiaSalGraphicsImpl* mpGraphics; +#ifndef NDEBUG +char* debugname; +#endif public: explicit SkiaFlushIdle(SkiaSalGraphicsImpl* pGraphics) -: Idle("skia idle swap") +: Idle(get_debug_name(pGraphics)) , mpGraphics(pGraphics) { // We don't want to be swapping before we've painted. SetPriority(TaskPriority::POST_PAINT); } +#ifndef NDEBUG +virtual ~SkiaFlushIdle() { free(debugname); } +const char* get_debug_name(SkiaSalGraphicsImpl* pGraphics) +{ +// Idle keeps just a pointer, so we need to store the string +debugname = strdup( +OString("skia idle 0x" + OString::number(reinterpret_cast(pGraphics), 16)) +.getStr()); +return debugname; +} +#else +const char* get_debug_name(SkiaSalGraphicsImpl*) { return "skia idle"; } +#endif virtual void Invoke() override { @@ -895,13 +911,24 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& rPosAry, SalGraphics* pSrcG src = this; if (rPosAry.mnSrcWidth == rPosAry.mnDestWidth && rPosAry.mnSrcHeight == rPosAry.mnDestHeight) { -SAL_INFO("vcl.skia.trace", "copybits(" << this << "): copy area:" << rPosAry); +auto srcDebug = [&]() -> std::string { +if (src == this) +return "(self)"; +else +{ +std::ostringstream stream; +stream << "(" << src << ")"; +return stream.str(); +} +}; +SAL_INFO("vcl.skia.trace", + "copybits(" << this << "): " << srcDebug() << " copy area: " << rPosAry); ::copyArea(getDrawCanvas(), src->mSurface, rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnDestWidth, rPosAry.mnDestHeight); } else { -SAL_INFO("vcl.skia.trace", "copybits(" << this << "): (" << src << "):" << rPosAry); +SAL_INFO("vcl.skia.trace", "copybits(" << this << "): (" << src << "): " << rPosAry); // Do not use makeImageSnapshot(rect), as that one may make a needless data copy. sk_sp image = src->mSurface->makeImageSnapshot(); SkPaint paint; ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/utils.hxx |3 +++ vcl/skia/SkiaHelper.cxx | 29 + vcl/skia/gdiimpl.cxx|2 +- vcl/skia/salbmp.cxx | 22 ++ 4 files changed, 39 insertions(+), 17 deletions(-) New commits: commit fafc059a17416502722622ff52f38a3e4acd7998 Author: Luboš Luňák AuthorDate: Fri Apr 3 10:50:58 2020 +0200 Commit: Luboš Luňák CommitDate: Tue Apr 7 11:52:58 2020 +0200 avoid Skia bitmap->image pixel copying in raster mode SkImage::MakeFromBitmap() shares the pixels instead of copying, so in raster mode this saves some work. Change-Id: I89aa86c269c4b4f24e305dec390ae0f80e2537da Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91769 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index c1f35e812d00..16e5addd6909 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -43,6 +43,9 @@ inline sk_sp createSkSurface(const Size& size, SkColorType type = kN3 return createSkSurface(size.Width(), size.Height(), type); } +// Create SkImage, GPU-backed if possible. +VCL_DLLPUBLIC sk_sp createSkImage(const SkBitmap& bitmap); + // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index ed85cec00049..356570706f59 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -333,6 +333,35 @@ sk_sp createSkSurface(int width, int height, SkColorType type) return surface; } +sk_sp createSkImage(const SkBitmap& bitmap) +{ +SkiaZone zone; +assert(bitmap.colorType() == kN32_SkColorType || bitmap.colorType() == kAlpha_8_SkColorType); +switch (SkiaHelper::renderMethodToUse()) +{ +case SkiaHelper::RenderVulkan: +{ +if (GrContext* grContext = getSharedGrContext()) +{ +sk_sp surface = SkSurface::MakeRenderTarget( +grContext, SkBudgeted::kNo, bitmap.info().makeAlphaType(kPremul_SkAlphaType)); +assert(surface); +SkPaint paint; +paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha +surface->getCanvas()->drawBitmap(bitmap, 0, 0, ); +return surface->makeImageSnapshot(); +} +break; +} +default: +break; +} +// Create raster image as a fallback. +sk_sp image = SkImage::MakeFromBitmap(bitmap); +assert(image); +return image; +} + void cleanup() { delete sharedGrContext; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index e68d620ac894..e4f064589b21 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -944,7 +944,7 @@ bool SkiaSalGraphicsImpl::blendAlphaBitmap(const SalTwoRect& rPosAry, // This was originally implemented for the OpenGL drawing method and it is poorly documented. // The source and mask bitmaps are the usual data and alpha bitmaps, and 'alpha' // is the "alpha" layer of the VirtualDevice (the alpha in VirtualDevice is also stored -// as a separate bitmap). Now I understand it correctly these two alpha masks first need +// as a separate bitmap). Now if I understand it correctly these two alpha masks first need // to be combined into the actual alpha mask to be used. The formula for TYPE_BLEND // in opengl's combinedTextureFragmentShader.glsl is // "result_alpha = 1.0 - (1.0 - floor(alpha)) * mask". diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index c000b391eaa2..7c3d183a54d9 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -460,12 +460,9 @@ const sk_sp& SkiaSalBitmap::GetSkImage() const return mImage; } SkiaZone zone; -sk_sp surface = SkiaHelper::createSkSurface(mSize); -assert(surface); -SkPaint paint; -paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha -surface->getCanvas()->drawBitmap(GetAsSkBitmap(), 0, 0, ); -const_cast&>(mImage) = surface->makeImageSnapshot(); +sk_sp image = SkiaHelper::createSkImage(GetAsSkBitmap()); +assert(image); +const_cast&>(mImage) = image; SAL_INFO("vcl.skia.trace", "getskimage(" << this << ")"); return mImage; } @@ -528,16 +525,9 @@ const sk_sp& SkiaSalBitmap::GetAlphaSkImage() const delete convertedBitmap; alphaBitmap.setImmutable(); } -sk_sp surface = SkiaHelper::createSkSurface(mSize, kAlpha_8_SkColorType); -assert(surface); -// https://bugs.chromium.org/p/skia/issues/detail?id=9692 -// Raster kAlpha_8_SkColorType surfaces need empty contents for SkBlendMode::kSrc. -if (!surface->getCanvas()->getGrContext()) -surface->getCanvas()->clear(SkColorSetARGB(0x00, 0x00, 0x00, 0x00)); -SkPaint paint; -paint.setBlendMode(SkBlendMode::kSrc); // set as is, including
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source vcl/unx
vcl/inc/skia/utils.hxx |2 - vcl/inc/skia/x11/gdiimpl.hxx |6 ++-- vcl/skia/SkiaHelper.cxx| 37 +++ vcl/skia/win/gdiimpl.cxx |2 - vcl/skia/x11/gdiimpl.cxx | 49 + vcl/source/opengl/OpenGLHelper.cxx |5 +++ vcl/unx/generic/app/saldisp.cxx|4 ++- 7 files changed, 83 insertions(+), 22 deletions(-) New commits: commit b275cce0878ddb7a56361c8d626c76ad57ad7d72 Author: Luboš Luňák AuthorDate: Wed Mar 25 12:27:50 2020 +0100 Commit: Luboš Luňák CommitDate: Wed Mar 25 19:15:26 2020 +0100 make sure only VCL-Skia or VCL-OpenGL is enabled (tdf#131543) The bug is most likely caused by some code checking only the OpenGL setting and doing something, even though the Skia setting takes precedence. So make sure VCL OpenGL is considered disabled if Skia is enabled. Since isVCLOpenGLEnabled() is called right before setting up the X11 visual, which is normally needed by isVCLSkiaEnabled() to get Vulkan info to check blacklisting, this also requires using a temporary Skia Vulkan context using the default X11 visual to avoid the dependency loop. Change-Id: I2d9d9e81ab4ed5021b5f42e3c272dcd10fd32cce Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91044 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 0a93b3b16863..c1f35e812d00 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -46,7 +46,7 @@ inline sk_sp createSkSurface(const Size& size, SkColorType type = kN3 // Must be called in any VCL backend before any Skia functionality is used. // If not set, Skia will be disabled. VCL_DLLPUBLIC void -prepareSkia(std::unique_ptr (*createVulkanWindowContext)()); +prepareSkia(std::unique_ptr (*createVulkanWindowContext)(bool)); #ifdef DBG_UTIL void prefillSurface(sk_sp& surface); diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx index acfe9f7ce192..0f86f0907dcd 100644 --- a/vcl/inc/skia/x11/gdiimpl.hxx +++ b/vcl/inc/skia/x11/gdiimpl.hxx @@ -38,9 +38,9 @@ private: virtual void performFlush() override; virtual bool avoidRecreateByResize() const override; static std::unique_ptr -createWindowContext(Display* display, Drawable drawable, const SalVisual* visual, int width, -int height, SkiaHelper::RenderMethod renderMethod); -friend std::unique_ptr createVulkanWindowContext(); +createWindowContext(Display* display, Drawable drawable, const XVisualInfo* visual, int width, +int height, SkiaHelper::RenderMethod renderMethod, bool temporary); +friend std::unique_ptr createVulkanWindowContext(bool); }; #endif // INCLUDED_VCL_INC_SKIA_X11_GDIIMPL_HXX diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 4b21e6740603..ff2a2a588741 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -69,6 +69,8 @@ static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props) deviceIdStr); } +static sk_app::VulkanWindowContext::SharedGrContext getTemporaryGrContext(); + static void checkDeviceBlacklisted(bool blockDisable = false) { static bool done = false; @@ -80,9 +82,23 @@ static void checkDeviceBlacklisted(bool blockDisable = false) { case RenderVulkan: { -GrContext* grContext = SkiaHelper::getSharedGrContext(); +// First try if a GrContext already exists. +sk_app::VulkanWindowContext::SharedGrContext grContext += sk_app::VulkanWindowContext::getSharedGrContext(); +if (!grContext.getGrContext()) +{ +// This function is called from isVclSkiaEnabled(), which +// may be called when deciding which X11 visual to use, +// and that visual is normally needed when creating +// Skia's VulkanWindowContext, which is needed for the GrContext. +// Avoid the loop by creating a temporary GrContext +// that will use the default X11 visual (that shouldn't matter +// for just finding out information about Vulkan) and destroying +// the temporary context will clean up again. +grContext = getTemporaryGrContext(); +} bool blacklisted = true; // assume the worst -if (grContext) // Vulkan was initialized properly +if (grContext.getGrContext()) // Vulkan was initialized properly { blacklisted = isVulkanBlacklisted( sk_app::VulkanWindowContext::getPhysDeviceProperties()); @@ -230,8 +246,8 @@ void disableRenderMethod(RenderMethod
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx| 10 -- vcl/skia/gdiimpl.cxx| 13 - vcl/skia/win/gdiimpl.cxx|3 ++- vcl/skia/x11/textrender.cxx |3 ++- 4 files changed, 20 insertions(+), 9 deletions(-) New commits: commit 11847cc5fd22c9b98fd9c2cf1389eee6e404a4fb Author: Luboš Luňák AuthorDate: Tue Mar 17 11:53:26 2020 +0100 Commit: Luboš Luňák CommitDate: Wed Mar 18 10:48:35 2020 +0100 fix glyph rotation for Skia text rendering on Windows The makes the chart descriptions in tdf#114209 and e.g. Japanese from the document from tdf#126169 be rotated correctly, Change-Id: I09a739fea7629000f3f49e417531bc47ba99c68f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90610 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index a7de1cfc4872..630b7a138844 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -203,14 +203,20 @@ public: void drawBitmap(const SalTwoRect& rPosAry, const SkBitmap& aBitmap, SkBlendMode eBlendMode = SkBlendMode::kSrcOver); -void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font); +enum class GlyphOrientation +{ +Apply, +Ignore +}; +void drawGenericLayout(const GenericSalLayout& layout, Color textColor, const SkFont& font, + GlyphOrientation glyphOrientation); protected: // To be called before any drawing. void preDraw(); // To be called after any drawing. void postDraw(); -// The canvas to drawn to. Will be diverted to a temporary for Xor mode. +// The canvas to draw to. Will be diverted to a temporary for Xor mode. SkCanvas* getDrawCanvas() { return mXorMode ? getXorCanvas() : mSurface->getCanvas(); } virtual void createSurface(); diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 3bf0724de354..8ce3bf838872 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -1265,7 +1265,7 @@ static double toCos(int degree10th) { return SkScalarCos(toRadian(degree10th)); static double toSin(int degree10th) { return SkScalarSin(toRadian(degree10th)); } void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Color textColor, -const SkFont& font) +const SkFont& font, GlyphOrientation glyphOrientation) { std::vector glyphIds; std::vector glyphForms; @@ -1274,13 +1274,16 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const GenericSalLayout& layout, Colo Point aPos; const GlyphItem* pGlyph; int nStart = 0; -double orientationAngle = layout.GetOrientation(); // 10th of degree while (layout.GetNextGlyph(, aPos, nStart)) { glyphIds.push_back(pGlyph->glyphId()); -double angle = orientationAngle; -if (pGlyph->IsVertical()) -angle += 900; // 90 degree +int angle = 0; // 10th of degree +if (glyphOrientation == GlyphOrientation::Apply) +{ +angle = layout.GetOrientation(); +if (pGlyph->IsVertical()) +angle += 900; // 90 degree +} SkRSXform form = SkRSXform::Make(toCos(angle), toSin(angle), aPos.X(), aPos.Y()); glyphForms.emplace_back(std::move(form)); } diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index b7014ed33b48..0708c8ea633f 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -155,7 +155,8 @@ bool WinSkiaSalGraphicsImpl::DrawTextLayout(const GenericSalLayout& rLayout) SkiaSalGraphicsImpl* impl = static_cast(mWinParent.GetImpl()); COLORREF color = ::GetTextColor(mWinParent.getHDC()); Color salColor(GetRValue(color), GetGValue(color), GetBValue(color)); -impl->drawGenericLayout(rLayout, salColor, font); +// The font already is set up to have glyphs rotated as needed. +impl->drawGenericLayout(rLayout, salColor, font, SkiaSalGraphicsImpl::GlyphOrientation::Ignore); return true; } diff --git a/vcl/skia/x11/textrender.cxx b/vcl/skia/x11/textrender.cxx index 02911fcf5154..a980523476b3 100644 --- a/vcl/skia/x11/textrender.cxx +++ b/vcl/skia/x11/textrender.cxx @@ -59,7 +59,8 @@ void SkiaTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const SalGr assert(dynamic_cast(rGraphics.GetImpl())); SkiaSalGraphicsImpl* impl = static_cast(rGraphics.GetImpl()); -impl->drawGenericLayout(rLayout, mnTextColor, font); +impl->drawGenericLayout(rLayout, mnTextColor, font, +SkiaSalGraphicsImpl::GlyphOrientation::Apply); } void SkiaTextRender::ClearDevFontCache() { fontManager.reset(); } ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/unx vcl/win
vcl/inc/skia/utils.hxx |5 +++-- vcl/inc/skia/win/gdiimpl.hxx|2 ++ vcl/inc/skia/x11/gdiimpl.hxx|2 ++ vcl/skia/SkiaHelper.cxx | 25 ++--- vcl/skia/win/gdiimpl.cxx|8 ++-- vcl/skia/x11/gdiimpl.cxx|9 + vcl/unx/generic/app/salinst.cxx |6 ++ vcl/win/app/salinst.cxx |3 +++ 8 files changed, 41 insertions(+), 19 deletions(-) New commits: commit a3d3e076def075f0a5bced48d89ca0d989a2467c Author: Luboš Luňák AuthorDate: Thu Mar 12 12:04:08 2020 +0100 Commit: Luboš Luňák CommitDate: Thu Mar 12 13:04:03 2020 +0100 rework Skia setup Calls to SkiaHelper::isVCLSkiaEnabled() may be done from many places, even if LO uses a VCL plugin that doesn't use Skia, which leads to the Skia code not being prepared properly (and crashing/asserting). So make the SalInstance of those relevant VCL plugins call a setup function that is required for Skia actually getting enabled. Avoids crashes/asserts in the About dialog if the Skia UI checkbox is enabled but e.g. the KF5 VCL plugin is actually used. Change-Id: Ib56a5f32e88bd130a4c564031313f85e99898ba7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90376 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index cd6732a57a44..0a93b3b16863 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -43,9 +43,10 @@ inline sk_sp createSkSurface(const Size& size, SkColorType type = kN3 return createSkSurface(size.Width(), size.Height(), type); } -/// This function is in the X11/Win backend libs, but needs to be used in SkiaHelper in the vcl lib. +// Must be called in any VCL backend before any Skia functionality is used. +// If not set, Skia will be disabled. VCL_DLLPUBLIC void -setCreateVulkanWindowContext(std::unique_ptr (*function)()); +prepareSkia(std::unique_ptr (*createVulkanWindowContext)()); #ifdef DBG_UTIL void prefillSurface(sk_sp& surface); diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 5e8aee2e4523..676e743151e7 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -81,6 +81,8 @@ public: virtual void DeferredTextDraw(const CompatibleDC::Texture* pTexture, Color nMaskColor, const SalTwoRect& rPosAry) override; +static void prepareSkia(); + protected: virtual void createWindowContext() override; virtual void performFlush() override; diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx index 8cedf23d3e1b..acfe9f7ce192 100644 --- a/vcl/inc/skia/x11/gdiimpl.hxx +++ b/vcl/inc/skia/x11/gdiimpl.hxx @@ -31,6 +31,8 @@ public: virtual void DeInit() override; virtual void freeResources() override; +static void prepareSkia(); + private: virtual void createWindowContext() override; virtual void performFlush() override; diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index 50402cccf47c..4b21e6740603 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -102,7 +102,16 @@ static void checkDeviceBlacklisted(bool blockDisable = false) } } -static bool supportsVCLSkia() { return !getenv("SAL_DISABLESKIA"); } +static bool skiaSupportedByBackend = false; +static bool supportsVCLSkia() +{ +if (!skiaSupportedByBackend) +{ +SAL_INFO("vcl.skia", "Skia not supported by VCL backend, disabling"); +return false; +} +return getenv("SAL_DISABLESKIA") == nullptr; +} bool isVCLSkiaEnabled() { @@ -222,7 +231,7 @@ void disableRenderMethod(RenderMethod method) static sk_app::VulkanWindowContext::SharedGrContext* sharedGrContext; static std::unique_ptr (*createVulkanWindowContextFunction)() = nullptr; -void setCreateVulkanWindowContext(std::unique_ptr (*function)()) +static void setCreateVulkanWindowContext(std::unique_ptr (*function)()) { createVulkanWindowContextFunction = function; } @@ -248,7 +257,8 @@ GrContext* getSharedGrContext() if (done) return nullptr; done = true; -assert(createVulkanWindowContextFunction); +if (createVulkanWindowContextFunction == nullptr) +return nullptr; // not initialized properly (e.g. used from a VCL backend with no Skia support) std::unique_ptr tmpContext = createVulkanWindowContextFunction(); // Set up using the shared context created by the call above, if successful. context = sk_app::VulkanWindowContext::getSharedGrContext(); @@ -302,6 +312,15 @@ void cleanup() sharedGrContext = nullptr; } +// Skia should not be used from VCL backends that do not actually support it, as there will be setup missing. +// The code here (that is in the vcl lib) needs a function for creating Vulkan context that is +// usually available only in the backend libs. +void prepareSkia(std::unique_ptr
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/source
vcl/inc/driverblocklist.hxx | 23 +-- vcl/inc/skia/utils.hxx|8 vcl/skia/SkiaHelper.cxx | 18 -- vcl/skia/gdiimpl.cxx |7 +++ vcl/source/helper/driverblocklist.cxx | 17 + 5 files changed, 57 insertions(+), 16 deletions(-) New commits: commit 1127a8dea95488c7c9add42244a79bb20e7c6d95 Author: Luboš Luňák AuthorDate: Tue Feb 18 15:55:46 2020 +0100 Commit: Luboš Luňák CommitDate: Wed Feb 19 12:43:42 2020 +0100 work around a driver/card(?) problem with Skia and AA-ed polygons See description in SkiaSalGraphicsImpl::drawPolyPolygon(). Change-Id: I4b2626e26cac6d145b417426fc2575845386db57 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88941 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/driverblocklist.hxx b/vcl/inc/driverblocklist.hxx index 6a0180386a9a..c9b83b3f365e 100644 --- a/vcl/inc/driverblocklist.hxx +++ b/vcl/inc/driverblocklist.hxx @@ -23,6 +23,19 @@ VCL_DLLPUBLIC bool IsDeviceBlocked(const OUString& blocklistURL, const OUString& VCL_DLLPUBLIC int32_t GetWindowsVersion(); #endif +enum DeviceVendor +{ +VendorAll, +VendorIntel, +VendorNVIDIA, +VendorAMD, +VendorMicrosoft, +}; +const int DeviceVendorMax = VendorMicrosoft + 1; + +/// Returns vendor for the given vendor ID, or VendorAll if not known. +VCL_DLLPUBLIC DeviceVendor GetVendorFromId(uint32_t id); + // The rest should be private (only for the unittest). struct InvalidFileException @@ -59,16 +72,6 @@ enum VersionComparisonOp DRIVER_COMPARISON_IGNORED }; -enum DeviceVendor -{ -VendorAll, -VendorIntel, -VendorNVIDIA, -VendorAMD, -VendorMicrosoft, -}; -const int DeviceVendorMax = VendorMicrosoft + 1; - struct DriverInfo { DriverInfo(OperatingSystem os, const OUString& vendor, VersionComparisonOp op, diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index af81ca99f2dd..cd6732a57a44 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -23,6 +23,7 @@ #include #include +#include #include @@ -53,6 +54,13 @@ VCL_DLLPUBLIC void dump(const sk_sp& image, const char* file); VCL_DLLPUBLIC void dump(const sk_sp& surface, const char* file); #endif +extern uint32_t vendorId; + +inline DriverBlocklist::DeviceVendor getVendor() +{ +return DriverBlocklist::GetVendorFromId(vendorId); +} + } // namespace #endif // INCLUDED_VCL_INC_SKIA_UTILS_H diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index c0972ab2e0a0..50402cccf47c 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -38,6 +38,8 @@ bool isVCLSkiaEnabled() { return false; } namespace SkiaHelper { +uint32_t vendorId = 0; + static OUString getBlacklistFile() { OUString url("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER); @@ -53,19 +55,21 @@ static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props) OUString driverVersion = OUString::number(props.driverVersion >> 22) + "." + OUString::number((props.driverVersion >> 12) & 0x3ff) + "." + OUString::number(props.driverVersion & 0xfff); -OUString vendorId = "0x" + OUString::number(props.vendorID, 16); -OUString deviceId = "0x" + OUString::number(props.deviceID, 16); +vendorId = props.vendorID; +OUString vendorIdStr = "0x" + OUString::number(props.vendorID, 16); +OUString deviceIdStr = "0x" + OUString::number(props.deviceID, 16); SAL_INFO("vcl.skia", "Vulkan API version: " << (props.apiVersion >> 22) << "." << ((props.apiVersion >> 12) & 0x3ff) << "." << (props.apiVersion & 0xfff) << ", driver version: " << driverVersion - << ", vendor: " << vendorId << ", device: " << deviceId << ", type: " + << ", vendor: " << vendorIdStr << ", device: " << deviceIdStr << ", type: " << types[std::min(props.deviceType, SAL_N_ELEMENTS(types) - 1)] << ", name: " << props.deviceName); -return DriverBlocklist::IsDeviceBlocked(getBlacklistFile(), driverVersion, vendorId, deviceId); +return DriverBlocklist::IsDeviceBlocked(getBlacklistFile(), driverVersion, vendorIdStr, +deviceIdStr); } -static void checkDeviceBlacklisted() +static void checkDeviceBlacklisted(bool blockDisable = false) { static bool done = false; if (!done) @@ -86,7 +90,7 @@ static void checkDeviceBlacklisted() } else SAL_INFO("vcl.skia", "Vulkan could not be initialized"); -if (blacklisted) +if (blacklisted && !blockDisable) disableRenderMethod(RenderVulkan); break; } @@ -135,6 +139,8 @@ bool isVCLSkiaEnabled() if (bForceSkia) {
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |3 + vcl/skia/win/gdiimpl.cxx | 73 +-- 2 files changed, 59 insertions(+), 17 deletions(-) New commits: commit 7f56bbe3a09265a62792dc0624fdb44f8c176172 Author: Luboš Luňák AuthorDate: Thu Jan 30 13:04:23 2020 +0100 Commit: Luboš Luňák CommitDate: Thu Jan 30 15:14:01 2020 +0100 again finally(?) fix Skia Windows widget drawing (tdf#130051) I was correct to see in 202146901b6fbab92 that the black bitmap was in premultiplied alpha, but what I missed what that some controls keep the alpha set at zero (and only some work properly). So go back to the algorithm of synthetizing alpha from the red channel, compute it properly (before it was using alpha channel by mistake), and treat the data properly as premultiplied. This hopefully finally makes all Windows control widgets work. Change-Id: If2716eb8ecf623fcc57ee1db5904edfaee679aa9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87734 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 69ee6ba475af..5e8aee2e4523 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -32,8 +32,9 @@ public: virtual bool wantsTextColorWhite() const override { return true; } -sk_sp getAsImage(bool fromPremultiplied = false) const; +sk_sp getAsImage() const; sk_sp getAsMaskImage() const; +sk_sp getAsImageDiff(const SkiaCompatibleDC& white) const; struct Texture; struct PackedTexture; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index e9889415cc5e..aec2f22e5bb3 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -80,21 +80,15 @@ bool WinSkiaSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const& return true; } -bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& /*rWhite*/, - CompatibleDC& rBlack, int nX, int nY, +bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, + int nX, int nY, ControlCacheKey& aControlCacheKey) { -// assert(dynamic_cast()); +assert(dynamic_cast()); assert(dynamic_cast()); -// Native widgets are drawn twice on black/white background, which comes from an OpenGL -// commit c6b66646870cb2bffaa73565affcf80bf74e0b5c, where it is used to synthetize alpha. -// But getting the Windows theming API to draw into an empty area (fully transparent) -// actually results in the widget being in the premultiplied alpha format (and I have no -// idea why the OpenGL code uses the weird undocumented pixel diffing it does, probably -// the author did not realize this). Simply use the black variant as premultiplied data. -// TODO Remove the white variant completely once OpenGL code is removed. -sk_sp image = static_cast(rBlack).getAsImage(true); +sk_sp image = static_cast(rBlack).getAsImageDiff( +static_cast(rWhite)); preDraw(); mSurface->getCanvas()->drawImage(image, nX, nY); postDraw(); @@ -204,13 +198,12 @@ sk_sp SkiaCompatibleDC::getAsMaskImage() const return surface->makeImageSnapshot(); } -sk_sp SkiaCompatibleDC::getAsImage(bool fromPremultiplied) const +sk_sp SkiaCompatibleDC::getAsImage() const { SkBitmap tmpBitmap; -if (!tmpBitmap.installPixels( -SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, kBGRA__SkColorType, - fromPremultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType), -mpData, maRects.mnSrcWidth * 4)) +if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, + kBGRA__SkColorType, kUnpremul_SkAlphaType), + mpData, maRects.mnSrcWidth * 4)) abort(); tmpBitmap.setImmutable(); sk_sp surface = SkiaHelper::createSkSurface(tmpBitmap.width(), tmpBitmap.height()); @@ -230,6 +223,54 @@ sk_sp SkiaCompatibleDC::getAsImage(bool fromPremultiplied) const return surface->makeImageSnapshot(); } +sk_sp SkiaCompatibleDC::getAsImageDiff(const SkiaCompatibleDC& white) const +{ +assert(maRects.mnSrcWidth == white.maRects.mnSrcWidth + || maRects.mnSrcHeight == white.maRects.mnSrcHeight); +SkBitmap tmpBitmap; +if (!tmpBitmap.tryAllocPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, +kBGRA__SkColorType, kPremul_SkAlphaType), + maRects.mnSrcWidth * 4)) +abort(); +// Native widgets are drawn twice on black/white background to synthetize alpha +//
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/gdiimpl.hxx |1 + vcl/skia/gdiimpl.cxx | 16 vcl/skia/win/gdiimpl.cxx |1 + vcl/skia/x11/gdiimpl.cxx |1 + 4 files changed, 19 insertions(+) New commits: commit ad3580df085b3a3d66eb73cae997ea5ca178ccc1 Author: Luboš Luňák AuthorDate: Mon Jan 20 12:10:00 2020 +0100 Commit: Luboš Luňák CommitDate: Mon Jan 20 16:02:46 2020 +0100 workaround for Skia+Cairo text drawing exhausting GPU memory See the description in SkiaSalGraphicsImpl::postDraw(). Change-Id: Ia6b38741fcfe3f6b5f0a21051886c55ed5324c61 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/87062 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx index f1ddc20bdf01..10b6371b4dcd 100644 --- a/vcl/inc/skia/gdiimpl.hxx +++ b/vcl/inc/skia/gdiimpl.hxx @@ -277,6 +277,7 @@ protected: std::unique_ptr mXorCanvas; SkRect mXorExtents; // the area that needs updating for the xor operation (or empty for all) std::unique_ptr mFlush; +int mPendingPixelsToFlush; }; #endif diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index a88f78823382..66086c9af82b 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -177,6 +177,7 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& rParent, SalGeometryProvid , mFillColor(SALCOLOR_NONE) , mXorMode(false) , mFlush(new SkiaFlushIdle(this)) +, mPendingPixelsToFlush(0) { } @@ -375,6 +376,20 @@ void SkiaSalGraphicsImpl::postDraw() else if (!mFlush->IsActive()) mFlush->Start(); } +// Skia (at least when using Vulkan) queues drawing commands and executes them only later. +// But some operations may queue way too much data to draw, leading to Vulkan getting out of memory, +// which at least on Linux leads to driver problems affecting even the whole X11 session. +// One such problematic operation may be drawBitmap(SkBitmap), which is used by SkiaX11CairoTextRender +// to draw text, which is internally done by creating the SkBitmap from cairo surface data. Apparently +// the cairo surface's size matches the size of the destination (window), which may be large, +// and each text drawing allocates a new surface (and thus SkBitmap). So we may end up queueing up +// millions of pixels of bitmap data. So force a flush if such a possibly problematic operation +// has queued up too much data. +if (mPendingPixelsToFlush > 10 * 1024 * 1024) +{ +mSurface->flush(); +mPendingPixelsToFlush = 0; +} } // VCL can sometimes resize us without telling us, update the surface if needed. @@ -1125,6 +1140,7 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SkBitmap& getDrawCanvas()->drawBitmapRect(aBitmap, aSourceRect, aDestinationRect, ); if (mXorMode) // limit xor area update mXorExtents = aDestinationRect; +mPendingPixelsToFlush += aBitmap.width() * aBitmap.height(); postDraw(); } diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index deace0072630..e9889415cc5e 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -57,6 +57,7 @@ void WinSkiaSalGraphicsImpl::freeResources() {} void WinSkiaSalGraphicsImpl::performFlush() { +mPendingPixelsToFlush = 0; if (mWindowContext) mWindowContext->swapBuffers(); } diff --git a/vcl/skia/x11/gdiimpl.cxx b/vcl/skia/x11/gdiimpl.cxx index 04e2586e7f7a..a139a336c7b7 100644 --- a/vcl/skia/x11/gdiimpl.cxx +++ b/vcl/skia/x11/gdiimpl.cxx @@ -107,6 +107,7 @@ void X11SkiaSalGraphicsImpl::freeResources() {} void X11SkiaSalGraphicsImpl::performFlush() { +mPendingPixelsToFlush = 0; // TODO XPutImage() is somewhat inefficient, XShmPutImage() should be preferred. mWindowContext->swapBuffers(); } ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |4 vcl/skia/SkiaHelper.cxx |1 - vcl/skia/gdiimpl.cxx |3 +-- vcl/skia/salbmp.cxx |4 ++-- vcl/skia/win/gdiimpl.cxx | 18 -- 5 files changed, 3 insertions(+), 27 deletions(-) New commits: commit 552ec2a3e53c5267ee04dca2249fd30983c6a395 Author: Luboš Luňák AuthorDate: Mon Jan 20 15:30:13 2020 +0100 Commit: Luboš Luňák CommitDate: Mon Jan 20 15:31:27 2020 +0100 remove outdated Skia TODO comments Change-Id: Ia9925a703a4adca41e056916d285c21e5de4898f diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 7f11e4da628c..69ee6ba475af 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -63,11 +63,7 @@ private: public: WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, SalGeometryProvider* mpProvider); -#if 0 // TODO -virtual void Init() override; -#endif virtual void DeInit() override; - virtual void freeResources() override; virtual bool UseRenderNativeControl() const override { return true; } diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx index eff77ae5340f..4ea63f85db8a 100644 --- a/vcl/skia/SkiaHelper.cxx +++ b/vcl/skia/SkiaHelper.cxx @@ -74,7 +74,6 @@ bool isVCLSkiaEnabled() bool bRet = false; bool bSupportsVCLSkia = supportsVCLSkia(); -// TODO SKIA always call supportsVCLOpenGL to de-zombie the glxtest child process on X11 if (bForceSkia) { bRet = true; diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index 1c5474301034..a88f78823382 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -290,7 +290,6 @@ void SkiaSalGraphicsImpl::destroySurface() // if this fails, something forgot to use SkAutoCanvasRestore assert(mSurface->getCanvas()->getTotalMatrix().isIdentity()); } -// TODO Is this still needed? // If we use e.g. Vulkan, we must destroy the surface before the context, // otherwise destroying the surface will reference the context. This is // handled by calling destroySurface() before destroying the context. @@ -957,7 +956,7 @@ Color SkiaSalGraphicsImpl::getPixel(long nX, long nY) checkSurface(); SAL_INFO("vcl.skia", "getpixel(" << this << "): " << Point(nX, nY)); mSurface->getCanvas()->flush(); -// TODO this is presumably slow, and possibly won't work with GPU surfaces +// This is presumably slow, but getPixel() should be generally used only by unit tests. SkBitmap bitmap; if (!bitmap.tryAllocN32Pixels(GetWidth(), GetHeight())) abort(); diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 568996723011..925e27f6d9a8 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -299,7 +299,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) { -if (nMode == BitmapAccessMode::Write) // TODO something more? +if (nMode == BitmapAccessMode::Write) { #ifdef DBG_UTIL assert(mWriteAccessCount > 0); @@ -599,7 +599,7 @@ void SkiaSalBitmap::EnsureBitmapData() void SkiaSalBitmap::EnsureBitmapUniqueData() { EnsureBitmapData(); -// TODO threads? +// TODO thread safety? if (mBitmap.pixelRef() && !mBitmap.pixelRef()->unique()) { // SkBitmap copies share pixels, so make a deep copy. diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index ebaa81aa986a..deace0072630 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -25,24 +25,6 @@ WinSkiaSalGraphicsImpl::WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, { } -#if 0 // TODO -void WinSkiaSalGraphicsImpl::Init() -{ -if (!IsOffscreen() && mpContext.is() && mpContext->isInitialized()) -{ -const GLWinWindow& rGLWindow = static_cast(mpContext->getOpenGLWindow()); -if (rGLWindow.hWnd != mrWinParent.mhWnd || rGLWindow.hDC == mrWinParent.mhLocalDC) -{ -// This can legitimately happen, SalFrame keeps 2x -// SalGraphics which share the same hWnd and hDC. -// The shape 'Area' dialog does reparenting to trigger this. -SAL_WARN("vcl.opengl", "Unusual: Windows handle / DC changed without DeInit"); -DeInit(); -} -} -} -#endif - void WinSkiaSalGraphicsImpl::createWindowContext() { // When created, Init() gets called with size (0,0), which is invalid size ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia
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 AuthorDate: Wed Jan 15 11:26:49 2020 +0100 Commit: Luboš Luňák 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 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 mXorCanvas; +SkRect mXorExtents; // the area that needs updating for the xor operation (or empty for all) std::unique_ptr 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, ); +canvas.drawImageRect(mSurface->makeImageSnapshot(), mXorExtents, mXorExtents, ); // 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(surfaceBitmap.getAddr(0, y)); -const uint8_t* xordata = static_cast(mXorBitmap.getAddr(0, y)); -for (int x = 0; x < surfaceBitmap.width(); ++x) +uint8_t* data = static_cast(surfaceBitmap.getAddr(mXorExtents.x(), y)); +const uint8_t* xordata = static_cast(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, ); +mSurface->getCanvas()->drawBitmapRect(surfaceBitmap, mXorExtents, mXorExtents, ); 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
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |3 - vcl/skia/win/gdiimpl.cxx | 69 +-- 2 files changed, 17 insertions(+), 55 deletions(-) New commits: commit 202146901b6fbab923042d30f62b19992bf5179b Author: Luboš Luňák AuthorDate: Fri Jan 10 19:05:20 2020 +0100 Commit: Luboš Luňák CommitDate: Sun Jan 12 16:48:28 2020 +0100 finally fix Skia Windows widget drawing (tdf#129416) So much time wasted just because c6b66646870cb2bf couldn't be bothered spending a minute or two explaining the weird black/white alpha hack that it turns out is not even necessary as the resulting image is incidentally in the premultiplied alpha format. Change-Id: I810458a670b2c0c8047118f55f58bf588a37f9f1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86569 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index dabd56ad04a3..daf41e8e06d0 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -31,9 +31,8 @@ public: virtual bool wantsTextColorWhite() const override { return true; } -sk_sp getAsImage() const; +sk_sp getAsImage(bool fromPremultiplied = false) const; sk_sp getAsMaskImage() const; -sk_sp getAsImageDiff(const SkiaCompatibleDC& other) const; struct Texture; }; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index b3f538bcea5b..437e7c7d1e3f 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -97,15 +97,21 @@ bool WinSkiaSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const& return true; } -bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack, - int nX, int nY, +bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& /*rWhite*/, + CompatibleDC& rBlack, int nX, int nY, ControlCacheKey& aControlCacheKey) { -assert(dynamic_cast()); +// assert(dynamic_cast()); assert(dynamic_cast()); -sk_sp image = static_cast(rWhite).getAsImageDiff( -static_cast(rBlack)); +// Native widgets are drawn twice on black/white background, which comes from an OpenGL +// commit c6b66646870cb2bffaa73565affcf80bf74e0b5c, where it is used to synthetize alpha. +// But getting the Windows theming API to draw into an empty area (fully transparent) +// actually results in the widget being in the premultiplied alpha format (and I have no +// idea why the OpenGL code uses the weird undocumented pixel diffing it does, probably +// the author did not realize this). Simply use the black variant as premultiplied data. +// TODO Remove the white variant completely once OpenGL code is removed. +sk_sp image = static_cast(rBlack).getAsImage(true); preDraw(); mSurface->getCanvas()->drawImage(image, nX, nY); postDraw(); @@ -207,12 +213,13 @@ sk_sp SkiaCompatibleDC::getAsMaskImage() const return surface->makeImageSnapshot(); } -sk_sp SkiaCompatibleDC::getAsImage() const +sk_sp SkiaCompatibleDC::getAsImage(bool fromPremultiplied) const { SkBitmap tmpBitmap; -if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, - kBGRA__SkColorType, kUnpremul_SkAlphaType), - mpData, maRects.mnSrcWidth * 4)) +if (!tmpBitmap.installPixels( +SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, kBGRA__SkColorType, + fromPremultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType), +mpData, maRects.mnSrcWidth * 4)) abort(); tmpBitmap.setImmutable(); sk_sp surface = SkiaHelper::createSkSurface(tmpBitmap.width(), tmpBitmap.height()); @@ -232,50 +239,6 @@ sk_sp SkiaCompatibleDC::getAsImage() const return surface->makeImageSnapshot(); } -sk_sp SkiaCompatibleDC::getAsImageDiff(const SkiaCompatibleDC& other) const -{ -assert(maRects.mnSrcWidth == other.maRects.mnSrcWidth - || maRects.mnSrcHeight == other.maRects.mnSrcHeight); -SkBitmap tmpBitmap; -if (!tmpBitmap.tryAllocPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, -kBGRA__SkColorType, kUnpremul_SkAlphaType), - maRects.mnSrcWidth * 4)) -abort(); -// Native widgets are drawn twice on black/white background to synthetize alpha -// (commit c6b66646870cb2bffaa73565affcf80bf74e0b5c). -// Alpha is computed as "alpha = 1.0 - abs(black.red - white.red)". -// TODO I doubt this can be done using Skia, so do it manually here. Fortunately -// the bitmaps should be fairly small
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |4 +++- vcl/skia/salbmp.cxx | 12 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) New commits: commit 364cdd314fb4d6168990a469bfb10fc935dfc649 Author: Luboš Luňák AuthorDate: Fri Dec 20 11:40:59 2019 +0100 Commit: Luboš Luňák CommitDate: Mon Jan 6 11:15:08 2020 +0100 use boost::shared_ptr for allocating an array Using make_shared() results in just one allocation instead of having one for the data and one for the shared_ptr's control block. But std::shared_ptr supports make_shared() for arrays only in C++20. Change-Id: If2d1223ebcc54ccfdccb15601d69a3563bd4f6c0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/85589 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 78b864104a2c..40cbb62104d1 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -24,6 +24,8 @@ #include +#include + class VCL_PLUGIN_PUBLIC SkiaSalBitmap final : public SalBitmap { public: @@ -114,7 +116,7 @@ private: // mBitmap/mBuffer must be filled from it on demand if necessary by EnsureBitmapData(). SkBitmap mBitmap; sk_sp mImage; // possibly GPU-backed -std::shared_ptr mBuffer; +boost::shared_ptr mBuffer; int mScanlineSize; // size of one row in mBuffer sk_sp mAlphaImage; // cached contents as alpha image, possibly GPU-backed #ifdef DBG_UTIL diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 4430d7f672cd..172b7c37ef92 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -140,22 +141,21 @@ bool SkiaSalBitmap::CreateBitmapData() return false; } mScanlineSize = AlignedWidth4Bytes(bitScanlineWidth); -sal_uInt8* buffer = nullptr; if (mScanlineSize != 0 && mSize.Height() != 0) { size_t allocate = mScanlineSize * mSize.Height(); #ifdef DBG_UTIL allocate += sizeof(CANARY); #endif -buffer = new sal_uInt8[allocate]; +mBuffer = boost::make_shared(allocate); #ifdef DBG_UTIL // fill with random garbage +sal_uInt8* buffer = mBuffer.get(); for (size_t i = 0; i < allocate; i++) buffer[i] = (i & 0xFF); memcpy(buffer + allocate - sizeof(CANARY), CANARY, sizeof(CANARY)); #endif } -mBuffer.reset(buffer); } return true; } @@ -613,9 +613,9 @@ void SkiaSalBitmap::EnsureBitmapUniqueData() assert(memcmp(mBuffer.get() + allocate, CANARY, sizeof(CANARY)) == 0); allocate += sizeof(CANARY); #endif -sal_uInt8* newBuffer = new sal_uInt8[allocate]; -memcpy(newBuffer, mBuffer.get(), allocate); -mBuffer.reset(newBuffer); +boost::shared_ptr newBuffer = boost::make_shared(allocate); +memcpy(newBuffer.get(), mBuffer.get(), allocate); +mBuffer = newBuffer; } } ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
[Libreoffice-commits] core.git: vcl/inc vcl/skia vcl/unx vcl/win
vcl/inc/unx/salinst.h |2 ++ vcl/inc/win/salinst.h |1 + vcl/skia/salbmp.cxx | 19 ++- vcl/unx/generic/app/salinst.cxx | 10 ++ vcl/win/app/salinst.cxx | 10 ++ 5 files changed, 33 insertions(+), 9 deletions(-) New commits: commit b8c3ca05d04fb0bf3c27c889747bef99abcdf306 Author: Luboš Luňák AuthorDate: Thu Dec 19 20:26:03 2019 +0100 Commit: Luboš Luňák CommitDate: Mon Jan 6 11:14:23 2020 +0100 set BackendCapabilities::mbSupportsBitmap32 for Skia again This got reverted in 84f84f59ce7c83a99e4e340071d58b6557dbe91a, but using 24bpp bitmaps means SkiaSalBitmap::GetAsSkBitmap() does a needless 24bpp->32bpp conversion, and this whole rgb/a separation is kind of lame ancient cruft that it'd be better to get rid of, so enable this again to find all the code that can't handle 32bpp bitmaps properly, so that they can be fixed. Change-Id: I9bbd8ff94a4ad680cb42dee649e371c5716a9d20 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/85545 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/unx/salinst.h b/vcl/inc/unx/salinst.h index beff802c40c7..05b9f45f72e8 100644 --- a/vcl/inc/unx/salinst.h +++ b/vcl/inc/unx/salinst.h @@ -80,6 +80,8 @@ public: virtual voidAfterAppInit() override; +std::shared_ptr GetBackendCapabilities() override; + // dtrans implementation virtual css::uno::Reference< css::uno::XInterface > CreateClipboard( const css::uno::Sequence< css::uno::Any >& i_rArguments ) override; diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h index bcd3540ad8a9..c06e51c84050 100644 --- a/vcl/inc/win/salinst.h +++ b/vcl/inc/win/salinst.h @@ -73,6 +73,7 @@ public: virtual voidAddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override; virtual OUStringgetOSVersion() override; +virtual std::shared_ptr GetBackendCapabilities() override; static int WorkaroundExceptionHandlingInUSER32Lib(int nExcept, LPEXCEPTION_POINTERS pExceptionInfo); }; diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 9f81965de88d..4430d7f672cd 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -23,7 +23,9 @@ #include #include +#include #include +#include #include #include @@ -108,16 +110,15 @@ bool SkiaSalBitmap::CreateBitmapData() } if (colorType != kUnknown_SkColorType) { -// TODO -// As long as vcl::BackendCapabilities::mbSupportsBitmap32 is not set, we must use -// unpremultiplied alpha. This is because without mbSupportsBitmap32 set VCL uses -// an extra bitmap for the alpha channel and then merges the channels together -// into colors. kPremul_SkAlphaType would provide better performance, but -// without mbSupportsBitmap32 BitmapReadAccess::ImplSetAccessPointers() would use -// functions that merely read RGB without A, so the premultiplied values would -// not be converted back to unpremultiplied values. +// If vcl::BackendCapabilities::mbSupportsBitmap32 is set, +// BitmapReadAccess::ImplSetAccessPointers() uses functions that use premultiplied +// alpha. If not set, it would use functions that would read just RGB, so using +// premultiplied alpha here would change those values. +// Using kPremul_SkAlphaType should be better for performance, so ensure +// the flag is set. + assert(ImplGetSVData()->mpDefInst->GetBackendCapabilities()->mbSupportsBitmap32); if (!mBitmap.tryAllocPixels( -SkImageInfo::Make(mSize.Width(), mSize.Height(), colorType, kUnpremul_SkAlphaType))) +SkImageInfo::Make(mSize.Width(), mSize.Height(), colorType, kPremul_SkAlphaType))) { return false; } diff --git a/vcl/unx/generic/app/salinst.cxx b/vcl/unx/generic/app/salinst.cxx index f253f70d7d93..e5b2a92b89ce 100644 --- a/vcl/unx/generic/app/salinst.cxx +++ b/vcl/unx/generic/app/salinst.cxx @@ -224,4 +224,14 @@ std::unique_ptr X11SalInstance::CreatePrintGraphics() return std::make_unique(); } +std::shared_ptr X11SalInstance::GetBackendCapabilities() +{ +auto pBackendCapabilities = SalInstance::GetBackendCapabilities(); +#if HAVE_FEATURE_SKIA +if( SkiaHelper::isVCLSkiaEnabled()) +pBackendCapabilities->mbSupportsBitmap32 = true; +#endif +return pBackendCapabilities; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index cd9332e0c728..4b97215b6dac 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -1074,4 +1074,14 @@ OUString WinSalInstance::getOSVersion() return aVer.makeStringAndClear(); } +std::shared_ptr WinSalInstance::GetBackendCapabilities() +{ +auto
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/salbmp.hxx |7 +++- vcl/skia/salbmp.cxx | 70 2 files changed, 53 insertions(+), 24 deletions(-) New commits: commit 7702efe9ec6bbc428d89e83d957677cd3d323803 Author: Luboš Luňák AuthorDate: Thu Dec 19 12:54:39 2019 +0100 Commit: Luboš Luňák CommitDate: Mon Jan 6 11:12:37 2020 +0100 use copy-on-write for SkiaSalBitmap data E.g. scaling works by first making a copy using Create() and then Scale() is called for the copy. This means there was a needless data copy for mBuffer in Create(). Also make sure SkBitmap is properly unshared if needed, as it seems copies of it always share the pixels. Change-Id: I30a758c84e7218e9afe516477aa8429364ef8607 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/85543 Tested-by: Jenkins Reviewed-by: Luboš Luňák diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index a0fa2d900c78..78b864104a2c 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -74,6 +74,9 @@ private: // if necessary). void EnsureBitmapData(); void EnsureBitmapData() const { return const_cast(this)->EnsureBitmapData(); } +// Like EnsureBitmapData(), but will also make any shared data unique. +// Call before changing the data. +void EnsureBitmapUniqueData(); // Allocate mBitmap or mBuffer (with uninitialized contents). bool CreateBitmapData(); SkBitmap GetAsSkBitmap() const; @@ -90,7 +93,7 @@ private: // B - has SkBitmap, D - has data buffer, I/i - has SkImage (on GPU/CPU), // A/a - has alpha SkImage (on GPU/CPU) return stream << static_cast(bitmap) << " " << bitmap->GetSize() << "/" - << bitmap->mBitCount << (!bitmap->mBitmap.drawsNothing() ? "B" : "") + << bitmap->mBitCount << (!bitmap->mBitmap.isNull() ? "B" : "") << (bitmap->mBuffer.get() ? "D" : "") << (bitmap->mImage ? (bitmap->mImage->isTextureBacked() ? "I" : "i") : "") << (bitmap->mAlphaImage ? (bitmap->mAlphaImage->isTextureBacked() ? "A" : "a") @@ -111,7 +114,7 @@ private: // mBitmap/mBuffer must be filled from it on demand if necessary by EnsureBitmapData(). SkBitmap mBitmap; sk_sp mImage; // possibly GPU-backed -std::unique_ptr mBuffer; +std::shared_ptr mBuffer; int mScanlineSize; // size of one row in mBuffer sk_sp mAlphaImage; // cached contents as alpha image, possibly GPU-backed #ifdef DBG_UTIL diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index 9bc2d0ecf217..781d6f87c9ad 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -174,24 +174,16 @@ bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) const SkiaSalBitmap& src = static_cast(rSalBmp); if (nNewBitCount == src.GetBitCount()) { -mBitmap = src.mBitmap; // TODO unshare? -mImage = src.mImage; // TODO unshare? -mAlphaImage = src.mAlphaImage; // TODO unshare? +mBitmap = src.mBitmap; +// SkBitmap shares pixels on copy. +assert(mBitmap.getPixels() == src.mBitmap.getPixels()); +mImage = src.mImage; +mAlphaImage = src.mAlphaImage; +mBuffer = src.mBuffer; mPalette = src.mPalette; mBitCount = src.mBitCount; mSize = src.mSize; -if (src.mBuffer != nullptr) -{ -sal_uInt32 allocate = src.mScanlineSize * src.mSize.Height(); -#ifdef DBG_UTIL -assert(memcmp(src.mBuffer.get() + allocate, CANARY, sizeof(CANARY)) == 0); -allocate += sizeof(CANARY); -#endif -sal_uInt8* newBuffer = new sal_uInt8[allocate]; -memcpy(newBuffer, src.mBuffer.get(), allocate); -mBuffer.reset(newBuffer); -mScanlineSize = src.mScanlineSize; -} +mScanlineSize = src.mScanlineSize; #ifdef DBG_UTIL mWriteAccessCount = 0; #endif @@ -228,11 +220,18 @@ sal_uInt16 SkiaSalBitmap::GetBitCount() const { return mBitCount; } BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) { -#ifndef DBG_UTIL -(void)nMode; // TODO -#endif -EnsureBitmapData(); -if (mBitmap.drawsNothing() && !mBuffer) +switch (nMode) +{ +case BitmapAccessMode::Write: +EnsureBitmapUniqueData(); +break; +case BitmapAccessMode::Read: +EnsureBitmapData(); +break; +default: +break; +} +if (mBitmap.isNull() && !mBuffer) return nullptr; #ifdef DBG_UTIL // BitmapWriteAccess stores also a copy of the palette and it can @@ -358,7 +357,7 @@ SkBitmap SkiaSalBitmap::GetAsSkBitmap() const assert(mWriteAccessCount == 0); #endif EnsureBitmapData(); -if (!mBitmap.drawsNothing()) +if (!mBitmap.isNull()) return mBitmap; SkBitmap bitmap; if (mBuffer) @@ -495,7
[Libreoffice-commits] core.git: vcl/inc vcl/skia
vcl/inc/skia/win/gdiimpl.hxx |2 ++ vcl/skia/win/gdiimpl.cxx |5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) New commits: commit e9e0ccae48385fb949c2c3f0aac678784ab14705 Author: Stephan Bergmann AuthorDate: Thu Dec 5 09:45:13 2019 +0100 Commit: Stephan Bergmann CommitDate: Thu Dec 5 13:29:47 2019 +0100 Silence loplugin:unnecessaryoverride (clang-cl) ("public virtual function just calls public parent") Change-Id: Ifd8d6c794ae32af1fe5d2a97389ec87394fdffbc Reviewed-on: https://gerrit.libreoffice.org/84512 Tested-by: Jenkins Reviewed-by: Stephan Bergmann diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 75531ae9a164..37c8ad374aa8 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -55,7 +55,9 @@ private: public: WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, SalGeometryProvider* mpProvider); +#if 0 // TODO virtual void Init() override; +#endif virtual void DeInit() override; virtual void freeResources() override; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index dd63f4d6121e..53979f39aad4 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -24,9 +24,9 @@ WinSkiaSalGraphicsImpl::WinSkiaSalGraphicsImpl(WinSalGraphics& rGraphics, { } +#if 0 // TODO void WinSkiaSalGraphicsImpl::Init() { -#if 0 // TODO if (!IsOffscreen() && mpContext.is() && mpContext->isInitialized()) { const GLWinWindow& rGLWindow = static_cast(mpContext->getOpenGLWindow()); @@ -39,9 +39,8 @@ void WinSkiaSalGraphicsImpl::Init() DeInit(); } } -#endif -SkiaSalGraphicsImpl::Init(); } +#endif void WinSkiaSalGraphicsImpl::createWindowContext() { ___ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits