X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftexture.cc;fp=src%2Ftexture.cc;h=0000000000000000000000000000000000000000;hb=c2321281bf12a7efaedde930422c7ddbc92080d4;hp=6d3e912925b8f1376018b9cc612fde8db1d4677a;hpb=87bc17e55b0c1dc73ecc66df856d3f08fd7a7724;p=chaz%2Fyoink diff --git a/src/texture.cc b/src/texture.cc deleted file mode 100644 index 6d3e912..0000000 --- a/src/texture.cc +++ /dev/null @@ -1,404 +0,0 @@ - -/******************************************************************************* - - Copyright (c) 2009, Charles McGarvey - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*******************************************************************************/ - -#include - -#include - -#include -#include - -#include "mippleton.hh" - -#include "dispatcher.hh" -#include "opengl.hh" - -#include "texture.hh" - - -namespace dc { - - -/** - * The texture implementation just contains all the information about the image - * which is worth having in memory. The image data itself is not worth keeping - * in memory if the texture has been loaded to GL, but the name of the resource - * is retained so that it can be reloaded if necessary. The implementation is a - * mippleton so that multiple texture objects can share the same internal - * objects and avoid having duplicate textures loaded to GL. - */ - -class texture::texture_impl : public mippleton -{ - - /** - * Delete the texture (if it is loaded) from GL. - */ - - void unloadFromGL() - { - if (object_) - { - glDeleteTextures(1, &object_); - object_ = 0; - } - } - - /** - * If the GL context was recreated, we probably need to reload the texture. - * This may involve reading it from disk again, but hopefully the OS was - * smart enough to cache it if the client has plenty of RAM. - */ - - void contextRecreated(const notification& note) - { - unloadFromGL(); - uploadToGL(); - } - - /** - * This is a helper method used by some of the texture loading code. It - * returns the first power of two which is greater than the input value. - */ - - static int powerOfTwo(int input) - { - int value = 1; - - while (value < input) - { - value <<= 1; - } - return value; - } - -public: - - /** - * Construction is initialization. - */ - - explicit texture_impl(const std::string& name) : - mippleton(name), - width_(0), - height_(0), - mode_(0), - minFilter_(GL_NEAREST), - maxFilter_(GL_NEAREST), - wrapU_(GL_CLAMP), - wrapV_(GL_CLAMP), - object_(0) - { - uploadToGL(); - - // we want to know when the GL context is recreated - dispatcher::instance().addHandler("video.context_recreated", - boost::bind(&texture_impl::contextRecreated, this, _1), this); - } - - ~texture_impl() - { - unloadFromGL(); - - dispatcher::instance().removeHandler(this); - } - - - /** - * 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 GL-ready right out of the box. This - * method makes them ready. - */ - - static SDL_Surface* prepareImageForGL(SDL_Surface* surface) - { - int w = powerOfTwo(surface->w); - int h = powerOfTwo(surface->h); - - // 1. OpenGL images must (generally) have dimensions of a power-of-two. - // If this one doesn't, we can at least be more friendly by expanding - // the dimensions so that they are, though there will be some empty - // space within the range of normal texture coordinates. It's better of - // textures are the right size to begin with. - - SDL_Surface* image = SDL_CreateRGBSurface - ( - SDL_SWSURFACE, - w, h, - 32, -#if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0x000000FF, - 0x0000FF00, - 0x00FF0000, - 0xFF000000 -#else - 0xFF000000, - 0x00FF0000, - 0x0000FF00, - 0x000000FF -#endif - ); - - if (!image) - { - return 0; - } - - Uint32 savedFlags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK); - Uint8 savedAlpha = surface->format->alpha; - if (savedFlags & SDL_SRCALPHA) - { - SDL_SetAlpha(surface, 0, 0); - } - - SDL_Rect srcArea, destArea; - srcArea.x = 0; destArea.x = 0; - srcArea.y = 0; destArea.y = h - surface->h; - srcArea.w = surface->w; - srcArea.h = surface->h; - SDL_BlitSurface(surface, &srcArea, image, &destArea); - - if (savedFlags & SDL_SRCALPHA) - { - SDL_SetAlpha(surface, savedFlags, savedAlpha); - } - - // 2. OpenGL textures make more sense within the coordinate system when - // they are "upside down," so let's flip it. - - Uint8 line[image->pitch]; - - Uint8 *pixels = static_cast(image->pixels); - Uint16 pitch = image->pitch; - int ybegin = 0; - int yend = image->h - 1; - - 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); - ybegin++; - yend--; - } - if (SDL_MUSTLOCK(image)) SDL_UnlockSurface(image); - - return image; - } - - /** - * Use SDL_image to load images from file. A surface with the image data is - * returned. - * @return Image data. - */ - - SDL_Surface* loadImageData() - { - SDL_Surface* surface; - - surface = IMG_Load(texture::getPathToResource(getName()).c_str()); - - if (!surface) - { - throw texture::exception("loading failed"); - } - - SDL_Surface* temp = prepareImageForGL(surface); - SDL_FreeSurface(surface); - - if (!temp) - { - throw texture::exception("image couldn't be prepared for GL"); - } - - if (temp->format->BytesPerPixel == 3) - { - mode_ = GL_RGB; - } - else if (temp->format->BytesPerPixel == 4) - { - mode_ = GL_RGBA; - } - else - { - SDL_FreeSurface(temp); - throw texture::exception("image is not the required 24 or 32 bpp"); - } - - width_ = temp->w; - height_ = temp->h; - - return temp; - } - - - /** - * Upload the image to GL so that it will be accessible by a much more - * manageable handle and hopefully reside in video memory. - */ - - void uploadToGL() - { - if (object_) - { - // Already loaded. - return; - } - - SDL_Surface* imageData = loadImageData(); - - glGenTextures(1, &object_); - glBindTexture(GL_TEXTURE_2D, object_); - - glTexImage2D - ( - GL_TEXTURE_2D, - 0, - mode_, - imageData->w, - imageData->h, - 0, - mode_, - GL_UNSIGNED_BYTE, - imageData->pixels - ); - - setProperties(); - - SDL_FreeSurface(imageData); - } - - - /** - * Sets some texture properties such as the filters and external coordinate - * behavior. - */ - - void setProperties() - { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, maxFilter_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapU_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapV_); - } - - - unsigned width_; ///< Horizontal dimension of the image. - unsigned height_; ///< Vertical dimension. - - GLuint mode_; ///< Depth of the image, GL_RGB or GL_RGBA. - GLuint minFilter_; ///< Filter. - GLuint maxFilter_; ///< Filter. - GLuint wrapU_; ///< Wrapping behavior horizontally. - GLuint wrapV_; ///< Wrapping behavior vertically. - GLuint object_; ///< GL texture handle. -}; - - -texture::texture(const std::string& name) : - // pass through - impl(texture::texture_impl::retain(name), &texture::texture_impl::release) -{} - - -/** - * Bind the GL texture for mapping, etc. - */ - -void texture::bind() -{ - glBindTexture(GL_TEXTURE_2D, getObject()); -} - - -/** - * Get the texture object, for the curious. - */ - -GLuint texture::getObject() -{ - // pass through - return impl->object_; -} - - -unsigned texture::getWidth() -{ - // pass through - return impl->width_; -} - -unsigned texture::getHeight() -{ - // pass through - return impl->height_; -} - - -void texture::setMinFilter(GLuint filter) -{ - impl->minFilter_ = filter; -} - -void texture::setMaxFilter(GLuint filter) -{ - impl->maxFilter_ = filter; -} - -void texture::setWrapU(GLuint wrap) -{ - impl->wrapU_ = wrap; -} - -void texture::setWrapV(GLuint wrap) -{ - impl->wrapV_ = wrap; -} - - -void texture::applyChanges() -{ - bind(); - impl->setProperties(); -} - - -std::string texture::getPathToResource(const std::string& name) -{ - // TODO since this is a generic library class, more than PNG should be - // supported - return resource::getPathToResource("textures/" + name + ".png"); -} - - -} // namespace dc - -/** vim: set ts=4 sw=4 tw=80: *************************************************/ -