Kaydet (Commit) 02b1a996 authored tarafından Tomaž Vajngerl's avatar Tomaž Vajngerl Kaydeden (comit) Andras Timar

tdf#92018 cache native controls for X11 OpenGL backend (for now)

Change-Id: I85c7cc01113bc4ac810c450a6460059463cc8e03
(cherry picked from commit 450727fd)
Reviewed-on: https://gerrit.libreoffice.org/17554Reviewed-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
Tested-by: 's avatarMiklos Vajna <vmiklos@collabora.co.uk>
üst 9fdba37e
......@@ -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
......
......@@ -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
......
......@@ -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 );
......
......@@ -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
......
......@@ -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: */
......@@ -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();
......
......@@ -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
......
......@@ -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 )
......
......@@ -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 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment