From 1fe16bdda5fa0d7112f4568e7bcd892d01c197b9 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Sun, 22 Jul 2012 23:15:58 +0200 Subject: Avoid copying surfaces unnecessarily for upload to texture When uploading an SDL surface to an OpenGL texture, it was always making a copy that had the desired size and pixel format. Now this copy is no longer being made when the existing surface already has the target size and pixel format. In fact most images are already in 32-bit RGBA format after loading them. Reviewed-by: Erik Schilling --- src/resources/image.cpp | 60 ++++++++++++++++++++++++++++--------------------- src/resources/image.h | 2 +- 2 files changed, 36 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/resources/image.cpp b/src/resources/image.cpp index cf0d1483..b7e6c200 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -438,25 +438,22 @@ Image *Image::_SDLload(SDL_Surface *tmpImage) } #ifdef USE_OPENGL -Image *Image::_GLload(SDL_Surface *tmpImage) +Image *Image::_GLload(SDL_Surface *image) { // Flush current error flag. glGetError(); - int width = tmpImage->w; - int height = tmpImage->h; + int width = image->w; + int height = image->h; int realWidth = powerOfTwo(width); int realHeight = powerOfTwo(height); if (realWidth < width || realHeight < height) { logger->log("Warning: image too large, cropping to %dx%d texture!", - tmpImage->w, tmpImage->h); + realWidth, realHeight); } - // Make sure the alpha channel is not used, but copied to destination - SDL_SetAlpha(tmpImage, 0, SDL_ALPHA_OPAQUE); - // Determine 32-bit masks based on byte order Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN @@ -471,39 +468,52 @@ Image *Image::_GLload(SDL_Surface *tmpImage) amask = 0xff000000; #endif - SDL_Surface *oldImage = tmpImage; - tmpImage = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, - 32, rmask, gmask, bmask, amask); + bool needsConversion = !(realWidth == width && + realHeight == height && + image->format->BytesPerPixel == 4 && + image->format->Rmask == rmask && + image->format->Gmask == gmask && + image->format->Bmask == bmask && + image->format->Amask == amask); - if (!tmpImage) + if (needsConversion) { - logger->log("Error, image convert failed: out of memory"); - return NULL; - } + SDL_Surface *oldImage = image; + image = SDL_CreateRGBSurface(SDL_SWSURFACE, realWidth, realHeight, + 32, rmask, gmask, bmask, amask); - SDL_BlitSurface(oldImage, NULL, tmpImage, NULL); + if (!image) + { + logger->log("Error, image convert failed: out of memory"); + return NULL; + } + + // Make sure the alpha channel is not used, but copied to destination + SDL_SetAlpha(oldImage, 0, SDL_ALPHA_OPAQUE); + SDL_BlitSurface(oldImage, NULL, image, NULL); + } GLuint texture; glGenTextures(1, &texture); OpenGLGraphics::bindTexture(mTextureType, texture); - if (SDL_MUSTLOCK(tmpImage)) - SDL_LockSurface(tmpImage); + if (SDL_MUSTLOCK(image)) + SDL_LockSurface(image); - glTexImage2D( - mTextureType, 0, GL_RGBA8, - tmpImage->w, tmpImage->h, - 0, GL_RGBA, GL_UNSIGNED_BYTE, - tmpImage->pixels); + glTexImage2D(mTextureType, 0, GL_RGBA8, + image->w, image->h, + 0, GL_RGBA, GL_UNSIGNED_BYTE, + image->pixels); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glTexParameteri(mTextureType, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(mTextureType, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - if (SDL_MUSTLOCK(tmpImage)) - SDL_UnlockSurface(tmpImage); + if (SDL_MUSTLOCK(image)) + SDL_UnlockSurface(image); - SDL_FreeSurface(tmpImage); + if (needsConversion) + SDL_FreeSurface(image); GLenum error = glGetError(); if (error) diff --git a/src/resources/image.h b/src/resources/image.h index 33db7848..b1831ada 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -243,7 +243,7 @@ class Image : public Resource */ static int powerOfTwo(int input); - static Image *_GLload(SDL_Surface *tmpImage); + static Image *_GLload(SDL_Surface *image); GLuint mGLImage; int mTexWidth, mTexHeight; -- cgit v1.2.3-70-g09d2