2 * SDLEMU library - Free sdl related functions library
3 * Copyrigh(c) 1999-2004 sdlemu development crew
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.
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.
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
21 SDLEMU related sources for using OpenGL with SDL.
22 By Niels Wagenaar | http://sdlemu.ngemu.com | shalafi@xs4all.nl
24 Version 1.0.001 - 4-10-2004
26 - Added support for 16, 24 and 32 bit textures;
27 - Added support for 16, 24 and 32 bit texture rendering;
29 Version 1.0.002 - 6-10-2004
31 - Cleaned up a lot of code and removed non functional and obsolete code;
32 - Removed sdlemu_resize_texture function because of double code;
33 - Removed the texture creation from the sdlemu_init_opengl;
34 - Added sdlemu_create_texture function to replace the sdlemu_resize_texture function
35 and the texture creation in sdlemu_init_opengl;
36 - Added the usage of OPENGL_16BPP_CORRECT_RGBA for activating the correct 16bpp RGBA masks;
37 - Added the usage of WANT_OPENGL_ALPHA for using ALPHA blending with 32bpp textures;
38 - Added automatic and override texture bpp depth setting (based upon the src surface);
42 #include "sdlemu_opengl.h"
44 static SDL_Surface *texture = 0;
45 static GLuint texid = 0;
46 static GLfloat texcoord[4];
47 static unsigned int glFilter;
48 static unsigned int texturebpp = 0; // 16, 24 or 32 bpp
50 static SDL_Surface * overlay = 0;
51 static GLuint overlayID = 0;
52 static GLfloat overlayCoord[4];
53 void sdlemu_create_overlay(SDL_Surface * dst, int src_bpp);
55 static int showOverlay = 0;
57 static inline int power_of_two(int input)
67 void sdlemu_init_opengl(SDL_Surface * src, SDL_Surface * dst, int texturetype, int filter, int src_bpp)
69 printf("\nOpenGL driver information :\n");
71 printf("Vendor: %s\n", glGetString(GL_VENDOR));
72 printf("Renderer: %s\n", glGetString(GL_RENDERER));
73 printf("Version: %s\n", glGetString(GL_VERSION));
74 printf("OpenGL drawmethod: ");
79 printf("GL_QUAD rendering\n\n");
82 printf("GL_TRIANGLE rendering\n\n");
88 // Let us create the texture information :
89 sdlemu_create_texture(src, dst, filter, src_bpp);
91 sdlemu_create_overlay(dst, src_bpp);
94 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
97 This is needed when we want to render OpenGL textures with the Alpha mask set.
98 Be warned! This only works with the bpp of texture en *src set to 32.
100 #ifdef WANT_OPENGL_ALPHA
104 /* Save the alpha blending attributes */
105 saved_flags = src->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
106 saved_alpha = src->format->alpha;
107 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
108 SDL_SetAlpha(src, 0, 0);
111 // Blit the src display to the texture.
112 SDL_BlitSurface(src, NULL, texture, NULL);
114 /* Restore the alpha blending attributes */
115 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
116 SDL_SetAlpha(src, saved_flags, saved_alpha);
119 SDL_BlitSurface(src, NULL, texture, NULL);
121 // SDL_BlitSurface(src, NULL, overlay, NULL);
122 /*Uint32 * pix = (Uint32 *)overlay->pixels;
124 for(y=10; y<200; y++)
125 for(x=30; x<250; x++)
126 pix[x+(y*1024)] = 0x800000FF;//*/
128 glBlendFunc(GL_ONE, GL_ZERO);
129 glBindTexture(GL_TEXTURE_2D, texid);
130 // Texturemap complete texture to surface so we have free scaling
135 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
136 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
139 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
140 GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
144 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
145 GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
149 // Render the texture to the screen using OpenGL!
154 glTexCoord2f(texcoord[0], texcoord[1]);
156 glTexCoord2f(texcoord[2], texcoord[1]);
157 glVertex2f(dst->w, 0);
158 glTexCoord2f(texcoord[2], texcoord[3]);
159 glVertex2f(dst->w, dst->h);
160 glTexCoord2f(texcoord[0], texcoord[3]);
161 glVertex2f(0, dst->h);
165 glBegin(GL_TRIANGLE_STRIP);
166 glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
167 glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 0);
168 glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h, 0);
169 glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
175 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
176 glBindTexture(GL_TEXTURE_2D, overlayID);
177 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, overlay->w, overlay->h, GL_RGBA, GL_UNSIGNED_BYTE, overlay->pixels);
179 glTexCoord2f(overlayCoord[0], overlayCoord[1]);
181 glTexCoord2f(overlayCoord[2], overlayCoord[1]);
182 glVertex2f(dst->w, 0);
183 glTexCoord2f(overlayCoord[2], overlayCoord[3]);
184 glVertex2f(dst->w, dst->h);
185 glTexCoord2f(overlayCoord[0], overlayCoord[3]);
186 glVertex2f(0, dst->h);
190 //Do some OpenGL stuff here...
192 /*unsigned long int map[25] = {
193 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
194 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
195 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
196 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
197 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
199 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
200 glRasterPos2i(10, 10);
201 glDrawPixels(5, 5, GL_RGBA, GL_UNSIGNED_INT, map);//*/
204 SDL_GL_SwapBuffers();
209 void sdlemu_close_opengl(void)
212 SDL_FreeSurface(texture);
215 SDL_FreeSurface(overlay);
218 void sdlemu_create_overlay(SDL_Surface * dst, int src_bpp)
221 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
223 // Delete old texture (if allocated). Useful when there is a screen resize.
225 SDL_FreeSurface(overlay);
227 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
228 // So, find the largest power of two that will contain both the width and height
229 int w = power_of_two(dst->w);
230 int h = power_of_two(dst->h);
232 printf("OpenGL - Overlay size : %d x %d\n", w, h);
234 // Setting bpp based upon src_bpp.
237 // We allow the developer to set its own texture bpp. But if the value is NULL or
238 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
239 if (bpp == 16 || bpp == 24 || bpp == 32)
242 texturebpp = dst->format->BitsPerPixel;
244 printf("OpenGL - Overlay depth : %d bpp\n", texturebpp);
246 // Now were are going to create a SDL_Surface named texture. This will be our surface
247 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
248 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
249 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
252 // NOTE: Seems the byte order here *is* important!
255 case 16: // *src has depth of 16 bpp
257 According to information on the SDL mailinglist and on internet, the following
258 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
259 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
261 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
263 #ifdef OPENGL_16BPP_CORRECT_RGBA
275 case 24: // *src has depth of 24 bpp
276 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
280 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
285 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
288 case 32: //*src has depth of 32 bpp
289 default: //which is also the default.
290 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
304 // Creating SDL_Surface texture based upon the above settings.
305 overlay = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
307 // Setting up the texture coordinates.
308 overlayCoord[0] = 0.0f;
309 overlayCoord[1] = 0.0f;
310 overlayCoord[2] = (GLfloat)(dst->w) / overlay->w;
311 overlayCoord[3] = (GLfloat)(dst->h) / overlay->h;
313 // create a RGB(A) texture for the texture surface
314 glGenTextures(1, &overlayID);
315 glBindTexture(GL_TEXTURE_2D, overlayID);
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
320 // Setting texture mode.
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
324 // Generate the texture using the above information.
328 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
329 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
332 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
334 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
335 // If you use Alpha. Use textures with a depth of 32bpp.
336 // 24bpp textures are SLOW and avoid them at all costs!
337 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
341 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
342 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, overlay->w, overlay->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
347 void * sdlemuGetOverlayPixels(void)
349 return overlay->pixels;
352 Uint32 sdlemuGetOverlayWidthInPixels(void)
354 return overlay->pitch / 4;
357 void sdlemuEnableOverlay(void)
362 void sdlemuDisableOverlay(void)
367 void sdlemu_create_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
370 int w , h; // w and h contain the width and height of the OpenGL texture.
371 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
374 // Delete old texture (if allocated). Useful when there is a screen resize.
376 SDL_FreeSurface(texture);
378 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
379 // So, find the largest power of two that will contain both the width and height
380 w = power_of_two(src->w);
381 h = power_of_two(src->h);
383 printf("OpenGL - Texture size : %d x %d\n", w, h);
385 // Setting bpp based upon src_bpp.
388 // We allow the developer to set its own texture bpp. But if the value is NULL or
389 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
390 if (bpp == 16 || bpp == 24 || bpp == 32)
393 texturebpp = src->format->BitsPerPixel;
395 printf("OpenGL - Texture depth : %d bpp\n", texturebpp);
397 // Now were are going to create a SDL_Surface named texture. This will be our surface
398 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
399 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
400 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
403 // NOTE: Seems the byte order here *is* important!
406 case 16: // *src has depth of 16 bpp
408 According to information on the SDL mailinglist and on internet, the following
409 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
410 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
412 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
414 #ifdef OPENGL_16BPP_CORRECT_RGBA
426 case 24: // *src has depth of 24 bpp
427 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
431 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
436 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
439 case 32: //*src has depth of 32 bpp
440 default: //which is also the default.
441 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
455 // Creating SDL_Surface texture based upon the above settings.
456 texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
460 glDisable(GL_LIGHTING);
461 glDisable(GL_CULL_FACE);
462 glDisable(GL_DEPTH_TEST);
463 // glDisable(GL_BLEND);
465 glDisable(GL_NORMALIZE);
466 glDisable(GL_ALPHA_TEST);
467 glEnable(GL_TEXTURE_2D);
468 // glBlendFunc(GL_SRC_ALPHA, GL_ONE);
469 // glBlendFunc(GL_ONE, GL_SRC_ALPHA);
470 //This works, but in a wrong way...
471 // glBlendFunc(GL_ONE, GL_ONE);
473 // Definitely needed for screen resolution larger then the *src.
474 // This way we can have automatic scaling functionality.
475 glViewport(0, 0, dst->w, dst->h);
476 glMatrixMode(GL_PROJECTION);
479 glOrtho(0.0, (GLdouble)dst->w, (GLdouble)dst->h, 0.0, 0.0, 1.0);
480 glMatrixMode(GL_MODELVIEW);
484 // Setting up the texture coordinates.
487 texcoord[2] = (GLfloat)(src->w) / texture->w;
488 texcoord[3] = (GLfloat)(src->h) / texture->h;
490 // create a RGB(A) texture for the texture surface
491 glGenTextures(1, &texid);
492 glBindTexture(GL_TEXTURE_2D, texid);
494 // Setting up the OpenGL Filters. These filters are important when we/you
495 // want to scale the texture.
498 // Textures are rendered in best quality.
499 printf("OpenGL filters: enabled\n");
500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
501 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
505 // Textures are rendered in normal quality.
506 printf("OpenGL filters: disabled\n");
507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
508 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
511 // Setting texture mode.
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
515 // Generate the texture using the above information.
519 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
520 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
523 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
525 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
526 // If you use Alpha. Use textures with a depth of 32bpp.
527 // 24bpp textures are SLOW and avoid them at all costs!
528 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
532 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);