44 void initGLWindow(Visual* pVisual);
50 virtual void sync()
override;
56 int unxErrorHandler(
Display* dpy, XErrorEvent* event)
61 XGetErrorText(dpy, event->error_code,
err, 256);
62 XGetErrorText(dpy, event->request_code, req, 256);
63 XGetErrorText(dpy, event->minor_code, minor, 256);
64 SAL_WARN(
"vcl.opengl",
"Error: " <<
err <<
", Req: " << req <<
", Minor: " << minor);
69 typedef int (*errorHandler)(
Display* , XErrorEvent* );
71 class TempErrorHandler
74 errorHandler oldErrorHandler;
78 TempErrorHandler(
Display* dpy, errorHandler newErrorHandler)
79 : oldErrorHandler(
nullptr)
86 oldErrorHandler = XSetErrorHandler(newErrorHandler);
97 XSetErrorHandler(oldErrorHandler);
104 int oglErrorHandler(
Display* , XErrorEvent* )
106 errorTriggered =
true;
111 GLXFBConfig* getFBConfig(
Display* dpy,
Window win,
int& nBestFBC)
115 if( dpy ==
nullptr || !glXQueryExtension( dpy,
nullptr,
nullptr ) )
120 XWindowAttributes xattr;
121 if( !XGetWindowAttributes( dpy, win, &xattr ) )
123 SAL_WARN(
"vcl.opengl",
"Failed to get window attributes for fbconfig " << win);
124 xattr.screen =
nullptr;
125 xattr.visual =
nullptr;
128 int screen = XScreenNumberOfScreen( xattr.screen );
131 static int visual_attribs[] =
133 GLX_DOUBLEBUFFER,
True,
134 GLX_X_RENDERABLE,
True,
140 GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
145 GLXFBConfig* pFBC = glXChooseFBConfig( dpy,
147 visual_attribs, &fbCount );
151 SAL_WARN(
"vcl.opengl",
"no suitable fb format found");
155 int best_num_samp = -1;
156 for(
int i = 0;
i < fbCount; ++
i)
158 XVisualInfo* pVi = glXGetVisualFromFBConfig( dpy, pFBC[
i] );
159 if(pVi && (xattr.visual && pVi->visualid == xattr.visual->visualid) )
164 glXGetFBConfigAttrib( dpy, pFBC[
i], GLX_SAMPLE_BUFFERS, &nSampleBuf );
165 glXGetFBConfigAttrib( dpy, pFBC[
i], GLX_SAMPLES , &nSamples );
167 if ( nBestFBC < 0 || (nSampleBuf && ( nSamples > best_num_samp )) )
170 best_num_samp = nSamples;
180void X11OpenGLContext::sync()
184 XSync(m_aGLWin.dpy,
false);
187void X11OpenGLContext::swapBuffers()
191 glXSwapBuffers(m_aGLWin.dpy, m_aGLWin.win);
196void X11OpenGLContext::resetCurrent()
204 glXMakeCurrent(m_aGLWin.dpy, None,
nullptr);
209bool X11OpenGLContext::isCurrent()
212 return g_bAnyCurrent && m_aGLWin.ctx && glXGetCurrentContext() == m_aGLWin.ctx &&
213 glXGetCurrentDrawable() == m_aGLWin.win;
216bool X11OpenGLContext::isAnyCurrent()
234 if( dpy ==
nullptr || !glXQueryExtension( dpy,
nullptr,
nullptr ) )
238 GLXFBConfig* pFBC = getFBConfig(dpy, win, best_fbc);
243 XVisualInfo* vi =
nullptr;
245 vi = glXGetVisualFromFBConfig( dpy, pFBC[best_fbc] );
252 aWinData.
pVisual =
static_cast<void*
>(vi->visual);
258bool X11OpenGLContext::ImplInit()
265 GLXContext pSharedCtx(
nullptr );
267 TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
276 static bool hasCreateContextAttribsARB = glXGetProcAddress(
reinterpret_cast<const GLubyte*
>(
"glXCreateContextAttribsARB")) !=
nullptr;
277 if (hasCreateContextAttribsARB && !mbRequestLegacyContext)
280 GLXFBConfig* pFBC = getFBConfig(m_aGLWin.dpy, m_aGLWin.win, best_fbc);
282 if (pFBC && best_fbc != -1)
284 int const pContextAttribs[] =
287 GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
288 GLX_CONTEXT_MINOR_VERSION_ARB, 2,
293 m_aGLWin.ctx = glXCreateContextAttribsARB(m_aGLWin.dpy, pFBC[best_fbc], pSharedCtx, GL_TRUE, pContextAttribs);
294 SAL_INFO_IF(m_aGLWin.ctx,
"vcl.opengl",
"created a 3.2 core context");
297 SAL_WARN(
"vcl.opengl",
"unable to find correct FBC");
305 SAL_WARN(
"vcl.opengl",
"attempting to create a non-double-buffered "
306 "visual matching the context");
308 m_aGLWin.ctx = glXCreateContext(m_aGLWin.dpy,
320 SAL_WARN(
"vcl.opengl",
"unable to create GLX context");
324 if( !glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ) )
327 SAL_WARN(
"vcl.opengl",
"unable to select current GLX context");
333 int glxMinor, glxMajor;
334 double nGLXVersion = 0;
335 if( glXQueryVersion( m_aGLWin.dpy, &glxMajor, &glxMinor ) )
336 nGLXVersion = glxMajor + 0.1*glxMinor;
337 SAL_INFO(
"vcl.opengl",
"available GLX version: " << nGLXVersion);
339 SAL_INFO(
"vcl.opengl",
"available GL extensions: " << glGetString(GL_EXTENSIONS));
341 XWindowAttributes aWinAttr;
342 if( !XGetWindowAttributes( m_aGLWin.dpy, m_aGLWin.win, &aWinAttr ) )
344 SAL_WARN(
"vcl.opengl",
"Failed to get window attributes on " << m_aGLWin.win);
350 m_aGLWin.Width = aWinAttr.width;
351 m_aGLWin.Height = aWinAttr.height;
354 if( m_aGLWin.HasGLXExtension(
"GLX_SGI_swap_control" ) )
357 typedef GLint (*glXSwapIntervalProc)(GLint);
358 glXSwapIntervalProc glXSwapInterval =
reinterpret_cast<glXSwapIntervalProc
>(glXGetProcAddress(
reinterpret_cast<const GLubyte*
>(
"glXSwapIntervalSGI") ));
359 if( glXSwapInterval )
361 TempErrorHandler aLocalErrorHandler(m_aGLWin.dpy, oglErrorHandler);
363 errorTriggered =
false;
365 glXSwapInterval( 1 );
368 SAL_WARN(
"vcl.opengl",
"error when trying to set swap interval, NVIDIA or Mesa bug?");
370 VCL_GL_INFO(
"set swap interval to 1 (enable vsync)");
374 bool bRet = InitGL();
377 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
384void X11OpenGLContext::makeCurrent()
394 TempErrorHandler aErrorHandler(m_aGLWin.dpy, unxErrorHandler);
399 if (!glXMakeCurrent( m_aGLWin.dpy, m_aGLWin.win, m_aGLWin.ctx ))
402 SAL_WARN(
"vcl.opengl",
"OpenGLContext::makeCurrent failed "
403 "on drawable " << m_aGLWin.win);
412void X11OpenGLContext::destroyCurrentContext()
421 glXMakeCurrent(m_aGLWin.dpy, None,
nullptr);
423 if( glGetError() != GL_NO_ERROR )
425 SAL_WARN(
"vcl.opengl",
"glError: " << glGetError());
427 glXDestroyContext(m_aGLWin.dpy, m_aGLWin.ctx);
428 m_aGLWin.ctx =
nullptr;
431void X11OpenGLContext::initGLWindow(Visual* pVisual)
437 XVisualInfo aTemplate;
438 aTemplate.visualid = XVisualIDFromVisual( pVisual );
440 XVisualInfo* pInfo = XGetVisualInfo( m_aGLWin.dpy, VisualIDMask, &aTemplate, &nVisuals );
442 SAL_WARN(
"vcl.opengl",
"match count for visual id is not 1" );
450 glXGetConfig(m_aGLWin.dpy, m_aGLWin.vi, GLX_SAMPLES, &nSamples);
452 m_aGLWin.bMultiSampleSupported =
true;
454 m_aGLWin.GLXExtensions = glXQueryExtensionsString( m_aGLWin.dpy, m_aGLWin.screen );
455 SAL_INFO(
"vcl.opengl",
"available GLX extensions: " << m_aGLWin.GLXExtensions);
458void X11OpenGLContext::initWindow()
464 if( !m_pChildWindow )
468 pChildSysData = m_pChildWindow->GetSystemData();
471 if (!m_pChildWindow || !pChildSysData)
474 InitChildWindow(m_pChildWindow.get());
477 m_aGLWin.win = pChildSysData->
GetWindowHandle(m_pChildWindow->ImplGetFrame());
478 m_aGLWin.screen = pChildSysData->
nScreen;
480 Visual* pVisual =
static_cast<Visual*
>(pChildSysData->
pVisual);
481 initGLWindow(pVisual);
495 for (sal_Int32
i = 0;
i != -1;) {
510 XSynchronize(
dpy, bOnoff);
516 return new X11OpenGLContext;
#define VCL_GL_INFO(stream)
Helper to do a SAL_INFO as well as a GL log.
virtual bool Synchronize(bool bOnoff) const override
virtual ~GLX11Window() override
bool HasGLXExtension(const char *name) const
virtual const GLWindow & getOpenGLWindow() const =0
virtual void makeCurrent()
make this GL context current - so it is implicit in subsequent GL calls
virtual void destroyCurrentContext()
virtual SystemWindowData generateWinData(vcl::Window *pParent, bool bRequestLegacyContext)
virtual void initWindow()
virtual bool isAnyCurrent()
Is any GL context the current context ?
virtual void swapBuffers()
virtual void resetCurrent()
reset the GL context so this context is not implicit in subsequent GL calls.
virtual GLWindow & getModifiableOpenGLWindow()=0
virtual bool isCurrent()
Is this GL context the current context ?
We want to be able to detect if a given crash came from the OpenGL code, so use this helper to track ...
static VclPtr< reference_type > Create(Arg &&... arg)
A construction helper for VclPtr.
virtual OpenGLContext * CreateOpenGLContext() override
SalFrame * ImplGetFrame() const
virtual const SystemEnvData * GetSystemData() const
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
const wchar_t *typedef int(__stdcall *DllNativeUnregProc)(int
Holds the information of our new child window.
sal_uIntPtr GetWindowHandle(const SalFrame *pReference) const
bool bClipUsingNativeWidget
static std::vector< GLXContext > g_vShareList
static bool g_bAnyCurrent