--- /dev/null
+/******************************************************************************
+ * 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);
+}