This keyword is not expanded by Git which means it's not replaced with the correct revision value in the releases made using git-based scripts and it's confusing to have lines with unexpanded "$Id$" in the released files. As expanding them with Git is not that simple (it could be done with git archive and export-subst attribute) and there are not many benefits in having them in the first place, just remove all these lines. If nothing else, this will make an eventual transition to Git simpler. Closes #14487. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@74602 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
379 lines
8.9 KiB
C++
379 lines
8.9 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/common/glcmn.cpp
|
|
// Purpose: wxGLCanvasBase implementation
|
|
// Author: Vadim Zeitlin
|
|
// Created: 2007-04-09
|
|
// 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"
|
|
|
|
#ifdef __BORLANDC__
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
#if wxUSE_GLCANVAS
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/log.h"
|
|
#endif // WX_PRECOMP
|
|
|
|
#include "wx/glcanvas.h"
|
|
|
|
// DLL options compatibility check:
|
|
#include "wx/build.h"
|
|
WX_CHECK_BUILD_OPTIONS("wxGL")
|
|
|
|
IMPLEMENT_CLASS(wxGLApp, wxApp)
|
|
|
|
// ============================================================================
|
|
// implementation
|
|
// ============================================================================
|
|
|
|
wxGLCanvasBase::wxGLCanvasBase()
|
|
{
|
|
#if WXWIN_COMPATIBILITY_2_8
|
|
m_glContext = NULL;
|
|
#endif
|
|
|
|
// we always paint background entirely ourselves so prevent wx from erasing
|
|
// it to avoid flicker
|
|
SetBackgroundStyle(wxBG_STYLE_CUSTOM);
|
|
}
|
|
|
|
bool wxGLCanvasBase::SetCurrent(const wxGLContext& context) const
|
|
{
|
|
// although on MSW it works even if the window is still hidden, it doesn't
|
|
// work in other ports (notably X11-based ones) and documentation mentions
|
|
// that SetCurrent() can only be called for a shown window, so check for it
|
|
wxASSERT_MSG( IsShownOnScreen(), wxT("can't make hidden GL canvas current") );
|
|
|
|
|
|
return context.SetCurrent(*static_cast<const wxGLCanvas *>(this));
|
|
}
|
|
|
|
bool wxGLCanvasBase::SetColour(const wxString& colour)
|
|
{
|
|
wxColour col = wxTheColourDatabase->Find(colour);
|
|
if ( !col.IsOk() )
|
|
return false;
|
|
|
|
#ifdef wxHAS_OPENGL_ES
|
|
wxGLAPI::glColor3f((GLfloat) (col.Red() / 256.), (GLfloat) (col.Green() / 256.),
|
|
(GLfloat) (col.Blue() / 256.));
|
|
#else
|
|
GLboolean isRGBA;
|
|
glGetBooleanv(GL_RGBA_MODE, &isRGBA);
|
|
if ( isRGBA )
|
|
{
|
|
glColor3f((GLfloat) (col.Red() / 256.), (GLfloat) (col.Green() / 256.),
|
|
(GLfloat) (col.Blue() / 256.));
|
|
}
|
|
else // indexed colour
|
|
{
|
|
GLint pix = GetColourIndex(col);
|
|
if ( pix == -1 )
|
|
{
|
|
wxLogError(_("Failed to allocate colour for OpenGL"));
|
|
return false;
|
|
}
|
|
|
|
glIndexi(pix);
|
|
}
|
|
#endif
|
|
return true;
|
|
}
|
|
|
|
wxGLCanvasBase::~wxGLCanvasBase()
|
|
{
|
|
#if WXWIN_COMPATIBILITY_2_8
|
|
delete m_glContext;
|
|
#endif // WXWIN_COMPATIBILITY_2_8
|
|
}
|
|
|
|
#if WXWIN_COMPATIBILITY_2_8
|
|
|
|
wxGLContext *wxGLCanvasBase::GetContext() const
|
|
{
|
|
return m_glContext;
|
|
}
|
|
|
|
void wxGLCanvasBase::SetCurrent()
|
|
{
|
|
if ( m_glContext )
|
|
SetCurrent(*m_glContext);
|
|
}
|
|
|
|
void wxGLCanvasBase::OnSize(wxSizeEvent& WXUNUSED(event))
|
|
{
|
|
}
|
|
|
|
#endif // WXWIN_COMPATIBILITY_2_8
|
|
|
|
/* static */
|
|
bool wxGLCanvasBase::IsExtensionInList(const char *list, const char *extension)
|
|
{
|
|
if ( !list )
|
|
return false;
|
|
|
|
for ( const char *p = list; *p; p++ )
|
|
{
|
|
// advance up to the next possible match
|
|
p = wxStrstr(p, extension);
|
|
if ( !p )
|
|
break;
|
|
|
|
// check that the extension appears at the beginning/ending of the list
|
|
// or is preceded/followed by a space to avoid mistakenly finding
|
|
// "glExtension" in a list containing some "glFunkyglExtension"
|
|
if ( (p == list || p[-1] == ' ') )
|
|
{
|
|
char c = p[strlen(extension)];
|
|
if ( c == '\0' || c == ' ' )
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// ============================================================================
|
|
// compatibility layer for OpenGL 3 and OpenGL ES
|
|
// ============================================================================
|
|
|
|
static wxGLAPI s_glAPI;
|
|
|
|
#if wxUSE_OPENGL_EMULATION
|
|
|
|
#include "wx/vector.h"
|
|
|
|
static GLenum s_mode;
|
|
|
|
static GLfloat s_currentTexCoord[2];
|
|
static GLfloat s_currentColor[4];
|
|
static GLfloat s_currentNormal[3];
|
|
|
|
// TODO move this into a different construct with locality for all attributes
|
|
// of a vertex
|
|
|
|
static wxVector<GLfloat> s_texCoords;
|
|
static wxVector<GLfloat> s_vertices;
|
|
static wxVector<GLfloat> s_normals;
|
|
static wxVector<GLfloat> s_colors;
|
|
|
|
static bool s_texCoordsUsed;
|
|
static bool s_colorsUsed;
|
|
static bool s_normalsUsed;
|
|
|
|
bool SetState( int flag, bool desired )
|
|
{
|
|
bool former = glIsEnabled( flag );
|
|
if ( former != desired )
|
|
{
|
|
if ( desired )
|
|
glEnableClientState(flag);
|
|
else
|
|
glDisableClientState(flag);
|
|
}
|
|
return former;
|
|
}
|
|
|
|
void RestoreState( int flag, bool desired )
|
|
{
|
|
if ( desired )
|
|
glEnableClientState(flag);
|
|
else
|
|
glDisableClientState(flag);
|
|
}
|
|
#endif
|
|
|
|
wxGLAPI::wxGLAPI()
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
s_mode = 0xFF;
|
|
#endif
|
|
}
|
|
|
|
wxGLAPI::~wxGLAPI()
|
|
{
|
|
}
|
|
|
|
void wxGLAPI::glFrustum(GLfloat left, GLfloat right, GLfloat bottom,
|
|
GLfloat top, GLfloat zNear, GLfloat zFar)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
::glFrustumf(left, right, bottom, top, zNear, zFar);
|
|
#else
|
|
::glFrustum(left, right, bottom, top, zNear, zFar);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glBegin(GLenum mode)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
if ( s_mode != 0xFF )
|
|
{
|
|
wxFAIL_MSG("nested glBegin");
|
|
}
|
|
|
|
s_mode = mode;
|
|
s_texCoordsUsed = false;
|
|
s_colorsUsed = false;
|
|
s_normalsUsed = false;
|
|
|
|
s_texCoords.clear();
|
|
s_normals.clear();
|
|
s_colors.clear();
|
|
s_vertices.clear();
|
|
#else
|
|
::glBegin(mode);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glTexCoord2f(GLfloat s, GLfloat t)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
if ( s_mode == 0xFF )
|
|
{
|
|
wxFAIL_MSG("glTexCoord2f called outside glBegin/glEnd");
|
|
}
|
|
|
|
else
|
|
{
|
|
s_texCoordsUsed = true;
|
|
s_currentTexCoord[0] = s;
|
|
s_currentTexCoord[1] = t;
|
|
}
|
|
#else
|
|
::glTexCoord2f(s,t);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glVertex3f(GLfloat x, GLfloat y, GLfloat z)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
if ( s_mode == 0xFF )
|
|
{
|
|
wxFAIL_MSG("glVertex3f called outside glBegin/glEnd");
|
|
}
|
|
else
|
|
{
|
|
s_texCoords.push_back(s_currentTexCoord[0]);
|
|
s_texCoords.push_back(s_currentTexCoord[1]);
|
|
|
|
s_normals.push_back(s_currentNormal[0]);
|
|
s_normals.push_back(s_currentNormal[1]);
|
|
s_normals.push_back(s_currentNormal[2]);
|
|
|
|
s_colors.push_back(s_currentColor[0]);
|
|
s_colors.push_back(s_currentColor[1]);
|
|
s_colors.push_back(s_currentColor[2]);
|
|
s_colors.push_back(s_currentColor[3]);
|
|
|
|
s_vertices.push_back(x);
|
|
s_vertices.push_back(y);
|
|
s_vertices.push_back(z);
|
|
}
|
|
#else
|
|
::glVertex3f(x,y,z);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
if ( s_mode == 0xFF )
|
|
::glNormal3f(nx,ny,nz);
|
|
else
|
|
{
|
|
s_normalsUsed = true;
|
|
s_currentNormal[0] = nx;
|
|
s_currentNormal[1] = ny;
|
|
s_currentNormal[2] = nz;
|
|
}
|
|
#else
|
|
::glNormal3f(nx,ny,nz);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
if ( s_mode == 0xFF )
|
|
::glColor4f(r,g,b,a);
|
|
else
|
|
{
|
|
s_colorsUsed = true;
|
|
s_currentColor[0] = r;
|
|
s_currentColor[1] = g;
|
|
s_currentColor[2] = b;
|
|
s_currentColor[3] = a;
|
|
}
|
|
#else
|
|
::glColor4f(r,g,b,a);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glColor3f(GLfloat r, GLfloat g, GLfloat b)
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
glColor4f(r,g,b,1.0);
|
|
#else
|
|
::glColor3f(r,g,b);
|
|
#endif
|
|
}
|
|
|
|
void wxGLAPI::glEnd()
|
|
{
|
|
#if wxUSE_OPENGL_EMULATION
|
|
bool formerColors = SetState( GL_COLOR_ARRAY, s_colorsUsed );
|
|
bool formerNormals = SetState( GL_NORMAL_ARRAY, s_normalsUsed );
|
|
bool formerTexCoords = SetState( GL_TEXTURE_COORD_ARRAY, s_texCoordsUsed );
|
|
bool formerVertex = glIsEnabled(GL_VERTEX_ARRAY);
|
|
|
|
if( !formerVertex )
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
if ( s_colorsUsed )
|
|
glColorPointer( 4, GL_FLOAT, 0, &s_colors[0] );
|
|
|
|
if ( s_normalsUsed )
|
|
glNormalPointer( GL_FLOAT, 0, &s_normals[0] );
|
|
|
|
if ( s_texCoordsUsed )
|
|
glTexCoordPointer( 2, GL_FLOAT, 0, &s_texCoords[0] );
|
|
|
|
glVertexPointer(3, GL_FLOAT, 0, &s_vertices[0]);
|
|
glDrawArrays( s_mode, 0, s_vertices.size() / 3 );
|
|
|
|
if ( s_colorsUsed != formerColors )
|
|
RestoreState( GL_COLOR_ARRAY, formerColors );
|
|
|
|
if ( s_normalsUsed != formerNormals )
|
|
RestoreState( GL_NORMAL_ARRAY, formerColors );
|
|
|
|
if ( s_texCoordsUsed != formerTexCoords )
|
|
RestoreState( GL_TEXTURE_COORD_ARRAY, formerColors );
|
|
|
|
if( !formerVertex )
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
s_mode = 0xFF;
|
|
#else
|
|
::glEnd();
|
|
#endif
|
|
}
|
|
|
|
#endif // wxUSE_GLCANVAS
|
|
|