22726e4d |
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 | } |