X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/35f1f4f7ea3c88fa680ba69de487f67967ac51d1..9bfdedfb3ee1c5c88f33cf39b292efe2b3c23be0:/src/common/glcmn.cpp diff --git a/src/common/glcmn.cpp b/src/common/glcmn.cpp index 0d85eab14c..94c1327432 100644 --- a/src/common/glcmn.cpp +++ b/src/common/glcmn.cpp @@ -52,14 +52,15 @@ wxGLCanvasBase::wxGLCanvasBase() SetBackgroundStyle(wxBG_STYLE_CUSTOM); } -void wxGLCanvasBase::SetCurrent(const wxGLContext& context) const +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(), _T("can't make hidden GL canvas current") ); + wxASSERT_MSG( IsShownOnScreen(), wxT("can't make hidden GL canvas current") ); - context.SetCurrent(*wx_static_cast(const wxGLCanvas *, this)); + + return context.SetCurrent(*static_cast(this)); } bool wxGLCanvasBase::SetColour(const wxString& colour) @@ -68,11 +69,16 @@ bool wxGLCanvasBase::SetColour(const wxString& colour) if ( !col.Ok() ) 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(col.Red() / 256., col.Green() / 256., col.Blue() / 256.); + glColor3f((GLfloat) (col.Red() / 256.), (GLfloat) (col.Green() / 256.), + (GLfloat) (col.Blue() / 256.)); } else // indexed colour { @@ -85,7 +91,7 @@ bool wxGLCanvasBase::SetColour(const wxString& colour) glIndexi(pix); } - +#endif return true; } @@ -115,5 +121,259 @@ 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 s_texCoords; +static wxVector s_vertices; +static wxVector s_normals; +static wxVector 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