42 void initGLWindow(Visual* pVisual);
48 virtual void sync()
override;
54 int unxErrorHandler(
Display* dpy, XErrorEvent* event)
59 XGetErrorText(dpy, event->error_code, err, 256);
60 XGetErrorText(dpy, event->request_code, req, 256);
61 XGetErrorText(dpy, event->minor_code, minor, 256);
62 SAL_WARN(
"vcl.opengl",
"Error: " << err <<
", Req: " << req <<
", Minor: " << minor);
67 typedef int (*errorHandler)(
Display* , XErrorEvent* );
69 class TempErrorHandler
72 errorHandler oldErrorHandler;
76 TempErrorHandler(Display* dpy, errorHandler newErrorHandler)
77 : oldErrorHandler(
nullptr)
84 oldErrorHandler = XSetErrorHandler(newErrorHandler);
95 XSetErrorHandler(oldErrorHandler);
102 int oglErrorHandler( Display* , XErrorEvent* )
104 errorTriggered =
true;
109 GLXFBConfig* getFBConfig(Display* dpy,
Window win,
int& nBestFBC)
113 if( dpy ==
nullptr || !glXQueryExtension( dpy,
nullptr,
nullptr ) )
118 XWindowAttributes xattr;
119 if( !XGetWindowAttributes( dpy, win, &xattr ) )
121 SAL_WARN(
"vcl.opengl",
"Failed to get window attributes for fbconfig " << win);
122 xattr.screen =
nullptr;
123 xattr.visual =
nullptr;
126 int screen = XScreenNumberOfScreen( xattr.screen );
129 static int visual_attribs[] =
131 GLX_DOUBLEBUFFER,
True,
132 GLX_X_RENDERABLE, True,
138 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
143 GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
145 visual_attribs, &fbCount );
149 SAL_WARN(
"vcl.opengl",
"no suitable fb format found");
153 int best_num_samp = -1;
154 for(
int i = 0;
i < fbCount; ++
i)
156 XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[
i] );
157 if(pVi && (xattr.visual && pVi->visualid == xattr.visual->visualid) )
162 glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
163 glXGetFBConfigAttrib( dpy, pFBC[i], GLX_SAMPLES , &nSamples );
165 if ( nBestFBC < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
168 best_num_samp = nSamples;
178 void X11OpenGLContext::sync()
182 XSync(m_aGLWin.dpy,
false);
185 void X11OpenGLContext::swapBuffers()
189 glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
194 void X11OpenGLContext::resetCurrent()
202 glXMakeCurrent(m_aGLWin.dpy, None,
nullptr);
207 bool X11OpenGLContext::isCurrent()
210 return g_bAnyCurrent && m_aGLWin.ctx && glXGetCurrentContext() == m_aGLWin.ctx &&
211 glXGetCurrentDrawable() == m_aGLWin.win;
214 bool X11OpenGLContext::isAnyCurrent()
232 if( dpy ==
nullptr || !glXQueryExtension( dpy,
nullptr,
nullptr ) )
236 GLXFBConfig* pFBC = getFBConfig(dpy, win, best_fbc);
241 XVisualInfo* vi =
nullptr;
243 vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
250 aWinData.
pVisual =
static_cast<void*
>(vi->visual);
256 bool X11OpenGLContext::ImplInit()
263 GLXContext pSharedCtx(
nullptr );
265 TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
274 static bool hasCreateContextAttribsARB = glXGetProcAddress(reinterpret_cast<const GLubyte*>(
"glXCreateContextAttribsARB")) !=
nullptr;
275 if (hasCreateContextAttribsARB && !mbRequestLegacyContext)
278 GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc);
280 if (pFBC && best_fbc != -1)
282 int const pContextAttribs[] =
284 #if 0 // defined(DBG_UTIL)
285 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
286 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
291 m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, GL_TRUE, pContextAttribs);
292 SAL_INFO_IF(m_aGLWin.ctx,
"vcl.opengl",
"created a 3.2 core context");
295 SAL_WARN(
"vcl.opengl",
"unable to find correct FBC");
303 SAL_WARN(
"vcl.opengl",
"attempting to create a non-double-buffered "
304 "visual matching the context");
306 m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
318 SAL_WARN(
"vcl.opengl",
"unable to create GLX context");
322 if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
325 SAL_WARN(
"vcl.opengl",
"unable to select current GLX context");
331 int glxMinor, glxMajor;
332 double nGLXVersion = 0;
333 if( glXQueryVersion( m_aGLWin.dpy, &glxMajor, &glxMinor ) )
334 nGLXVersion = glxMajor + 0.1*glxMinor;
335 SAL_INFO(
"vcl.opengl",
"available GLX version: " << nGLXVersion);
337 SAL_INFO(
"vcl.opengl",
"available GL extensions: " << glGetString(GL_EXTENSIONS));
339 XWindowAttributes aWinAttr;
340 if( !XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &aWinAttr ) )
342 SAL_WARN(
"vcl.opengl",
"Failed to get window attributes on " << m_aGLWin.win);
348 m_aGLWin.Width = aWinAttr.width;
349 m_aGLWin.Height = aWinAttr.height;
352 if( m_aGLWin.HasGLXExtension(
"GLX_SGI_swap_control" ) )
355 typedef GLint (*glXSwapIntervalProc)(GLint);
356 glXSwapIntervalProc glXSwapInterval =
reinterpret_cast<glXSwapIntervalProc
>(glXGetProcAddress( reinterpret_cast<const GLubyte*>(
"glXSwapIntervalSGI") ));
357 if( glXSwapInterval )
359 TempErrorHandler aLocalErrorHandler(m_aGLWin.dpy, oglErrorHandler);
361 errorTriggered =
false;
363 glXSwapInterval( 1 );
366 SAL_WARN(
"vcl.opengl",
"error when trying to set swap interval, NVIDIA or Mesa bug?");
368 VCL_GL_INFO(
"set swap interval to 1 (enable vsync)");
372 bool bRet = InitGL();
375 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
382 void X11OpenGLContext::makeCurrent()
392 TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
397 if (!glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ))
400 SAL_WARN(
"vcl.opengl",
"OpenGLContext::makeCurrent failed "
401 "on drawable " << m_aGLWin.win);
410 void X11OpenGLContext::destroyCurrentContext()
419 glXMakeCurrent(m_aGLWin.dpy, None,
nullptr);
421 if( glGetError() != GL_NO_ERROR )
423 SAL_WARN(
"vcl.opengl",
"glError: " << glGetError());
425 glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
426 m_aGLWin.ctx =
nullptr;
429 void X11OpenGLContext::initGLWindow(Visual* pVisual)
435 XVisualInfo aTemplate;
436 aTemplate.visualid = XVisualIDFromVisual( pVisual );
438 XVisualInfo* pInfo = XGetVisualInfo( m_aGLWin.dpy, VisualIDMask, &aTemplate, &nVisuals );
440 SAL_WARN(
"vcl.opengl",
"match count for visual id is not 1" );
448 glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
450 m_aGLWin.bMultiSampleSupported =
true;
452 m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
453 SAL_INFO(
"vcl.opengl",
"available GLX extensions: " << m_aGLWin.GLXExtensions);
456 void X11OpenGLContext::initWindow()
462 if( !m_pChildWindow )
466 pChildSysData = m_pChildWindow->GetSystemData();
469 if (!m_pChildWindow || !pChildSysData)
472 InitChildWindow(m_pChildWindow.get());
475 m_aGLWin.win = pChildSysData->
GetWindowHandle(m_pChildWindow->ImplGetFrame());
476 m_aGLWin.screen = pChildSysData->
nScreen;
478 Visual* pVisual =
static_cast<Visual*
>(pChildSysData->
pVisual);
479 initGLWindow(pVisual);
493 for (sal_Int32
i = 0;
i != -1;) {
508 XSynchronize(dpy, bOnoff);
514 return new X11OpenGLContext;
virtual ~GLX11Window() override
static std::vector< GLXContext > g_vShareList
#define SAL_INFO_IF(condition, area, stream)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
virtual void initWindow()
sal_uIntPtr GetWindowHandle(const SalFrame *pReference) const
virtual bool isAnyCurrent()
Is any GL context the current context ?
bool HasGLXExtension(const char *name) const
static bool g_bAnyCurrent
virtual GLWindow & getModifiableOpenGLWindow()=0
virtual bool Synchronize(bool bOnoff) const override
virtual void resetCurrent()
reset the GL context so this context is not implicit in subsequent GL calls.
Holds the information of our new child window.
#define VCL_GL_INFO(stream)
Helper to do a SAL_INFO as well as a GL log.
virtual void swapBuffers()
virtual const GLWindow & getOpenGLWindow() const =0
virtual const SystemEnvData * GetSystemData() const
We want to be able to detect if a given crash came from the OpenGL code, so use this helper to track ...
virtual void makeCurrent()
make this GL context current - so it is implicit in subsequent GL calls
SalFrame * ImplGetFrame() const
virtual void destroyCurrentContext()
virtual OpenGLContext * CreateOpenGLContext() override
#define SAL_INFO(area, stream)
static VclPtr< reference_type > Create(Arg &&...arg)
A construction helper for VclPtr.
bool bClipUsingNativeWidget
#define SAL_WARN(area, stream)
virtual SystemWindowData generateWinData(vcl::Window *pParent, bool bRequestLegacyContext)
virtual bool isCurrent()
Is this GL context the current context ?