Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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 : */
9 :
10 : #include <vcl/opengl/GLMHelper.hxx>
11 : #include <vcl/opengl/OpenGLHelper.hxx>
12 :
13 : #include <osl/file.hxx>
14 : #include <rtl/bootstrap.hxx>
15 : #include <config_folders.h>
16 : #include <vcl/salbtype.hxx>
17 : #include <vcl/bmpacc.hxx>
18 : #include <boost/scoped_array.hpp>
19 : #include <vcl/pngwrite.hxx>
20 : #include <vcl/graph.hxx>
21 : #include <vcl/svapp.hxx>
22 : #include <officecfg/Office/Common.hxx>
23 :
24 : #include <vector>
25 :
26 : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID
27 : #include "opengl/x11/X11DeviceInfo.hxx"
28 : #elif defined (_WIN32)
29 : #include "opengl/win/WinDeviceInfo.hxx"
30 : #endif
31 :
32 : namespace {
33 :
34 0 : OUString getShaderFolder()
35 : {
36 0 : OUString aUrl("$BRAND_BASE_DIR/" LIBO_ETC_FOLDER);
37 0 : rtl::Bootstrap::expandMacros(aUrl);
38 :
39 0 : return aUrl + "/opengl/";
40 : }
41 :
42 0 : OString loadShader(const OUString& rFilename)
43 : {
44 0 : OUString aFileURL = getShaderFolder() + rFilename +".glsl";
45 0 : osl::File aFile(aFileURL);
46 0 : if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None)
47 : {
48 0 : sal_uInt64 nSize = 0;
49 0 : aFile.getSize(nSize);
50 0 : boost::scoped_array<char> content(new char[nSize+1]);
51 0 : sal_uInt64 nBytesRead = 0;
52 0 : aFile.read(content.get(), nSize, nBytesRead);
53 : assert(nSize == nBytesRead);
54 0 : content.get()[nBytesRead] = 0;
55 0 : return OString(content.get());
56 : }
57 : else
58 : {
59 : SAL_WARN("vcl.opengl", "could not load the file: " << aFileURL);
60 : }
61 :
62 0 : return OString();
63 : }
64 :
65 : }
66 :
67 : namespace {
68 0 : int LogCompilerError(GLuint nId, const rtl::OUString &rDetail,
69 : const rtl::OUString &rName, bool bShaderNotProgram)
70 : {
71 0 : int InfoLogLength = 0;
72 :
73 0 : CHECK_GL_ERROR();
74 :
75 0 : if (bShaderNotProgram)
76 0 : glGetShaderiv (nId, GL_INFO_LOG_LENGTH, &InfoLogLength);
77 : else
78 0 : glGetProgramiv(nId, GL_INFO_LOG_LENGTH, &InfoLogLength);
79 :
80 0 : CHECK_GL_ERROR();
81 :
82 0 : if ( InfoLogLength > 0 )
83 : {
84 0 : std::vector<char> ErrorMessage(InfoLogLength+1);
85 0 : if (bShaderNotProgram)
86 0 : glGetShaderInfoLog (nId, InfoLogLength, NULL, &ErrorMessage[0]);
87 : else
88 0 : glGetProgramInfoLog(nId, InfoLogLength, NULL, &ErrorMessage[0]);
89 0 : CHECK_GL_ERROR();
90 :
91 0 : ErrorMessage.push_back('\0');
92 0 : SAL_WARN("vcl.opengl", rDetail << " shader " << nId << " compile for " << rName << " failed : " << &ErrorMessage[0]);
93 : }
94 : else
95 : SAL_WARN("vcl.opengl", rDetail << " shader: " << rName << " compile " << nId << " failed without error log");
96 0 : return 0;
97 : }
98 : }
99 :
100 0 : static void addPreamble(OString& rShaderSource, const OString& rPreamble)
101 : {
102 0 : if (rPreamble.isEmpty())
103 0 : return;
104 :
105 0 : OString aVersionStr("#version");
106 0 : int nVersionStrStartPos = rShaderSource.indexOf(aVersionStr, 0);
107 :
108 0 : if (nVersionStrStartPos == -1)
109 : {
110 0 : rShaderSource = rPreamble + "\n" + rShaderSource;
111 : }
112 : else
113 : {
114 0 : int nVersionStrEndPos = rShaderSource.indexOf('\n', nVersionStrStartPos);
115 :
116 : SAL_WARN_IF(nVersionStrEndPos == -1, "vcl.opengl", "syntax error in shader");
117 :
118 0 : if (nVersionStrEndPos == -1)
119 0 : nVersionStrEndPos = nVersionStrStartPos + 8;
120 :
121 0 : OString aVersionLine = rShaderSource.copy(0, nVersionStrEndPos - nVersionStrStartPos);
122 0 : OString aShaderBody = rShaderSource.copy(nVersionStrEndPos - nVersionStrStartPos);
123 :
124 0 : rShaderSource = aVersionLine + "\n" + rPreamble + "\n" + aShaderBody;
125 0 : }
126 : }
127 :
128 0 : GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,const OUString& rFragmentShaderName, const OString& preamble)
129 : {
130 : // Create the shaders
131 0 : GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
132 0 : GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
133 :
134 0 : GLint Result = GL_FALSE;
135 :
136 : // Compile Vertex Shader
137 0 : OString aVertexShaderSource = loadShader(rVertexShaderName);
138 0 : if( !preamble.isEmpty())
139 0 : addPreamble( aVertexShaderSource, preamble );
140 0 : char const * VertexSourcePointer = aVertexShaderSource.getStr();
141 0 : glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
142 0 : glCompileShader(VertexShaderID);
143 :
144 : // Check Vertex Shader
145 0 : glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
146 0 : if (!Result)
147 : return LogCompilerError(VertexShaderID, "vertex",
148 0 : rVertexShaderName, true);
149 :
150 : // Compile Fragment Shader
151 0 : OString aFragmentShaderSource = loadShader(rFragmentShaderName);
152 0 : if( !preamble.isEmpty())
153 0 : addPreamble( aFragmentShaderSource, preamble );
154 0 : char const * FragmentSourcePointer = aFragmentShaderSource.getStr();
155 0 : glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
156 0 : glCompileShader(FragmentShaderID);
157 :
158 : // Check Fragment Shader
159 0 : glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
160 0 : if (!Result)
161 : return LogCompilerError(FragmentShaderID, "fragment",
162 0 : rFragmentShaderName, true);
163 :
164 : // Link the program
165 0 : GLint ProgramID = glCreateProgram();
166 0 : glAttachShader(ProgramID, VertexShaderID);
167 0 : glAttachShader(ProgramID, FragmentShaderID);
168 0 : glLinkProgram(ProgramID);
169 :
170 0 : glDeleteShader(VertexShaderID);
171 0 : glDeleteShader(FragmentShaderID);
172 :
173 : // Check the program
174 0 : glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
175 0 : if (!Result)
176 0 : return LogCompilerError(ProgramID, "program", "<both>", false);
177 :
178 0 : CHECK_GL_ERROR();
179 0 : return ProgramID;
180 : }
181 :
182 1 : void OpenGLHelper::ConvertBitmapExToRGBATextureBuffer(const BitmapEx& rBitmapEx, sal_uInt8* o_pRGBABuffer, const bool bFlip)
183 : {
184 1 : long nBmpWidth = rBitmapEx.GetSizePixel().Width();
185 1 : long nBmpHeight = rBitmapEx.GetSizePixel().Height();
186 :
187 1 : Bitmap aBitmap (rBitmapEx.GetBitmap());
188 2 : AlphaMask aAlpha (rBitmapEx.GetAlpha());
189 2 : Bitmap::ScopedReadAccess pReadAccces( aBitmap );
190 2 : AlphaMask::ScopedReadAccess pAlphaReadAccess( aAlpha );
191 1 : size_t i = 0;
192 513 : for (long ny = (bFlip ? nBmpHeight - 1 : 0); (bFlip ? ny >= 0 : ny < nBmpHeight); (bFlip ? ny-- : ny++))
193 : {
194 512 : Scanline pAScan = pAlphaReadAccess ? pAlphaReadAccess->GetScanline(ny) : 0;
195 262656 : for(long nx = 0; nx < nBmpWidth; nx++)
196 : {
197 262144 : BitmapColor aCol = pReadAccces->GetColor( ny, nx );
198 262144 : o_pRGBABuffer[i++] = aCol.GetRed();
199 262144 : o_pRGBABuffer[i++] = aCol.GetGreen();
200 262144 : o_pRGBABuffer[i++] = aCol.GetBlue();
201 262144 : o_pRGBABuffer[i++] = pAScan ? 255 - *pAScan++ : 255;
202 262144 : }
203 1 : }
204 1 : }
205 :
206 0 : void OpenGLHelper::renderToFile(long nWidth, long nHeight, const OUString& rFileName)
207 : {
208 0 : boost::scoped_array<sal_uInt8> pBuffer(new sal_uInt8[nWidth*nHeight*4]);
209 0 : glReadPixels(0, 0, nWidth, nHeight, GL_BGRA, GL_UNSIGNED_BYTE, pBuffer.get());
210 0 : BitmapEx aBitmap = ConvertBGRABufferToBitmapEx(pBuffer.get(), nWidth, nHeight);
211 : try {
212 0 : vcl::PNGWriter aWriter( aBitmap );
213 0 : SvFileStream sOutput( rFileName, StreamMode::WRITE );
214 0 : aWriter.Write( sOutput );
215 0 : sOutput.Close();
216 0 : } catch (...) {
217 : SAL_WARN("vcl.opengl", "Error writing png to " << rFileName);
218 : }
219 :
220 0 : CHECK_GL_ERROR();
221 0 : }
222 :
223 0 : BitmapEx OpenGLHelper::ConvertBGRABufferToBitmapEx(const sal_uInt8* const pBuffer, long nWidth, long nHeight)
224 : {
225 : assert(pBuffer);
226 0 : Bitmap aBitmap( Size(nWidth, nHeight), 24 );
227 0 : AlphaMask aAlpha( Size(nWidth, nHeight) );
228 :
229 : {
230 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
231 0 : AlphaMask::ScopedWriteAccess pAlphaWriteAccess( aAlpha );
232 :
233 0 : size_t nCurPos = 0;
234 0 : for( long y = 0; y < nHeight; ++y)
235 : {
236 0 : Scanline pScan = pWriteAccess->GetScanline(y);
237 0 : Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(y);
238 0 : for( long x = 0; x < nWidth; ++x )
239 : {
240 0 : *pScan++ = pBuffer[nCurPos];
241 0 : *pScan++ = pBuffer[nCurPos+1];
242 0 : *pScan++ = pBuffer[nCurPos+2];
243 :
244 0 : nCurPos += 3;
245 0 : *pAlphaScan++ = static_cast<sal_uInt8>( 255 - pBuffer[nCurPos++] );
246 : }
247 0 : }
248 : }
249 0 : return BitmapEx(aBitmap, aAlpha);
250 : }
251 :
252 0 : const char* OpenGLHelper::GLErrorString(GLenum errorCode)
253 : {
254 : static const struct {
255 : GLenum code;
256 : const char *string;
257 : } errors[]=
258 : {
259 : /* GL */
260 : {GL_NO_ERROR, "no error"},
261 : {GL_INVALID_ENUM, "invalid enumerant"},
262 : {GL_INVALID_VALUE, "invalid value"},
263 : {GL_INVALID_OPERATION, "invalid operation"},
264 : {GL_STACK_OVERFLOW, "stack overflow"},
265 : {GL_STACK_UNDERFLOW, "stack underflow"},
266 : {GL_OUT_OF_MEMORY, "out of memory"},
267 : {GL_INVALID_FRAMEBUFFER_OPERATION, "invalid framebuffer operation"},
268 :
269 : {0, NULL }
270 : };
271 :
272 : int i;
273 :
274 0 : for (i=0; errors[i].string; i++)
275 : {
276 0 : if (errors[i].code == errorCode)
277 : {
278 0 : return errors[i].string;
279 : }
280 : }
281 :
282 0 : return NULL;
283 : }
284 :
285 0 : std::ostream& operator<<(std::ostream& rStrm, const glm::vec4& rPos)
286 : {
287 0 : rStrm << "( " << rPos[0] << ", " << rPos[1] << ", " << rPos[2] << ", " << rPos[3] << ")";
288 0 : return rStrm;
289 : }
290 :
291 0 : std::ostream& operator<<(std::ostream& rStrm, const glm::vec3& rPos)
292 : {
293 0 : rStrm << "( " << rPos[0] << ", " << rPos[1] << ", " << rPos[2] << ")";
294 0 : return rStrm;
295 : }
296 :
297 0 : std::ostream& operator<<(std::ostream& rStrm, const glm::mat4& rMatrix)
298 : {
299 0 : for(int i = 0; i < 4; ++i)
300 : {
301 0 : rStrm << "\n( ";
302 0 : for(int j = 0; j < 4; ++j)
303 : {
304 0 : rStrm << rMatrix[j][i];
305 0 : rStrm << " ";
306 : }
307 0 : rStrm << ")\n";
308 : }
309 0 : return rStrm;
310 : }
311 :
312 0 : void OpenGLHelper::createFramebuffer(long nWidth, long nHeight, GLuint& nFramebufferId,
313 : GLuint& nRenderbufferDepthId, GLuint& nRenderbufferColorId, bool bRenderbuffer)
314 : {
315 : // create a renderbuffer for depth attachment
316 0 : glGenRenderbuffers(1, &nRenderbufferDepthId);
317 0 : glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
318 0 : glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, nWidth, nHeight);
319 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
320 :
321 0 : if(bRenderbuffer)
322 : {
323 : // create a renderbuffer for color attachment
324 0 : glGenRenderbuffers(1, &nRenderbufferColorId);
325 0 : glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferColorId);
326 0 : glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, nWidth, nHeight);
327 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
328 : }
329 : else
330 : {
331 0 : glGenTextures(1, &nRenderbufferColorId);
332 0 : glBindTexture(GL_TEXTURE_2D, nRenderbufferColorId);
333 0 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
334 0 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
335 0 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
336 0 : glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
337 : glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, nWidth, nHeight, 0,
338 0 : GL_RGBA, GL_UNSIGNED_BYTE, 0);
339 0 : glBindTexture(GL_TEXTURE_2D, 0);
340 :
341 : glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
342 0 : GL_TEXTURE_2D, nRenderbufferColorId, 0);
343 : }
344 :
345 : // create a framebuffer object and attach renderbuffer
346 0 : glGenFramebuffers(1, &nFramebufferId);
347 0 : glCheckFramebufferStatus(GL_FRAMEBUFFER);
348 0 : glBindFramebuffer(GL_FRAMEBUFFER, nFramebufferId);
349 : // attach a renderbuffer to FBO color attachment point
350 0 : glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferColorId);
351 0 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, nRenderbufferColorId);
352 0 : glCheckFramebufferStatus(GL_FRAMEBUFFER);
353 : // attach a renderbuffer to depth attachment point
354 0 : glBindRenderbuffer(GL_RENDERBUFFER, nRenderbufferDepthId);
355 0 : glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, nRenderbufferDepthId);
356 0 : GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
357 0 : if (status != GL_FRAMEBUFFER_COMPLETE)
358 : {
359 : SAL_WARN("vcl.opengl", "invalid framebuffer status");
360 : }
361 0 : glBindRenderbuffer(GL_RENDERBUFFER, 0);
362 0 : glBindFramebuffer(GL_FRAMEBUFFER, 0);
363 :
364 0 : CHECK_GL_ERROR();
365 0 : }
366 :
367 0 : float OpenGLHelper::getGLVersion()
368 : {
369 0 : float fVersion = 1.0;
370 0 : const GLubyte* aVersion = glGetString( GL_VERSION );
371 0 : if( aVersion && aVersion[0] )
372 : {
373 0 : fVersion = aVersion[0] - '0';
374 0 : if( aVersion[1] == '.' && aVersion[2] )
375 : {
376 0 : fVersion += (aVersion[2] - '0')/10.0;
377 : }
378 : }
379 :
380 0 : CHECK_GL_ERROR();
381 0 : return fVersion;
382 : }
383 :
384 0 : void OpenGLHelper::checkGLError(const char* pFile, size_t nLine)
385 : {
386 0 : GLenum glErr = glGetError();
387 0 : if (glErr != GL_NO_ERROR)
388 : {
389 0 : const char* sError = OpenGLHelper::GLErrorString(glErr);
390 :
391 0 : if (sError)
392 : SAL_WARN("vcl.opengl", "GL Error #" << glErr << "(" << sError << ") in File " << pFile << " at line: " << nLine);
393 : else
394 : SAL_WARN("vcl.opengl", "GL Error #" << glErr << " (no message available) in File " << pFile << " at line: " << nLine);
395 :
396 0 : glErr = glGetError();
397 : }
398 0 : }
399 :
400 12 : bool OpenGLHelper::isDeviceBlacklisted()
401 : {
402 : static bool bSet = false;
403 : static bool bBlacklisted = true; // assume the worst
404 12 : if (!bSet)
405 : {
406 : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID
407 12 : X11OpenGLDeviceInfo aInfo;
408 12 : bBlacklisted = aInfo.isDeviceBlocked();
409 : SAL_INFO("vcl.opengl", "blacklisted: " << bBlacklisted);
410 : #elif defined( _WIN32 )
411 : WinOpenGLDeviceInfo aInfo;
412 : bBlacklisted = aInfo.isDeviceBlocked();
413 : #else
414 : bBlacklisted = false;
415 : #endif
416 12 : bSet = true;
417 : }
418 :
419 12 : return bBlacklisted;
420 : }
421 :
422 12 : bool OpenGLHelper::supportsVCLOpenGL()
423 : {
424 12 : static bool bDisableGL = !!getenv("SAL_DISABLEGL");
425 12 : bool bBlacklisted = isDeviceBlacklisted();
426 :
427 12 : if (bDisableGL || bBlacklisted)
428 4 : return false;
429 : else
430 8 : return true;
431 : }
432 :
433 705 : bool OpenGLHelper::isVCLOpenGLEnabled()
434 : {
435 : /**
436 : * The !bSet part should only be called once! Changing the results in the same
437 : * run will mix OpenGL and normal rendering.
438 : */
439 : static bool bSet = false;
440 : static bool bEnable = false;
441 : static bool bForceOpenGL = false;
442 :
443 : // If we are a console app, then we don't use OpenGL
444 705 : if ( Application::IsConsoleOnly() )
445 0 : return false;
446 :
447 705 : if (bSet)
448 : {
449 693 : return bForceOpenGL || bEnable;
450 : }
451 : /*
452 : * There are a number of cases that these environment variables cover:
453 : * * SAL_FORCEGL forces OpenGL independent of any other option
454 : * * SAL_DISABLEGL or a blacklisted driver avoid the use of OpenGL if SAL_FORCEGL is not set
455 : * * SAL_ENABLEGL overrides VCL_HIDE_WINDOWS and the configuration variable
456 : * * the configuration variable is checked if no environment variable is set
457 : */
458 :
459 12 : bSet = true;
460 12 : bForceOpenGL = !!getenv("SAL_FORCEGL") || officecfg::Office::Common::VCL::ForceOpenGL::get();
461 12 : if (bForceOpenGL)
462 0 : return true;
463 :
464 12 : if (!supportsVCLOpenGL())
465 : {
466 4 : return false;
467 : }
468 :
469 8 : static bool bEnableGLEnv = !!getenv("SAL_ENABLEGL");
470 :
471 8 : bEnable = bEnableGLEnv;
472 :
473 8 : static bool bDuringBuild = getenv("VCL_HIDE_WINDOWS");
474 8 : if (bDuringBuild && !bEnable /* env. enable overrides */)
475 0 : bEnable = false;
476 8 : else if (officecfg::Office::Common::VCL::UseOpenGL::get())
477 0 : bEnable = true;
478 :
479 8 : return bEnable;
480 : }
481 :
482 : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID && !defined(LIBO_HEADLESS)
483 :
484 0 : bool OpenGLHelper::GetVisualInfo(Display* pDisplay, int nScreen, XVisualInfo& rVI)
485 : {
486 : XVisualInfo* pVI;
487 : int aAttrib[] = { GLX_RGBA,
488 : GLX_RED_SIZE, 8,
489 : GLX_GREEN_SIZE, 8,
490 : GLX_BLUE_SIZE, 8,
491 : GLX_DEPTH_SIZE, 24,
492 : GLX_STENCIL_SIZE, 8,
493 0 : None };
494 :
495 0 : pVI = glXChooseVisual( pDisplay, nScreen, aAttrib );
496 0 : if( !pVI )
497 0 : return false;
498 :
499 0 : rVI = *pVI;
500 0 : XFree( pVI );
501 :
502 0 : CHECK_GL_ERROR();
503 0 : return true;
504 : }
505 :
506 0 : GLXFBConfig OpenGLHelper::GetPixmapFBConfig( Display* pDisplay, bool& bInverted )
507 : {
508 0 : int nScreen = DefaultScreen( pDisplay );
509 : GLXFBConfig *aFbConfigs;
510 : int i, nFbConfigs, nValue;
511 :
512 0 : aFbConfigs = glXGetFBConfigs( pDisplay, nScreen, &nFbConfigs );
513 0 : for( i = 0; i < nFbConfigs; i++ )
514 : {
515 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_DRAWABLE_TYPE, &nValue );
516 0 : if( !(nValue & GLX_PIXMAP_BIT) )
517 0 : continue;
518 :
519 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_BIND_TO_TEXTURE_TARGETS_EXT, &nValue );
520 0 : if( !(nValue & GLX_TEXTURE_2D_BIT_EXT) )
521 0 : continue;
522 :
523 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_DEPTH_SIZE, &nValue );
524 0 : if( nValue != 24 )
525 0 : continue;
526 :
527 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_RED_SIZE, &nValue );
528 0 : if( nValue != 8 )
529 0 : continue;
530 : SAL_INFO( "vcl.opengl", "Red is " << nValue );
531 :
532 : // TODO: lfrb: Make it configurable wrt RGB/RGBA
533 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_BIND_TO_TEXTURE_RGB_EXT, &nValue );
534 0 : if( nValue == False )
535 : {
536 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_BIND_TO_TEXTURE_RGBA_EXT, &nValue );
537 0 : if( nValue == False )
538 0 : continue;
539 : }
540 :
541 0 : glXGetFBConfigAttrib( pDisplay, aFbConfigs[i], GLX_Y_INVERTED_EXT, &nValue );
542 0 : bInverted = nValue == True;
543 :
544 0 : break;
545 : }
546 :
547 0 : if( i == nFbConfigs )
548 : {
549 : SAL_WARN( "vcl.opengl", "Unable to find FBconfig for pixmap texturing" );
550 0 : return 0;
551 : }
552 :
553 0 : CHECK_GL_ERROR();
554 0 : return aFbConfigs[i];
555 : }
556 :
557 : #endif
558 :
559 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|