X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftexture.cc;fp=src%2Ftexture.cc;h=2f8f97a1c366f3befe9f8838f721ed3c608c5e9f;hb=6dfcfbd4a612230f2037cf891dd98520cb80c997;hp=b91d23ac7456349e85db9cca2cb55e16925f1d1f;hpb=79b5f738f2e38acb60cda7e09f54802933a17105;p=chaz%2Fyoink diff --git a/src/texture.cc b/src/texture.cc index b91d23a..2f8f97a 100644 --- a/src/texture.cc +++ b/src/texture.cc @@ -26,7 +26,6 @@ *******************************************************************************/ -#include #include #include @@ -61,8 +60,8 @@ class texture_impl } public: - texture_impl(const std::string& filePath, bool keepInMemory) - : object(0), imageData(0), imagePath(filePath), keepData(keepInMemory) + texture_impl(texture* outside, bool keepInMemory) + : interface(outside), keepData(keepInMemory), object(0), imageData(0) { dispatcher::instance().addHandler("video.context_recreated", boost::bind(&texture_impl::contextRecreated, this, _1), @@ -92,20 +91,24 @@ public: return value; } - // Adapted from some public domain code. This code is common enough that it - // really should be included in SDL_image... static SDL_Surface* prepareImageForGL(SDL_Surface* surface) { - /* Use the surface width and height expanded to powers of 2 */ + // Adapted from some public domain code. This stuff is common enough + // that it really should be included in SDL_image... We need this + // because images loaded with SDL_image aren't exactly OpenGL-ready + // right out of the box. + int w = powerOfTwo(surface->w); int h = powerOfTwo(surface->h); + // 1. OpenGL images must (generally) have dimensions of a power-of-two. + SDL_Surface* image = SDL_CreateRGBSurface ( SDL_SWSURFACE, w, h, 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ +#if SDL_BYTEORDER == SDL_LIL_ENDIAN 0x000000FF, 0x0000FF00, 0x00FF0000, @@ -123,7 +126,6 @@ public: return 0; } - // Save the alpha blending attributes. Uint32 savedFlags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); Uint8 savedAlpha = surface->format->alpha; if (savedFlags & SDL_SRCALPHA) @@ -132,44 +134,36 @@ public: } SDL_Rect srcArea, destArea; - /* Copy the surface into the GL texture image */ srcArea.x = 0; destArea.x = 0; - /* Copy it in at the bottom, because we're going to flip - this image upside-down in a moment - */ srcArea.y = 0; destArea.y = h - surface->h; srcArea.w = surface->w; srcArea.h = surface->h; SDL_BlitSurface(surface, &srcArea, image, &destArea); - /* Restore the alpha blending attributes */ if (savedFlags & SDL_SRCALPHA) { SDL_SetAlpha(surface, savedFlags, savedAlpha); } - /* Turn the image upside-down, because OpenGL textures - start at the bottom-left, instead of the top-left - */ + // 2. OpenGL textures make more sense when they are "upside down." + Uint8 line[image->pitch]; - /* These two make the following more readable */ Uint8 *pixels = static_cast(image->pixels); Uint16 pitch = image->pitch; int ybegin = 0; int yend = image->h - 1; - // TODO: consider if this lock is legal/appropriate - if (SDL_MUSTLOCK(image)) { SDL_LockSurface(image); } + if (SDL_MUSTLOCK(image)) SDL_LockSurface(image); while (ybegin < yend) { - memcpy(line, pixels + pitch*ybegin, pitch); - memcpy(pixels + pitch*ybegin, pixels + pitch*yend, pitch); - memcpy(pixels + pitch*yend, line, pitch); + memcpy(line, pixels + pitch * ybegin, pitch); + memcpy(pixels + pitch * ybegin, pixels + pitch * yend, pitch); + memcpy(pixels + pitch * yend, line, pitch); ybegin++; yend--; } - if (SDL_MUSTLOCK(image)) { SDL_UnlockSurface(image); } + if (SDL_MUSTLOCK(image)) SDL_UnlockSurface(image); return image; } @@ -179,11 +173,11 @@ public: { SDL_Surface* surface; - surface = IMG_Load(imagePath.c_str()); + surface = IMG_Load(interface->getPathToFile().c_str()); if (!surface) { - throw std::runtime_error("could not load image data from file"); + throw texture::exception("loading failed"); } imageData = prepareImageForGL(surface); @@ -191,7 +185,7 @@ public: if (!imageData) { - throw std::runtime_error("error in preparing image data for GL"); + throw texture::exception(""); } if (imageData->format->BytesPerPixel == 3) @@ -205,7 +199,7 @@ public: else { SDL_FreeSurface(imageData); - throw std::runtime_error("image must be 24 or 32 bpp"); + throw texture::exception("image is not the required 24 or 32 bpp"); } width = imageData->w; @@ -243,9 +237,8 @@ public: imageData->pixels ); - // These default filters can be changed later... glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (!keepData) { @@ -260,28 +253,23 @@ public: int mode; GLuint object; - std::string imagePath; bool keepData; SDL_Surface* imageData; + + texture* interface; }; -texture::texture(const std::string& filePath, bool keepInMemory) - : impl(new texture_impl(filePath, keepInMemory)) {} - - -const std::string& texture::filePath() -{ - return impl->imagePath; -} +texture::texture(const std::string& name, bool keepInMemory) + : resource(name), impl(new texture_impl(this, keepInMemory)) {} void texture::bind() { - glBindTexture(GL_TEXTURE_2D, object()); + glBindTexture(GL_TEXTURE_2D, getObject()); } -GLuint texture::object() +GLuint texture::getObject() { if (!impl->object) { @@ -292,17 +280,26 @@ GLuint texture::object() } -unsigned texture::width() +unsigned texture::getWidth() { + if (!impl->object) + { + impl->uploadToGL(); + } + return impl->width; } -unsigned texture::height() +unsigned texture::getHeight() { + if (!impl->object) + { + impl->uploadToGL(); + } + return impl->height; } - } // namespace dc