From 8f09ff003d6b94411befa10b105f23441d245c5b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 6 Nov 2001 01:48:36 +0000 Subject: [PATCH] Modified the logo texture load to accept any width/height image --- test/testgl.c | 308 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 222 insertions(+), 86 deletions(-) diff --git a/test/testgl.c b/test/testgl.c index ebd5681d6..4dcb26f61 100644 --- a/test/testgl.c +++ b/test/testgl.c @@ -6,12 +6,22 @@ #include "SDL.h" #ifdef HAVE_OPENGL + #include "SDL_opengl.h" +/* Undefine this if you want a flat cube instead of a rainbow cube */ #define SHADED_CUBE +/* Define this to be the name of the logo image to use with -logo */ +#define LOGO_FILE "icon.bmp" + +/* The SDL_OPENGLBLIT interface is deprecated. + The code is still available for benchmark purposes though. +*/ static SDL_bool USE_DEPRECATED_OPENGLBLIT = SDL_FALSE; +/**********************************************************************/ + void HotKey_ToggleFullScreen(void) { SDL_Surface *screen; @@ -134,10 +144,174 @@ void SDL_GL_Leave2DMode() glPopAttrib(); } -void DrawSDLLogo(void) +/* Quick utility function for texture creation */ +static int power_of_two(int input) +{ + int value = 1; + + while ( value < input ) { + value <<= 1; + } + return value; +} + +GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) +{ + GLuint texture; + int w, h; + SDL_Surface *image; + SDL_Rect area; + Uint32 saved_flags; + Uint8 saved_alpha; + + /* Use the surface width and height expanded to powers of 2 */ + w = power_of_two(surface->w); + h = power_of_two(surface->h); + texcoord[0] = 0.0f; /* Min X */ + texcoord[1] = 0.0f; /* Min Y */ + texcoord[2] = (GLfloat)surface->w / w; /* Max X */ + texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ + + image = SDL_CreateRGBSurface( + SDL_SWSURFACE, + w, h, + 32, +#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ + 0x000000FF, + 0x0000FF00, + 0x00FF0000, + 0xFF000000 +#else + 0xFF000000, + 0x00FF0000, + 0x0000FF00, + 0x000000FF +#endif + ); + if ( image == NULL ) { + return 0; + } + + /* Save the alpha blending attributes */ + saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); + saved_alpha = surface->format->alpha; + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, 0, 0); + } + + /* Copy the surface into the GL texture image */ + area.x = 0; + area.y = 0; + area.w = surface->w; + area.h = surface->h; + SDL_BlitSurface(surface, &area, image, &area); + + /* Restore the alpha blending attributes */ + if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { + SDL_SetAlpha(surface, saved_flags, saved_alpha); + } + + /* Create an OpenGL texture for the image */ + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + w, h, + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + image->pixels); + SDL_FreeSurface(image); /* No longer needed */ + + return texture; +} + +void DrawLogoTexture(void) +{ + static GLuint texture; + static GLfloat texMinX, texMinY; + static GLfloat texMaxX, texMaxY; + static int x = 0; + static int y = 0; + static int w, h; + static int delta_x = 1; + static int delta_y = 1; + static Uint32 last_moved = 0; + + SDL_Surface *screen = SDL_GetVideoSurface(); + + if ( ! texture ) { + SDL_Surface *image; + GLfloat texcoord[4]; + + /* Load the image (could use SDL_image library here) */ + image = SDL_LoadBMP(LOGO_FILE); + if ( image == NULL ) { + return; + } + w = image->w; + h = image->h; + + /* Convert the image into an OpenGL texture */ + texture = SDL_GL_LoadTexture(image, texcoord); + + /* Make texture coordinates easy to understand */ + texMinX = texcoord[0]; + texMinY = texcoord[1]; + texMaxX = texcoord[2]; + texMaxY = texcoord[3]; + + /* We don't need the original image anymore */ + SDL_FreeSurface(image); + + /* Make sure that the texture conversion is okay */ + if ( ! texture ) { + return; + } + } + + /* Move the image around */ + x += delta_x; + if ( x < 0 ) { + x = 0; + delta_x = -delta_x; + } else + if ( (x+w) > screen->w ) { + x = screen->w-w; + delta_x = -delta_x; + } + y += delta_y; + if ( y < 0 ) { + y = 0; + delta_y = -delta_y; + } else + if ( (y+h) > screen->h ) { + y = screen->h-h; + delta_y = -delta_y; + } + + /* Show the image on the screen */ + SDL_GL_Enter2DMode(); + glBindTexture(GL_TEXTURE_2D, texture); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(texMinX, texMinY); glVertex2i(x, y ); + glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y ); + glTexCoord2f(texMinX, texMaxY); glVertex2i(x, y+h); + glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h); + glEnd(); + SDL_GL_Leave2DMode(); +} + +/* This code is deprecated, but available for speed comparisons */ +void DrawLogoBlit(void) { static SDL_Surface *image = NULL; static GLuint texture; + static GLfloat texMinX, texMinY; + static GLfloat texMaxX, texMaxY; static int x = 0; static int y = 0; static int w, h; @@ -146,114 +320,72 @@ void DrawSDLLogo(void) static Uint32 last_moved = 0; SDL_Rect dst; - SDL_Surface *screen; + SDL_Surface *screen = SDL_GetVideoSurface(); if ( image == NULL ) { SDL_Surface *temp; - temp = SDL_LoadBMP("icon.bmp"); + /* Load the image (could use SDL_image library here) */ + temp = SDL_LoadBMP(LOGO_FILE); if ( temp == NULL ) { return; } + w = temp->w; + h = temp->h; + + /* Convert the image into the screen format */ image = SDL_CreateRGBSurface( SDL_SWSURFACE, - temp->w, temp->h, - 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ - 0x000000FF, - 0x0000FF00, - 0x00FF0000, - 0xFF000000 -#else - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF -#endif - ); - if ( image != NULL ) { + w, h, + screen->format->BitsPerPixel, + screen->format->Rmask, + screen->format->Gmask, + screen->format->Bmask, + screen->format->Amask); + if ( image ) { SDL_BlitSurface(temp, NULL, image, NULL); } SDL_FreeSurface(temp); - if ( image == NULL ) { - return; - } - w = image->w; - h = image->h; - /* Create an OpenGL texture for the image */ - if ( ! USE_DEPRECATED_OPENGLBLIT ) { - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MAG_FILTER, - GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, - GL_TEXTURE_MIN_FILTER, - GL_NEAREST); - glTexImage2D(GL_TEXTURE_2D, - 0, - GL_RGBA, - w, h, - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - image->pixels); - SDL_FreeSurface(image); /* No longer needed */ + /* Make sure that the texture conversion is okay */ + if ( ! image ) { + return; } } - screen = SDL_GetVideoSurface(); - - /* Show the image on the screen */ - dst.x = x; - dst.y = y; - dst.w = w; - dst.h = h; - - /* Move it around + /* Move the image around Note that we do not clear the old position. This is because we perform a glClear() which clears the framebuffer and then only update the new area. Note that you can also achieve interesting effects by modifying the screen surface alpha channel. It's set to 255 by default.. */ - if ( (SDL_GetTicks() - last_moved) > 100 ) { - x += delta_x; - if ( x < 0 ) { - x = 0; - delta_x = -delta_x; - } else - if ( (x+w) > screen->w ) { - x = screen->w-w; - delta_x = -delta_x; - } - y += delta_y; - if ( y < 0 ) { - y = 0; - delta_y = -delta_y; - } else - if ( (y+h) > screen->h ) { - y = screen->h-h; - delta_y = -delta_y; - } - if ( USE_DEPRECATED_OPENGLBLIT ) { - SDL_BlitSurface(image, NULL, screen, &dst); - } else { - SDL_GL_Enter2DMode(); - glBindTexture(GL_TEXTURE_2D, texture); - glBegin(GL_TRIANGLE_STRIP); - glTexCoord2f(0.0, 0.0); glVertex2i(x, y ); - glTexCoord2f(1.0, 0.0); glVertex2i(x+w, y ); - glTexCoord2f(0.0, 1.0); glVertex2i(x, y+h); - glTexCoord2f(1.0, 1.0); glVertex2i(x+w, y+h); - glEnd(); - SDL_GL_Leave2DMode(); - } + x += delta_x; + if ( x < 0 ) { + x = 0; + delta_x = -delta_x; + } else + if ( (x+w) > screen->w ) { + x = screen->w-w; + delta_x = -delta_x; } - if ( USE_DEPRECATED_OPENGLBLIT ) { - SDL_UpdateRects(screen, 1, &dst); + y += delta_y; + if ( y < 0 ) { + y = 0; + delta_y = -delta_y; + } else + if ( (y+h) > screen->h ) { + y = screen->h-h; + delta_y = -delta_y; } + dst.x = x; + dst.y = y; + dst.w = w; + dst.h = h; + SDL_BlitSurface(image, NULL, screen, &dst); + + /* Show the image on the screen */ + SDL_UpdateRects(screen, 1, &dst); } int RunGLTest( int argc, char* argv[], @@ -496,7 +628,11 @@ int RunGLTest( int argc, char* argv[], /* Draw 2D logo onto the 3D display */ if ( logo ) { - DrawSDLLogo(); + if ( USE_DEPRECATED_OPENGLBLIT ) { + DrawLogoBlit(); + } else { + DrawLogoTexture(); + } } SDL_GL_SwapBuffers( );