[Libreoffice-commits] core.git: vcl/inc vcl/skia

2023-08-19 Thread Patrick Luby (via logerrit)
 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

2023-07-02 Thread Noel Grandin (via logerrit)
 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

2022-11-19 Thread Khaled Hosny (via logerrit)
 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

2022-11-19 Thread Khaled Hosny (via logerrit)
 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

2022-09-14 Thread Luboš Luňák (via logerrit)
 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

2022-08-26 Thread Caolán McNamara (via logerrit)
 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

2022-03-16 Thread Caolán McNamara (via logerrit)
 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

2022-01-12 Thread Luboš Luňák (via logerrit)
 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

2022-01-11 Thread Caolán McNamara (via logerrit)
 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

2021-12-06 Thread Luboš Luňák (via logerrit)
 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

2021-11-29 Thread Luboš Luňák (via logerrit)
 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

2021-11-16 Thread Luboš Luňák (via logerrit)
 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

2021-11-16 Thread Luboš Luňák (via logerrit)
 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

2021-11-12 Thread Luboš Luňák (via logerrit)
 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

2021-08-31 Thread Luboš Luňák (via logerrit)
 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

2021-08-25 Thread Luboš Luňák (via logerrit)
 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

2021-08-23 Thread Luboš Luňák (via logerrit)
 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

2021-05-24 Thread Luboš Luňák (via logerrit)
 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

2021-05-24 Thread Luboš Luňák (via logerrit)
 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

2021-04-12 Thread Luboš Luňák (via logerrit)
 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

2021-04-07 Thread Luboš Luňák (via logerrit)
 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

2021-03-16 Thread Luboš Luňák (via logerrit)
 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

2021-03-03 Thread Luboš Luňák (via logerrit)
 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

2021-03-01 Thread Luboš Luňák (via logerrit)
 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

2021-03-01 Thread Luboš Luňák (via logerrit)
 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

2021-03-01 Thread Luboš Luňák (via logerrit)
 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

2020-12-15 Thread Luboš Luňák (via logerrit)
 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

2020-12-07 Thread Luboš Luňák (via logerrit)
 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

2020-11-17 Thread Jan-Marek Glogowski (via logerrit)
 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

2020-11-17 Thread Luboš Luňák (via logerrit)
 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

2020-10-07 Thread Luboš Luňák (via logerrit)
 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

2020-10-04 Thread Luboš Luňák (via logerrit)
 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

2020-09-30 Thread Luboš Luňák (via logerrit)
 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

2020-09-29 Thread Luboš Luňák (via logerrit)
 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

2020-09-29 Thread Luboš Luňák (via logerrit)
 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

2020-09-25 Thread Luboš Luňák (via logerrit)
 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

2020-09-23 Thread Luboš Luňák (via logerrit)
 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

2020-09-23 Thread Luboš Luňák (via logerrit)
 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

2020-09-08 Thread Luboš Luňák (via logerrit)
 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

2020-09-07 Thread Stephan Bergmann (via logerrit)
 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

2020-09-07 Thread Luboš Luňák (via logerrit)
 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

2020-09-07 Thread Luboš Luňák (via logerrit)
 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

2020-09-07 Thread Luboš Luňák (via logerrit)
 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

2020-08-26 Thread Luboš Luňák (via logerrit)
 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

2020-07-29 Thread Luboš Luňák (via logerrit)
 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

2020-07-16 Thread Luboš Luňák (via logerrit)
 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

2020-06-30 Thread Luboš Luňák (via logerrit)
 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

2020-06-27 Thread Luboš Luňák (via logerrit)
 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

2020-06-26 Thread Luboš Luňák (via logerrit)
 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

2020-05-15 Thread Luboš Luňák (via logerrit)
 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

2020-04-24 Thread Luboš Luňák (via logerrit)
 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

2020-04-20 Thread Luboš Luňák (via logerrit)
 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

2020-04-10 Thread Luboš Luňák (via logerrit)
 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

2020-04-08 Thread Luboš Luňák (via logerrit)
 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

2020-04-07 Thread Luboš Luňák (via logerrit)
 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

2020-03-25 Thread Luboš Luňák (via logerrit)
 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

2020-03-18 Thread Luboš Luňák (via logerrit)
 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

2020-03-12 Thread Luboš Luňák (via logerrit)
 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

2020-02-19 Thread Luboš Luňák (via logerrit)
 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

2020-01-30 Thread Luboš Luňák (via logerrit)
 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

2020-01-20 Thread Luboš Luňák (via logerrit)
 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

2020-01-20 Thread Luboš Luňák (via logerrit)
 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

2020-01-16 Thread Luboš Luňák (via logerrit)
 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

2020-01-12 Thread Luboš Luňák (via logerrit)
 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

2020-01-06 Thread Luboš Luňák (via logerrit)
 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

2020-01-06 Thread Luboš Luňák (via logerrit)
 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

2020-01-06 Thread Luboš Luňák (via logerrit)
 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

2019-12-05 Thread Stephan Bergmann (via logerrit)
 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