]> Shamusworld >> Repos - virtualjaguar/blob - src/sdlemu_opengl.c
Expended OpenGL rendering with 16, 24 and 32 bit texture types.
[virtualjaguar] / src / sdlemu_opengl.c
1 /*
2  * SDLEMU library - Free sdl related functions library
3  * Copyrigh(c) 1999-2002 sdlemu development crew
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (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     Version 1.0.001 - 4-10-2004
22     
23     - Added support for 16, 24 and 32 bit textures * new *;
24     - Added support for 16, 24 and 32 bit texture rendering *new*;
25
26 */
27
28 #include "sdlemu_opengl.h"
29
30 static SDL_Surface *texture      = 0;
31 static GLuint       texid        = 0;
32 static GLfloat      texcoord[4];
33 static unsigned int glFilter;
34 static unsigned int texturebpp  = 0; // 16, 24 or 32 bpp
35
36 static inline int power_of_two(int input)
37 {
38         int value = 1;
39
40         while (value < input)
41                 value <<= 1;
42
43         return value;
44 }
45
46 void sdlemu_init_opengl(SDL_Surface * src, int texturetype, float size, int filter, int src_bpp)
47 {
48         int w, h;
49         Uint32 rmask, gmask, bmask, amask;
50
51         // We allow the developer to set its own texture bpp. But if the value is NULL or
52         // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
53         if ( (src_bpp != NULL) && ( (src_bpp == 16) || (src_bpp == 24) || (src_bpp == 32) ) )
54        texturebpp = src_bpp;
55     else
56        texturebpp = src->format->BitsPerPixel;
57         
58         printf("\nOpenGL driver information :\n");
59         printf("\n");
60         printf("Vendor:             %s\n", glGetString(GL_VENDOR));
61         printf("Renderer:           %s\n", glGetString(GL_RENDERER));
62         printf("Version:            %s\n", glGetString(GL_VERSION));
63         printf("OpenGL Texture BPP: %d\n", texturebpp);
64         printf("OpenGL drawmethod: ");
65
66         switch (texturetype)
67         {
68         case 1:
69                 printf("GL_QUAD rendering\n\n");
70                 break;
71         default:
72                 printf("GL_TRIANGLE rendering\n\n");
73                 break;
74         }
75
76         glFilter = filter;
77
78         // Texture width/height should be power of 2
79         // So, find the largest power of two that will contain both the width and height
80         // w = power_of_two(src->w);
81         // h = power_of_two(src->h);
82         w = 512;
83         h = 512;
84
85         switch ( texturebpp )
86         {
87     case 16:
88     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
89         
90 //         rmask = 0xff000000;
91 //         gmask = 0x00ff0000;
92 //         bmask = 0x0000ff00;
93 //         amask = 0x00000000;
94
95         rmask = 0x0000;
96                 gmask = 0x0000;
97                 bmask = 0x0000;
98                 amask = 0x0000;
99
100         #else
101
102 //          rmask = 0x000000ff;
103 //          gmask = 0x0000ff00;
104 //          bmask = 0x00ff0000;
105 //          amask = 0x00000000;
106
107       rmask = 0x0000;
108       gmask = 0x0000;
109       bmask = 0x0000;
110       amask = 0x0000;
111
112     #endif
113         
114         break;
115     case 24:
116     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
117             rmask = 0x00ff0000;
118                 gmask = 0x0000ff00;
119                 bmask = 0x000000ff;
120                 amask = 0x00000000;
121         #else
122             rmask = 0x000000ff;
123             gmask = 0x0000ff00;
124             bmask = 0x00ff0000;
125             amask = 0x00000000;
126     #endif
127        break;
128     case 32: 
129     default:
130     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
131             rmask = 0xff000000;
132                 gmask = 0x00ff0000;
133                 bmask = 0x0000ff00;
134                 amask = 0x000000ff;
135         #else
136             rmask = 0x000000ff;
137             gmask = 0x0000ff00;
138             bmask = 0x00ff0000;
139             amask = 0xff000000;
140     #endif
141         break;
142     }    
143
144         // create texture surface
145         texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
146 /*      
147     #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
148                 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
149         #else
150                 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
151         #endif
152 */
153
154         // setup 2D gl environment
155         //glPushAttrib(GL_ENABLE_BIT);
156         //glDisable(GL_DEPTH_TEST);
157         //glDisable(GL_CULL_FACE);
158         //glEnable(GL_TEXTURE_2D);
159
160         glDisable(GL_FOG);
161         glDisable(GL_LIGHTING);
162         glDisable(GL_CULL_FACE);
163         glDisable(GL_DEPTH_TEST);
164         glDisable(GL_BLEND);
165         glDisable(GL_NORMALIZE);
166         glDisable(GL_ALPHA_TEST);
167         glEnable(GL_TEXTURE_2D);
168         glBlendFunc (GL_SRC_ALPHA, GL_ONE);
169
170         glViewport(0, 0, src->w * size, src->h * size);
171
172         glMatrixMode(GL_PROJECTION);
173         glPushMatrix();
174         glLoadIdentity();
175
176         glOrtho(0.0, (GLdouble)(src->w * size), (GLdouble)(src->h * size), 0.0, 0.0, 1.0);
177         glMatrixMode(GL_MODELVIEW);
178         glPushMatrix();
179         glLoadIdentity();
180
181         // texture coordinates
182         texcoord[0] = 0.0f;
183         texcoord[1] = 0.0f;
184         texcoord[2] = (GLfloat)(src->w) / texture->w;
185         texcoord[3] = (GLfloat)(src->h) / texture->h;
186
187         // create an RGBA texture for the texture surface
188         glGenTextures(1, &texid);
189         glBindTexture(GL_TEXTURE_2D, texid);
190         
191         if (glFilter)
192         {
193        printf("OpenGL filters: enabled\n");
194            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
195            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
196         }
197         else
198         {
199        printf("OpenGL filters: disabled\n");
200            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
201            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
202     }
203     
204     switch ( texturebpp )
205     {
206     case 16:
207             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
208         break;
209     case 24:
210             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
211         break;
212     case 32:
213     default:
214             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
215         break;        
216     }    
217
218 }
219
220 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
221 {
222         //SDL_Rect rect = { 0, 0, src->w, src->h };
223
224         // convert color-indexed surface to RGB texture
225         //SDL_BlitSurface(src, &rect, texture, &rect);
226         //glFlush();
227         
228         SDL_BlitSurface(src, NULL, texture, NULL);
229
230 //      printf("Rmask - src : %d\n", src->format->Rmask);
231 //      printf("Gmask - src : %d\n", src->format->Gmask);
232 //      printf("Bmask - src : %d\n", src->format->Bmask);
233 //      printf("Amask - src : %d\n", src->format->Amask);
234
235 //      printf("Rmask - texture : %d\n", texture->format->Rmask);
236 //      printf("Gmask - texture : %d\n", texture->format->Gmask);
237 //      printf("Bmask - texture : %d\n", texture->format->Bmask);
238 //      printf("Amask - texture : %d\n", texture->format->Amask);
239
240         // Texturemap complete texture to surface so we have free scaling 
241         // and antialiasing
242     switch ( texturebpp )
243     {
244     case 16:
245         // GL_UNSIGNED_SHORT_5_6_5
246         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
247                         GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
248         break;
249     case 24:
250         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
251                         GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
252         break;
253     case 32:
254     default:
255         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
256                         GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
257         break;
258     }     
259         
260         switch (texturetype)
261         {
262         case 1:
263         glBegin(GL_QUADS);
264                 glTexCoord2f(texcoord[0], texcoord[1]);
265                 glVertex2f(0, 0);
266                 glTexCoord2f(texcoord[2], texcoord[1]);
267                 glVertex2f(dst->w , 0);
268                 glTexCoord2f(texcoord[2], texcoord[3]);
269                 glVertex2f(dst->w , dst->h );
270                 glTexCoord2f(texcoord[0], texcoord[3]);
271                 glVertex2f(0, dst->h );
272         glEnd();      
273
274         default:
275                 glBegin(GL_TRIANGLE_STRIP);
276                                 glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
277                                 glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 0);
278                                 glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h, 0);
279                                 glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
280                 glEnd();
281         }
282         
283 //  glFlush();
284         SDL_GL_SwapBuffers();    
285 //      glFinish();
286
287 }
288
289 void sdlemu_close_opengl(void)
290 {
291         if (texture)
292                 SDL_FreeSurface(texture);
293 }
294
295
296 //
297 // Resize the texture
298 // This should honor the glFilter flag that is passed in to the initialization code,
299 // but, at the moment, it doesn't...
300 // Now it does...!
301 //
302 void sdlemu_resize_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
303 {
304         // Texture width/height should be power of 2
305         // So, find the largest power of two that will contain both the width and height
306         //int w = power_of_two(src->w), h = power_of_two(src->h);
307         int w = 512, h = 512;
308         Uint32 rmask, gmask, bmask, amask;
309         
310         // We allow the developer to set its own texture bpp. But if the value is NULL or
311         // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
312         if ( (src_bpp != NULL) && ( (src_bpp == 16) || (src_bpp == 24) || (src_bpp == 32) ) )
313        texturebpp = src_bpp;
314     else
315        texturebpp = src->format->BitsPerPixel;
316         
317         // Delete old texture (if allocated)
318         if (texture)
319                 SDL_FreeSurface(texture);
320
321         // create texture surface
322         //NOTE: Seems the byte order here *is* important! (Perhaps only for 32 BPP?)
323         //
324         // NOTE : Nope! Not any more. We can now producte textures based upon 16, 24 or 32 bpp.
325         switch ( texturebpp )
326         {
327     case 16:
328     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
329
330 //          rmask = 0xff000000;
331 //              gmask = 0x00ff0000;
332 //              bmask = 0x0000ff00;
333 //              amask = 0x00000000;
334
335         rmask = 0x0000;
336                 gmask = 0x0000;
337                 bmask = 0x0000;
338                 amask = 0x0000;
339                 
340         #else
341
342 //          rmask = 0x000000ff;
343 //          gmask = 0x0000ff00;
344 //          bmask = 0x00ff0000;
345 //          amask = 0x00000000;
346
347         rmask = 0x0000;
348                 gmask = 0x0000;
349                 bmask = 0x0000;
350                 amask = 0x0000;
351
352     #endif
353         break;
354     case 24:
355     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
356             rmask = 0x00ff0000;
357                 gmask = 0x0000ff00;
358                 bmask = 0x000000ff;
359                 amask = 0x00000000;
360         #else
361             rmask = 0x000000ff;
362             gmask = 0x0000ff00;
363             bmask = 0x00ff0000;
364             amask = 0x00000000;
365     #endif
366        break;
367     case 32: 
368     default:
369     #if SDL_BYTEORDER == SDL_BIG_ENDIAN
370             rmask = 0xff000000;
371                 gmask = 0x00ff0000;
372                 bmask = 0x0000ff00;
373                 amask = 0x000000ff;
374         #else
375             rmask = 0x000000ff;
376             gmask = 0x0000ff00;
377             bmask = 0x00ff0000;
378             amask = 0xff000000;
379     #endif
380         break;
381     }    
382
383         // create texture surface
384         texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
385 /*      
386     #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
387                 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
388         #else
389                 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
390         #endif
391 */
392         
393  
394 /* 
395     texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32,
396         #if SDL_BYTEORDER == SDL_LIL_ENDIAN 
397                 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000);
398         #else
399                 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
400         #endif
401 */
402         // setup 2D gl environment
403         //glPushAttrib(GL_ENABLE_BIT);
404         //glDisable(GL_DEPTH_TEST);
405         //glDisable(GL_CULL_FACE);
406         //glEnable(GL_TEXTURE_2D);
407
408         glDisable(GL_FOG);
409         glDisable(GL_LIGHTING);
410         glDisable(GL_CULL_FACE);
411         glDisable(GL_DEPTH_TEST);
412         glDisable(GL_BLEND);
413         glDisable(GL_NORMALIZE);
414         glDisable(GL_ALPHA_TEST);
415         glEnable(GL_TEXTURE_2D);
416         glBlendFunc (GL_SRC_ALPHA, GL_ONE);
417
418         glViewport(0, 0, dst->w, dst->h);
419
420         glMatrixMode(GL_PROJECTION);
421         glPushMatrix();
422         glLoadIdentity();
423
424         glOrtho(0.0, (GLdouble)dst->w, (GLdouble)dst->h, 0.0, 0.0, 1.0);
425         glMatrixMode(GL_MODELVIEW);
426         glPushMatrix();
427         glLoadIdentity();
428
429         // texture coordinates
430         texcoord[0] = 0.0f, texcoord[1] = 0.0f,
431         texcoord[2] = (GLfloat)(src->w) / texture->w,
432         texcoord[3] = (GLfloat)(src->h) / texture->h;
433
434         // create an RGBA texture for the texture surface
435         glGenTextures(1, &texid);
436         glBindTexture(GL_TEXTURE_2D, texid);
437         
438 //      if (glFilter)
439         if (filter)
440         {
441        printf("OpenGL filters: enabled\n");
442            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
443            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
444         }
445         else
446         {
447        printf("OpenGL filters: disabled\n");
448            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
449            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
450     }
451
452     switch ( texturebpp )
453     {
454     case 16:
455             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
456         break;
457     case 24:
458             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
459         break;
460     case 32:
461     default:
462             glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
463         break;        
464     }    
465
466         //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
467 }