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/.
10 #include <vcl/salbtype.hxx>
14 #include <unx/pixmap.hxx>
15 #include <unx/saldisp.hxx>
16 #include <unx/salframe.h>
17 #include <unx/salgdi.h>
18 #include <unx/salvd.h>
19 #include <unx/x11/xlimits.hxx>
21 #include <opengl/texture.hxx>
22 #include <opengl/x11/gdiimpl.hxx>
23 #include <opengl/x11/salvd.hxx>
25 #include <vcl/opengl/OpenGLContext.hxx>
26 #include <vcl/opengl/OpenGLHelper.hxx>
28 #include <o3tl/lru_map.hxx>
30 X11OpenGLSalGraphicsImpl::X11OpenGLSalGraphicsImpl( X11SalGraphics
& rParent
):
31 OpenGLSalGraphicsImpl(rParent
,rParent
.GetGeometryProvider()),
36 X11OpenGLSalGraphicsImpl::~X11OpenGLSalGraphicsImpl()
40 void X11OpenGLSalGraphicsImpl::Init()
42 // The m_pFrame and m_pVDev pointers are updated late in X11
43 mpProvider
= mrParent
.GetGeometryProvider();
44 OpenGLSalGraphicsImpl::Init();
47 rtl::Reference
<OpenGLContext
> X11OpenGLSalGraphicsImpl::CreateWinContext()
49 X11WindowProvider
*pProvider
= dynamic_cast<X11WindowProvider
*>(mrParent
.m_pFrame
);
54 Window aWin
= pProvider
->GetX11Window();
55 rtl::Reference
<OpenGLContext
> pContext
= OpenGLContext::Create();
56 pContext
->init( mrParent
.GetXDisplay(), aWin
,
57 mrParent
.m_nXScreen
.getXScreen() );
61 bool X11OpenGLSalGraphicsImpl::UseContext( const rtl::Reference
<OpenGLContext
> &pContext
)
63 X11WindowProvider
*pProvider
= dynamic_cast<X11WindowProvider
*>(mrParent
.m_pFrame
);
65 if( !pContext
->isInitialized() || IsForeignContext( pContext
) )
68 return pContext
->getOpenGLWindow().win
!= None
;
70 return pContext
->getOpenGLWindow().win
== pProvider
->GetX11Window();
73 void X11OpenGLSalGraphicsImpl::copyBits( const SalTwoRect
& rPosAry
, SalGraphics
* pSrcGraphics
)
75 OpenGLSalGraphicsImpl
*pImpl
= pSrcGraphics
? static_cast< OpenGLSalGraphicsImpl
* >(pSrcGraphics
->GetImpl()) : static_cast< OpenGLSalGraphicsImpl
*>(mrParent
.GetImpl());
76 OpenGLSalGraphicsImpl::DoCopyBits( rPosAry
, *pImpl
);
79 bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap
* pPixmap
, int nX
, int nY
)
81 Display
* pDisplay
= mrParent
.GetXDisplay();
82 SalX11Screen nScreen
= mrParent
.GetScreenNumber();
83 XVisualInfo aVisualInfo
;
87 SAL_INFO( "vcl.opengl", "FillPixmapFromScreen" );
89 if( !OpenGLHelper::GetVisualInfo( pDisplay
, nScreen
.getXScreen(), aVisualInfo
) )
92 // make sure everything is synced up before reading back
93 mpContext
->makeCurrent();
96 // TODO: lfrb: What if offscreen?
97 pData
= static_cast<char*>(malloc( pPixmap
->GetWidth() * pPixmap
->GetHeight() * 4 ));
98 glPixelStorei( GL_PACK_ALIGNMENT
, 1 );
99 glReadPixels( nX
, GetHeight() - nY
, pPixmap
->GetWidth(), pPixmap
->GetHeight(),
100 GL_RGBA
, GL_UNSIGNED_BYTE
, pData
);
102 pImage
= XCreateImage( pDisplay
, aVisualInfo
.visual
, 24, ZPixmap
, 0, pData
,
103 pPixmap
->GetWidth(), pPixmap
->GetHeight(), 8, 0 );
104 XInitImage( pImage
);
105 GC aGC
= XCreateGC( pDisplay
, pPixmap
->GetPixmap(), 0, NULL
);
106 XPutImage( pDisplay
, pPixmap
->GetDrawable(), aGC
, pImage
,
107 0, 0, 0, 0, pPixmap
->GetWidth(), pPixmap
->GetHeight() );
108 XFreeGC( pDisplay
, aGC
);
109 XDestroyImage( pImage
);
115 typedef typename
std::pair
<ControlCacheKey
, std::unique_ptr
<TextureCombo
>> ControlCachePair
;
116 typedef o3tl::lru_map
<ControlCacheKey
, std::unique_ptr
<TextureCombo
>, ControlCacheHashFunction
> ControlCacheType
;
118 ControlCacheType
gTextureCache(200);
120 bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap
* pPixmap
, X11Pixmap
* pMask
, int nX
, int nY
, TextureCombo
& rCombo
)
122 const int aAttribs
[] =
124 GLX_TEXTURE_TARGET_EXT
, GLX_TEXTURE_2D_EXT
,
125 GLX_TEXTURE_FORMAT_EXT
, GLX_TEXTURE_FORMAT_RGBA_EXT
,
129 Display
* pDisplay
= mrParent
.GetXDisplay();
132 const long nWidth
= pPixmap
->GetWidth();
133 const long nHeight
= pPixmap
->GetHeight();
134 SalTwoRect
aPosAry(0, 0, nWidth
, nHeight
, nX
, nY
, nWidth
, nHeight
);
137 //glClear( GL_COLOR_BUFFER_BIT );
139 XSync( pDisplay
, 0 );
140 GLXFBConfig pFbConfig
= OpenGLHelper::GetPixmapFBConfig( pDisplay
, bInverted
);
141 GLXPixmap pGlxPixmap
= glXCreatePixmap( pDisplay
, pFbConfig
, pPixmap
->GetPixmap(), aAttribs
);
144 pGlxMask
= glXCreatePixmap( pDisplay
, pFbConfig
, pMask
->GetPixmap(), aAttribs
);
147 XSync( pDisplay
, 0 );
150 SAL_WARN( "vcl.opengl", "Couldn't create GLXPixmap" );
152 //TODO: lfrb: glXGetProc to get the functions
154 rCombo
.mpTexture
.reset(new OpenGLTexture(pPixmap
->GetWidth(), pPixmap
->GetHeight(), false));
156 glActiveTexture( GL_TEXTURE0
);
157 rCombo
.mpTexture
->Bind();
158 glXBindTexImageEXT( pDisplay
, pGlxPixmap
, GLX_FRONT_LEFT_EXT
, NULL
);
159 rCombo
.mpTexture
->Unbind();
161 if( pMask
!= NULL
&& pGlxMask
)
163 rCombo
.mpMask
.reset(new OpenGLTexture(pPixmap
->GetWidth(), pPixmap
->GetHeight(), false));
164 rCombo
.mpMask
->Bind();
165 glXBindTexImageEXT( pDisplay
, pGlxMask
, GLX_FRONT_LEFT_EXT
, NULL
);
166 rCombo
.mpMask
->Unbind();
168 DrawTextureDiff(*rCombo
.mpTexture
, *rCombo
.mpMask
, aPosAry
, bInverted
);
170 glXReleaseTexImageEXT( pDisplay
, pGlxMask
, GLX_FRONT_LEFT_EXT
);
171 glXDestroyPixmap( pDisplay
, pGlxMask
);
175 DrawTexture(*rCombo
.mpTexture
, aPosAry
, bInverted
);
180 glXReleaseTexImageEXT( pDisplay
, pGlxPixmap
, GLX_FRONT_LEFT_EXT
);
181 glXDestroyPixmap( pDisplay
, pGlxPixmap
);
190 bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap
* pPixmap
, X11Pixmap
* pMask
, int nX
, int nY
)
192 SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX
<< " " << nY
<< ")" );
195 return RenderPixmap(pPixmap
, pMask
, nX
, nY
, aCombo
);
198 bool X11OpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey
& rControlCacheKey
, int nX
, int nY
)
200 static bool gbCacheEnabled
= !getenv("SAL_WITHOUT_WIDGET_CACHE");
205 ControlCacheType::const_iterator iterator
= gTextureCache
.find(rControlCacheKey
);
207 if (iterator
== gTextureCache
.end())
210 const std::unique_ptr
<TextureCombo
>& pCombo
= iterator
->second
;
214 OpenGLTexture
& rTexture
= *pCombo
->mpTexture
;
216 SalTwoRect
aPosAry(0, 0, rTexture
.GetWidth(), rTexture
.GetHeight(),
217 nX
, nY
, rTexture
.GetWidth(), rTexture
.GetHeight());
220 DrawTextureDiff(rTexture
, *pCombo
->mpMask
, aPosAry
, true);
222 DrawTexture(rTexture
, aPosAry
, true);
229 bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap
* pPixmap
, X11Pixmap
* pMask
, int nX
, int nY
,
230 ControlCacheKey
& aControlCacheKey
)
232 std::unique_ptr
<TextureCombo
> pCombo(new TextureCombo
);
233 bool bResult
= RenderPixmap(pPixmap
, pMask
, nX
, nY
, *pCombo
);
237 if (!aControlCacheKey
.canCacheControl())
240 ControlCachePair
pair(aControlCacheKey
, std::move(pCombo
));
241 gTextureCache
.insert(std::move(pair
));
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */