Refactor all code common to X11 OpenGL implementations into glx11.h/.cpp

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@45486 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2007-04-15 23:06:45 +00:00
parent e4e83f385a
commit 498ace9e1f
13 changed files with 711 additions and 976 deletions

359
src/unix/glx11.cpp Normal file
View File

@@ -0,0 +1,359 @@
///////////////////////////////////////////////////////////////////////////////
// Name: src/univ/glx11.cpp
// Purpose: code common to all X11-based wxGLCanvas implementations
// Author: Vadim Zeitlin
// Created: 2007-04-15
// RCS-ID: $Id$
// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwindows.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// for compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
#if wxUSE_GLCANVAS
#ifndef WX_PRECOMP
#endif //WX_PRECOMP
#include "wx/glcanvas.h"
// ============================================================================
// wxGLContext implementation
// ============================================================================
IMPLEMENT_CLASS(wxGLContext, wxObject)
wxGLContext::wxGLContext(wxGLCanvas *gc, const wxGLContext *other)
{
if ( wxGLCanvas::GetGLXVersion() >= 13 )
{
GLXFBConfig *fbc = gc->GetGLXFBConfig();
wxCHECK_RET( fbc, _T("invalid GLXFBConfig for OpenGL") );
m_glContext = glXCreateNewContext( wxGetX11Display(), fbc[0], GLX_RGBA_TYPE,
other ? other->m_glContext : None,
GL_TRUE );
}
else // GLX <= 1.2
{
XVisualInfo *vi = gc->GetXVisualInfo();
wxCHECK_RET( vi, _T("invalid visual for OpenGL") );
m_glContext = glXCreateContext( wxGetX11Display(), vi,
other ? other->m_glContext : None,
GL_TRUE );
}
wxASSERT_MSG( m_glContext, _T("Couldn't create OpenGL context") );
}
wxGLContext::~wxGLContext()
{
if ( !m_glContext )
return;
if ( m_glContext == glXGetCurrentContext() )
MakeCurrent(None, NULL);
glXDestroyContext( wxGetX11Display(), m_glContext );
}
void wxGLContext::SetCurrent(const wxGLCanvas& win) const
{
if ( !m_glContext )
return;
const Window xid = win.GetXWindow();
wxCHECK_RET( xid, _T("window must be shown") );
MakeCurrent(xid, m_glContext);
}
// wrapper around glXMakeContextCurrent/glXMakeCurrent depending on GLX
// version
/* static */
void wxGLContext::MakeCurrent(GLXDrawable drawable, GLXContext context)
{
if (wxGLCanvas::GetGLXVersion() >= 13)
glXMakeContextCurrent( wxGetX11Display(), drawable, drawable, context);
else // GLX <= 1.2 doesn't have glXMakeContextCurrent()
glXMakeCurrent( wxGetX11Display(), drawable, context);
}
// ============================================================================
// wxGLCanvasX11 implementation
// ============================================================================
// ----------------------------------------------------------------------------
// initialization methods and dtor
// ----------------------------------------------------------------------------
wxGLCanvasX11::wxGLCanvasX11()
{
m_fbc = NULL;
m_vi = NULL;
}
bool wxGLCanvasX11::InitVisual(const int *attribList)
{
return InitXVisualInfo(attribList, &m_fbc, &m_vi);
}
wxGLCanvasX11::~wxGLCanvasX11()
{
if ( m_fbc && m_fbc != ms_glFBCInfo )
XFree(m_fbc);
if ( m_vi && m_vi != ms_glVisualInfo )
XFree(m_vi);
}
// ----------------------------------------------------------------------------
// working with GL attributes
// ----------------------------------------------------------------------------
bool
wxGLCanvasX11::ConvertWXAttrsToGL(const int *wxattrs, int *glattrs, size_t n)
{
wxCHECK_MSG( n >= 16, false, _T("GL attributes buffer too small") );
if ( !wxattrs )
{
if ( GetGLXVersion() >= 13 )
{
// leave GLX >= 1.3 choose the default attributes
glattrs[0] = None;
}
else // GLX < 1.3
{
// default settings if attriblist = 0
size_t i = 0;
glattrs[i++] = GLX_RGBA;
glattrs[i++] = GLX_DOUBLEBUFFER;
glattrs[i++] = GLX_DEPTH_SIZE; glattrs[i++] = 1;
glattrs[i++] = GLX_RED_SIZE; glattrs[i++] = 1;
glattrs[i++] = GLX_GREEN_SIZE; glattrs[i++] = 1;
glattrs[i++] = GLX_BLUE_SIZE; glattrs[i++] = 1;
glattrs[i++] = GLX_ALPHA_SIZE; glattrs[i++] = 0;
glattrs[i++] = None;
wxASSERT_MSG( i < n, _T("GL attributes buffer too small") );
}
}
else // have non-default attributes
{
size_t p = 0;
for ( int arg = 0; wxattrs[arg] != 0; )
{
// check if we have any space left, knowing that we may insert 2
// more elements during this loop iteration and we always need to
// terminate the list with None (hence -3)
if ( p >= n - 2 )
return false;
// notice that for boolean attributes we use "continue" in the
// switch to skip the assignment of the attribute value at the end
// of the loop which is done for integer attributes
switch ( wxattrs[arg++] )
{
case WX_GL_RGBA:
// for GLX >= 1.3, GLX_RGBA is useless and apparently
// harmful for some implementations
//
// FIXME: is this true?
if ( GetGLXVersion() <= 12 )
{
glattrs[p++] = GLX_RGBA;
}
continue;
case WX_GL_BUFFER_SIZE:
glattrs[p++] = GLX_BUFFER_SIZE;
break;
case WX_GL_LEVEL:
glattrs[p++] = GLX_LEVEL;
break;
case WX_GL_DOUBLEBUFFER:
glattrs[p++] = GLX_DOUBLEBUFFER;
continue;
case WX_GL_STEREO:
glattrs[p++] = GLX_STEREO;
break;
case WX_GL_AUX_BUFFERS:
glattrs[p++] = GLX_AUX_BUFFERS;
break;
case WX_GL_MIN_RED:
glattrs[p++] = GLX_RED_SIZE;
break;
case WX_GL_MIN_GREEN:
glattrs[p++] = GLX_GREEN_SIZE;
break;
case WX_GL_MIN_BLUE:
glattrs[p++] = GLX_BLUE_SIZE;
break;
case WX_GL_MIN_ALPHA:
glattrs[p++] = GLX_ALPHA_SIZE;
break;
case WX_GL_DEPTH_SIZE:
glattrs[p++] = GLX_DEPTH_SIZE;
break;
case WX_GL_STENCIL_SIZE:
glattrs[p++] = GLX_STENCIL_SIZE;
break;
case WX_GL_MIN_ACCUM_RED:
glattrs[p++] = GLX_ACCUM_RED_SIZE;
break;
case WX_GL_MIN_ACCUM_GREEN:
glattrs[p++] = GLX_ACCUM_GREEN_SIZE;
break;
case WX_GL_MIN_ACCUM_BLUE:
glattrs[p++] = GLX_ACCUM_BLUE_SIZE;
break;
case WX_GL_MIN_ACCUM_ALPHA:
glattrs[p++] = GLX_ACCUM_ALPHA_SIZE;
break;
default:
wxLogDebug(_T("Unsupported OpenGL attribute %d"),
wxattrs[arg - 1]);
continue;
}
// copy attribute value as is
glattrs[p++] = wxattrs[arg++];
}
glattrs[p] = None;
}
return true;
}
/* static */
bool
wxGLCanvasX11::InitXVisualInfo(const int *attribList,
GLXFBConfig **pFBC,
XVisualInfo **pXVisual)
{
int data[512];
if ( !ConvertWXAttrsToGL(attribList, data, WXSIZEOF(data)) )
return false;
Display * const dpy = wxGetX11Display();
if ( GetGLXVersion() >= 13 )
{
int returned;
*pFBC = glXChooseFBConfig(dpy, DefaultScreen(dpy), data, &returned);
if ( *pFBC )
{
*pXVisual = glXGetVisualFromFBConfig(wxGetX11Display(), **pFBC);
if ( !*pXVisual )
{
XFree(*pFBC);
*pFBC = NULL;
}
}
}
else // GLX <= 1.2
{
*pFBC = NULL;
*pXVisual = glXChooseVisual(dpy, DefaultScreen(dpy), data);
}
return *pXVisual != NULL;
}
// ----------------------------------------------------------------------------
// default visual management
// ----------------------------------------------------------------------------
XVisualInfo *wxGLCanvasX11::ms_glVisualInfo = NULL;
GLXFBConfig *wxGLCanvasX11::ms_glFBCInfo = NULL;
/* static */
bool wxGLCanvasX11::InitDefaultVisualInfo(const int *attribList)
{
FreeDefaultVisualInfo();
return InitXVisualInfo(attribList, &ms_glFBCInfo, &ms_glVisualInfo);
}
/* static */
void wxGLCanvasX11::FreeDefaultVisualInfo()
{
if ( ms_glFBCInfo )
{
XFree(ms_glFBCInfo);
ms_glFBCInfo = NULL;
}
if ( ms_glVisualInfo )
{
XFree(ms_glVisualInfo);
ms_glVisualInfo = NULL;
}
}
// ----------------------------------------------------------------------------
// other GL methods
// ----------------------------------------------------------------------------
/* static */
int wxGLCanvasX11::GetGLXVersion()
{
static int s_glxVersion = 0;
if ( s_glxVersion == 0 )
{
// check the GLX version
int glxMajorVer, glxMinorVer;
bool ok = glXQueryVersion(wxGetX11Display(), &glxMajorVer, &glxMinorVer);
wxASSERT_MSG( ok, _T("GLX version not found") );
if (!ok)
s_glxVersion = 10; // 1.0 by default
else
s_glxVersion = glxMajorVer*10 + glxMinorVer;
}
return s_glxVersion;
}
void wxGLCanvasX11::SwapBuffers()
{
const Window xid = GetXWindow();
wxCHECK_RET( xid, _T("window must be shown") );
glXSwapBuffers(wxGetX11Display(), xid);
}
bool wxGLCanvasX11::IsShownOnScreen() const
{
return GetXWindow() && wxGLCanvasBase::IsShownOnScreen();
}
#endif // wxUSE_GLCANVAS