]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/glcmn.cpp
use common bottleneck
[wxWidgets.git] / src / common / glcmn.cpp
index ffcb45a60366083877286f4be102f24b2cf00949..4d9e2dd144c0f377a0ca383ee79a30bda7fe7234 100644 (file)
@@ -41,27 +41,44 @@ IMPLEMENT_CLASS(wxGLApp, wxApp)
 // implementation
 // ============================================================================
 
-void wxGLCanvasBase::SetCurrent(const wxGLContext& context) const
+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(), _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<const wxGLCanvas *>(this));
 }
 
-bool wxGLCanvasBase::SetColour(const wxChar *colour)
+bool wxGLCanvasBase::SetColour(const wxString& colour)
 {
     wxColour col = wxTheColourDatabase->Find(colour);
-    if ( !col.Ok() )
+    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(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
     {
@@ -74,7 +91,7 @@ bool wxGLCanvasBase::SetColour(const wxChar *colour)
 
         glIndexi(pix);
     }
-
+#endif
     return true;
 }
 
@@ -104,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<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