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/OpenGLContext.hxx>
11 : #include <vcl/syschild.hxx>
12 : #include <vcl/sysdata.hxx>
13 :
14 : #include <boost/scoped_array.hpp>
15 : #include <vcl/pngwrite.hxx>
16 : #include <vcl/bmpacc.hxx>
17 : #include <vcl/graph.hxx>
18 : #include <vcl/bitmapex.hxx>
19 :
20 : using namespace com::sun::star;
21 :
22 0 : OpenGLContext::OpenGLContext():
23 : mpWindow(NULL),
24 0 : mbInitialized(false)
25 : {
26 0 : }
27 :
28 0 : OpenGLContext::~OpenGLContext()
29 : {
30 0 : }
31 :
32 : #if defined( _WIN32 )
33 : static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
34 : {
35 : switch (message)
36 : {
37 : case WM_CREATE:
38 : return 0;
39 : case WM_CLOSE:
40 : PostQuitMessage(0);
41 : return 0;
42 : case WM_DESTROY:
43 : return 0;
44 : case WM_KEYDOWN:
45 : switch(wParam)
46 : {
47 : case VK_ESCAPE:
48 : PostQuitMessage(0);
49 : return 0;
50 :
51 : case VK_SPACE:
52 : break;
53 : }
54 : default:
55 : return DefWindowProc(hwnd, message, wParam, lParam);
56 : }
57 : }
58 :
59 : int InitTempWindow(HWND *hwnd, int width, int height, PIXELFORMATDESCRIPTOR inPfd, GLWindow glWin)
60 : {
61 : PIXELFORMATDESCRIPTOR pfd = inPfd;
62 : int pfmt;
63 : int ret;
64 : WNDCLASS wc;
65 : wc.style = 0;
66 : wc.lpfnWndProc = WndProc;
67 : wc.cbClsExtra = wc.cbWndExtra = 0;
68 : wc.hInstance = NULL;
69 : wc.hIcon = NULL;
70 : wc.hCursor = NULL;
71 : wc.hbrBackground = NULL;
72 : wc.lpszMenuName = NULL;
73 : wc.lpszClassName = (LPCSTR)"GLRenderer";
74 : RegisterClass(&wc);
75 : *hwnd = CreateWindow(wc.lpszClassName, NULL, WS_DISABLED, 0, 0, width, height, NULL, NULL, wc.hInstance, NULL);
76 : glWin.hDC = GetDC(*hwnd);
77 : pfmt = ChoosePixelFormat(glWin.hDC, &pfd);
78 : if (!pfmt)
79 : {
80 : return -1;
81 : }
82 : ret = SetPixelFormat(glWin.hDC, pfmt, &pfd);
83 : if(!ret)
84 : {
85 : return -1;
86 : }
87 : glWin.hRC = wglCreateContext(glWin.hDC);
88 : if(!(glWin.hRC))
89 : {
90 : return -1;
91 : }
92 : ret = wglMakeCurrent(glWin.hDC, glWin.hRC);
93 : if(!ret)
94 : {
95 : return -1;
96 : }
97 : return 0;
98 : }
99 :
100 : bool WGLisExtensionSupported(const char *extension)
101 : {
102 : const size_t extlen = strlen(extension);
103 : const char *supported = NULL;
104 :
105 : // Try To Use wglGetExtensionStringARB On Current DC, If Possible
106 : PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
107 :
108 : if (wglGetExtString)
109 : supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());
110 : // If That Failed, Try Standard Opengl Extensions String
111 : if (supported == NULL)
112 : supported = (char*)glGetString(GL_EXTENSIONS);
113 : // If That Failed Too, Must Be No Extensions Supported
114 : if (supported == NULL)
115 : return 0;
116 :
117 : // Begin Examination At Start Of String, Increment By 1 On False Match
118 : for (const char* p = supported; ; p++)
119 : {
120 : // Advance p Up To The Next Possible Match
121 : p = strstr(p, extension);
122 :
123 : if (p == NULL)
124 : return 0; // No Match
125 :
126 : // Make Sure That Match Is At The Start Of The String Or That
127 : // The Previous Char Is A Space, Or Else We Could Accidentally
128 : // Match "wglFunkywglExtension" With "wglExtension"
129 :
130 : // Also, Make Sure That The Following Character Is Space Or NULL
131 : // Or Else "wglExtensionTwo" Might Match "wglExtension"
132 : if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
133 : return 1; // Match
134 : }
135 : }
136 :
137 : bool InitMultisample(PIXELFORMATDESCRIPTOR pfd, int& rPixelFormat)
138 : {
139 : HWND hWnd = NULL;
140 : GLWindow glWin;
141 : //create a temp windwo to check whether support multi-sample, if support, get the format
142 : if (InitTempWindow(&hWnd, 1, 1, pfd, glWin) < 0)
143 : {
144 : SAL_WARN("vcl.opengl", "Can't create temp window to test");
145 : return false;
146 : }
147 :
148 : // See If The String Exists In WGL!
149 : if (!WGLisExtensionSupported("WGL_ARB_multisample"))
150 : {
151 : SAL_WARN("vcl.opengl", "Device doesn't support multi sample");
152 : return false;
153 : }
154 : // Get Our Pixel Format
155 : PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
156 : if (!wglChoosePixelFormatARB)
157 : {
158 : return false;
159 : }
160 : // Get Our Current Device Context
161 : HDC hDC = GetDC(hWnd);
162 :
163 : int pixelFormat;
164 : int valid;
165 : UINT numFormats;
166 : float fAttributes[] = {0,0};
167 : // These Attributes Are The Bits We Want To Test For In Our Sample
168 : // Everything Is Pretty Standard, The Only One We Want To
169 : // Really Focus On Is The SAMPLE BUFFERS ARB And WGL SAMPLES
170 : // These Two Are Going To Do The Main Testing For Whether Or Not
171 : // We Support Multisampling On This Hardware.
172 : int iAttributes[] =
173 : {
174 : WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
175 : WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
176 : WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
177 : WGL_COLOR_BITS_ARB,24,
178 : WGL_ALPHA_BITS_ARB,8,
179 : WGL_DEPTH_BITS_ARB,16,
180 : WGL_STENCIL_BITS_ARB,0,
181 : WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
182 : WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
183 : WGL_SAMPLES_ARB,8,
184 : 0,0
185 : };
186 :
187 : bool bArbMultisampleSupported = true;
188 :
189 : // First We Check To See If We Can Get A Pixel Format For 4 Samples
190 : valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
191 : // If We Returned True, And Our Format Count Is Greater Than 1
192 : if (valid && numFormats >= 1)
193 : {
194 : bArbMultisampleSupported = true;
195 : rPixelFormat = pixelFormat;
196 : wglMakeCurrent(NULL, NULL);
197 : wglDeleteContext(glWin.hRC);
198 : ReleaseDC(hWnd, glWin.hDC);
199 : DestroyWindow(hWnd);
200 : return bArbMultisampleSupported;
201 : }
202 : // Our Pixel Format With 4 Samples Failed, Test For 2 Samples
203 : iAttributes[19] = 2;
204 : valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats);
205 : if (valid && numFormats >= 1)
206 : {
207 : bArbMultisampleSupported = true;
208 : rPixelFormat = pixelFormat;
209 : wglMakeCurrent(NULL, NULL);
210 : wglDeleteContext(glWin.hRC);
211 : ReleaseDC(hWnd, glWin.hDC);
212 : DestroyWindow(hWnd);
213 : return bArbMultisampleSupported;
214 : }
215 : // Return The Valid Format
216 : wglMakeCurrent(NULL, NULL);
217 : wglDeleteContext(glWin.hRC);
218 : ReleaseDC(hWnd, glWin.hDC);
219 : DestroyWindow(hWnd);
220 :
221 : return bArbMultisampleSupported;
222 : }
223 : #endif
224 :
225 : #ifdef DBG_UTIL
226 :
227 : namespace {
228 :
229 : const char* getSeverityString(GLenum severity)
230 : {
231 : switch(severity)
232 : {
233 : case GL_DEBUG_SEVERITY_LOW:
234 : return "low";
235 : case GL_DEBUG_SEVERITY_MEDIUM:
236 : return "medium";
237 : case GL_DEBUG_SEVERITY_HIGH:
238 : return "high";
239 : default:
240 : ;
241 : }
242 :
243 : return "unknown";
244 : }
245 :
246 : const char* getSourceString(GLenum source)
247 : {
248 : switch(source)
249 : {
250 : case GL_DEBUG_SOURCE_API:
251 : return "API";
252 : case GL_DEBUG_SOURCE_SHADER_COMPILER:
253 : return "shader compiler";
254 : case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
255 : return "window system";
256 : case GL_DEBUG_SOURCE_THIRD_PARTY:
257 : return "third party";
258 : case GL_DEBUG_SOURCE_APPLICATION:
259 : return "Libreoffice";
260 : case GL_DEBUG_SOURCE_OTHER:
261 : return "unknown";
262 : default:
263 : ;
264 : }
265 :
266 : return "unknown";
267 : }
268 :
269 : const char* getTypeString(GLenum type)
270 : {
271 : switch(type)
272 : {
273 : case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
274 : return "deprecated behavior";
275 : case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
276 : return "undefined behavior";
277 : case GL_DEBUG_TYPE_PERFORMANCE:
278 : return "performance";
279 : case GL_DEBUG_TYPE_PORTABILITY:
280 : return "portability";
281 : case GL_DEBUG_TYPE_MARKER:
282 : return "marker";
283 : case GL_DEBUG_TYPE_PUSH_GROUP:
284 : return "push group";
285 : case GL_DEBUG_TYPE_POP_GROUP:
286 : return "pop group";
287 : case GL_DEBUG_TYPE_OTHER:
288 : return "other";
289 : default:
290 : ;
291 : }
292 :
293 : return "unkown";
294 : }
295 :
296 : extern "C" void
297 : #if defined _WIN32
298 : APIENTRY
299 : #endif
300 : debug_callback(GLenum source, GLenum type, GLuint id,
301 : GLenum severity, GLsizei , const GLchar* message, GLvoid* )
302 : {
303 : SAL_WARN("vcl.opengl", "OpenGL debug message: source: " << getSourceString(source) << ", type: "
304 : << getTypeString(type) << ", id: " << id << ", severity: " << getSeverityString(severity) << " with message: " << message);
305 : }
306 :
307 : }
308 :
309 : #endif
310 :
311 : #if defined UNX && !defined MACOSX && !defined IOS && !defined ANDROID
312 :
313 : namespace {
314 :
315 : static bool errorTriggered;
316 0 : int oglErrorHandler( Display* /*dpy*/, XErrorEvent* /*evnt*/ )
317 : {
318 0 : errorTriggered = true;
319 :
320 0 : return 0;
321 : }
322 :
323 : }
324 :
325 : #endif
326 :
327 0 : bool OpenGLContext::init( Window* pParent )
328 : {
329 0 : if(mbInitialized)
330 0 : return true;
331 :
332 0 : m_pWindow.reset(pParent ? NULL : new Window(0, WB_NOBORDER|WB_NODIALOGCONTROL));
333 0 : mpWindow = pParent ? pParent : m_pWindow.get();
334 : SAL_INFO("vcl.opengl", "OpenGLContext::OpenGLContext----start");
335 0 : initWindow();
336 0 : if(m_pWindow)
337 0 : m_pWindow->setPosSizePixel(0,0,0,0);
338 0 : m_aGLWin.Width = 0;
339 0 : m_aGLWin.Height = 0;
340 :
341 : #if defined( WNT )
342 : m_aGLWin.hDC = GetDC(m_aGLWin.hWnd);
343 : #elif defined( MACOSX )
344 :
345 : #elif defined( IOS )
346 :
347 : #elif defined( ANDROID )
348 :
349 : #elif defined( UNX )
350 : m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
351 : m_aGLWin.vi,
352 : 0,
353 0 : GL_TRUE);
354 0 : if( m_aGLWin.ctx == NULL )
355 : {
356 : SAL_INFO("vcl.opengl", "unable to create GLX context");
357 0 : return false;
358 : }
359 : #endif
360 :
361 : #if defined( WNT )
362 : PIXELFORMATDESCRIPTOR PixelFormatFront = // PixelFormat Tells Windows How We Want Things To Be
363 : {
364 : sizeof(PIXELFORMATDESCRIPTOR),
365 : 1, // Version Number
366 : PFD_DRAW_TO_WINDOW |
367 : PFD_SUPPORT_OPENGL |
368 : PFD_DOUBLEBUFFER,
369 : PFD_TYPE_RGBA, // Request An RGBA Format
370 : (BYTE)32, // Select Our Color Depth
371 : 0, 0, 0, 0, 0, 0, // Color Bits Ignored
372 : 0, // No Alpha Buffer
373 : 0, // Shift Bit Ignored
374 : 0, // No Accumulation Buffer
375 : 0, 0, 0, 0, // Accumulation Bits Ignored
376 : 64, // 32 bit Z-BUFFER
377 : 0, // 0 bit stencil buffer
378 : 0, // No Auxiliary Buffer
379 : 0, // now ignored
380 : 0, // Reserved
381 : 0, 0, 0 // Layer Masks Ignored
382 : };
383 :
384 : // we must check whether can set the MSAA
385 : int WindowPix;
386 : bool bMultiSampleSupport = InitMultisample(PixelFormatFront, WindowPix);
387 : if (bMultiSampleSupport)
388 : {
389 : m_aGLWin.bMultiSampleSupported = true;
390 : }
391 : else
392 : {
393 : WindowPix = ChoosePixelFormat(m_aGLWin.hDC,&PixelFormatFront);
394 : }
395 : SetPixelFormat(m_aGLWin.hDC,WindowPix,&PixelFormatFront);
396 : m_aGLWin.hRC = wglCreateContext(m_aGLWin.hDC);
397 : wglMakeCurrent(m_aGLWin.hDC,m_aGLWin.hRC);
398 :
399 : #elif defined( MACOSX )
400 :
401 : #elif defined( IOS )
402 :
403 : #elif defined( ANDROID )
404 :
405 : #elif defined( UNX )
406 0 : if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
407 : {
408 : SAL_INFO("vcl.opengl", "unable to select current GLX context");
409 0 : return false;
410 : }
411 :
412 : int glxMinor, glxMajor;
413 0 : double nGLXVersion = 0;
414 0 : if( glXQueryVersion( m_aGLWin.dpy, &glxMajor, &glxMinor ) )
415 0 : nGLXVersion = glxMajor + 0.1*glxMinor;
416 : SAL_INFO("vcl.opengl", "available GLX version: " << nGLXVersion);
417 :
418 0 : m_aGLWin.GLExtensions = glGetString( GL_EXTENSIONS );
419 : SAL_INFO("vcl.opengl", "available GL extensions: " << m_aGLWin.GLExtensions);
420 :
421 0 : if( m_aGLWin.HasGLXExtension("GLX_SGI_swap_control" ) )
422 : {
423 : // enable vsync
424 : typedef GLint (*glXSwapIntervalProc)(GLint);
425 0 : glXSwapIntervalProc glXSwapInterval = (glXSwapIntervalProc) glXGetProcAddress( (const GLubyte*) "glXSwapIntervalSGI" );
426 0 : if( glXSwapInterval ) {
427 : int (*oldHandler)(Display* /*dpy*/, XErrorEvent* /*evnt*/);
428 :
429 : // replace error handler temporarily
430 0 : oldHandler = XSetErrorHandler( oglErrorHandler );
431 :
432 0 : errorTriggered = false;
433 :
434 0 : glXSwapInterval( 1 );
435 :
436 : // sync so that we possibly get an XError
437 0 : glXWaitGL();
438 0 : XSync(m_aGLWin.dpy, false);
439 :
440 0 : if( errorTriggered )
441 : SAL_INFO("vcl.opengl", "error when trying to set swap interval, NVIDIA or Mesa bug?");
442 : else
443 : SAL_INFO("vcl.opengl", "set swap interval to 1 (enable vsync)");
444 :
445 : // restore the error handler
446 0 : XSetErrorHandler( oldHandler );
447 : }
448 : }
449 :
450 : #endif
451 :
452 : //rGLRender.InitOpenGL(m_aGLWin);
453 :
454 : #ifdef DBG_UTIL
455 : // only enable debug output in dbgutil build
456 : if( GLEW_ARB_debug_output )
457 : {
458 : glEnable(GL_DEBUG_OUTPUT);
459 : glDebugMessageCallback(&debug_callback, NULL);
460 : }
461 :
462 : #endif
463 :
464 : static bool bGlewInit = false;
465 0 : if(!bGlewInit)
466 : {
467 0 : glewExperimental = GL_TRUE;
468 0 : if (glewInit() != GLEW_OK)
469 : {
470 : SAL_WARN("vcl.opengl", "Failed to initialize GLEW");
471 0 : return false;
472 : }
473 : else
474 0 : bGlewInit = true;
475 : }
476 :
477 : SAL_INFO("vcl.opengl", "OpenGLContext::init----end");
478 0 : mbInitialized = true;
479 0 : return true;
480 : }
481 :
482 0 : void OpenGLContext::setWinSize(const Size& rSize)
483 : {
484 0 : if(m_pWindow)
485 0 : m_pWindow->SetSizePixel(rSize);
486 0 : m_pChildWindow->SetSizePixel(rSize);
487 :
488 0 : m_aGLWin.Width = rSize.Width();
489 0 : m_aGLWin.Height = rSize.Height();
490 0 : }
491 :
492 0 : GLWindow& OpenGLContext::getOpenGLWindow()
493 : {
494 0 : return m_aGLWin;
495 : }
496 :
497 0 : void OpenGLContext::renderToFile()
498 : {
499 0 : int iWidth = m_aGLWin.Width;
500 0 : int iHeight = m_aGLWin.Height;
501 0 : boost::scoped_array<sal_uInt8> buf(new sal_uInt8[iWidth * iHeight * 4]);
502 0 : glReadPixels(0, 0, iWidth, iHeight, GL_BGRA, GL_UNSIGNED_BYTE, buf.get());
503 :
504 0 : Bitmap aBitmap( Size(iWidth, iHeight), 24 );
505 0 : AlphaMask aAlpha( Size(iWidth, iHeight) );
506 :
507 : {
508 0 : Bitmap::ScopedWriteAccess pWriteAccess( aBitmap );
509 0 : AlphaMask::ScopedWriteAccess pAlphaWriteAccess( aAlpha );
510 :
511 0 : size_t nCurPos = 0;
512 0 : for( int y = 0; y < iHeight; ++y)
513 : {
514 0 : Scanline pScan = pWriteAccess->GetScanline(y);
515 0 : Scanline pAlphaScan = pAlphaWriteAccess->GetScanline(y);
516 0 : for( int x = 0; x < iWidth; ++x )
517 : {
518 0 : *pScan++ = buf[nCurPos];
519 0 : *pScan++ = buf[nCurPos+1];
520 0 : *pScan++ = buf[nCurPos+2];
521 :
522 0 : nCurPos += 3;
523 0 : *pAlphaScan++ = static_cast<sal_uInt8>( 255 - buf[nCurPos++] );
524 : }
525 0 : }
526 : }
527 :
528 0 : BitmapEx aBmp(aBitmap, aAlpha);
529 : static int nIdx = 0;
530 0 : OUString aName = OUString( "file:///home/moggi/Documents/work/text" ) + OUString::number( nIdx++ ) + ".png";
531 : try {
532 0 : vcl::PNGWriter aWriter( aBmp );
533 0 : SvFileStream sOutput( aName, STREAM_WRITE );
534 0 : aWriter.Write( sOutput );
535 0 : sOutput.Close();
536 0 : } catch (...) {
537 : SAL_WARN("chart2.opengl", "Error writing png to " << aName);
538 0 : }
539 0 : }
540 :
541 : #if defined( WNT )
542 :
543 : bool OpenGLContext::initWindow()
544 : {
545 : const SystemEnvData* sysData(mpWindow->GetSystemData());
546 : m_aGLWin.hWnd = sysData->hWnd;
547 : SystemWindowData winData;
548 : winData.nSize = sizeof(winData);
549 : m_pChildWindow.reset(new SystemChildWindow(mpWindow, 0, &winData, sal_False));
550 :
551 : if( m_pChildWindow )
552 : {
553 : m_pChildWindow->SetMouseTransparent( sal_True );
554 : m_pChildWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
555 : m_pChildWindow->EnableEraseBackground( sal_False );
556 : m_pChildWindow->SetControlForeground();
557 : m_pChildWindow->SetControlBackground();
558 : m_pChildWindow->EnablePaint(sal_False);
559 : m_aGLWin.hWnd = sysData->hWnd;
560 : }
561 :
562 : return true;
563 : }
564 :
565 : #elif defined( MACOSX ) || defined( IOS) || defined( ANDROID )
566 :
567 : bool OpenGLContext::initWindow()
568 : {
569 : return false;
570 : }
571 :
572 : #elif defined( UNX )
573 :
574 : namespace {
575 :
576 : // we need them before glew can initialize them
577 : // glew needs an OpenGL context so we need to get the address manually
578 0 : void initOpenGLFunctionPointers()
579 : {
580 0 : glXChooseFBConfig = (GLXFBConfig*(*)(Display *dpy, int screen, const int *attrib_list, int *nelements))glXGetProcAddressARB((GLubyte*)"glXChooseFBConfig");
581 0 : glXGetVisualFromFBConfig = (XVisualInfo*(*)(Display *dpy, GLXFBConfig config))glXGetProcAddressARB((GLubyte*)"glXGetVisualFromFBConfig"); // try to find a visual for the current set of attributes
582 0 : glXGetFBConfigAttrib = (int(*)(Display *dpy, GLXFBConfig config, int attribute, int* value))glXGetProcAddressARB((GLubyte*)"glXGetFBConfigAttrib");
583 0 : }
584 :
585 : }
586 :
587 0 : bool OpenGLContext::initWindow()
588 : {
589 0 : const SystemEnvData* sysData(mpWindow->GetSystemData());
590 :
591 0 : m_aGLWin.dpy = reinterpret_cast<Display*>(sysData->pDisplay);
592 :
593 0 : if( !glXQueryExtension( m_aGLWin.dpy, NULL, NULL ) )
594 0 : return false;
595 :
596 0 : m_aGLWin.win = sysData->aWindow;
597 :
598 : SAL_INFO("vcl.opengl", "parent window: " << m_aGLWin.win);
599 :
600 : XWindowAttributes xattr;
601 0 : XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &xattr );
602 :
603 0 : m_aGLWin.screen = XScreenNumberOfScreen( xattr.screen );
604 :
605 : static int visual_attribs[] =
606 : {
607 : GLX_RED_SIZE, 8,
608 : GLX_GREEN_SIZE, 8,
609 : GLX_BLUE_SIZE, 8,
610 : GLX_ALPHA_SIZE, 8,
611 : GLX_DEPTH_SIZE, 24,
612 : GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
613 : None
614 : };
615 :
616 0 : const SystemEnvData* pChildSysData = NULL;
617 0 : m_pChildWindow.reset();
618 :
619 0 : initOpenGLFunctionPointers();
620 :
621 0 : int fbCount = 0;
622 : GLXFBConfig* pFBC = glXChooseFBConfig( m_aGLWin.dpy,
623 : m_aGLWin.screen,
624 0 : visual_attribs, &fbCount );
625 :
626 0 : if(!pFBC)
627 : {
628 : SAL_WARN("vcl.opengl", "no suitable fb format found");
629 0 : return false;
630 : }
631 :
632 0 : int best_fbc = -1, best_num_samp = -1;
633 0 : for(int i = 0; i < fbCount; ++i)
634 : {
635 0 : XVisualInfo* pVi = glXGetVisualFromFBConfig( m_aGLWin.dpy, pFBC[i] );
636 0 : if(pVi)
637 : {
638 : // pick the one with the most samples per pixel
639 0 : int nSampleBuf = 0;
640 0 : int nSamples = 0;
641 0 : glXGetFBConfigAttrib( m_aGLWin.dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
642 0 : glXGetFBConfigAttrib( m_aGLWin.dpy, pFBC[i], GLX_SAMPLES , &nSamples );
643 :
644 0 : if ( best_fbc < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
645 : {
646 0 : best_fbc = i;
647 0 : best_num_samp = nSamples;
648 : }
649 : }
650 0 : XFree( pVi );
651 : }
652 :
653 0 : if(best_num_samp > 0)
654 0 : m_aGLWin.bMultiSampleSupported = true;
655 :
656 0 : XVisualInfo* vi = glXGetVisualFromFBConfig( m_aGLWin.dpy, pFBC[best_fbc] );
657 0 : if( vi )
658 : {
659 : SystemWindowData winData;
660 0 : winData.nSize = sizeof(winData);
661 : SAL_INFO("vcl.opengl", "using VisualID " << vi->visualid);
662 0 : winData.pVisual = (void*)(vi->visual);
663 0 : m_pChildWindow.reset(new SystemChildWindow(mpWindow, 0, &winData, false));
664 0 : pChildSysData = m_pChildWindow->GetSystemData();
665 : }
666 :
667 0 : if (!m_pChildWindow || !pChildSysData)
668 0 : return false;
669 :
670 0 : m_pChildWindow->SetMouseTransparent( true );
671 0 : m_pChildWindow->SetParentClipMode( PARENTCLIPMODE_NOCLIP );
672 0 : m_pChildWindow->EnableEraseBackground( false );
673 0 : m_pChildWindow->SetControlForeground();
674 0 : m_pChildWindow->SetControlBackground();
675 :
676 0 : m_aGLWin.dpy = reinterpret_cast<Display*>(pChildSysData->pDisplay);
677 0 : m_aGLWin.win = pChildSysData->aWindow;
678 0 : m_aGLWin.vi = vi;
679 0 : m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
680 : SAL_INFO("vcl.opengl", "available GLX extensions: " << m_aGLWin.GLXExtensions);
681 :
682 0 : return true;
683 : }
684 :
685 : #endif
686 :
687 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|