Ticket #7989: fb2opengl.h

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

New fb2opengl.h (C++)

Line 
1// FrameBuffer renderer in an OpenGL texture
2// Andre Souza <asouza@olinux.com.br>
3
4#include <GL/gl.h>
5#include <SDL/SDL.h>
6#include <stdlib.h>
7#include <string.h>
8
9// FLAGS
10#define FB2GL_FS 1 // FULLSCREEN
11#define FB2GL_RGBA 2 // Use RGBA (else use palette)
12#define FB2GL_320 4 // 320x256 texture (else use 256x256)
13#define FB2GL_AUDIO 8 // Activate SDL Audio
14#define FB2GL_PITCH 16 // On fb2l_update, use pitch (else bytes per pixel)
15#define FB2GL_EXPAND 32 // Create a RGB fb with the color lookup table
16
17// This extension isn't defined in OpenGL 1.1
18#ifndef GL_EXT_paletted_texture
19#define GL_EXT_paletted_texture 1
20#endif
21
22class FB2GL {
23 private:
24 // Framebuffer for 8 bpp
25 unsigned char ogl_fb[256][256];
26 unsigned char ogl_fbb[256][64];
27 // Framebuffer for RGBA */
28 unsigned char ogl_fb1[256][256][4];
29 unsigned char ogl_fb2[256][64][4];
30 // Texture(s)
31 GLuint texture;
32 GLuint textureb;
33 // Display list
34 GLuint dlist;
35 // Color Table (256 colors, RGB)
36 char ogl_ctable[256][3];
37 char ogl_temp_ctable[256][3]; // Support for OpenGL 1.1
38 char flags;
39 void maketex();
40 void makedlist(int xf, int yf);
41 void display();
42
43 public:
44 SDL_Surface *screen;
45 FB2GL() {
46 flags=0;
47 screen=NULL;
48 }
49 int init(int width, int height, int xfix, int yfix, char _flags);
50 void update(void *fb, int width, int height, int pitch, int xskip, int yskip);
51 void palette(int index, int r, int g, int b);
52 void setPalette(int first, int ncolors);
53};
54
55void FB2GL::maketex()
56{
57 glGenTextures(0,&texture);
58 glBindTexture(GL_TEXTURE_2D,texture);
59
60 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
61 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
62
63 // Bilinear filtering
64 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
66/*
67 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
68 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
69*/
70
71 if (flags & FB2GL_RGBA) {
72 glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,256,256,0,GL_RGBA, GL_UNSIGNED_BYTE, ogl_fb1);
73 }
74 else {
75 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,256,256,0,GL_COLOR_INDEX, GL_UNSIGNED_BYTE, ogl_fb);
76 }
77
78 if (flags & FB2GL_320) {
79 glGenTextures(1,&textureb);
80 glBindTexture(GL_TEXTURE_2D,textureb);
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,64,256,0,GL_RGBA,
95 GL_UNSIGNED_BYTE, ogl_fb2);
96 }
97 else {
98 glTexImage2D(GL_TEXTURE_2D,0,GL_COLOR_INDEX,64,256,0,GL_COLOR_INDEX,
99 GL_UNSIGNED_BYTE, ogl_fbb);
100 }
101 }
102
103}
104
105void FB2GL::makedlist(int xf, int yf)
106{
107 double xfix=(double)xf/128; // 128 = 256/2 (half texture => 0.0 to 1.0)
108 double yfix=(double)yf/128;
109 // End of 256x256 (from -1.0 to 1.0)
110 double texend = (double)96/160; // 160=320/2 (== 0.0), 256-160=96.
111
112 dlist=glGenLists(1);
113 glNewList(dlist,GL_COMPILE);
114
115 glEnable(GL_TEXTURE_2D);
116
117 glBindTexture(GL_TEXTURE_2D, texture);
118
119 if (!(flags & FB2GL_320)) { // Normal 256x256
120 glBegin(GL_QUADS);
121 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
122 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
123 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
124 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
125 glEnd();
126 }
127 else { // 320x256
128
129 // First, the 256x256 texture
130 glBegin(GL_QUADS);
131 glTexCoord2f(0.0,1.0); glVertex2f(-1.0,-1.0-yfix); // upper left
132 glTexCoord2f(0.0,0.0); glVertex2f(-1.0,1.0); // lower left
133 glTexCoord2f(1.0,0.0); glVertex2f(texend+xfix,1.0); // lower right
134 glTexCoord2f(1.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper right
135 glEnd();
136
137 // 64x256
138 glBindTexture(GL_TEXTURE_2D, textureb);
139
140 glBegin(GL_QUADS);
141 glTexCoord2f(0.0,1.0); glVertex2f(texend+xfix,-1.0-yfix); // upper left
142 glTexCoord2f(0.0,0.0); glVertex2f(texend+xfix,1.0); // lower left
143 glTexCoord2f(1.0,0.0); glVertex2f(1.0+xfix,1.0); // lower right
144 glTexCoord2f(1.0,1.0); glVertex2f(1.0+xfix,-1.0-yfix); // upper right
145 glEnd();
146 }
147
148 glDisable(GL_TEXTURE_2D);
149
150 glEndList();
151}
152
153int FB2GL::init(int width, int height, int xfix, int yfix, char _flags)
154{
155 char gl_ext[4096];
156 gl_ext[0]='\0';
157
158 flags = _flags;
159
160 // Fullscreen?
161 if ((flags & FB2GL_FS) && !screen) {
162 screen = SDL_SetVideoMode(width, height, 0, SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_FULLSCREEN);
163 }
164 else if (!screen) {
165 screen = SDL_SetVideoMode(width, height, 0, SDL_HWPALETTE | SDL_HWSURFACE | SDL_OPENGL | SDL_GL_DOUBLEBUFFER);
166 }
167
168 if (!screen) {
169 fprintf(stderr, "Couldn't start video res %dx%d\n", width, height);
170 return 0;
171 }
172
173
174 if (!(flags & FB2GL_RGBA)) { // Check for Paletted Texture Extension
175
176 strcpy(gl_ext, (char *)glGetString(GL_EXTENSIONS));
177 fprintf(stderr,"gl_ext= %s\n",gl_ext);
178
179 if ( strstr( gl_ext , "GL_EXT_paletted_texture") )
180 glEnable(GL_EXT_paletted_texture);
181 else {
182 fprintf(stderr,"Your OpenGL version doesn't support paletted texture\n");
183 return 0;
184 }
185 }
186
187 maketex();
188 makedlist(xfix, yfix);
189
190 return 1;
191}
192
193void FB2GL::display()
194{
195 glCallList(dlist);
196 SDL_GL_SwapBuffers();
197}
198
199void FB2GL::update(void *fb, int w, int h, int pitch, int xskip, int yskip) {
200 unsigned char *fb1=(unsigned char *)fb;
201 int x,y,scr_pitch,byte=0;
202
203 if (flags & FB2GL_PITCH) scr_pitch=pitch;
204 else {
205 scr_pitch=w*pitch;
206 byte = pitch; // Bytes perl pixel (for RGBA mode)
207 }
208
209 if (flags & FB2GL_RGBA) {
210
211 if (flags & FB2GL_EXPAND) { // Expand the 8 bit fb into a RGB fb
212
213 for (y=yskip; y<h; y++) {
214 for (x=xskip; x<w; x++) {
215 if (x<256) {
216 ogl_fb1[y][x][0] = ogl_ctable[*(fb1+x)][0];
217 ogl_fb1[y][x][1] = ogl_ctable[*(fb1+x)][1];
218 ogl_fb1[y][x][2] = ogl_ctable[*(fb1+x)][2];
219 }
220 else {
221 ogl_fb2[y][x-256][0] = ogl_ctable[*(fb1+x)][0];
222 ogl_fb2[y][x-256][1] = ogl_ctable[*(fb1+x)][1];
223 ogl_fb2[y][x-256][2] = ogl_ctable[*(fb1+x)][2];
224 }
225 }
226 fb1 += scr_pitch;
227 }
228 }
229 else { // No expansion
230 for (y=yskip; y<h; y++) {
231 for (x=xskip; x<w; x++) {
232 if (x<256) {
233 ogl_fb1[y-yskip][x-xskip][0] = *(fb1+(x*byte));
234 ogl_fb1[y-yskip][x-xskip][1] = *(fb1+(x*byte)+1);
235 ogl_fb1[y-yskip][x-xskip][2] = *(fb1+(x*byte)+2);
236 }
237 else {
238 ogl_fb2[y-yskip][x-256][0] = *(fb1+(x*byte));
239 ogl_fb2[y-yskip][x-256][1] = *(fb1+(x*byte)+1);
240 ogl_fb2[y-yskip][x-256][2] = *(fb1+(x*byte)+2);
241 }
242 }
243 fb1 += scr_pitch;
244 }
245 }
246
247 // Update 256x256 texture
248 glBindTexture(GL_TEXTURE_2D,texture);
249 glFlush();
250 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,GL_RGBA,
251 GL_UNSIGNED_BYTE,ogl_fb1);
252
253 if (flags & FB2GL_320) {
254 // Update 64x256 texture
255 glBindTexture(GL_TEXTURE_2D,textureb);
256 glFlush();
257 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,GL_RGBA,
258 GL_UNSIGNED_BYTE,ogl_fb2);
259 }
260
261 }
262 else { // non RGBA (paletted)
263
264 for (y=0; y<h; y++)
265 for (x=0; x<w; x++) {
266 if (x<256) {
267 ogl_fb[ y ][ x ] = *(fb1 + (y)*scr_pitch + x);
268 }
269 else {
270 ogl_fbb[ y ][ x - 256 ] = *(fb1 + y*scr_pitch + x);
271 }
272 }
273
274 // Update 256x256 texture
275 glBindTexture(GL_TEXTURE_2D,texture);
276 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,256-xskip,256-yskip,
277 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fb);
278
279 if (flags & FB2GL_320) {
280 // Update 64x256 texture
281 glBindTexture(GL_TEXTURE_2D,textureb);
282 glTexSubImage2D(GL_TEXTURE_2D,0,xskip,yskip,64-xskip,256-yskip,
283 GL_COLOR_INDEX, GL_UNSIGNED_BYTE,ogl_fbb);
284 }
285
286 }
287
288 display();
289
290}
291
292void FB2GL::palette(int i, int r, int g, int b) {
293 if (flags & FB2GL_EXPAND) {
294 ogl_temp_ctable[i][0]=r;
295 ogl_temp_ctable[i][1]=g;
296 ogl_temp_ctable[i][2]=b;
297 }
298 else { // Paletted texture
299 ogl_ctable[i][0]=r;
300 ogl_ctable[i][1]=g;
301 ogl_ctable[i][2]=b;
302 }
303}
304
305void FB2GL::setPalette(int f, int n) {
306 char temp[256][3];
307 int i;
308
309 if (flags & FB2GL_EXPAND) {
310 for (i=f; i<n; i++) {
311 ogl_ctable[i][0] = ogl_temp_ctable[i][0];
312 ogl_ctable[i][1] = ogl_temp_ctable[i][1];
313 ogl_ctable[i][2] = ogl_temp_ctable[i][2];
314 }
315 }
316 else { // Paletted texture
317 glBindTexture(GL_TEXTURE_2D,texture);
318 glGetColorTable(GL_TEXTURE_2D,GL_RGB,GL_UNSIGNED_BYTE,&temp);
319
320 for (i=f; i<n; i++) {
321 temp[i][0] = ogl_ctable[i][0];
322 temp[i][1] = ogl_ctable[i][1];
323 temp[i][2] = ogl_ctable[i][2];
324 }
325
326 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
327
328 if (flags & FB2GL_320) {
329 glBindTexture(GL_TEXTURE_2D,textureb);
330 glColorTable(GL_TEXTURE_2D,GL_RGB,256,GL_RGB,GL_UNSIGNED_BYTE,&temp);
331 }
332
333 }
334
335}