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 // We want alpha on our OpenGL contexts...!
45 // Or do we? Seems to kill performance on X...
46 // Or does it? Could it be bad blitter performance?
47 #define WANT_OPENGL_ALPHA
49 static SDL_Surface *texture = 0;
50 static GLuint texid = 0;
51 static GLfloat texcoord[4];
52 static unsigned int glFilter;
53 static unsigned int texturebpp = 0; // 16, 24 or 32 bpp
55 static SDL_Surface * overlay = 0;
56 static GLuint overlayID = 0;
57 static GLfloat overlayCoord[4];
58 void sdlemu_create_overlay(SDL_Surface * dst, int src_bpp);
60 static int showOverlay = 0;
62 static inline int power_of_two(int input)
72 void sdlemu_init_opengl(SDL_Surface * src, SDL_Surface * dst, int texturetype, int filter, int src_bpp)
74 printf("\nOpenGL driver information :\n");
76 printf("Vendor: %s\n", glGetString(GL_VENDOR));
77 printf("Renderer: %s\n", glGetString(GL_RENDERER));
78 printf("Version: %s\n", glGetString(GL_VERSION));
79 printf("OpenGL drawmethod: ");
84 printf("GL_QUAD rendering\n\n");
87 printf("GL_TRIANGLE rendering\n\n");
93 // Let us create the texture information :
94 sdlemu_create_texture(src, dst, filter, src_bpp);
95 sdlemu_create_overlay(dst, src_bpp);
98 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
101 This is needed when we want to render OpenGL textures with the Alpha mask set.
102 Be warned! This only works with the bpp of texture en *src set to 32.
104 #ifdef WANT_OPENGL_ALPHA
108 /* Save the alpha blending attributes */
109 saved_flags = src->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
110 saved_alpha = src->format->alpha;
111 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
112 SDL_SetAlpha(src, 0, 0);
115 // Blit the src display to the texture.
116 SDL_BlitSurface(src, NULL, texture, NULL);
118 /* Restore the alpha blending attributes */
119 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
120 SDL_SetAlpha(src, saved_flags, saved_alpha);
123 SDL_BlitSurface(src, NULL, texture, NULL);
125 // SDL_BlitSurface(src, NULL, overlay, NULL);
126 /*Uint32 * pix = (Uint32 *)overlay->pixels;
128 for(y=10; y<200; y++)
129 for(x=30; x<250; x++)
130 pix[x+(y*1024)] = 0x800000FF;//*/
132 glBlendFunc(GL_ONE, GL_ZERO);
133 glBindTexture(GL_TEXTURE_2D, texid);
134 // Texturemap complete texture to surface so we have free scaling
139 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
140 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
143 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
144 GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
148 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
149 GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
153 // Render the texture to the screen using OpenGL!
158 glTexCoord2f(texcoord[0], texcoord[1]);
160 glTexCoord2f(texcoord[2], texcoord[1]);
161 glVertex2f(dst->w, 0);
162 glTexCoord2f(texcoord[2], texcoord[3]);
163 glVertex2f(dst->w, dst->h);
164 glTexCoord2f(texcoord[0], texcoord[3]);
165 glVertex2f(0, dst->h);
169 glBegin(GL_TRIANGLE_STRIP);
170 glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
171 glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 0);
172 glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h, 0);
173 glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
179 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
180 glBindTexture(GL_TEXTURE_2D, overlayID);
181 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, overlay->w, overlay->h, GL_RGBA, GL_UNSIGNED_BYTE, overlay->pixels);
183 glTexCoord2f(overlayCoord[0], overlayCoord[1]);
185 glTexCoord2f(overlayCoord[2], overlayCoord[1]);
186 glVertex2f(dst->w, 0);
187 glTexCoord2f(overlayCoord[2], overlayCoord[3]);
188 glVertex2f(dst->w, dst->h);
189 glTexCoord2f(overlayCoord[0], overlayCoord[3]);
190 glVertex2f(0, dst->h);
194 //Do some OpenGL stuff here...
196 /*unsigned long int map[25] = {
197 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
198 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
199 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
200 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
201 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
203 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
204 glRasterPos2i(10, 10);
205 glDrawPixels(5, 5, GL_RGBA, GL_UNSIGNED_INT, map);//*/
208 SDL_GL_SwapBuffers();
213 void sdlemu_close_opengl(void)
216 SDL_FreeSurface(texture);
219 SDL_FreeSurface(overlay);
222 void sdlemu_create_overlay(SDL_Surface * dst, int src_bpp)
225 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
227 // Delete old texture (if allocated). Useful when there is a screen resize.
229 SDL_FreeSurface(overlay);
231 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
232 // So, find the largest power of two that will contain both the width and height
233 int w = power_of_two(dst->w);
234 int h = power_of_two(dst->h);
236 printf("OpenGL - Overlay size : %d x %d\n", w, h);
238 // Setting bpp based upon src_bpp.
241 // We allow the developer to set its own texture bpp. But if the value is NULL or
242 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
243 if (bpp == 16 || bpp == 24 || bpp == 32)
246 texturebpp = dst->format->BitsPerPixel;
248 printf("OpenGL - Overlay depth : %d bpp\n", texturebpp);
250 // Now were are going to create a SDL_Surface named texture. This will be our surface
251 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
252 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
253 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
256 // NOTE: Seems the byte order here *is* important!
259 case 16: // *src has depth of 16 bpp
261 According to information on the SDL mailinglist and on internet, the following
262 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
263 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
265 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
267 #ifdef OPENGL_16BPP_CORRECT_RGBA
279 case 24: // *src has depth of 24 bpp
280 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
284 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
289 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
292 case 32: //*src has depth of 32 bpp
293 default: //which is also the default.
294 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
308 // Creating SDL_Surface texture based upon the above settings.
309 overlay = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
311 // Setting up the texture coordinates.
312 overlayCoord[0] = 0.0f;
313 overlayCoord[1] = 0.0f;
314 overlayCoord[2] = (GLfloat)(dst->w) / overlay->w;
315 overlayCoord[3] = (GLfloat)(dst->h) / overlay->h;
317 // create a RGB(A) texture for the texture surface
318 glGenTextures(1, &overlayID);
319 glBindTexture(GL_TEXTURE_2D, overlayID);
321 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
322 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
324 // Setting texture mode.
325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
326 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
328 // Generate the texture using the above information.
332 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
333 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
336 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
338 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
339 // If you use Alpha. Use textures with a depth of 32bpp.
340 // 24bpp textures are SLOW and avoid them at all costs!
341 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, overlay->w, overlay->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
345 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
346 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, overlay->w, overlay->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
351 void * sdlemuGetOverlayPixels(void)
353 return overlay->pixels;
356 Uint32 sdlemuGetOverlayWidthInPixels(void)
358 return overlay->pitch / 4;
361 void sdlemuEnableOverlay(void)
366 void sdlemuDisableOverlay(void)
371 void sdlemu_create_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
374 int w , h; // w and h contain the width and height of the OpenGL texture.
375 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
378 // Delete old texture (if allocated). Useful when there is a screen resize.
380 SDL_FreeSurface(texture);
382 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
383 // So, find the largest power of two that will contain both the width and height
384 w = power_of_two(src->w);
385 h = power_of_two(src->h);
387 printf("OpenGL - Texture size : %d x %d\n", w, h);
389 // Setting bpp based upon src_bpp.
392 // We allow the developer to set its own texture bpp. But if the value is NULL or
393 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
394 if (bpp == 16 || bpp == 24 || bpp == 32)
397 texturebpp = src->format->BitsPerPixel;
399 printf("OpenGL - Texture depth : %d bpp\n", texturebpp);
401 // Now were are going to create a SDL_Surface named texture. This will be our surface
402 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
403 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
404 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
407 // NOTE: Seems the byte order here *is* important!
410 case 16: // *src has depth of 16 bpp
412 According to information on the SDL mailinglist and on internet, the following
413 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
414 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
416 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
418 #ifdef OPENGL_16BPP_CORRECT_RGBA
430 case 24: // *src has depth of 24 bpp
431 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
435 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
440 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
443 case 32: //*src has depth of 32 bpp
444 default: //which is also the default.
445 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
459 // Creating SDL_Surface texture based upon the above settings.
460 texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
464 glDisable(GL_LIGHTING);
465 glDisable(GL_CULL_FACE);
466 glDisable(GL_DEPTH_TEST);
467 // glDisable(GL_BLEND);
469 glDisable(GL_NORMALIZE);
470 glDisable(GL_ALPHA_TEST);
471 glEnable(GL_TEXTURE_2D);
472 // glBlendFunc(GL_SRC_ALPHA, GL_ONE);
473 // glBlendFunc(GL_ONE, GL_SRC_ALPHA);
474 //This works, but in a wrong way...
475 // glBlendFunc(GL_ONE, GL_ONE);
477 // Definitely needed for screen resolution larger then the *src.
478 // This way we can have automatic scaling functionality.
479 glViewport(0, 0, dst->w, dst->h);
480 glMatrixMode(GL_PROJECTION);
483 glOrtho(0.0, (GLdouble)dst->w, (GLdouble)dst->h, 0.0, 0.0, 1.0);
484 glMatrixMode(GL_MODELVIEW);
488 // Setting up the texture coordinates.
491 texcoord[2] = (GLfloat)(src->w) / texture->w;
492 texcoord[3] = (GLfloat)(src->h) / texture->h;
494 // create a RGB(A) texture for the texture surface
495 glGenTextures(1, &texid);
496 glBindTexture(GL_TEXTURE_2D, texid);
498 // Setting up the OpenGL Filters. These filters are important when we/you
499 // want to scale the texture.
502 // Textures are rendered in best quality.
503 printf("OpenGL filters: enabled\n");
504 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
505 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
509 // Textures are rendered in normal quality.
510 printf("OpenGL filters: disabled\n");
511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
515 // Setting texture mode.
516 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
517 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
519 // Generate the texture using the above information.
523 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
524 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
527 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
529 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
530 // If you use Alpha. Use textures with a depth of 32bpp.
531 // 24bpp textures are SLOW and avoid them at all costs!
532 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
536 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
537 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);