*******************************************************************************/
-#include <stdexcept>
#include <cstdlib>
#include <boost/bind.hpp>
}
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),
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,
return 0;
}
- // Save the alpha blending attributes.
Uint32 savedFlags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
Uint8 savedAlpha = surface->format->alpha;
if (savedFlags & SDL_SRCALPHA)
}
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;
}
{
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);
if (!imageData)
{
- throw std::runtime_error("error in preparing image data for GL");
+ throw texture::exception("");
}
if (imageData->format->BytesPerPixel == 3)
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;
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)
{
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)
{
}
-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