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 absolete 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 inline int power_of_two(int input)
60 void sdlemu_init_opengl(SDL_Surface * src, SDL_Surface * dst, int texturetype, int filter, int src_bpp)
63 printf("\nOpenGL driver information :\n");
65 printf("Vendor: %s\n", glGetString(GL_VENDOR));
66 printf("Renderer: %s\n", glGetString(GL_RENDERER));
67 printf("Version: %s\n", glGetString(GL_VERSION));
68 printf("OpenGL drawmethod: ");
73 printf("GL_QUAD rendering\n\n");
76 printf("GL_TRIANGLE rendering\n\n");
82 // Let us create the texture information :
83 sdlemu_create_texture( src, dst, filter , src_bpp);
87 void sdlemu_draw_texture(SDL_Surface * dst, SDL_Surface * src, int texturetype)
90 This is needed when we want to render OpenGL textures with the Alpha mask set.
91 Be warned! This only works with the bpp of texture en *src set to 32.
93 #ifdef WANT_OPENGL_ALPHA
97 /* Save the alpha blending attributes */
98 saved_flags = src->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
99 saved_alpha = src->format->alpha;
100 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
101 SDL_SetAlpha(src, 0, 0);
104 // Blit the src display to the texture.
105 SDL_BlitSurface(src, NULL, texture, NULL);
107 /* Restore the alpha blending attributes */
108 if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
109 SDL_SetAlpha(src, saved_flags, saved_alpha);
112 SDL_BlitSurface(src, NULL, texture, NULL);
115 // Texturemap complete texture to surface so we have free scaling
117 switch ( texturebpp )
120 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
121 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture->pixels);
124 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
125 GL_RGB, GL_UNSIGNED_BYTE, texture->pixels);
129 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->w, texture->h,
130 GL_RGBA, GL_UNSIGNED_BYTE, texture->pixels);
134 // Render the texture to the screen using OpenGL!
139 glTexCoord2f(texcoord[0], texcoord[1]);
141 glTexCoord2f(texcoord[2], texcoord[1]);
142 glVertex2f(dst->w , 0);
143 glTexCoord2f(texcoord[2], texcoord[3]);
144 glVertex2f(dst->w , dst->h );
145 glTexCoord2f(texcoord[0], texcoord[3]);
146 glVertex2f(0, dst->h );
150 glBegin(GL_TRIANGLE_STRIP);
151 glTexCoord2f(texcoord[0], texcoord[1]); glVertex3i(0, 0, 0);
152 glTexCoord2f(texcoord[2], texcoord[1]); glVertex3i(dst->w, 0, 0);
153 glTexCoord2f(texcoord[0], texcoord[3]); glVertex3i(0, dst->h, 0);
154 glTexCoord2f(texcoord[2], texcoord[3]); glVertex3i(dst->w, dst->h, 0);
159 SDL_GL_SwapBuffers();
164 void sdlemu_close_opengl(void)
167 SDL_FreeSurface(texture);
170 void sdlemu_create_texture(SDL_Surface * src, SDL_Surface * dst, int filter, int src_bpp)
173 int w , h; // w and h contain the width and height of the OpenGL texture.
174 Uint32 rmask, gmask, bmask, amask; // Needed for creating RGBA masks.
177 // Delete old texture (if allocated). Usefull when there is a screen resize.
179 SDL_FreeSurface(texture);
181 // Texture width/height should be power of 2 of the SDL_Surface *src when using OpenGL.
182 // So, find the largest power of two that will contain both the width and height
183 w = power_of_two(src->w);
184 h = power_of_two(src->h);
186 printf("OpenGL - Texture size : %d x %d\n", w, h);
188 // Setting bpp based upon src_bpp.
191 // We allow the developer to set its own texture bpp. But if the value is NULL or
192 // not equal to 16, 24 or 32, we make the texturebpp the same as the BPP from src.
193 if ( (bpp != NULL) && ( (bpp == 16) || (bpp == 24) || (bpp == 32) ) )
196 texturebpp = src->format->BitsPerPixel;
198 printf("OpenGL - Texture depth : %d bpp\n", texturebpp);
200 // Now were are going to create a SDL_Surface named texture. This will be our surface
201 // which will function as a buffer between the SDL_Surface *src and SDL_Surface *dst.
202 // This buffer is needed because we need to convert the SDL_Surface *src to an OpenGL
203 // texture with a depth of 16, 24 or 32 bpp, before we can blit the pixels to *dst
206 // NOTE: Seems the byte order here *is* important!
207 switch ( texturebpp )
209 case 16: // *src has depth of 16 bpp
212 According to information on the SDL mailinglist and on internet, the following
213 rgba masks should be the ones to use. But somehow the screen gets f*cked up and
214 the RGB colours are incorrect (at least in Virtual Jaguar/SDL).
216 Compile with -DOPENGL_16BPP_CORRECT_RGBA to use this RGBA values.
219 #ifdef OPENGL_16BPP_CORRECT_RGBA
235 case 24: // *src has depth of 24 bpp
236 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
240 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
245 amask = 0x00000000; // IMPORTANT! 24 bpp doesn't use Alpha (at least in our case).
248 case 32: //*src has depth of 32 bpp
249 default: //which is also the default.
250 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
264 // Creating SDL_Surface texture based upon the above settings.
265 texture = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, texturebpp, rmask, gmask, bmask, amask);
269 glDisable(GL_LIGHTING);
270 glDisable(GL_CULL_FACE);
271 glDisable(GL_DEPTH_TEST);
273 glDisable(GL_NORMALIZE);
274 glDisable(GL_ALPHA_TEST);
275 glEnable(GL_TEXTURE_2D);
276 glBlendFunc (GL_SRC_ALPHA, GL_ONE);
278 // Definately needed for screen resolution larger then the *src.
279 // This way we can have automatic scaling fucntionality.
280 glViewport(0, 0, dst->w, dst->h);
281 glMatrixMode(GL_PROJECTION);
284 glOrtho(0.0, (GLdouble)dst->w, (GLdouble)dst->h, 0.0, 0.0, 1.0);
285 glMatrixMode(GL_MODELVIEW);
289 // Setting up the texture coordinates.
292 texcoord[2] = (GLfloat)(src->w) / texture->w;
293 texcoord[3] = (GLfloat)(src->h) / texture->h;
295 // create a RGB(A) texture for the texture surface
296 glGenTextures(1, &texid);
297 glBindTexture(GL_TEXTURE_2D, texid);
299 // Srtting up the OpenGL Filters. These filters are important when we/you
300 // want to scale the texture.
303 // Textures are rendered in best quality.
304 printf("OpenGL filters: enabled\n");
305 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
310 // Textures are rendered in normal quality.
311 printf("OpenGL filters: disabled\n");
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
316 // Setting texture mode.
317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
321 // Genereate the texture using the above information.
322 switch ( texturebpp )
325 // Normal 16bpp depth based textures consist out of GL_RGB5 and doesn't have support for Alpha channels.
326 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
329 // The 24bpp depth based textures consist out of GL_RGB8 and doesn't have support for Alpha channels.
331 // IMPORTANT : If you don't use Alpha. Use textures with a depth of 16bpp.
332 // If you use Alpha. Use textures with a depth of 32bpp.
333 // 24bpp textures are SLOW and avoid them at all costst!
334 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture->w, texture->h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
338 // The 32bpp depth based textures consist out of GL_RGBA8 and has support for Alpha channels.
339 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, texture->w, texture->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);