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);
90 sdlemu_create_overlay(dst, src_bpp);
93 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
96 This is needed when we want to render OpenGL textures with the Alpha mask set.
97 Be warned! This only works with the bpp of texture en *src set to 32.
99 #ifdef WANT_OPENGL_ALPHA
103 /* Save the alpha blending attributes */
104 saved_flags = src->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
105 saved_alpha = src->format->alpha;
106 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
107 SDL_SetAlpha(src, 0, 0);
110 // Blit the src display to the texture.
111 SDL_BlitSurface(src, NULL, texture, NULL);
113 /* Restore the alpha blending attributes */
114 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
115 SDL_SetAlpha(src, saved_flags, saved_alpha);
118 SDL_BlitSurface(src, NULL, texture, NULL);
120 // SDL_BlitSurface(src, NULL, overlay, NULL);
121 /*Uint32 * pix = (Uint32 *)overlay->pixels;
123 for(y=10; y<200; y++)
124 for(x=30; x<250; x++)
125 pix[x+(y*1024)] = 0x800000FF;//*/
127 glBlendFunc(GL_ONE, GL_ZERO);
128 glBindTexture(GL_TEXTURE_2D, texid);
129 // Texturemap complete texture to surface so we have free scaling
134 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
135 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
138 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
139 GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
143 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
144 GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
148 // Render the texture to the screen using OpenGL!
153 glTexCoord2f(texcoord[0], texcoord[1]);
155 glTexCoord2f(texcoord[2], texcoord[1]);
156 glVertex2f(dst->w, 0);
157 glTexCoord2f(texcoord[2], texcoord[3]);
158 glVertex2f(dst->w, dst->h);
159 glTexCoord2f(texcoord[0], texcoord[3]);
160 glVertex2f(0, dst->h);
164 glBegin(GL_TRIANGLE_STRIP);
165 glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
166 glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 0);
167 glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h, 0);
168 glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
174 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
175 glBindTexture(GL_TEXTURE_2D, overlayID);
176 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, overlay->w, overlay->h, GL_RGBA, GL_UNSIGNED_BYTE, overlay->pixels);
178 glTexCoord2f(overlayCoord[0], overlayCoord[1]);
180 glTexCoord2f(overlayCoord[2], overlayCoord[1]);
181 glVertex2f(dst->w, 0);
182 glTexCoord2f(overlayCoord[2], overlayCoord[3]);
183 glVertex2f(dst->w, dst->h);
184 glTexCoord2f(overlayCoord[0], overlayCoord[3]);
185 glVertex2f(0, dst->h);
189 //Do some OpenGL stuff here...
191 /*unsigned long int map[25] = {
192 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
193 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
194 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
195 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
196 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
198 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
199 glRasterPos2i(10, 10);
200 glDrawPixels(5, 5, GL_RGBA, GL_UNSIGNED_INT, map);//*/
203 SDL_GL_SwapBuffers();
208 void sdlemu_close_opengl(void)
211 SDL_FreeSurface(texture);
214 SDL_FreeSurface(overlay);
217 void sdlemu_create_overlay(SDL_Surface * dst, int src_bpp)
220 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
222 // Delete old texture (if allocated). Useful when there is a screen resize.
224 SDL_FreeSurface(overlay);
226 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
227 // So, find the largest power of two that will contain both the width and height
228 int w = power_of_two(dst->w);
229 int h = power_of_two(dst->h);
231 printf("OpenGL - Overlay size : %d x %d\n", w, h);
233 // Setting bpp based upon src_bpp.
236 // We allow the developer to set its own texture bpp. But if the value is NULL or
237 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
238 if (bpp == 16 || bpp == 24 || bpp == 32)
241 texturebpp = dst->format->BitsPerPixel;
243 printf("OpenGL - Overlay depth : %d bpp\n", texturebpp);
245 // Now were are going to create a SDL_Surface named texture. This will be our surface
246 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
247 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
248 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
251 // NOTE: Seems the byte order here *is* important!
254 case 16: // *src has depth of 16 bpp
256 According to information on the SDL mailinglist and on internet, the following
257 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
258 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
260 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
262 #ifdef OPENGL_16BPP_CORRECT_RGBA
274 case 24: // *src has depth of 24 bpp
275 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
279 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
284 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
287 case 32: //*src has depth of 32 bpp
288 default: //which is also the default.
289 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
303 // Creating SDL_Surface texture based upon the above settings.
304 overlay = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
306 // Setting up the texture coordinates.
307 overlayCoord[0] = 0.0f;
308 overlayCoord[1] = 0.0f;
309 overlayCoord[2] = (GLfloat)(dst->w) / overlay->w;
310 overlayCoord[3] = (GLfloat)(dst->h) / overlay->h;
312 // create a RGB(A) texture for the texture surface
313 glGenTextures(1, &overlayID);
314 glBindTexture(GL_TEXTURE_2D, overlayID);
316 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
319 // Setting texture mode.
320 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
323 // Generate the texture using the above information.
327 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
328 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
331 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
333 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
334 // If you use Alpha. Use textures with a depth of 32bpp.
335 // 24bpp textures are SLOW and avoid them at all costs!
336 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
340 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
341 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, overlay->w, overlay->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
346 void * sdlemuGetOverlayPixels(void)
348 return overlay->pixels;
351 Uint32 sdlemuGetOverlayWidthInPixels(void)
353 return overlay->pitch / 4;
356 void sdlemuEnableOverlay(void)
361 void sdlemuDisableOverlay(void)
366 void sdlemu_create_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
369 int w , h; // w and h contain the width and height of the OpenGL texture.
370 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
373 // Delete old texture (if allocated). Useful when there is a screen resize.
375 SDL_FreeSurface(texture);
377 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
378 // So, find the largest power of two that will contain both the width and height
379 w = power_of_two(src->w);
380 h = power_of_two(src->h);
382 printf("OpenGL - Texture size : %d x %d\n", w, h);
384 // Setting bpp based upon src_bpp.
387 // We allow the developer to set its own texture bpp. But if the value is NULL or
388 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
389 if (bpp == 16 || bpp == 24 || bpp == 32)
392 texturebpp = src->format->BitsPerPixel;
394 printf("OpenGL - Texture depth : %d bpp\n", texturebpp);
396 // Now were are going to create a SDL_Surface named texture. This will be our surface
397 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
398 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
399 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
402 // NOTE: Seems the byte order here *is* important!
405 case 16: // *src has depth of 16 bpp
407 According to information on the SDL mailinglist and on internet, the following
408 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
409 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
411 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
413 #ifdef OPENGL_16BPP_CORRECT_RGBA
425 case 24: // *src has depth of 24 bpp
426 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
430 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
435 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
438 case 32: //*src has depth of 32 bpp
439 default: //which is also the default.
440 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
454 // Creating SDL_Surface texture based upon the above settings.
455 texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
459 glDisable(GL_LIGHTING);
460 glDisable(GL_CULL_FACE);
461 glDisable(GL_DEPTH_TEST);
462 // glDisable(GL_BLEND);
464 glDisable(GL_NORMALIZE);
465 glDisable(GL_ALPHA_TEST);
466 glEnable(GL_TEXTURE_2D);
467 // glBlendFunc(GL_SRC_ALPHA, GL_ONE);
468 // glBlendFunc(GL_ONE, GL_SRC_ALPHA);
469 //This works, but in a wrong way...
470 // glBlendFunc(GL_ONE, GL_ONE);
472 // Definitely needed for screen resolution larger then the *src.
473 // This way we can have automatic scaling functionality.
474 glViewport(0, 0, dst->w, dst->h);
475 glMatrixMode(GL_PROJECTION);
478 glOrtho(0.0, (GLdouble)dst->w, (GLdouble)dst->h, 0.0, 0.0, 1.0);
479 glMatrixMode(GL_MODELVIEW);
483 // Setting up the texture coordinates.
486 texcoord[2] = (GLfloat)(src->w) / texture->w;
487 texcoord[3] = (GLfloat)(src->h) / texture->h;
489 // create a RGB(A) texture for the texture surface
490 glGenTextures(1, &texid);
491 glBindTexture(GL_TEXTURE_2D, texid);
493 // Setting up the OpenGL Filters. These filters are important when we/you
494 // want to scale the texture.
497 // Textures are rendered in best quality.
498 printf("OpenGL filters: enabled\n");
499 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
500 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
504 // Textures are rendered in normal quality.
505 printf("OpenGL filters: disabled\n");
506 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
507 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
510 // Setting texture mode.
511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
514 // Generate the texture using the above information.
518 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
519 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
522 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
524 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
525 // If you use Alpha. Use textures with a depth of 32bpp.
526 // 24bpp textures are SLOW and avoid them at all costs!
527 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
531 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
532 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);