[Libreoffice-commits] core.git: Branch 'feature/skia' - vcl/inc vcl/opengl vcl/skia vcl/win

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Thu Oct 31 10:51:07 UTC 2019


 vcl/inc/opengl/win/gdiimpl.hxx        |   12 ++--
 vcl/inc/skia/win/gdiimpl.hxx          |   19 +++++++
 vcl/inc/win/saldata.hxx               |    6 +-
 vcl/opengl/win/gdiimpl.cxx            |   18 +++----
 vcl/skia/win/gdiimpl.cxx              |   85 +++++++++++++++++++++++++++++-----
 vcl/win/app/salinst.cxx               |    1 
 vcl/win/gdi/salnativewidgets-luna.cxx |   20 ++++----
 7 files changed, 123 insertions(+), 38 deletions(-)

New commits:
commit cdee4592e7598b217972ffab1efb08599e375514
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Thu Oct 31 11:47:18 2019 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Thu Oct 31 11:50:28 2019 +0100

    implement Skia native controls drawing/caching for Windows
    
    This actually fixes a number of drawing problems (e.g. highlight
    in popup menus), it seems the other code path is buggy.
    
    Change-Id: Iea697f577d08d20e338224d5ff5b3bf7b653f8d1

diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx
index 2101818472ae..98ddabbc7a53 100644
--- a/vcl/inc/opengl/win/gdiimpl.hxx
+++ b/vcl/inc/opengl/win/gdiimpl.hxx
@@ -79,16 +79,16 @@ public:
 
 };
 
-typedef std::pair<ControlCacheKey, std::unique_ptr<TextureCombo>> ControlCachePair;
-typedef o3tl::lru_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
+typedef std::pair<ControlCacheKey, std::unique_ptr<TextureCombo>> OpenGLControlCachePair;
+typedef o3tl::lru_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> OpenGLControlCacheType;
 
-class TheTextureCache {
-    ControlCacheType cache;
+class OpenGLControlsCache {
+    OpenGLControlCacheType cache;
 
-    TheTextureCache();
+    OpenGLControlsCache();
 
 public:
-    static ControlCacheType & get();
+    static OpenGLControlCacheType & get();
 };
 
 #endif
diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx
index 6bd52b073aa5..321f35f24366 100644
--- a/vcl/inc/skia/win/gdiimpl.hxx
+++ b/vcl/inc/skia/win/gdiimpl.hxx
@@ -16,6 +16,9 @@
 #include <skia/gdiimpl.hxx>
 #include <win/salgdi.h>
 #include <win/wingdiimpl.hxx>
+#include <o3tl/lru_map.hxx>
+#include <ControlCacheKey.hxx>
+#include <svdata.hxx>
 
 class ControlCacheKey;
 namespace sk_app
@@ -34,6 +37,9 @@ public:
 
     virtual bool wantsTextColorWhite() const override { return true; }
 
+    SkBitmap getAsBitmap();
+    SkBitmap getAsMaskBitmap();
+
     struct Texture;
 };
 
@@ -80,6 +86,19 @@ private:
     std::unique_ptr<sk_app::WindowContext> mWindowContext;
 };
 
+typedef std::pair<ControlCacheKey, SkBitmap> SkiaControlCachePair;
+typedef o3tl::lru_map<ControlCacheKey, SkBitmap, ControlCacheHashFunction> SkiaControlCacheType;
+
+class SkiaControlsCache
+{
+    SkiaControlCacheType cache;
+
+    SkiaControlsCache();
+
+public:
+    static SkiaControlCacheType& get();
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx
index e9889e6653d1..0e657e15ed95 100644
--- a/vcl/inc/win/saldata.hxx
+++ b/vcl/inc/win/saldata.hxx
@@ -42,7 +42,8 @@ struct GlobalWinGlyphCache;
 struct HDCCache;
 struct TempFontItem;
 class TextOutRenderer;
-class TheTextureCache;
+class OpenGLControlsCache;
+class SkiaControlsCache;
 
 #define MAX_STOCKPEN            4
 #define MAX_STOCKBRUSH          4
@@ -123,7 +124,8 @@ public:
     // tdf#107205 need 2 instances because D2DWrite can't rotate text
     std::unique_ptr<TextOutRenderer> m_pExTextOutRenderer;
     std::unique_ptr<GlobalWinGlyphCache> m_pGlobalWinGlyphCache;
-    std::unique_ptr<TheTextureCache> m_pTextureCache;
+    std::unique_ptr<OpenGLControlsCache> m_pOpenGLControlsCache;
+    std::unique_ptr<SkiaControlsCache> m_pSkiaControlsCache;
 };
 
 inline void SetSalData( SalData* pData ) { ImplGetSVData()->mpSalData = pData; }
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index bb6e5bf0a16c..c47de25b19f3 100644
--- a/vcl/opengl/win/gdiimpl.cxx
+++ b/vcl/opengl/win/gdiimpl.cxx
@@ -746,14 +746,14 @@ void WinOpenGLSalGraphicsImpl::Init()
     OpenGLSalGraphicsImpl::Init();
 }
 
-TheTextureCache::TheTextureCache(): cache(200) {}
+OpenGLControlsCache::OpenGLControlsCache(): cache(200) {}
 
-ControlCacheType & TheTextureCache::get() {
+OpenGLControlCacheType & OpenGLControlsCache::get() {
     SalData * data = GetSalData();
-    if (!data->m_pTextureCache) {
-        data->m_pTextureCache.reset(new TheTextureCache);
+    if (!data->m_pOpenGLControlsCache) {
+        data->m_pOpenGLControlsCache.reset(new OpenGLControlsCache);
     }
-    return data->m_pTextureCache->cache;
+    return data->m_pOpenGLControlsCache->cache;
 }
 
 OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height)
@@ -794,8 +794,8 @@ bool WinOpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey cons
     if (!gbCacheEnabled)
         return false;
 
-    auto & gTextureCache = TheTextureCache::get();
-    ControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
+    auto & gTextureCache = OpenGLControlsCache::get();
+    OpenGLControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
 
     if (iterator == gTextureCache.end())
         return false;
@@ -857,8 +857,8 @@ bool WinOpenGLSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite,
     if (!aControlCacheKey.canCacheControl())
         return true;
 
-    ControlCachePair pair(aControlCacheKey, std::move(pCombo));
-    TheTextureCache::get().insert(std::move(pair));
+    OpenGLControlCachePair pair(aControlCacheKey, std::move(pCombo));
+    OpenGLControlsCache::get().insert(std::move(pair));
 
     return bResult;
 }
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index 3be821c350ec..ac1ff016d3c4 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -11,6 +11,7 @@
 
 #include <tools/sk_app/win/WindowContextFactory_win.h>
 #include <tools/sk_app/WindowContext.h>
+#include <win/saldata.hxx>
 
 #include <SkColorFilter.h>
 #include <SkPixelRef.h>
@@ -84,22 +85,40 @@ void WinSkiaSalGraphicsImpl::performFlush()
 bool WinSkiaSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const& rControlCacheKey,
                                                           int nX, int nY)
 {
-    (void)rControlCacheKey;
-    (void)nX;
-    (void)nY;
-    return false; // TODO
+    static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE");
+    if (!gbCacheEnabled)
+        return false;
+
+    auto& controlsCache = SkiaControlsCache::get();
+    SkiaControlCacheType::const_iterator iterator = controlsCache.find(rControlCacheKey);
+    if (iterator == controlsCache.end())
+        return false;
+
+    preDraw();
+    mSurface->getCanvas()->drawBitmap(iterator->second, nX, nY);
+    postDraw();
+    return true;
 }
 
 bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack,
                                                          int nX, int nY,
                                                          ControlCacheKey& aControlCacheKey)
 {
-    (void)rWhite;
+    assert(dynamic_cast<SkiaCompatibleDC*>(&rWhite));
+    assert(dynamic_cast<SkiaCompatibleDC*>(&rBlack));
+
+    SkBitmap bitmap = static_cast<SkiaCompatibleDC&>(rWhite).getAsBitmap();
+    preDraw();
+    mSurface->getCanvas()->drawBitmap(bitmap, nX, nY);
+    postDraw();
+    // TODO what is the point of the second texture?
     (void)rBlack;
-    (void)nX;
-    (void)nY;
-    (void)aControlCacheKey;
-    return false; // TODO
+
+    if (!aControlCacheKey.canCacheControl())
+        return true;
+    SkiaControlCachePair pair(aControlCacheKey, std::move(bitmap));
+    SkiaControlsCache::get().insert(std::move(pair));
+    return true;
 }
 
 void WinSkiaSalGraphicsImpl::PreDrawText() { preDraw(); }
@@ -146,6 +165,12 @@ SkiaCompatibleDC::SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int wid
 std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture()
 {
     auto ret = std::make_unique<SkiaCompatibleDC::Texture>();
+    ret->bitmap = getAsMaskBitmap();
+    return ret;
+}
+
+SkBitmap SkiaCompatibleDC::getAsMaskBitmap()
+{
     // mpData is in the BGRA format, with A unused (and set to 0), and RGB are grey,
     // so convert it to Skia format, then to 8bit and finally use as alpha mask
     SkBitmap tmpBitmap;
@@ -171,8 +196,7 @@ std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture()
     alpha.setInfo(bitmap8.info().makeColorType(kAlpha_8_SkColorType), bitmap8.rowBytes());
     alpha.setPixelRef(sk_ref_sp(bitmap8.pixelRef()), bitmap8.pixelRefOrigin().x(),
                       bitmap8.pixelRefOrigin().y());
-    ret->bitmap = alpha;
-    return ret;
+    return alpha;
 }
 
 bool SkiaCompatibleDC::copyToTexture(CompatibleDC::Texture& aTexture)
@@ -199,4 +223,43 @@ bool SkiaCompatibleDC::copyToTexture(CompatibleDC::Texture& aTexture)
     return true;
 }
 
+SkBitmap SkiaCompatibleDC::getAsBitmap()
+{
+    SkBitmap tmpBitmap;
+    if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight,
+                                                   kBGRA_8888_SkColorType, kUnpremul_SkAlphaType),
+                                 mpData, maRects.mnSrcWidth * 4))
+        abort();
+    SkBitmap bitmap;
+    if (!bitmap.tryAllocPixels(tmpBitmap.info()))
+        abort();
+    SkPaint paint;
+    paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
+    SkCanvas canvas(bitmap);
+    // The data we got is upside-down.
+    SkMatrix matrix;
+    matrix.preTranslate(0, maRects.mnSrcHeight);
+    matrix.setConcat(matrix, SkMatrix::MakeScale(1, -1));
+    canvas.concat(matrix);
+    canvas.drawBitmapRect(tmpBitmap,
+                          SkRect::MakeXYWH(0, 0, maRects.mnSrcWidth, maRects.mnSrcHeight),
+                          SkRect::MakeXYWH(0, 0, maRects.mnSrcWidth, maRects.mnSrcHeight), &paint);
+    return bitmap;
+}
+
+SkiaControlsCache::SkiaControlsCache()
+    : cache(200)
+{
+}
+
+SkiaControlCacheType& SkiaControlsCache::get()
+{
+    SalData* data = GetSalData();
+    if (!data->m_pSkiaControlsCache)
+    {
+        data->m_pSkiaControlsCache.reset(new SkiaControlsCache);
+    }
+    return data->m_pSkiaControlsCache->cache;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx
index 1dde24c85464..a27ffee2779b 100644
--- a/vcl/win/app/salinst.cxx
+++ b/vcl/win/app/salinst.cxx
@@ -51,6 +51,7 @@
 #include <vcl/skia/SkiaHelper.hxx>
 #if HAVE_FEATURE_SKIA
 #include <skia/salbmp.hxx>
+#include <skia/win/gdiimpl.hxx>
 #endif
 
 #include <salsys.hxx>
diff --git a/vcl/win/gdi/salnativewidgets-luna.cxx b/vcl/win/gdi/salnativewidgets-luna.cxx
index 7da5b223481d..93770c955c75 100644
--- a/vcl/win/gdi/salnativewidgets-luna.cxx
+++ b/vcl/win/gdi/salnativewidgets-luna.cxx
@@ -1300,19 +1300,19 @@ bool WinSalGraphics::drawNativeControl( ControlType nType,
     }
     else
     {
-        // We can do OpenGL
-        OpenGLCompatibleDC aBlackDC(*this, cacheRect.Left(), cacheRect.Top(), cacheRect.GetWidth()+1, cacheRect.GetHeight()+1);
-        SetTextAlign(aBlackDC.getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
-        aBlackDC.fill(RGB(0, 0, 0));
+        // We can do OpenGL/Skia
+        std::unique_ptr<CompatibleDC> aBlackDC(CompatibleDC::create(*this, cacheRect.Left(), cacheRect.Top(), cacheRect.GetWidth()+1, cacheRect.GetHeight()+1));
+        SetTextAlign(aBlackDC->getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
+        aBlackDC->fill(RGB(0, 0, 0));
 
-        OpenGLCompatibleDC aWhiteDC(*this, cacheRect.Left(), cacheRect.Top(), cacheRect.GetWidth()+1, cacheRect.GetHeight()+1);
-        SetTextAlign(aWhiteDC.getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
-        aWhiteDC.fill(RGB(0xff, 0xff, 0xff));
+        std::unique_ptr<CompatibleDC> aWhiteDC(CompatibleDC::create(*this, cacheRect.Left(), cacheRect.Top(), cacheRect.GetWidth()+1, cacheRect.GetHeight()+1));
+        SetTextAlign(aWhiteDC->getCompatibleHDC(), TA_LEFT|TA_TOP|TA_NOUPDATECP);
+        aWhiteDC->fill(RGB(0xff, 0xff, 0xff));
 
-        if (ImplDrawNativeControl(aBlackDC.getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr) &&
-            ImplDrawNativeControl(aWhiteDC.getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr))
+        if (ImplDrawNativeControl(aBlackDC->getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr) &&
+            ImplDrawNativeControl(aWhiteDC->getCompatibleHDC(), hTheme, rc, nType, nPart, nState, aValue, aCaptionStr))
         {
-            bOk = pImpl->RenderAndCacheNativeControl(aWhiteDC, aBlackDC, cacheRect.Left(), cacheRect.Top(), aControlCacheKey);
+            bOk = pImpl->RenderAndCacheNativeControl(*aWhiteDC, *aBlackDC, cacheRect.Left(), cacheRect.Top(), aControlCacheKey);
         }
     }
 


More information about the Libreoffice-commits mailing list