Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / framebuffer / FrameBuffer.cpp
diff --git a/source/mupen64plus-video-arachnoid/src/framebuffer/FrameBuffer.cpp b/source/mupen64plus-video-arachnoid/src/framebuffer/FrameBuffer.cpp
new file mode 100755 (executable)
index 0000000..31255da
--- /dev/null
@@ -0,0 +1,371 @@
+/******************************************************************************
+ * Arachnoid Graphics Plugin for Mupen64Plus
+ * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
+ *
+ * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *****************************************************************************/
+
+#include "FrameBuffer.h"
+#include "m64p.h"
+#include "OpenGL.h"
+
+#ifndef GL_GLEXT_VERSION
+#ifndef HAVE_GLES
+    //-----------------------------------------------------------------------------
+    //OpenGL Texture Definitions
+    //-----------------------------------------------------------------------------
+    typedef GLvoid (APIENTRY *PFNGLACTIVETEXTUREPROC) (GLenum texture);
+    PFNGLACTIVETEXTUREPROC      glActiveTexture = NULL;
+#endif
+#endif
+
+#ifndef GL_TEXTURE0
+    #define GL_TEXTURE0     0x84C0
+#endif
+#ifndef GL_CLAMP_TO_EDGE
+    #define GL_CLAMP_TO_EDGE  0x812F
+#endif
+
+//-----------------------------------------------------------------------------
+//! Constructor
+//-----------------------------------------------------------------------------
+FrameBuffer::FrameBuffer()
+{
+    m_id = ~0U;
+}
+
+//-----------------------------------------------------------------------------
+//! Destructor
+//-----------------------------------------------------------------------------
+FrameBuffer::~FrameBuffer()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+//* Initialize
+//! @param width Width of framebuffer, usually equal to window-client-width
+//! @param height Height of framebuffer, usually equal to window-client-height
+//-----------------------------------------------------------------------------
+void FrameBuffer::initialize(int width, int height)
+{
+    //Save parameters
+    m_width    = width;
+    m_height   = height;
+    int channels = 3;     //!< RGB=3 or RGBA=4    
+
+    //Allocate memory
+    unsigned char* data = new unsigned char[width * height * channels];
+    memset(data, 0, width * height * channels * sizeof(unsigned char));    
+
+    //Register the texture with OpenGL and bind it to the texture ID
+    glGenTextures(1, &m_id);                                
+    glBindTexture(GL_TEXTURE_2D, m_id);                    
+
+    //Create the texture and store it on the video card
+#ifdef HAVE_GLES
+    if (channels == 3)
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);    
+    else
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);    
+#else
+    glTexImage2D(GL_TEXTURE_2D, 0, channels, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);    
+#endif
+        
+    //No texure filtering
+    //glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );            
+    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+    //Clamp texture to edges
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    //Delete data (no need for it when it is stored in video card)
+    delete[] data;
+    data = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Dispose
+//-----------------------------------------------------------------------------
+void FrameBuffer::dispose()
+{
+    if ( m_id != ~0U )
+    {
+        glDeleteTextures(1, &m_id);        
+        m_id = -1;
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Resize
+//-----------------------------------------------------------------------------
+void FrameBuffer::resize(int width, int height)
+{
+    dispose();
+    initialize(width, height);
+}
+
+//-----------------------------------------------------------------------------
+//* Begin Rendering
+//! 
+//-----------------------------------------------------------------------------
+void FrameBuffer::beginRendering()
+{
+    //Get viewport
+    glGetIntegerv(GL_VIEWPORT, m_oldViewport);
+
+    //Set new viewport for texture
+    //glViewport(0, 20, m_width, m_height);
+
+    //glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+    //glClear(GL_COLOR_BUFFER_BIT);
+    //glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+
+    //Clear Buffers
+   // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+//-----------------------------------------------------------------------------
+//* End Rendering
+//! Will save all rendering to a texture
+//-----------------------------------------------------------------------------
+void FrameBuffer::endRendering()
+{
+    //Activate texture
+    _activate();
+
+    //Render to Texture
+    glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 20, m_width, m_height );
+
+    //TODO Deactivate texture?
+    //_deactivate();
+
+    //Reset Viewport
+    //glViewport(m_oldViewport[0], m_oldViewport[1], m_oldViewport[2], m_oldViewport[3]);
+
+    //Clear Buffers
+    //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+}
+
+//-----------------------------------------------------------------------------
+//* Render
+//! Will render frame buffer to screen.
+//-----------------------------------------------------------------------------
+void FrameBuffer::render()
+{
+    //Push states
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+     //glOrtho( 0, m_width, 0, m_height, -1.0f, 1.0f );
+    //glViewport( 0, 0, m_width, m_height );
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    //glPushAttrib(GL_LIGHTING_BIT);
+    glDisable(GL_LIGHTING);
+
+    //Render QUAD (using framebuffer texture)
+    _activate();
+    {
+#ifdef HAVE_GLES
+               GLfloat tex[] = {
+                       0, 0,
+                       1, 0,
+                       1, 1,
+                       0, 1
+               };
+               GLfloat vtx[] = {
+                       -1, -1, 0,
+                       0, -1, 0,
+                       0, 0, 0,
+                       -1, 0, 0
+               };
+               glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
+               
+               GLboolean glcol = glIsEnabled(GL_COLOR_ARRAY);
+               if (glcol) glDisableClientState(GL_COLOR_ARRAY);
+               GLboolean glvtx = glIsEnabled(GL_VERTEX_ARRAY);
+               if (!glvtx)
+                       glEnableClientState(GL_VERTEX_ARRAY);
+               glVertexPointer(3,GL_FLOAT, 0,&vtx);
+               glActiveTexture( GL_TEXTURE1 );
+               GLboolean gltex1 = glIsEnabled(GL_TEXTURE_2D);
+               if (gltex1) glDisable(GL_TEXTURE_2D);
+               glActiveTexture( GL_TEXTURE0 );
+               glClientActiveTexture( GL_TEXTURE0 );
+               glTexCoordPointer(2, GL_FLOAT, 0, &tex);
+               // draw
+               glDrawArrays(GL_TRIANGLE_FAN,0,4);
+               // restaure
+               if (glcol) glEnableClientState(GL_COLOR_ARRAY);
+               glActiveTexture( GL_TEXTURE1 );
+               if (gltex1) glEnable(GL_TEXTURE_2D);
+               if (!glvtx)
+                       glDisableClientState(GL_VERTEX_ARRAY);
+               else
+                       glVertexPointer(glsav_vtx_size, glsav_vtx_type, glsav_vtx_stride, glsav_vtx_array );
+               glActiveTexture( GL_TEXTURE0 );
+               glTexCoordPointer( glsav_tex_size, glsav_tex_type, glsav_tex_stride, glsav_tex_array );
+               
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+#else
+        glBegin(GL_QUADS);
+        {
+            glColor3f(0.0f, 0.0f, 1.0f);
+            glTexCoord2f(0,0);
+            glVertex3f(-1,-1,0);
+            glTexCoord2f(1,0);
+            glVertex3f( 0,-1,0);
+            glTexCoord2f(1,1);
+            glVertex3f( 0, 0,0);
+            glTexCoord2f(0,1);
+            glVertex3f(-1, 0,0);
+            glColor3f(1.0f, 1.0f, 1.0f);
+        }
+        glEnd();
+#endif
+    }
+    _deactivate();
+
+    //Pop states
+    //glPopAttrib();
+    glMatrixMode(GL_MODELVIEW);
+    glPopMatrix();
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix(); 
+}
+
+//-----------------------------------------------------------------------------
+//* Render
+//! Will render frame buffer to screen.
+//-----------------------------------------------------------------------------
+void FrameBuffer::render2()
+{
+    //Push states
+    glMatrixMode(GL_PROJECTION);
+    glPushMatrix();
+    glLoadIdentity();
+     //glOrtho( 0, m_width, 0, m_height, -1.0f, 1.0f );
+    //glViewport( 0, 0, m_width, m_height );
+    glMatrixMode(GL_MODELVIEW);
+    glPushMatrix();
+    glLoadIdentity();
+    //glPushAttrib(GL_LIGHTING_BIT);
+    glDisable(GL_LIGHTING);
+
+    //Render QUAD (using framebuffer texture)
+    _activate();
+    {
+#ifdef HAVE_GLES
+               GLfloat tex[] = {
+                       0, 0,
+                       1, 0,
+                       1, 1,
+                       0, 1
+               };
+               GLfloat vtx[] = {
+                       -1, -1, 0,
+                       0, -1, 0,
+                       0, 0, 0,
+                       -1, 0, 0
+               };
+               
+               GLboolean glcol = glIsEnabled(GL_COLOR_ARRAY);
+               if (glcol) glDisableClientState(GL_COLOR_ARRAY);
+               GLboolean glvtx = glIsEnabled(GL_VERTEX_ARRAY);         
+               if (!glvtx)
+                       glEnableClientState(GL_VERTEX_ARRAY);
+               glVertexPointer(3,GL_FLOAT, 0,&vtx);
+               glActiveTexture( GL_TEXTURE1 );
+               GLboolean gltex1 = glIsEnabled(GL_TEXTURE_2D);
+               if (gltex1) glDisable(GL_TEXTURE_2D);
+               glActiveTexture( GL_TEXTURE0 );
+               glClientActiveTexture( GL_TEXTURE0 );
+               glTexCoordPointer(2, GL_FLOAT, 0, &tex);
+               // draw
+               glDrawArrays(GL_TRIANGLE_FAN,0,4);
+               // restaure
+               if (glcol) glEnableClientState(GL_COLOR_ARRAY);
+               glActiveTexture( GL_TEXTURE1 );
+               if (gltex1) glEnable(GL_TEXTURE_2D);
+               if (!glvtx)
+                       glDisableClientState(GL_VERTEX_ARRAY);
+               else 
+                       glVertexPointer(glsav_vtx_size, glsav_vtx_type, glsav_vtx_stride, glsav_vtx_array );
+               glActiveTexture( GL_TEXTURE0 );
+               glTexCoordPointer( glsav_tex_size, glsav_tex_type, glsav_tex_stride, glsav_tex_array );
+               
+        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+#else
+        glBegin(GL_QUADS);
+        {
+            glTexCoord2f(0,0);
+            glVertex3f(-1,-1,0);
+            glTexCoord2f(1,0);
+            glVertex3f( 1,-1,0);
+            glTexCoord2f(1,1);
+            glVertex3f( 1, 1,0);
+            glTexCoord2f(0,1);
+            glVertex3f(-1, 1,0);
+            glColor3f(1.0f, 1.0f, 1.0f);
+        }
+        glEnd();
+#endif
+    }
+    _deactivate();
+
+    //Pop states
+    //glPopAttrib();
+    glMatrixMode(GL_MODELVIEW);
+    glPopMatrix();
+    glMatrixMode(GL_PROJECTION);
+    glPopMatrix(); 
+}
+
+//-----------------------------------------------------------------------------
+// Activate
+//-----------------------------------------------------------------------------
+void FrameBuffer::_activate()
+{
+    //Activate Texture (so we can copy to it)
+#ifndef GL_GLEXT_VERSION
+#ifndef HAVE_GLES
+    if ( glActiveTexture == 0 ) {
+        glActiveTexture = (PFNGLACTIVETEXTUREPROC) CoreVideo_GL_GetProcAddress("glActiveTexture");
+    }
+#endif
+#endif
+    glActiveTexture(GL_TEXTURE0);
+    glEnable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, m_id);
+}
+
+//-----------------------------------------------------------------------------
+// Deactivate
+//-----------------------------------------------------------------------------
+void FrameBuffer::_deactivate()
+{
+    glActiveTexture((GLuint)GL_TEXTURE0);
+    glDisable(GL_TEXTURE_2D);
+    glBindTexture(GL_TEXTURE_2D, 0);
+}