1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 #include <vcl/salbtype.hxx>
12 #include <vcl/lazydelete.hxx>
16 #include <unx/pixmap.hxx>
17 #include <unx/saldisp.hxx>
18 #include <unx/salframe.h>
19 #include <unx/salgdi.h>
20 #include <unx/salinst.h>
21 #include <unx/salvd.h>
22 #include <unx/x11/xlimits.hxx>
24 #include <opengl/texture.hxx>
25 #include <opengl/zone.hxx>
26 #include <opengl/RenderState.hxx>
27 #include <opengl/x11/gdiimpl.hxx>
28 #include <opengl/x11/salvd.hxx>
30 #include <vcl/opengl/OpenGLContext.hxx>
31 #include <vcl/opengl/OpenGLHelper.hxx>
33 #include <o3tl/lru_map.hxx>
34 #include <ControlCacheKey.hxx>
36 static std::vector
<GLXContext
> g_vShareList
;
37 static bool g_bAnyCurrent
;
39 class X11OpenGLContext
: public OpenGLContext
42 void init(Display
* dpy
, Window win
, int screen
);
43 virtual void initWindow() override
;
46 virtual const GLWindow
& getOpenGLWindow() const override
{ return m_aGLWin
; }
47 virtual GLWindow
& getModifiableOpenGLWindow() override
{ return m_aGLWin
; }
48 virtual bool ImplInit() override
;
49 void initGLWindow(Visual
* pVisual
);
50 virtual SystemWindowData
generateWinData(vcl::Window
* pParent
, bool bRequestLegacyContext
) override
;
51 virtual void makeCurrent() override
;
52 virtual void destroyCurrentContext() override
;
53 virtual bool isCurrent() override
;
54 virtual bool isAnyCurrent() override
;
55 virtual void sync() override
;
56 virtual void resetCurrent() override
;
57 virtual void swapBuffers() override
;
64 int unxErrorHandler(Display
* dpy
, XErrorEvent
* event
)
69 XGetErrorText(dpy
, event
->error_code
, err
, 256);
70 XGetErrorText(dpy
, event
->request_code
, req
, 256);
71 XGetErrorText(dpy
, event
->minor_code
, minor
, 256);
72 SAL_WARN("vcl.opengl", "Error: " << err
<< ", Req: " << req
<< ", Minor: " << minor
);
77 typedef int (*errorHandler
)(Display
* /*dpy*/, XErrorEvent
* /*evnt*/);
79 class TempErrorHandler
82 errorHandler oldErrorHandler
;
86 TempErrorHandler(Display
* dpy
, errorHandler newErrorHandler
)
87 : oldErrorHandler(nullptr)
94 oldErrorHandler
= XSetErrorHandler(newErrorHandler
);
102 // sync so that we possibly get an XError
105 XSetErrorHandler(oldErrorHandler
);
106 XUnlockDisplay(mdpy
);
111 static bool errorTriggered
;
112 int oglErrorHandler( Display
* /*dpy*/, XErrorEvent
* /*evnt*/ )
114 errorTriggered
= true;
119 GLXFBConfig
* getFBConfig(Display
* dpy
, Window win
, int& nBestFBC
, bool bUseDoubleBufferedRendering
)
123 if( dpy
== nullptr || !glXQueryExtension( dpy
, nullptr, nullptr ) )
126 VCL_GL_INFO("window: " << win
);
128 XWindowAttributes xattr
;
129 if( !XGetWindowAttributes( dpy
, win
, &xattr
) )
131 SAL_WARN("vcl.opengl", "Failed to get window attributes for fbconfig " << win
);
132 xattr
.screen
= nullptr;
133 xattr
.visual
= nullptr;
136 int screen
= XScreenNumberOfScreen( xattr
.screen
);
138 // TODO: moggi: Select colour channel depth based on visual attributes, not hardcoded */
139 static int visual_attribs
[] =
141 GLX_DOUBLEBUFFER
, True
,
142 GLX_X_RENDERABLE
, True
,
148 GLX_X_VISUAL_TYPE
, GLX_TRUE_COLOR
,
152 if (!bUseDoubleBufferedRendering
)
153 visual_attribs
[1] = False
;
156 GLXFBConfig
* pFBC
= glXChooseFBConfig( dpy
,
158 visual_attribs
, &fbCount
);
162 SAL_WARN("vcl.opengl", "no suitable fb format found");
166 int best_num_samp
= -1;
167 for(int i
= 0; i
< fbCount
; ++i
)
169 XVisualInfo
* pVi
= glXGetVisualFromFBConfig( dpy
, pFBC
[i
] );
170 if(pVi
&& (xattr
.visual
&& pVi
->visualid
== xattr
.visual
->visualid
) )
172 // pick the one with the most samples per pixel
175 glXGetFBConfigAttrib( dpy
, pFBC
[i
], GLX_SAMPLE_BUFFERS
, &nSampleBuf
);
176 glXGetFBConfigAttrib( dpy
, pFBC
[i
], GLX_SAMPLES
, &nSamples
);
178 if ( nBestFBC
< 0 || (nSampleBuf
&& ( nSamples
> best_num_samp
)) )
181 best_num_samp
= nSamples
;
190 Visual
* getVisual(Display
* dpy
, Window win
)
194 XWindowAttributes xattr
;
195 if( !XGetWindowAttributes( dpy
, win
, &xattr
) )
197 SAL_WARN("vcl.opengl", "Failed to get window attributes for getVisual " << win
);
198 xattr
.visual
= nullptr;
200 VCL_GL_INFO("using VisualID " << xattr
.visual
);
205 void X11OpenGLContext::sync()
209 XSync(m_aGLWin
.dpy
, false);
212 void X11OpenGLContext::swapBuffers()
216 glXSwapBuffers(m_aGLWin
.dpy
, m_aGLWin
.win
);
221 void X11OpenGLContext::resetCurrent()
229 glXMakeCurrent(m_aGLWin
.dpy
, None
, nullptr);
230 g_bAnyCurrent
= false;
234 bool X11OpenGLContext::isCurrent()
237 return g_bAnyCurrent
&& m_aGLWin
.ctx
&& glXGetCurrentContext() == m_aGLWin
.ctx
&&
238 glXGetCurrentDrawable() == m_aGLWin
.win
;
241 bool X11OpenGLContext::isAnyCurrent()
243 return g_bAnyCurrent
&& glXGetCurrentContext() != None
;
246 SystemWindowData
X11OpenGLContext::generateWinData(vcl::Window
* pParent
, bool /*bRequestLegacyContext*/)
250 SystemWindowData aWinData
;
251 aWinData
.pVisual
= nullptr;
253 const SystemEnvData
* sysData(pParent
->GetSystemData());
255 Display
*dpy
= static_cast<Display
*>(sysData
->pDisplay
);
256 Window win
= sysData
->aWindow
;
258 if( dpy
== nullptr || !glXQueryExtension( dpy
, nullptr, nullptr ) )
262 GLXFBConfig
* pFBC
= getFBConfig(dpy
, win
, best_fbc
, true);
267 XVisualInfo
* vi
= nullptr;
269 vi
= glXGetVisualFromFBConfig( dpy
, pFBC
[best_fbc
] );
275 VCL_GL_INFO("using VisualID " << vi
->visualid
);
276 aWinData
.pVisual
= static_cast<void*>(vi
->visual
);
282 bool X11OpenGLContext::ImplInit()
289 GLXContext
pSharedCtx( nullptr );
291 TempErrorHandler
aErrorHandler(m_aGLWin
.dpy
, unxErrorHandler
);
294 VCL_GL_INFO("OpenGLContext::ImplInit----start");
296 if (!g_vShareList
.empty())
297 pSharedCtx
= g_vShareList
.front();
299 //tdf#112166 for, e.g. VirtualBox GL, claiming OpenGL 2.1
300 static bool hasCreateContextAttribsARB
= glXGetProcAddress(reinterpret_cast<const GLubyte
*>("glXCreateContextAttribsARB")) != nullptr;
301 if (hasCreateContextAttribsARB
&& !mbRequestLegacyContext
)
304 GLXFBConfig
* pFBC
= getFBConfig(m_aGLWin
.dpy
, m_aGLWin
.win
, best_fbc
, mbUseDoubleBufferedRendering
);
306 if (pFBC
&& best_fbc
!= -1)
308 int const pContextAttribs
[] =
310 #if 0 // defined(DBG_UTIL)
311 GLX_CONTEXT_MAJOR_VERSION_ARB
, 3,
312 GLX_CONTEXT_MINOR_VERSION_ARB
, 2,
317 m_aGLWin
.ctx
= glXCreateContextAttribsARB(m_aGLWin
.dpy
, pFBC
[best_fbc
], pSharedCtx
, /* direct, not via X */ GL_TRUE
, pContextAttribs
);
318 SAL_INFO_IF(m_aGLWin
.ctx
, "vcl.opengl", "created a 3.2 core context");
321 SAL_WARN("vcl.opengl", "unable to find correct FBC");
329 SAL_WARN("vcl.opengl", "attempting to create a non-double-buffered "
330 "visual matching the context");
332 m_aGLWin
.ctx
= glXCreateContext(m_aGLWin
.dpy
,
335 GL_TRUE
/* direct, not via X server */);
340 g_vShareList
.push_back( m_aGLWin
.ctx
);
344 SAL_WARN("vcl.opengl", "unable to create GLX context");
348 if( !glXMakeCurrent( m_aGLWin
.dpy
, m_aGLWin
.win
, m_aGLWin
.ctx
) )
350 g_bAnyCurrent
= false;
351 SAL_WARN("vcl.opengl", "unable to select current GLX context");
355 g_bAnyCurrent
= true;
357 int glxMinor
, glxMajor
;
358 double nGLXVersion
= 0;
359 if( glXQueryVersion( m_aGLWin
.dpy
, &glxMajor
, &glxMinor
) )
360 nGLXVersion
= glxMajor
+ 0.1*glxMinor
;
361 SAL_INFO("vcl.opengl", "available GLX version: " << nGLXVersion
);
363 SAL_INFO("vcl.opengl", "available GL extensions: " << glGetString(GL_EXTENSIONS
));
365 XWindowAttributes aWinAttr
;
366 if( !XGetWindowAttributes( m_aGLWin
.dpy
, m_aGLWin
.win
, &aWinAttr
) )
368 SAL_WARN("vcl.opengl", "Failed to get window attributes on " << m_aGLWin
.win
);
374 m_aGLWin
.Width
= aWinAttr
.width
;
375 m_aGLWin
.Height
= aWinAttr
.height
;
378 if( m_aGLWin
.HasGLXExtension("GLX_SGI_swap_control" ) )
381 typedef GLint (*glXSwapIntervalProc
)(GLint
);
382 glXSwapIntervalProc glXSwapInterval
= reinterpret_cast<glXSwapIntervalProc
>(glXGetProcAddress( reinterpret_cast<const GLubyte
*>("glXSwapIntervalSGI") ));
383 if( glXSwapInterval
)
385 TempErrorHandler
aLocalErrorHandler(m_aGLWin
.dpy
, oglErrorHandler
);
387 errorTriggered
= false;
389 glXSwapInterval( 1 );
392 SAL_WARN("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
394 VCL_GL_INFO("set swap interval to 1 (enable vsync)");
398 bool bRet
= InitGL();
401 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
408 void X11OpenGLContext::makeCurrent()
418 TempErrorHandler
aErrorHandler(m_aGLWin
.dpy
, unxErrorHandler
);
423 if (!glXMakeCurrent( m_aGLWin
.dpy
, m_aGLWin
.win
, m_aGLWin
.ctx
))
425 g_bAnyCurrent
= false;
426 SAL_WARN("vcl.opengl", "OpenGLContext::makeCurrent failed "
427 "on drawable " << m_aGLWin
.win
);
430 g_bAnyCurrent
= true;
436 void X11OpenGLContext::destroyCurrentContext()
440 std::vector
<GLXContext
>::iterator itr
= std::remove( g_vShareList
.begin(), g_vShareList
.end(), m_aGLWin
.ctx
);
441 if (itr
!= g_vShareList
.end())
442 g_vShareList
.erase(itr
);
444 glXMakeCurrent(m_aGLWin
.dpy
, None
, nullptr);
445 g_bAnyCurrent
= false;
446 if( glGetError() != GL_NO_ERROR
)
448 SAL_WARN("vcl.opengl", "glError: " << glGetError());
450 glXDestroyContext(m_aGLWin
.dpy
, m_aGLWin
.ctx
);
451 m_aGLWin
.ctx
= nullptr;
455 void X11OpenGLContext::init(Display
* dpy
, Window win
, int screen
)
467 m_aGLWin
.screen
= screen
;
469 Visual
* pVisual
= getVisual(dpy
, win
);
471 initGLWindow(pVisual
);
476 void X11OpenGLContext::initGLWindow(Visual
* pVisual
)
482 XVisualInfo aTemplate
;
483 aTemplate
.visualid
= XVisualIDFromVisual( pVisual
);
485 XVisualInfo
* pInfo
= XGetVisualInfo( m_aGLWin
.dpy
, VisualIDMask
, &aTemplate
, &nVisuals
);
487 SAL_WARN( "vcl.opengl", "match count for visual id is not 1" );
491 // Check multisample support
492 /* TODO: moggi: This is not necessarily correct in the DBG_UTIL path, as it picks
493 * an FBConfig instead ... */
495 glXGetConfig(m_aGLWin
.dpy
, m_aGLWin
.vi
, GLX_SAMPLES
, &nSamples
);
497 m_aGLWin
.bMultiSampleSupported
= true;
499 m_aGLWin
.GLXExtensions
= glXQueryExtensionsString( m_aGLWin
.dpy
, m_aGLWin
.screen
);
500 SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin
.GLXExtensions
);
503 void X11OpenGLContext::initWindow()
505 const SystemEnvData
* pChildSysData
= nullptr;
506 SystemWindowData winData
= generateWinData(mpWindow
, false);
507 if( winData
.pVisual
)
509 if( !m_pChildWindow
)
511 m_pChildWindow
= VclPtr
<SystemChildWindow
>::Create(mpWindow
, 0, &winData
, false);
513 pChildSysData
= m_pChildWindow
->GetSystemData();
516 if (!m_pChildWindow
|| !pChildSysData
)
519 InitChildWindow(m_pChildWindow
.get());
521 m_aGLWin
.dpy
= static_cast<Display
*>(pChildSysData
->pDisplay
);
522 m_aGLWin
.win
= pChildSysData
->aWindow
;
523 m_aGLWin
.screen
= pChildSysData
->nScreen
;
525 Visual
* pVisual
= static_cast<Visual
*>(pChildSysData
->pVisual
);
526 initGLWindow(pVisual
);
529 GLX11Window::GLX11Window()
538 bool GLX11Window::HasGLXExtension( const char* name
) const
540 for (sal_Int32 i
= 0; i
!= -1;) {
541 if (GLXExtensions
.getToken(0, ' ', i
) == name
) {
548 GLX11Window::~GLX11Window()
553 bool GLX11Window::Synchronize(bool bOnoff
) const
555 XSynchronize(dpy
, bOnoff
);
559 OpenGLContext
* X11SalInstance::CreateOpenGLContext()
561 return new X11OpenGLContext
;
564 X11OpenGLSalGraphicsImpl::X11OpenGLSalGraphicsImpl( X11SalGraphics
& rParent
):
565 OpenGLSalGraphicsImpl(rParent
,rParent
.GetGeometryProvider()),
570 X11OpenGLSalGraphicsImpl::~X11OpenGLSalGraphicsImpl()
574 void X11OpenGLSalGraphicsImpl::Init()
576 // The m_pFrame and m_pVDev pointers are updated late in X11
577 mpProvider
= mrX11Parent
.GetGeometryProvider();
578 OpenGLSalGraphicsImpl::Init();
581 rtl::Reference
<OpenGLContext
> X11OpenGLSalGraphicsImpl::CreateWinContext()
583 NativeWindowHandleProvider
*pProvider
= dynamic_cast<NativeWindowHandleProvider
*>(mrX11Parent
.m_pFrame
);
588 sal_uIntPtr aWin
= pProvider
->GetNativeWindowHandle();
589 rtl::Reference
<X11OpenGLContext
> xContext
= new X11OpenGLContext
;
590 xContext
->setVCLOnly();
591 xContext
->init( mrX11Parent
.GetXDisplay(), aWin
,
592 mrX11Parent
.m_nXScreen
.getXScreen() );
593 return rtl::Reference
<OpenGLContext
>(xContext
.get());
596 void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect
& rPosAry
, SalGraphics
* pSrcGraphics
)
598 OpenGLSalGraphicsImpl
*pImpl
= pSrcGraphics
? static_cast< OpenGLSalGraphicsImpl
* >(pSrcGraphics
->GetImpl()) : static_cast< OpenGLSalGraphicsImpl
*>(mrX11Parent
.GetImpl());
599 OpenGLSalGraphicsImpl::DoCopyBits( rPosAry
, *pImpl
);
602 void X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap
* pPixmap
, int nX
, int nY
)
604 Display
* pDisplay
= mrX11Parent
.GetXDisplay();
605 SalX11Screen nScreen
= mrX11Parent
.GetScreenNumber();
606 XVisualInfo aVisualInfo
;
610 SAL_INFO( "vcl.opengl", "FillPixmapFromScreen" );
612 if (!SalDisplay::BestOpenGLVisual(pDisplay
, nScreen
.getXScreen(), aVisualInfo
))
615 // make sure everything is synced up before reading back
616 mpContext
->makeCurrent();
619 // TODO: lfrb: What if offscreen?
620 pData
= static_cast<char*>(malloc( pPixmap
->GetWidth() * pPixmap
->GetHeight() * 4 ));
621 glPixelStorei( GL_PACK_ALIGNMENT
, 1 );
623 glReadPixels( nX
, GetHeight() - nY
, pPixmap
->GetWidth(), pPixmap
->GetHeight(),
624 GL_RGBA
, GL_UNSIGNED_BYTE
, pData
);
627 pImage
= XCreateImage( pDisplay
, aVisualInfo
.visual
, 24, ZPixmap
, 0, pData
,
628 pPixmap
->GetWidth(), pPixmap
->GetHeight(), 8, 0 );
629 XInitImage( pImage
);
630 GC aGC
= XCreateGC( pDisplay
, pPixmap
->GetPixmap(), 0, nullptr );
631 XPutImage( pDisplay
, pPixmap
->GetDrawable(), aGC
, pImage
,
632 0, 0, 0, 0, pPixmap
->GetWidth(), pPixmap
->GetHeight() );
633 XFreeGC( pDisplay
, aGC
);
634 XDestroyImage( pImage
);
637 typedef typename
std::pair
<ControlCacheKey
, std::unique_ptr
<TextureCombo
>> ControlCachePair
;
638 typedef o3tl::lru_map
<ControlCacheKey
, std::unique_ptr
<TextureCombo
>, ControlCacheHashFunction
> ControlCacheType
;
640 static vcl::DeleteOnDeinit
<ControlCacheType
> gTextureCache(new ControlCacheType(200));
644 GLXFBConfig
GetPixmapFBConfig( Display
* pDisplay
, bool& bInverted
)
648 int nScreen
= DefaultScreen( pDisplay
);
649 GLXFBConfig
*aFbConfigs
;
650 int i
, nFbConfigs
, nValue
;
652 aFbConfigs
= glXGetFBConfigs( pDisplay
, nScreen
, &nFbConfigs
);
653 for( i
= 0; i
< nFbConfigs
; i
++ )
655 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_DRAWABLE_TYPE
, &nValue
);
656 if( !(nValue
& GLX_PIXMAP_BIT
) )
659 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_BIND_TO_TEXTURE_TARGETS_EXT
, &nValue
);
660 if( !(nValue
& GLX_TEXTURE_2D_BIT_EXT
) )
663 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_DEPTH_SIZE
, &nValue
);
667 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_RED_SIZE
, &nValue
);
670 SAL_INFO( "vcl.opengl", "Red is " << nValue
);
672 // TODO: lfrb: Make it configurable wrt RGB/RGBA
673 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_BIND_TO_TEXTURE_RGB_EXT
, &nValue
);
674 if( nValue
== False
)
676 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_BIND_TO_TEXTURE_RGBA_EXT
, &nValue
);
677 if( nValue
== False
)
681 glXGetFBConfigAttrib( pDisplay
, aFbConfigs
[i
], GLX_Y_INVERTED_EXT
, &nValue
);
683 // Looks like that X sends GLX_DONT_CARE but this usually means "true" for most
684 // of the X implementations. Investigation on internet pointed that this could be
685 // safely "true" all the time (for example gnome-shell always assumes "true").
686 bInverted
= nValue
== True
|| nValue
== int(GLX_DONT_CARE
);
691 if( i
== nFbConfigs
)
693 SAL_WARN( "vcl.opengl", "Unable to find FBconfig for pixmap texturing" );
698 return aFbConfigs
[i
];
702 bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap
const * pPixmap
, X11Pixmap
const * pMask
, int nX
, int nY
, TextureCombo
& rCombo
)
704 const int aAttribs
[] =
706 GLX_TEXTURE_TARGET_EXT
, GLX_TEXTURE_2D_EXT
,
707 GLX_TEXTURE_FORMAT_EXT
, GLX_TEXTURE_FORMAT_RGBA_EXT
,
711 Display
* pDisplay
= mrX11Parent
.GetXDisplay();
712 bool bInverted
= false;
714 const long nWidth
= pPixmap
->GetWidth();
715 const long nHeight
= pPixmap
->GetHeight();
716 SalTwoRect
aPosAry(0, 0, nWidth
, nHeight
, nX
, nY
, nWidth
, nHeight
);
719 //glClear( GL_COLOR_BUFFER_BIT );
721 XSync( pDisplay
, 0 );
722 GLXFBConfig pFbConfig
= GetPixmapFBConfig( pDisplay
, bInverted
);
723 GLXPixmap pGlxPixmap
= glXCreatePixmap( pDisplay
, pFbConfig
, pPixmap
->GetPixmap(), aAttribs
);
725 if( pMask
!= nullptr )
726 pGlxMask
= glXCreatePixmap( pDisplay
, pFbConfig
, pMask
->GetPixmap(), aAttribs
);
729 XSync( pDisplay
, 0 );
732 SAL_WARN( "vcl.opengl", "Couldn't create GLXPixmap" );
734 //TODO: lfrb: glXGetProc to get the functions
736 rCombo
.mpTexture
.reset(new OpenGLTexture(pPixmap
->GetWidth(), pPixmap
->GetHeight(), false));
738 mpContext
->state().texture().active(0);
740 rCombo
.mpTexture
->Bind();
741 glXBindTexImageEXT( pDisplay
, pGlxPixmap
, GLX_FRONT_LEFT_EXT
, nullptr );
742 rCombo
.mpTexture
->Unbind();
744 if( pMask
!= nullptr && pGlxMask
)
746 rCombo
.mpMask
.reset(new OpenGLTexture(pPixmap
->GetWidth(), pPixmap
->GetHeight(), false));
747 rCombo
.mpMask
->Bind();
748 glXBindTexImageEXT( pDisplay
, pGlxMask
, GLX_FRONT_LEFT_EXT
, nullptr );
749 rCombo
.mpMask
->Unbind();
751 DrawTextureDiff(*rCombo
.mpTexture
, *rCombo
.mpMask
, aPosAry
, bInverted
);
753 glXReleaseTexImageEXT( pDisplay
, pGlxMask
, GLX_FRONT_LEFT_EXT
);
754 glXDestroyPixmap( pDisplay
, pGlxMask
);
758 DrawTexture(*rCombo
.mpTexture
, aPosAry
, bInverted
);
763 glXReleaseTexImageEXT( pDisplay
, pGlxPixmap
, GLX_FRONT_LEFT_EXT
);
764 glXDestroyPixmap( pDisplay
, pGlxPixmap
);
773 bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap
* pPixmap
, X11Pixmap
* pMask
, int nX
, int nY
)
775 SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX
<< " " << nY
<< ")" );
778 return RenderPixmap(pPixmap
, pMask
, nX
, nY
, aCombo
);
781 bool X11OpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey
& rControlCacheKey
, int nX
, int nY
)
783 static bool gbCacheEnabled
= !getenv("SAL_WITHOUT_WIDGET_CACHE");
785 if (!gbCacheEnabled
|| !gTextureCache
.get())
788 ControlCacheType::const_iterator iterator
= gTextureCache
.get()->find(rControlCacheKey
);
790 if (iterator
== gTextureCache
.get()->end())
793 const std::unique_ptr
<TextureCombo
>& pCombo
= iterator
->second
;
797 OpenGLTexture
& rTexture
= *pCombo
->mpTexture
;
799 SalTwoRect
aPosAry(0, 0, rTexture
.GetWidth(), rTexture
.GetHeight(),
800 nX
, nY
, rTexture
.GetWidth(), rTexture
.GetHeight());
803 DrawTextureDiff(rTexture
, *pCombo
->mpMask
, aPosAry
, true);
805 DrawTexture(rTexture
, aPosAry
, true);
812 bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap
* pPixmap
, X11Pixmap
* pMask
, int nX
, int nY
,
813 ControlCacheKey
& aControlCacheKey
)
815 std::unique_ptr
<TextureCombo
> pCombo(new TextureCombo
);
816 bool bResult
= RenderPixmap(pPixmap
, pMask
, nX
, nY
, *pCombo
);
820 if (!aControlCacheKey
.canCacheControl())
823 ControlCachePair
pair(aControlCacheKey
, std::move(pCombo
));
824 if (gTextureCache
.get())
825 gTextureCache
.get()->insert(std::move(pair
));
830 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */