summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToma┼ż Vajngerl <tomaz.vajngerl@collabora.co.uk>2015-07-23 19:15:20 +0900
committerMiklos Vajna <vmiklos@collabora.co.uk>2015-08-07 09:33:40 +0000
commitb4faa69e4a9a99cdd12b7999d95459b1a8639e9f (patch)
tree177d5938e3d78b9d532b52b9040c7ed462a30c94
parentc978ce3b0774912ec0979b6cfec02927d8837a3e (diff)
tdf#92018 cache native controls for X11 OpenGL backend (for now)
Change-Id: I85c7cc01113bc4ac810c450a6460059463cc8e03 (cherry picked from commit 450727fdffa4a0dc3b2d4e635a5c1bc0411b3c36) Reviewed-on: https://gerrit.libreoffice.org/17554 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
-rw-r--r--include/vcl/salnativewidgets.hxx42
-rw-r--r--vcl/inc/opengl/x11/gdiimpl.hxx11
-rw-r--r--vcl/inc/unx/salgdi.h6
-rw-r--r--vcl/inc/unx/x11/x11gdiimpl.h6
-rw-r--r--vcl/opengl/x11/gdiimpl.cxx84
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.cxx11
-rw-r--r--vcl/unx/generic/gdi/gdiimpl.hxx5
-rw-r--r--vcl/unx/generic/gdi/salgdi2.cxx15
-rw-r--r--vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx23
9 files changed, 182 insertions, 21 deletions
diff --git a/include/vcl/salnativewidgets.hxx b/include/vcl/salnativewidgets.hxx
index 66bc74420f58..9692a80cbab8 100644
--- a/include/vcl/salnativewidgets.hxx
+++ b/include/vcl/salnativewidgets.hxx
@@ -25,6 +25,8 @@
#include <tools/gen.hxx>
#include <o3tl/typed_flags_set.hxx>
+#include <boost/functional/hash.hpp>
+
/* Control Types:
*
* Specify the overall, whole control
@@ -254,6 +256,46 @@ namespace o3tl
template<> struct typed_flags<ControlState> : is_typed_flags<ControlState, 0xc007f> {};
}
+class ControlCacheKey
+{
+public:
+ ControlType mnType;
+ ControlPart mnPart;
+ ControlState mnState;
+ Size maSize;
+
+ ControlCacheKey(ControlType nType, ControlPart nPart, ControlState nState, const Size& rSize)
+ : mnType(nType)
+ , mnPart(nPart)
+ , mnState(nState)
+ , maSize(rSize)
+ {}
+
+ bool operator==(ControlCacheKey const& aOther) const
+ {
+ return mnType == aOther.mnType
+ && mnPart == aOther.mnPart
+ && mnState == aOther.mnState
+ && maSize.Width() == aOther.maSize.Width()
+ && maSize.Height() == aOther.maSize.Height();
+ }
+};
+
+struct ControlCacheHashFunction
+{
+ std::size_t operator()(ControlCacheKey const& aCache) const
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, aCache.mnType);
+ boost::hash_combine(seed, aCache.mnPart);
+ boost::hash_combine(seed, aCache.mnState);
+ boost::hash_combine(seed, aCache.maSize.Width());
+ boost::hash_combine(seed, aCache.maSize.Height());
+ return seed;
+ }
+};
+
+
/* ButtonValue:
*
* Identifies the tri-state value options
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index feb3961a5e71..9e2ece3448c0 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -16,6 +16,8 @@
#include "unx/x11/x11gdiimpl.h"
#include "openglgdiimpl.hxx"
+class TextureCombo;
+
class VCL_PLUGIN_PUBLIC X11OpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl, public X11GraphicsImpl
{
private:
@@ -29,6 +31,8 @@ protected:
virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
virtual bool UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
+ bool RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo);
+
public:
// implementation of X11GraphicsImpl
@@ -37,7 +41,12 @@ public:
virtual void Init() SAL_OVERRIDE;
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
- bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
+ bool RenderPixmapToScreen(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY) SAL_OVERRIDE;
+
+ bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) SAL_OVERRIDE;
+ bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey,
+ int nX, int nY) SAL_OVERRIDE;
};
#endif // INCLUDED_VCL_INC_OPENGL_X11_GDIIMPL_HXX
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 0a0d0d329bce..a44ef1edfa72 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -272,6 +272,12 @@ public:
virtual void BeginPaint() SAL_OVERRIDE;
virtual void EndPaint() SAL_OVERRIDE;
+ bool TryRenderCachedNativeControl(ControlCacheKey& aControlCacheKey,
+ int nX, int nY);
+
+ bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey);
+
// fill a pixmap from a screen region
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY );
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 22859c315b6d..c5043646e422 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -12,6 +12,8 @@
#include "unx/pixmap.hxx"
+class ControlCacheKey;
+
class X11GraphicsImpl
{
public:
@@ -19,6 +21,10 @@ public:
virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0;
+
+ virtual bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY) = 0;
+ virtual bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) = 0;
};
#endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 1d453dabf007..3890b6443de3 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -111,18 +111,28 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
return true;
}
-bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
+struct TextureCombo
+{
+ std::unique_ptr<OpenGLTexture> mpTexture;
+ std::unique_ptr<OpenGLTexture> mpMask;
+};
+
+typedef std::unordered_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
+
+ControlCacheType gTextureCache;
+
+bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo)
{
- const int aAttribs[] = {
+ const int aAttribs[] =
+ {
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
None
};
+
Display* pDisplay = mrParent.GetXDisplay();
bool bInverted;
- SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX << " " << nY << ")" );
-
const long nWidth = pPixmap->GetWidth();
const long nHeight = pPixmap->GetHeight();
SalTwoRect aPosAry(0, 0, nWidth, nHeight, nX, nY, nWidth, nHeight);
@@ -145,27 +155,28 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
//TODO: lfrb: glXGetProc to get the functions
- OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false );
+ rCombo.mpTexture.reset(new OpenGLTexture(pPixmap->GetWidth(), pPixmap->GetHeight(), false));
+
glActiveTexture( GL_TEXTURE0 );
- aTexture.Bind();
+ rCombo.mpTexture->Bind();
glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL );
- aTexture.Unbind();
+ rCombo.mpTexture->Unbind();
if( pMask != NULL && pGlxMask )
{
- OpenGLTexture aMaskTexture( pMask->GetWidth(), pMask->GetHeight(), false );
- aMaskTexture.Bind();
+ rCombo.mpMask.reset(new OpenGLTexture(pPixmap->GetWidth(), pPixmap->GetHeight(), false));
+ rCombo.mpMask->Bind();
glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL );
- aMaskTexture.Unbind();
+ rCombo.mpMask->Unbind();
- DrawTextureDiff( aTexture, aMaskTexture, aPosAry, bInverted );
+ DrawTextureDiff(*rCombo.mpTexture, *rCombo.mpMask, aPosAry, bInverted);
glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT );
glXDestroyPixmap( pDisplay, pGlxMask );
}
else
{
- DrawTexture( aTexture, aPosAry, bInverted );
+ DrawTexture(*rCombo.mpTexture, aPosAry, bInverted);
}
CHECK_GL_ERROR();
@@ -176,7 +187,56 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
PostDraw();
CHECK_GL_ERROR();
+
return true;
}
+bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
+{
+ SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX << " " << nY << ")" );
+
+ TextureCombo aCombo;
+ return RenderPixmap(pPixmap, pMask, nX, nY, aCombo);
+}
+
+bool X11OpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY)
+{
+ static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE");
+
+ if (!gbCacheEnabled)
+ return false;
+
+ ControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
+
+ if (iterator == gTextureCache.end())
+ return false;
+
+ const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
+
+ PreDraw();
+
+ OpenGLTexture& rTexture = *pCombo->mpTexture;
+
+ SalTwoRect aPosAry(0, 0, rTexture.GetWidth(), rTexture.GetHeight(),
+ nX, nY, rTexture.GetWidth(), rTexture.GetHeight());
+
+ if (pCombo->mpMask)
+ DrawTextureDiff(rTexture, *pCombo->mpMask, aPosAry, true);
+ else
+ DrawTexture(rTexture, aPosAry, true);
+
+ PostDraw();
+
+ return true;
+}
+
+bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey)
+{
+ std::unique_ptr<TextureCombo> pCombo(new TextureCombo);
+ bool bResult = RenderPixmap(pPixmap, pMask, nX, nY, *pCombo);
+ gTextureCache[aControlCacheKey] = std::move(pCombo);
+ return bResult;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index f5b80988a3f4..1408edf4515d 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -212,6 +212,17 @@ bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*
return true;
}
+bool X11SalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& /*rControlCacheKey*/, int /*nX*/, int /*nY*/)
+{
+ return false;
+}
+
+bool X11SalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& /*rControlCacheKey*/)
+{
+ return RenderPixmapToScreen(pPixmap, pMask, nX, nY);
+}
+
XID X11SalGraphicsImpl::GetXRenderPicture()
{
XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index 9b2b9d53d5b8..2cf40f9ce701 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -284,6 +284,11 @@ public:
void Init() SAL_OVERRIDE;
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
+
+ virtual bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey,
+ int nX, int nY) SAL_OVERRIDE;
+ virtual bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) SAL_OVERRIDE;
};
#endif
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index 7b667cb1b5b1..b6be71f3d536 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -90,6 +90,21 @@ bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask,
return rImpl.RenderPixmapToScreen( pPixmap, pMask, nX, nY );
}
+bool X11SalGraphics::TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY)
+{
+ SAL_INFO( "vcl", "TryRenderCachedNativeControl" );
+ X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mxImpl.get());
+ return rImpl.TryRenderCachedNativeControl(rControlCacheKey, nX, nY);
+}
+
+bool X11SalGraphics::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& rControlCacheKey)
+{
+ SAL_INFO( "vcl", "RenderAndCachePixmap" );
+ X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mxImpl.get());
+ return rImpl.RenderAndCacheNativeControl(pPixmap, pMask, nX, nY, rControlCacheKey);
+}
+
extern "C"
{
static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow )
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 0e0331ece032..d49f045204ad 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -887,12 +887,23 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
if( aClipRegion.IsNull() )
aClipRegion = aCtrlRect;
+ Rectangle aPixmapRect;
+
+ // make pixmap a little larger since some themes draw decoration
+ // outside the rectangle, see e.g. checkbox
+ aPixmapRect = Rectangle(Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
+ Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
+
+ ControlCacheKey aControlCacheKey(nType, nPart, nState, aPixmapRect.GetSize());
+ if (TryRenderCachedNativeControl(aControlCacheKey, aPixmapRect.Left(), aPixmapRect.Top()))
+ return true;
+
clipList aClip;
int nPasses = 0;
GdkDrawable* gdkDrawable[2];
std::unique_ptr<GdkX11Pixmap> xPixmap;
std::unique_ptr<GdkX11Pixmap> xMask;
- Rectangle aPixmapRect;
+
if ((bNeedPixmapPaint || (nState & ControlState::DOUBLEBUFFERING))
&& nType != CTRL_SCROLLBAR
&& nType != CTRL_SPINBOX
@@ -902,11 +913,6 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
&& ! (nType == CTRL_TOOLBAR && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
)
{
- // make pixmap a little larger since some themes draw decoration
- // outside the rectangle, see e.g. checkbox
- aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
- Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
-
if( bNeedTwoPasses )
{
xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) );
@@ -960,7 +966,9 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
}
if( xPixmap )
- returnVal = NWRenderPixmapToScreen( xPixmap.get(), xMask.get(), aPixmapRect) && returnVal;
+ returnVal = returnVal && RenderAndCacheNativeControl(xPixmap.get(), xMask.get(),
+ aPixmapRect.Left(), aPixmapRect.Top(),
+ aControlCacheKey);
return returnVal;
}
@@ -4261,7 +4269,6 @@ GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect, int nBgC
{
GdkX11Pixmap* pPixmap;
int nDepth = vcl_sal::getSalDisplay(GetGenericData())->GetVisual( m_nXScreen ).GetDepth();
-;
pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), nDepth );