Ticket #8102: fb2opengl.h

File fb2opengl.h, 12.1 KB (added by SF/luke_br, 18 years ago)

Functions for rendering in OpenGL (new blit16 method)

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 // Framebuffer for the blit function (SDL Blitting)
52 unsigned char fb1[256*256*4]; // Enough room for RGBA
53 unsigned char fb2[64*256*4]; // Enough room for RGBA
54 // Texture(s)
55 GLuint texture;
56 GLuint textureb;
57 // Display list
58 GLuint dlist;
59 // Color Table (256 colors, RGB)
60 char ogl_ctable[256][3];
61 char ogl_temp_ctable[256][3]; // Support for OpenGL 1.1
62 char flags;
63 void maketex();
64 void makedlist(int xf, int yf);
65
66 public:
67 SDL_Surface *screen;
68 FB2GL() {
69 flags=0;
70 screen=NULL;
71 }
72 int init(int width, int height, int xfix, int yfix, char _flags);
73 void update(void *fb, int width, int height, int pitch, int xskip, int yskip);
74 void palette(int index, int r, int g, int b);
75 void setPalette(int first, int ncolors);
76 void blit16(SDL_Surface *fb, int num_rect, SDL_Rect *rectlist, int xskip, int yskip);
77 void display();
78};
79
80void FB2GL::maketex()
81{
82 glGenTextures(0,&texture);
83 glBindTexture(GL_TEXTURE_2D,texture);
84
85 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
86 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
87
88 // Bilinear filtering
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
91/*
92 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
93 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
94*/
95
96 if (flags & FB2GL_RGBA) {
97 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,256,0,GL_RGBA, GL_UNSIGNED_BYTE, ogl_fb1);
98 }
99 else {
100 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,256,256,0,GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ogl_fb);
101 }
102
103 if (flags & FB2GL_320) {
104 glGenTextures(1,&textureb);
105 glBindTexture(GL_TEXTURE_2D,textureb);
106
107 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
108 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
109
110 // Bilinear filtering
111 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
112 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
113/*
114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
116*/
117
118 if (flags & FB2GL_RGBA) {
119 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,64,256,0,GL_RGBA,
120 GL_UNSIGNED_BYTE, ogl_fb2);
121 }
122 else {
123 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,64,256,0,GL_COLOR_INDEX,
124 GL_UNSIGNED_BYTE, ogl_fbb);
125 }
126 }
127
128}
129
130void FB2GL::makedlist(int xf, int yf)
131{
132 double xfix=(double)xf/128; // 128 = 256/2 (half texture => 0.0 to 1.0)
133 double yfix=(double)yf/128;
134 // End of 256x256 (from -1.0 to 1.0)
135 double texend = (double)96/160; // 160=320/2 (== 0.0), 256-160=96.
136
137 dlist=glGenLists(1);
138 glNewList(dlist,GL_COMPILE);
139
140 glEnable(GL_TEXTURE_2D);
141
142 glBindTexture(GL_TEXTURE_2D, texture);
143
144 if (!(flags & FB2GL_320)) { // Normal 256x256
145 glBegin(GL_QUADS);
146 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
147 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
148 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
149 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
150 glEnd();
151 }
152 else { // 320x256
153
154 // First, the 256x256 texture
155 glBegin(GL_QUADS);
156 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
157 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
158 glTexCoord2f(1.0,0.0); glVertex2f(texend+xfix,1.0); // lower right
159 glTexCoord2f(1.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper right
160 glEnd();
161
162 // 64x256
163 glBindTexture(GL_TEXTURE_2D, textureb);
164
165 glBegin(GL_QUADS);
166 glTexCoord2f(0.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper left
167 glTexCoord2f(0.0,0.0); glVertex2f(texend+xfix,1.0); // lower left
168 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
169 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
170 glEnd();
171 }
172
173 glDisable(GL_TEXTURE_2D);
174
175 glEndList();
176}
177
178int FB2GL::init(int width, int height, int xfix, int yfix, char _flags)
179{
180 char gl_ext[4096];
181 gl_ext[0]='\0';
182
183 flags = _flags;
184
185 // Fullscreen?
186 if ((flags & FB2GL_FS) && !screen) {
187 screen = SDL_SetVideoMode(width, height, 0, SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_FULLSCREEN);
188 }
189 else if (!screen) {
190 screen = SDL_SetVideoMode(width, height, 0, SDL_HWPALETTE | SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
191 }
192
193 if (!screen) {
194 fprintf(stderr, "Couldn't start video res %dx%d\n", width, height);
195 return 0;
196 }
197
198
199 if (!(flags & FB2GL_RGBA)) { // Check for Paletted Texture Extension
200
201 strcpy(gl_ext, (char *)glGetString(GL_EXTENSIONS));
202 fprintf(stderr,"gl_ext= %s\n",gl_ext);
203
204 if ( strstr( gl_ext , "GL_EXT_paletted_texture") )
205 glEnable(GL_EXT_paletted_texture);
206 else {
207 fprintf(stderr,"Your OpenGL version doesn't support paletted texture\n");
208 return 0;
209 }
210 }
211
212 maketex();
213 makedlist(xfix, yfix);
214
215/* glEnable(GL_ALPHA_TEST);
216 glEnable(GL_BLEND);
217 glAlphaFunc(GL_GREATER,0);
218 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);*/
219
220 return 1;
221}
222
223void FB2GL::display()
224{
225 glCallList(dlist);
226 SDL_GL_SwapBuffers();
227}
228
229void FB2GL::update(void *fb, int w, int h, int pitch, int xskip, int yskip) {
230 unsigned char *fb1=(unsigned char *)fb;
231 int x,y,scr_pitch,byte=0;
232
233 if (flags & FB2GL_PITCH) scr_pitch=pitch;
234 else {
235 scr_pitch=w*pitch;
236 byte = pitch; // Bytes perl pixel (for RGBA mode)
237 }
238
239 if (flags & FB2GL_RGBA) {
240
241 if (flags & FB2GL_EXPAND) { // Expand the 8 bit fb into a RGB fb
242
243 for (y=yskip; y<h; y++) {
244 for (x=xskip; x<w; x++) {
245 if (x<256) {
246 ogl_fb1[y][x][0] = ogl_ctable[*(fb1+x)][0];
247 ogl_fb1[y][x][1] = ogl_ctable[*(fb1+x)][1];
248 ogl_fb1[y][x][2] = ogl_ctable[*(fb1+x)][2];
249 ogl_fb1[y][x][3] = 255;
250 }
251 else {
252 ogl_fb2[y][x-256][0] = ogl_ctable[*(fb1+x)][0];
253 ogl_fb2[y][x-256][1] = ogl_ctable[*(fb1+x)][1];
254 ogl_fb2[y][x-256][2] = ogl_ctable[*(fb1+x)][2];
255 ogl_fb2[y][x-256][3] = 255;
256 }
257 }
258 fb1 += scr_pitch;
259 }
260 }
261 else { // No expansion
262 for (y=yskip; y<h; y++) {
263 for (x=xskip; x<w; x++) {
264 if (x<256) {
265 ogl_fb1[y-yskip][x-xskip][0] = *(fb1+(x*byte));
266 ogl_fb1[y-yskip][x-xskip][1] = *(fb1+(x*byte)+1);
267 ogl_fb1[y-yskip][x-xskip][2] = *(fb1+(x*byte)+2);
268 }
269 else {
270 ogl_fb2[y-yskip][x-256][0] = *(fb1+(x*byte));
271 ogl_fb2[y-yskip][x-256][1] = *(fb1+(x*byte)+1);
272 ogl_fb2[y-yskip][x-256][2] = *(fb1+(x*byte)+2);
273 }
274 }
275 fb1 += scr_pitch;
276 }
277 }
278
279 // Update 256x256 texture
280 glBindTexture(GL_TEXTURE_2D,texture);
281 glFlush();
282 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,GL_RGBA,
283 GL_UNSIGNED_BYTE,ogl_fb1);
284
285 if (flags & FB2GL_320) {
286 // Update 64x256 texture
287 glBindTexture(GL_TEXTURE_2D,textureb);
288 glFlush();
289 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,GL_RGBA,
290 GL_UNSIGNED_BYTE,ogl_fb2);
291 }
292
293 }
294 else { // non RGBA (paletted)
295
296 for (y=0; y<h; y++)
297 for (x=0; x<w; x++) {
298 if (x<256) {
299 ogl_fb[ y ][ x ] = *(fb1 + (y)*scr_pitch + x);
300 }
301 else {
302 ogl_fbb[ y ][ x - 256 ] = *(fb1 + y*scr_pitch + x);
303 }
304 }
305
306 // Update 256x256 texture
307 glBindTexture(GL_TEXTURE_2D,texture);
308 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,
309 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fb);
310
311 if (flags & FB2GL_320) {
312 // Update 64x256 texture
313 glBindTexture(GL_TEXTURE_2D,textureb);
314 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,
315 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fbb);
316 }
317
318 }
319
320 display();
321
322}
323
324void FB2GL::blit16(SDL_Surface *fb, int num_rect, SDL_Rect *rect, int xskip, int yskip) {
325 int x, y, i;
326 int rx, ry, rw, rh;
327 int xend=0, yend=0;
328 int pitch = fb->pitch/2; // 16 bit pointer access (not char *)
329 int tex1_w = 0, tex2_w = 0, tex2_x = 0;
330
331 for (i=0; i<num_rect; i++) {
332 tex1_w = tex2_w = tex2_x = 0;
333 rx = rect[i].x;
334 ry = rect[i].y;
335 rw = rect[i].w;
336 rh = rect[i].h;
337 xend = rx + rw;
338 yend = ry + rh;
339 if (xend > fb->w) continue;
340 if (yend > fb->h) continue;
341
342 if (rx < 256) { // Begins before the end of the 1st texture
343 if (xend >= 256) { // Ends after the first texture
344 tex2_w = xend-256; // For the 2nd texture
345 tex1_w = rw - tex2_w; // For the 1st texture
346 }
347 else tex1_w = rw;
348 }
349 else {
350 tex2_w = rw;
351 tex2_x = rx - 256;
352 }
353
354 for (y = ry; y < yend; y++) {
355 for (x = rx; x < xend; x++) {
356
357 if (x < 256 && tex1_w) {
358 int pos = (x-rx+(y-ry)*tex1_w)*4; // RGBA
359 SDL_GetRGB(((Uint16 *)fb->pixels)[x+y*(pitch)],fb->format,
360 &fb1[pos],
361 &fb1[pos+1],
362 &fb1[pos+2]);
363 }
364 else if (x >= 256 && tex2_w) {
365 int rx2 = rx < 256? 256: rx;
366 int pos = (x-rx2+(y-ry)*tex2_w)*4; // RGBA
367 SDL_GetRGB(((Uint16 *)fb->pixels)[x+y*(pitch)],fb->format,
368 &fb2[pos],
369 &fb2[pos+1],
370 &fb2[pos+2]);
371 }
372 }
373 }
374
375 if (tex1_w > 0) {
376 // Update 256x256 texture
377 glBindTexture(GL_TEXTURE_2D,texture);
378 glFlush();
379 glTexSubImage2D(GL_TEXTURE_2D,0,rx+xskip,ry+yskip,tex1_w,rh,GL_RGBA,
380 GL_UNSIGNED_BYTE,fb1);
381 }
382 if (tex2_w > 0) { // What was left for this texture
383 // Update 64x256 texture
384 glBindTexture(GL_TEXTURE_2D,textureb);
385 glFlush();
386 glTexSubImage2D(GL_TEXTURE_2D,0,tex2_x+xskip,ry+yskip,tex2_w,rh,GL_RGBA,
387 GL_UNSIGNED_BYTE,fb2);
388 }
389 }
390}
391
392void FB2GL::palette(int i, int r, int g, int b) {
393 if (flags & FB2GL_EXPAND) {
394 ogl_temp_ctable[i][0]=r;
395 ogl_temp_ctable[i][1]=g;
396 ogl_temp_ctable[i][2]=b;
397 }
398 else { // Paletted texture
399 ogl_ctable[i][0]=r;
400 ogl_ctable[i][1]=g;
401 ogl_ctable[i][2]=b;
402 }
403}
404
405void FB2GL::setPalette(int f, int n) {
406 char temp[256][3];
407 int i;
408
409 if (flags & FB2GL_EXPAND) {
410 for (i=f; i<n; i++) {
411 ogl_ctable[i][0] = ogl_temp_ctable[i][0];
412 ogl_ctable[i][1] = ogl_temp_ctable[i][1];
413 ogl_ctable[i][2] = ogl_temp_ctable[i][2];
414 }
415 }
416 else { // Paletted texture
417 glBindTexture(GL_TEXTURE_2D,texture);
418 glGetColorTable(GL_TEXTURE_2D,GL_RGB,GL_UNSIGNED_BYTE,&temp);
419
420 for (i=f; i<n; i++) {
421 temp[i][0] = ogl_ctable[i][0];
422 temp[i][1] = ogl_ctable[i][1];
423 temp[i][2] = ogl_ctable[i][2];
424 }
425
426 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
427
428 if (flags & FB2GL_320) {
429 glBindTexture(GL_TEXTURE_2D,textureb);
430 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
431 }
432
433 }
434
435}