Ticket #8101: fb2opengl.h

File fb2opengl.h, 11.2 KB (added by SF/luke_br, 22 years ago)

Functions for OpenGL rendering

Line 
1/* ScummVM - Scumm Interpreter
2 * Copyright (C) 2001 Ludvig Strigeus
3 * Copyright (C) 2001/2002 The ScummVM project
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 *
19 */
20
21// FrameBuffer renderer in an OpenGL texture
22// Andre Souza <asouza@olinux.com.br>
23
24#include <SDL.h>
25//#include <SDL_opengl.h>
26#include <GL/gl.h>
27#include <stdlib.h>
28#include <string.h>
29
30// FLAGS
31#define FB2GL_FS 1 // FULLSCREEN
32#define FB2GL_RGBA 2 // Use RGBA (else use palette)
33#define FB2GL_320 4 // 320x256 texture (else use 256x256)
34#define FB2GL_AUDIO 8 // Activate SDL Audio
35#define FB2GL_PITCH 16 // On fb2l_update, use pitch (else bytes per pixel)
36#define FB2GL_EXPAND 32 // Create a RGB fb with the color lookup table
37
38// This extension isn't defined in OpenGL 1.1
39#ifndef GL_EXT_paletted_texture
40#define GL_EXT_paletted_texture 1
41#endif
42
43class FB2GL {
44 private:
45 // Framebuffer for 8 bpp
46 unsigned char ogl_fb[256][256];
47 unsigned char ogl_fbb[256][64];
48 // Framebuffer for RGBA */
49 unsigned char ogl_fb1[256][256][4];
50 unsigned char ogl_fb2[256][64][4];
51 // Texture(s)
52 GLuint texture;
53 GLuint textureb;
54 // Display list
55 GLuint dlist;
56 // Color Table (256 colors, RGB)
57 char ogl_ctable[256][3];
58 char ogl_temp_ctable[256][3]; // Support for OpenGL 1.1
59 char flags;
60 void maketex();
61 void makedlist(int xf, int yf);
62
63 public:
64 SDL_Surface *screen;
65 FB2GL() {
66 flags=0;
67 screen=NULL;
68 }
69 int init(int width, int height, int xfix, int yfix, char _flags);
70 void update(void *fb, int width, int height, int pitch, int xskip, int yskip);
71 void palette(int index, int r, int g, int b);
72 void setPalette(int first, int ncolors);
73 void update_scummvm_screen(void *fb, int width, int height, int pitch, int x, int y);
74 void display();
75};
76
77void FB2GL::maketex()
78{
79 glGenTextures(0,&texture);
80 glBindTexture(GL_TEXTURE_2D,texture);
81
82 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
84
85 // Bilinear filtering
86 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
88/*
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
91*/
92
93 if (flags & FB2GL_RGBA) {
94 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,256,0,GL_RGBA, GL_UNSIGNED_BYTE, ogl_fb1);
95 }
96 else {
97 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,256,256,0,GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ogl_fb);
98 }
99
100 if (flags & FB2GL_320) {
101 glGenTextures(1,&textureb);
102 glBindTexture(GL_TEXTURE_2D,textureb);
103
104 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
105 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
106
107 // Bilinear filtering
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
109 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
110/*
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
113*/
114
115 if (flags & FB2GL_RGBA) {
116 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,256,0,GL_RGBA,
117 GL_UNSIGNED_BYTE, ogl_fb2);
118 }
119 else {
120 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,64,256,0,GL_COLOR_INDEX,
121 GL_UNSIGNED_BYTE, ogl_fbb);
122 }
123 }
124
125}
126
127void FB2GL::makedlist(int xf, int yf)
128{
129 double xfix=(double)xf/128; // 128 = 256/2 (half texture => 0.0 to 1.0)
130 double yfix=(double)yf/128;
131 // End of 256x256 (from -1.0 to 1.0)
132 double texend = (double)96/160; // 160=320/2 (== 0.0), 256-160=96.
133
134 dlist=glGenLists(1);
135 glNewList(dlist,GL_COMPILE);
136
137 glEnable(GL_TEXTURE_2D);
138
139 glBindTexture(GL_TEXTURE_2D, texture);
140
141 if (!(flags & FB2GL_320)) { // Normal 256x256
142 glBegin(GL_QUADS);
143 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
144 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
145 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
146 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
147 glEnd();
148 }
149 else { // 320x256
150
151 // First, the 256x256 texture
152 glBegin(GL_QUADS);
153 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
154 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
155 glTexCoord2f(1.0,0.0); glVertex2f(texend+xfix,1.0); // lower right
156 glTexCoord2f(1.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper right
157 glEnd();
158
159 // 64x256
160 glBindTexture(GL_TEXTURE_2D, textureb);
161
162 glBegin(GL_QUADS);
163 glTexCoord2f(0.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper left
164 glTexCoord2f(0.0,0.0); glVertex2f(texend+xfix,1.0); // lower left
165 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
166 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
167 glEnd();
168 }
169
170 glDisable(GL_TEXTURE_2D);
171
172 glEndList();
173}
174
175int FB2GL::init(int width, int height, int xfix, int yfix, char _flags)
176{
177 char gl_ext[4096];
178 gl_ext[0]='\0';
179
180 flags = _flags;
181
182 // Fullscreen?
183 if ((flags & FB2GL_FS) && !screen) {
184 screen = SDL_SetVideoMode(width, height, 0, SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_FULLSCREEN);
185 }
186 else if (!screen) {
187 screen = SDL_SetVideoMode(width, height, 0, SDL_HWPALETTE | SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
188 }
189
190 if (!screen) {
191 fprintf(stderr, "Couldn't start video res %dx%d\n", width, height);
192 return 0;
193 }
194
195
196 if (!(flags & FB2GL_RGBA)) { // Check for Paletted Texture Extension
197
198 strcpy(gl_ext, (char *)glGetString(GL_EXTENSIONS));
199 fprintf(stderr,"gl_ext= %s\n",gl_ext);
200
201 if ( strstr( gl_ext , "GL_EXT_paletted_texture") )
202 glEnable(GL_EXT_paletted_texture);
203 else {
204 fprintf(stderr,"Your OpenGL version doesn't support paletted texture\n");
205 return 0;
206 }
207 }
208
209 maketex();
210 makedlist(xfix, yfix);
211
212/* glEnable(GL_ALPHA_TEST);
213 glEnable(GL_BLEND);
214 glAlphaFunc(GL_GREATER,0);
215 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);*/
216
217 return 1;
218}
219
220void FB2GL::display()
221{
222 glCallList(dlist);
223 SDL_GL_SwapBuffers();
224}
225
226void FB2GL::update(void *fb, int w, int h, int pitch, int xskip, int yskip) {
227 unsigned char *fb1=(unsigned char *)fb;
228 int x,y,scr_pitch,byte=0;
229
230 if (flags & FB2GL_PITCH) scr_pitch=pitch;
231 else {
232 scr_pitch=w*pitch;
233 byte = pitch; // Bytes perl pixel (for RGBA mode)
234 }
235
236 if (flags & FB2GL_RGBA) {
237
238 if (flags & FB2GL_EXPAND) { // Expand the 8 bit fb into a RGB fb
239
240 for (y=yskip; y<h; y++) {
241 for (x=xskip; x<w; x++) {
242 if (x<256) {
243 ogl_fb1[y][x][0] = ogl_ctable[*(fb1+x)][0];
244 ogl_fb1[y][x][1] = ogl_ctable[*(fb1+x)][1];
245 ogl_fb1[y][x][2] = ogl_ctable[*(fb1+x)][2];
246 ogl_fb1[y][x][3] = 255;
247 }
248 else {
249 ogl_fb2[y][x-256][0] = ogl_ctable[*(fb1+x)][0];
250 ogl_fb2[y][x-256][1] = ogl_ctable[*(fb1+x)][1];
251 ogl_fb2[y][x-256][2] = ogl_ctable[*(fb1+x)][2];
252 ogl_fb2[y][x-256][3] = 255;
253 }
254 }
255 fb1 += scr_pitch;
256 }
257 }
258 else { // No expansion
259 for (y=yskip; y<h; y++) {
260 for (x=xskip; x<w; x++) {
261 if (x<256) {
262 ogl_fb1[y-yskip][x-xskip][0] = *(fb1+(x*byte));
263 ogl_fb1[y-yskip][x-xskip][1] = *(fb1+(x*byte)+1);
264 ogl_fb1[y-yskip][x-xskip][2] = *(fb1+(x*byte)+2);
265 }
266 else {
267 ogl_fb2[y-yskip][x-256][0] = *(fb1+(x*byte));
268 ogl_fb2[y-yskip][x-256][1] = *(fb1+(x*byte)+1);
269 ogl_fb2[y-yskip][x-256][2] = *(fb1+(x*byte)+2);
270 }
271 }
272 fb1 += scr_pitch;
273 }
274 }
275
276 // Update 256x256 texture
277 glBindTexture(GL_TEXTURE_2D,texture);
278 glFlush();
279 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,GL_RGBA,
280 GL_UNSIGNED_BYTE,ogl_fb1);
281
282 if (flags & FB2GL_320) {
283 // Update 64x256 texture
284 glBindTexture(GL_TEXTURE_2D,textureb);
285 glFlush();
286 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,GL_RGBA,
287 GL_UNSIGNED_BYTE,ogl_fb2);
288 }
289
290 }
291 else { // non RGBA (paletted)
292
293 for (y=0; y<h; y++)
294 for (x=0; x<w; x++) {
295 if (x<256) {
296 ogl_fb[ y ][ x ] = *(fb1 + (y)*scr_pitch + x);
297 }
298 else {
299 ogl_fbb[ y ][ x - 256 ] = *(fb1 + y*scr_pitch + x);
300 }
301 }
302
303 // Update 256x256 texture
304 glBindTexture(GL_TEXTURE_2D,texture);
305 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,
306 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fb);
307
308 if (flags & FB2GL_320) {
309 // Update 64x256 texture
310 glBindTexture(GL_TEXTURE_2D,textureb);
311 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,
312 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fbb);
313 }
314
315 }
316
317 display();
318
319}
320
321void FB2GL::update_scummvm_screen(void *fb, int w, int h, int pitch, int xpos, int ypos) {
322 uint16 *fb1 = (uint16 *)(((SDL_Surface *)fb)->pixels);
323 int x, y;
324 unsigned char r, g, b, a;
325
326 for (y=0; y<h; y++) {
327 for (x=0; x<w; x++) {
328
329 SDL_GetRGBA(fb1[x],((SDL_Surface *)fb)->format,&r,&g,&b,&a);
330
331 if (x<256) {
332 ogl_fb1[y][x][0] = r;
333 ogl_fb1[y][x][1] = g;
334 ogl_fb1[y][x][2] = b;
335 ogl_fb1[y][x][3] = a; // Alpha
336 }
337 else {
338 ogl_fb2[y][x-256][0] = r;
339 ogl_fb2[y][x-256][1] = g;
340 ogl_fb2[y][x-256][2] = b;
341 ogl_fb2[y][x-256][3] = a; // Alpha
342 }
343 }
344 fb1 += pitch;
345 }
346
347 // Update 256x256 texture
348 glBindTexture(GL_TEXTURE_2D,texture);
349 glFlush();
350 glTexSubImage2D(GL_TEXTURE_2D,0,xpos,ypos,256-xpos,256-ypos,GL_RGBA,
351 GL_UNSIGNED_BYTE,ogl_fb1);
352
353 // Update 64x256 texture
354 glBindTexture(GL_TEXTURE_2D,textureb);
355 glFlush();
356 glTexSubImage2D(GL_TEXTURE_2D,0,xpos,ypos,64-xpos,256-ypos,GL_RGBA,
357 GL_UNSIGNED_BYTE,ogl_fb2);
358
359 display();
360}
361
362void FB2GL::palette(int i, int r, int g, int b) {
363 if (flags & FB2GL_EXPAND) {
364 ogl_temp_ctable[i][0]=r;
365 ogl_temp_ctable[i][1]=g;
366 ogl_temp_ctable[i][2]=b;
367 }
368 else { // Paletted texture
369 ogl_ctable[i][0]=r;
370 ogl_ctable[i][1]=g;
371 ogl_ctable[i][2]=b;
372 }
373}
374
375void FB2GL::setPalette(int f, int n) {
376 char temp[256][3];
377 int i;
378
379 if (flags & FB2GL_EXPAND) {
380 for (i=f; i<n; i++) {
381 ogl_ctable[i][0] = ogl_temp_ctable[i][0];
382 ogl_ctable[i][1] = ogl_temp_ctable[i][1];
383 ogl_ctable[i][2] = ogl_temp_ctable[i][2];
384 }
385 }
386 else { // Paletted texture
387 glBindTexture(GL_TEXTURE_2D,texture);
388 glGetColorTable(GL_TEXTURE_2D,GL_RGB,GL_UNSIGNED_BYTE,&temp);
389
390 for (i=f; i<n; i++) {
391 temp[i][0] = ogl_ctable[i][0];
392 temp[i][1] = ogl_ctable[i][1];
393 temp[i][2] = ogl_ctable[i][2];
394 }
395
396 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
397
398 if (flags & FB2GL_320) {
399 glBindTexture(GL_TEXTURE_2D,textureb);
400 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
401 }
402
403 }
404
405}