31255da758cd00f95d35f3f5c7988f74d4df263e
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / framebuffer / FrameBuffer.cpp
1 /******************************************************************************
2  * Arachnoid Graphics Plugin for Mupen64Plus
3  * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4  *
5  * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  *****************************************************************************/
21
22 #include "FrameBuffer.h"
23 #include "m64p.h"
24 #include "OpenGL.h"
25
26 #ifndef GL_GLEXT_VERSION
27 #ifndef HAVE_GLES
28     //-----------------------------------------------------------------------------
29     //OpenGL Texture Definitions
30     //-----------------------------------------------------------------------------
31     typedef GLvoid (APIENTRY *PFNGLACTIVETEXTUREPROC) (GLenum texture);
32     PFNGLACTIVETEXTUREPROC      glActiveTexture = NULL;
33 #endif
34 #endif
35
36 #ifndef GL_TEXTURE0
37     #define GL_TEXTURE0     0x84C0
38 #endif
39 #ifndef GL_CLAMP_TO_EDGE
40     #define GL_CLAMP_TO_EDGE  0x812F
41 #endif
42
43 //-----------------------------------------------------------------------------
44 //! Constructor
45 //-----------------------------------------------------------------------------
46 FrameBuffer::FrameBuffer()
47 {
48     m_id = ~0U;
49 }
50
51 //-----------------------------------------------------------------------------
52 //! Destructor
53 //-----------------------------------------------------------------------------
54 FrameBuffer::~FrameBuffer()
55 {
56
57 }
58
59 //-----------------------------------------------------------------------------
60 //* Initialize
61 //! @param width Width of framebuffer, usually equal to window-client-width
62 //! @param height Height of framebuffer, usually equal to window-client-height
63 //-----------------------------------------------------------------------------
64 void FrameBuffer::initialize(int width, int height)
65 {
66     //Save parameters
67     m_width    = width;
68     m_height   = height;
69     int channels = 3;     //!< RGB=3 or RGBA=4    
70
71     //Allocate memory
72     unsigned char* data = new unsigned char[width * height * channels];
73     memset(data, 0, width * height * channels * sizeof(unsigned char));    
74
75     //Register the texture with OpenGL and bind it to the texture ID
76     glGenTextures(1, &m_id);                                
77     glBindTexture(GL_TEXTURE_2D, m_id);                    
78
79     //Create the texture and store it on the video card
80 #ifdef HAVE_GLES
81     if (channels == 3)
82         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);    
83     else
84         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);    
85 #else
86     glTexImage2D(GL_TEXTURE_2D, 0, channels, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);    
87 #endif
88         
89     //No texure filtering
90     //glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );            
91     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
92     //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
93     
94     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
95     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
96
97     //Clamp texture to edges
98     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
99     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
100
101     //Delete data (no need for it when it is stored in video card)
102     delete[] data;
103     data = 0;
104 }
105
106 //-----------------------------------------------------------------------------
107 // Dispose
108 //-----------------------------------------------------------------------------
109 void FrameBuffer::dispose()
110 {
111     if ( m_id != ~0U )
112     {
113         glDeleteTextures(1, &m_id);        
114         m_id = -1;
115     }
116 }
117
118 //-----------------------------------------------------------------------------
119 // Resize
120 //-----------------------------------------------------------------------------
121 void FrameBuffer::resize(int width, int height)
122 {
123     dispose();
124     initialize(width, height);
125 }
126
127 //-----------------------------------------------------------------------------
128 //* Begin Rendering
129 //! 
130 //-----------------------------------------------------------------------------
131 void FrameBuffer::beginRendering()
132 {
133     //Get viewport
134     glGetIntegerv(GL_VIEWPORT, m_oldViewport);
135
136     //Set new viewport for texture
137     //glViewport(0, 20, m_width, m_height);
138
139     //glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
140     //glClear(GL_COLOR_BUFFER_BIT);
141     //glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
142
143     //Clear Buffers
144    // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
145 }
146
147 //-----------------------------------------------------------------------------
148 //* End Rendering
149 //! Will save all rendering to a texture
150 //-----------------------------------------------------------------------------
151 void FrameBuffer::endRendering()
152 {
153     //Activate texture
154     _activate();
155
156     //Render to Texture
157     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 20, m_width, m_height );
158
159     //TODO Deactivate texture?
160     //_deactivate();
161
162     //Reset Viewport
163     //glViewport(m_oldViewport[0], m_oldViewport[1], m_oldViewport[2], m_oldViewport[3]);
164
165     //Clear Buffers
166     //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
167 }
168
169 //-----------------------------------------------------------------------------
170 //* Render
171 //! Will render frame buffer to screen.
172 //-----------------------------------------------------------------------------
173 void FrameBuffer::render()
174 {
175     //Push states
176     glMatrixMode(GL_PROJECTION);
177     glPushMatrix();
178     glLoadIdentity();
179      //glOrtho( 0, m_width, 0, m_height, -1.0f, 1.0f );
180     //glViewport( 0, 0, m_width, m_height );
181     glMatrixMode(GL_MODELVIEW);
182     glPushMatrix();
183     glLoadIdentity();
184     //glPushAttrib(GL_LIGHTING_BIT);
185     glDisable(GL_LIGHTING);
186
187     //Render QUAD (using framebuffer texture)
188     _activate();
189     {
190 #ifdef HAVE_GLES
191                 GLfloat tex[] = {
192                         0, 0,
193                         1, 0,
194                         1, 1,
195                         0, 1
196                 };
197                 GLfloat vtx[] = {
198                         -1, -1, 0,
199                         0, -1, 0,
200                         0, 0, 0,
201                         -1, 0, 0
202                 };
203                 glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
204                 
205                 GLboolean glcol = glIsEnabled(GL_COLOR_ARRAY);
206                 if (glcol) glDisableClientState(GL_COLOR_ARRAY);
207                 GLboolean glvtx = glIsEnabled(GL_VERTEX_ARRAY);
208                 if (!glvtx)
209                         glEnableClientState(GL_VERTEX_ARRAY);
210                 glVertexPointer(3,GL_FLOAT, 0,&vtx);
211                 glActiveTexture( GL_TEXTURE1 );
212                 GLboolean gltex1 = glIsEnabled(GL_TEXTURE_2D);
213                 if (gltex1) glDisable(GL_TEXTURE_2D);
214                 glActiveTexture( GL_TEXTURE0 );
215                 glClientActiveTexture( GL_TEXTURE0 );
216                 glTexCoordPointer(2, GL_FLOAT, 0, &tex);
217                 // draw
218                 glDrawArrays(GL_TRIANGLE_FAN,0,4);
219                 // restaure
220                 if (glcol) glEnableClientState(GL_COLOR_ARRAY);
221                 glActiveTexture( GL_TEXTURE1 );
222                 if (gltex1) glEnable(GL_TEXTURE_2D);
223                 if (!glvtx)
224                         glDisableClientState(GL_VERTEX_ARRAY);
225                 else
226                         glVertexPointer(glsav_vtx_size, glsav_vtx_type, glsav_vtx_stride, glsav_vtx_array );
227                 glActiveTexture( GL_TEXTURE0 );
228                 glTexCoordPointer( glsav_tex_size, glsav_tex_type, glsav_tex_stride, glsav_tex_array );
229                 
230         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
231 #else
232         glBegin(GL_QUADS);
233         {
234             glColor3f(0.0f, 0.0f, 1.0f);
235             glTexCoord2f(0,0);
236             glVertex3f(-1,-1,0);
237             glTexCoord2f(1,0);
238             glVertex3f( 0,-1,0);
239             glTexCoord2f(1,1);
240             glVertex3f( 0, 0,0);
241             glTexCoord2f(0,1);
242             glVertex3f(-1, 0,0);
243             glColor3f(1.0f, 1.0f, 1.0f);
244         }
245         glEnd();
246 #endif
247     }
248     _deactivate();
249
250     //Pop states
251     //glPopAttrib();
252     glMatrixMode(GL_MODELVIEW);
253     glPopMatrix();
254     glMatrixMode(GL_PROJECTION);
255     glPopMatrix(); 
256 }
257
258 //-----------------------------------------------------------------------------
259 //* Render
260 //! Will render frame buffer to screen.
261 //-----------------------------------------------------------------------------
262 void FrameBuffer::render2()
263 {
264     //Push states
265     glMatrixMode(GL_PROJECTION);
266     glPushMatrix();
267     glLoadIdentity();
268      //glOrtho( 0, m_width, 0, m_height, -1.0f, 1.0f );
269     //glViewport( 0, 0, m_width, m_height );
270     glMatrixMode(GL_MODELVIEW);
271     glPushMatrix();
272     glLoadIdentity();
273     //glPushAttrib(GL_LIGHTING_BIT);
274     glDisable(GL_LIGHTING);
275
276     //Render QUAD (using framebuffer texture)
277     _activate();
278     {
279 #ifdef HAVE_GLES
280                 GLfloat tex[] = {
281                         0, 0,
282                         1, 0,
283                         1, 1,
284                         0, 1
285                 };
286                 GLfloat vtx[] = {
287                         -1, -1, 0,
288                         0, -1, 0,
289                         0, 0, 0,
290                         -1, 0, 0
291                 };
292                 
293                 GLboolean glcol = glIsEnabled(GL_COLOR_ARRAY);
294                 if (glcol) glDisableClientState(GL_COLOR_ARRAY);
295                 GLboolean glvtx = glIsEnabled(GL_VERTEX_ARRAY);         
296                 if (!glvtx)
297                         glEnableClientState(GL_VERTEX_ARRAY);
298                 glVertexPointer(3,GL_FLOAT, 0,&vtx);
299                 glActiveTexture( GL_TEXTURE1 );
300                 GLboolean gltex1 = glIsEnabled(GL_TEXTURE_2D);
301                 if (gltex1) glDisable(GL_TEXTURE_2D);
302                 glActiveTexture( GL_TEXTURE0 );
303                 glClientActiveTexture( GL_TEXTURE0 );
304                 glTexCoordPointer(2, GL_FLOAT, 0, &tex);
305                 // draw
306                 glDrawArrays(GL_TRIANGLE_FAN,0,4);
307                 // restaure
308                 if (glcol) glEnableClientState(GL_COLOR_ARRAY);
309                 glActiveTexture( GL_TEXTURE1 );
310                 if (gltex1) glEnable(GL_TEXTURE_2D);
311                 if (!glvtx)
312                         glDisableClientState(GL_VERTEX_ARRAY);
313                 else 
314                         glVertexPointer(glsav_vtx_size, glsav_vtx_type, glsav_vtx_stride, glsav_vtx_array );
315                 glActiveTexture( GL_TEXTURE0 );
316                 glTexCoordPointer( glsav_tex_size, glsav_tex_type, glsav_tex_stride, glsav_tex_array );
317                 
318         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
319 #else
320         glBegin(GL_QUADS);
321         {
322             glTexCoord2f(0,0);
323             glVertex3f(-1,-1,0);
324             glTexCoord2f(1,0);
325             glVertex3f( 1,-1,0);
326             glTexCoord2f(1,1);
327             glVertex3f( 1, 1,0);
328             glTexCoord2f(0,1);
329             glVertex3f(-1, 1,0);
330             glColor3f(1.0f, 1.0f, 1.0f);
331         }
332         glEnd();
333 #endif
334     }
335     _deactivate();
336
337     //Pop states
338     //glPopAttrib();
339     glMatrixMode(GL_MODELVIEW);
340     glPopMatrix();
341     glMatrixMode(GL_PROJECTION);
342     glPopMatrix(); 
343 }
344
345 //-----------------------------------------------------------------------------
346 // Activate
347 //-----------------------------------------------------------------------------
348 void FrameBuffer::_activate()
349 {
350     //Activate Texture (so we can copy to it)
351 #ifndef GL_GLEXT_VERSION
352 #ifndef HAVE_GLES
353     if ( glActiveTexture == 0 ) {
354         glActiveTexture = (PFNGLACTIVETEXTUREPROC) CoreVideo_GL_GetProcAddress("glActiveTexture");
355     }
356 #endif
357 #endif
358     glActiveTexture(GL_TEXTURE0);
359     glEnable(GL_TEXTURE_2D);
360     glBindTexture(GL_TEXTURE_2D, m_id);
361 }
362
363 //-----------------------------------------------------------------------------
364 // Deactivate
365 //-----------------------------------------------------------------------------
366 void FrameBuffer::_deactivate()
367 {
368     glActiveTexture((GLuint)GL_TEXTURE0);
369     glDisable(GL_TEXTURE_2D);
370     glBindTexture(GL_TEXTURE_2D, 0);
371 }