tdf#136545 use pre-existing cairo_surface
for the cairo-canvas case which has a surface for the drawable already created.
Vaving two of them, one via cairo_xlib_surface_create and one via
cairo_xlib_surface_create_with_xrender_format both alive at the same time seems
understandably unreliable.
This aligns the gen+X11 case closer to the gtk3 case wrt the situation of
tdf#127529
Change-Id: I411649ee36fa944b77c4b09f940a059f507be2cc
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/102200
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index caef46a..027d0aa 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -76,7 +76,8 @@ public:
virtual ~X11SalGraphics() COVERITY_NOEXCEPT_FALSE override;
void Init( SalFrame *pFrame, Drawable aDrawable, SalX11Screen nXScreen );
void Init( X11SalVirtualDevice *pVirtualDevice, SalColormap* pColormap = nullptr, bool bDeleteColormap = false );
void Init( X11SalVirtualDevice *pVirtualDevice, cairo_surface_t* pPreExistingTarget = nullptr,
SalColormap* pColormap = nullptr, bool bDeleteColormap = false );
void Init( X11OpenGLSalVirtualDevice *pVirtualDevice );
void Init( X11SkiaSalVirtualDevice *pVirtualDevice );
void DeInit();
@@ -86,8 +87,8 @@ public:
inline Display* GetXDisplay() const;
inline const SalVisual& GetVisual() const;
SalGeometryProvider* GetGeometryProvider() const;
Drawable GetDrawable() const { return hDrawable_; }
void SetDrawable( Drawable d, SalX11Screen nXScreen );
Drawable GetDrawable() const { return hDrawable_; }
void SetDrawable(Drawable d, cairo_surface_t* surface, SalX11Screen nXScreen);
XRenderPictFormat* GetXRenderFormat() const;
void SetXRenderFormat( XRenderPictFormat* pXRenderFormat ) { m_pXRenderFormat = pXRenderFormat; }
const SalColormap& GetColormap() const { return *m_pColormap; }
@@ -296,6 +297,7 @@ private:
const SalColormap* m_pColormap;
std::unique_ptr<SalColormap> m_pDeleteColormap;
Drawable hDrawable_; // use
cairo_surface_t* m_pExternalSurface;
SalX11Screen m_nXScreen;
mutable XRenderPictFormat* m_pXRenderFormat;
XID m_aXRenderPicture;
diff --git a/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx b/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx
index 3a82505..1bbf8d3 100644
--- a/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx
+++ b/vcl/unx/generic/gdi/cairo_xlib_cairo.cxx
@@ -248,12 +248,15 @@ namespace cairo
{
SystemGraphicsData aSystemGraphicsData;
cairo_surface_t* pSurface = mpSurface.get();
aSystemGraphicsData.nSize = sizeof(SystemGraphicsData);
aSystemGraphicsData.hDrawable = mpPixmap ? mpPixmap->mhDrawable : maSysData.hDrawable;
aSystemGraphicsData.pXRenderFormat = maSysData.pRenderFormat;
aSystemGraphicsData.pSurface = pSurface;
int width = cairo_xlib_surface_get_width(mpSurface.get());
int height = cairo_xlib_surface_get_height(mpSurface.get());
int width = cairo_xlib_surface_get_width(pSurface);
int height = cairo_xlib_surface_get_height(pSurface);
return VclPtr<VirtualDevice>::Create(aSystemGraphicsData,
Size(width, height),
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 4b26320..79037c1 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -66,6 +66,7 @@ X11SalGraphics::X11SalGraphics():
m_pVDev(nullptr),
m_pColormap(nullptr),
hDrawable_(None),
m_pExternalSurface(nullptr),
m_nXScreen( 0 ),
m_pXRenderFormat(nullptr),
m_aXRenderPicture(0),
@@ -144,8 +145,10 @@ SalGraphicsImpl* X11SalGraphics::GetImpl() const
return mxImpl.get();
}
void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* pExternalSurface, SalX11Screen nXScreen)
{
m_pExternalSurface = pExternalSurface;
// shortcut if nothing changed
if( hDrawable_ == aDrawable )
return;
@@ -165,8 +168,6 @@ void X11SalGraphics::SetDrawable( Drawable aDrawable, SalX11Screen nXScreen )
XRenderPeer::GetInstance().FreePicture( m_aXRenderPicture );
m_aXRenderPicture = 0;
}
// TODO: moggi: FIXME nTextPixel_ = GetPixel( nTextColor_ );
}
void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
@@ -181,14 +182,14 @@ void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
bWindow_ = true;
bVirDev_ = false;
SetDrawable( aTarget, nXScreen );
SetDrawable(aTarget, nullptr, nXScreen);
mxImpl->Init();
}
void X11SalGraphics::DeInit()
{
mxImpl->DeInit();
SetDrawable( None, m_nXScreen );
SetDrawable(None, nullptr, m_nXScreen);
}
void X11SalGraphics::SetClipRegion( GC pGC, Region pXReg ) const
@@ -782,6 +783,9 @@ SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const
cairo_t* X11SalGraphics::getCairoContext()
{
if (m_pExternalSurface)
return cairo_create(m_pExternalSurface);
cairo_surface_t* surface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_,
GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx
index 74de1ba..00a6f0a 100644
--- a/vcl/unx/generic/gdi/salvd.cxx
+++ b/vcl/unx/generic/gdi/salvd.cxx
@@ -59,7 +59,7 @@ std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateVirtualDevice(SalGraphic
return CreateX11VirtualDevice(pGraphics, nDX, nDY, eFormat, pData, std::make_unique<X11SalGraphics>());
}
void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, SalColormap* pColormap,
void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, cairo_surface_t* pPreExistingTarget, SalColormap* pColormap,
bool bDeleteColormap )
{
SalDisplay *pDisplay = pDevice->GetDisplay();
@@ -88,8 +88,7 @@ void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, SalColormap* pColormap,
bWindow_ = pDisplay->IsDisplay();
bVirDev_ = true;
const Drawable aVdevDrawable = pDevice->GetDrawable();
SetDrawable( aVdevDrawable, m_nXScreen );
SetDrawable(pDevice->GetDrawable(), pPreExistingTarget, m_nXScreen);
mxImpl->Init();
}
@@ -171,7 +170,11 @@ X11SalVirtualDevice::X11SalVirtualDevice(SalGraphics const * pGraphics, long &nD
}
pGraphics_->SetLayout( SalLayoutFlags::NONE ); // by default no! mirroring for VirtualDevices, can be enabled with EnableRTL()
pGraphics_->Init( this, pColormap, bDeleteColormap );
// tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget
cairo_surface_t* pPreExistingTarget = pData ? static_cast<cairo_surface_t*>(pData->pSurface) : nullptr;
pGraphics_->Init( this, pPreExistingTarget, pColormap, bDeleteColormap );
}
X11SalVirtualDevice::~X11SalVirtualDevice()
diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx
index 8d6be94..14b73dc 100644
--- a/vcl/unx/generic/window/salframe.cxx
+++ b/vcl/unx/generic/window/salframe.cxx
@@ -991,9 +991,9 @@ void X11SalFrame::updateGraphics( bool bClear )
{
Drawable aDrawable = bClear ? None : GetWindow();
if( pGraphics_ )
pGraphics_->SetDrawable( aDrawable, m_nXScreen );
pGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen );
if( pFreeGraphics_ )
pFreeGraphics_->SetDrawable( aDrawable, m_nXScreen );
pFreeGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen );
}
void X11SalFrame::SetIcon( sal_uInt16 nIcon )