Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / opengl / x11 / gdiimpl.cxx
blobfa47b271aec41484eeb6ac156a2e0920508152a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <vcl/salbtype.hxx>
12 #include <svdata.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()),
32 mrParent(rParent)
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);
51 if( !pProvider )
52 return NULL;
54 Window aWin = pProvider->GetX11Window();
55 rtl::Reference<OpenGLContext> pContext = OpenGLContext::Create();
56 pContext->init( mrParent.GetXDisplay(), aWin,
57 mrParent.m_nXScreen.getXScreen() );
58 return pContext;
61 bool X11OpenGLSalGraphicsImpl::UseContext( const rtl::Reference<OpenGLContext> &pContext )
63 X11WindowProvider *pProvider = dynamic_cast<X11WindowProvider*>(mrParent.m_pFrame);
65 if( !pContext->isInitialized() || IsForeignContext( pContext ) )
66 return false;
67 if( !pProvider )
68 return pContext->getOpenGLWindow().win != None;
69 else
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;
84 XImage* pImage;
85 char* pData;
87 SAL_INFO( "vcl.opengl", "FillPixmapFromScreen" );
89 if( !OpenGLHelper::GetVisualInfo( pDisplay, nScreen.getXScreen(), aVisualInfo ) )
90 return false;
92 // make sure everything is synced up before reading back
93 mpContext->makeCurrent();
94 glXWaitX();
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 );
111 CHECK_GL_ERROR();
112 return true;
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,
126 None
129 Display* pDisplay = mrParent.GetXDisplay();
130 bool bInverted;
132 const long nWidth = pPixmap->GetWidth();
133 const long nHeight = pPixmap->GetHeight();
134 SalTwoRect aPosAry(0, 0, nWidth, nHeight, nX, nY, nWidth, nHeight);
136 PreDraw();
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);
142 GLXPixmap pGlxMask;
143 if( pMask != NULL )
144 pGlxMask = glXCreatePixmap( pDisplay, pFbConfig, pMask->GetPixmap(), aAttribs);
145 else
146 pGlxMask = 0;
147 XSync( pDisplay, 0 );
149 if( !pGlxPixmap )
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 );
173 else
175 DrawTexture(*rCombo.mpTexture, aPosAry, bInverted);
178 CHECK_GL_ERROR();
180 glXReleaseTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT );
181 glXDestroyPixmap( pDisplay, pGlxPixmap );
183 PostDraw();
185 CHECK_GL_ERROR();
187 return true;
190 bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
192 SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX << " " << nY << ")" );
194 TextureCombo aCombo;
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");
202 if (!gbCacheEnabled)
203 return false;
205 ControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
207 if (iterator == gTextureCache.end())
208 return false;
210 const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
212 PreDraw();
214 OpenGLTexture& rTexture = *pCombo->mpTexture;
216 SalTwoRect aPosAry(0, 0, rTexture.GetWidth(), rTexture.GetHeight(),
217 nX, nY, rTexture.GetWidth(), rTexture.GetHeight());
219 if (pCombo->mpMask)
220 DrawTextureDiff(rTexture, *pCombo->mpMask, aPosAry, true);
221 else
222 DrawTexture(rTexture, aPosAry, true);
224 PostDraw();
226 return 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);
234 if (!bResult)
235 return false;
237 if (!aControlCacheKey.canCacheControl())
238 return true;
240 ControlCachePair pair(aControlCacheKey, std::move(pCombo));
241 gTextureCache.insert(std::move(pair));
243 return bResult;
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */