]> Dogcows Code - chaz/yoink/blobdiff - src/texture.cc
new classes: resource, tilemap, animation
[chaz/yoink] / src / texture.cc
index b91d23ac7456349e85db9cca2cb55e16925f1d1f..2f8f97a1c366f3befe9f8838f721ed3c608c5e9f 100644 (file)
@@ -26,7 +26,6 @@
 
 *******************************************************************************/
 
-#include <stdexcept>
 #include <cstdlib>
 
 #include <boost/bind.hpp>
@@ -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<Uint8*>(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
 
This page took 0.026736 seconds and 4 git commands to generate.