X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FTexture.cc;h=22d3f15e92cab597259673d86c08cd2f4692d292;hp=128d54f3d7c8750b2087859a22b81aa6c5f18dc6;hb=b357615aba1dbde81e3c6999366604e6001010a7;hpb=29e3d45f7bbbf31eadf793c41ff2b3d9c47b7539 diff --git a/src/Moof/Texture.cc b/src/Moof/Texture.cc index 128d54f..22d3f15 100644 --- a/src/Moof/Texture.cc +++ b/src/Moof/Texture.cc @@ -26,15 +26,17 @@ *******************************************************************************/ -#include // memcpy +#include // FILE +#include // strncmp #include -#include -#include - -#include "Dispatcher.hh" -#include "Mippleton.hh" +#include "Dispatch.hh" +#include "Engine.hh" +#include "Exception.hh" +#include "Image.hh" +#include "Library.hh" +#include "Log.hh" #include "OpenGL.hh" #include "Texture.hh" @@ -47,11 +49,11 @@ namespace Mf { * 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. + * library so that multiple texture objects can share the same internal objects + * and avoid having duplicate textures loaded to GL. */ -class Texture::TextureImpl : public Mippleton +class Texture::Impl : public Library { /** @@ -60,15 +62,15 @@ class Texture::TextureImpl : public Mippleton void unloadFromGL() { - if (object_) + if (mObject) { - if (object_ == globalObject_) + if (mObject == gObject) { - globalObject_ = 0; + gObject = 0; } - glDeleteTextures(1, &object_); - object_ = 0; + glDeleteTextures(1, &mObject); + mObject = 0; } } @@ -78,9 +80,9 @@ class Texture::TextureImpl : public Mippleton * to cache it if the client has plenty of RAM. */ - void contextRecreated(const Notification& note) + void contextRecreated() { - object_ = globalObject_ = 0; + mObject = gObject = 0; uploadToGL(); } @@ -100,64 +102,40 @@ class Texture::TextureImpl : public Mippleton return value; } - - static void flipSurface(SDL_Surface* image) - { - unsigned char* pixels = (Uint8*)(image->pixels); - - unsigned pitch = image->pitch; - unsigned char line[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); - } - public: /** * Construction is initialization. */ - explicit TextureImpl(const std::string& name) : - Mippleton(name), - surface_(0), - width_(0), - height_(0), - mode_(0), - minFilter_(GL_NEAREST), - magFilter_(GL_NEAREST), - wrapS_(GL_CLAMP), - wrapT_(GL_CLAMP), - object_(0) + explicit Impl(const std::string& name) : + Library(name), + //mContext(0), + mImage(Texture::getPath(getName())), + mWidth(0), + mHeight(0), + mMode(0), + mMinFilter(GL_NEAREST), + mMagFilter(GL_NEAREST), + mWrapS(GL_CLAMP), + mWrapT(GL_CLAMP), + mObject(0) { - loadFromFile(); + // make sure the engine is initialized + Engine& engine = Engine::getInstance(); + VideoP video = engine.getVideo(); + ASSERT(video && "cannot load textures without a current video context"); // we want to know when the GL context is recreated - Dispatcher::instance().addHandler("video.context_recreated", - boost::bind(&TextureImpl::contextRecreated, this, _1), this); + mDispatchHandler = engine.addHandler("video.newcontext", + boost::bind(&Impl::contextRecreated, this)); + + loadFromFile(); } - ~TextureImpl() + ~Impl() { - if (surface_) - { - SDL_FreeSurface(surface_); - } - unloadFromGL(); - - Dispatcher::instance().removeHandler(this); } @@ -168,6 +146,7 @@ public: * method makes them ready. */ + /* static SDL_Surface* prepareImageForGL(SDL_Surface* surface) { int w = powerOfTwo(surface->w); @@ -228,6 +207,7 @@ public: return image; } + */ /** * Use SDL_image to load images from file. A surface with the image data is @@ -237,41 +217,17 @@ public: void loadFromFile() { - SDL_Surface* surface; - - surface = IMG_Load(Texture::getPathToResource(getName()).c_str()); - - if (!surface) + if (!mImage.isValid()) { - throw Texture::Exception("loading from file failed"); + logWarning << "texture not found: " << getName() << std::endl; + throw Exception(ErrorCode::RESOURCE_NOT_FOUND, getName()); } - SDL_Surface* temp = prepareImageForGL(surface); - SDL_FreeSurface(surface); + mImage.flip(); - if (!temp) - { - throw Texture::Exception("uploading to opengl failed"); - } - - if (temp->format->BytesPerPixel == 3) - { - mode_ = GL_RGB; - } - else if (temp->format->BytesPerPixel == 4) - { - mode_ = GL_RGBA; - } - else - { - SDL_FreeSurface(temp); - throw Texture::Exception("incompatible color mode"); - } - - width_ = temp->w; - height_ = temp->h; - - surface_ = temp; + mWidth = mImage.getWidth(); + mHeight = mImage.getHeight(); + mMode = mImage.getColorMode(); } @@ -282,34 +238,36 @@ public: void uploadToGL() { - if (object_) + if (mObject) { // already loaded return; } - if (!surface_) loadFromFile(); + //if (!mContext) loadFromFile(); - glGenTextures(1, &object_); - glBindTexture(GL_TEXTURE_2D, object_); + glGenTextures(1, &mObject); + glBindTexture(GL_TEXTURE_2D, mObject); glTexImage2D + //gluBuild2DMipmaps ( GL_TEXTURE_2D, 0, - mode_, - surface_->w, - surface_->h, + mMode, + //3, + mWidth, + mHeight, 0, - mode_, + mMode, GL_UNSIGNED_BYTE, - surface_->pixels + mImage.getPixels() ); setProperties(); - SDL_FreeSurface(surface_); - surface_ = 0; + //SDL_FreeSurface(mContext); + //mContext = 0; } @@ -320,76 +278,77 @@ public: void setProperties() { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS_); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT_); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT); } inline void setMinFilter(GLuint filter) { bind(); - minFilter_ = filter; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter_); + mMinFilter = filter; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mMinFilter); } inline void setMagFilter(GLuint filter) { bind(); - magFilter_ = filter; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter_); + mMagFilter = filter; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mMagFilter); } inline void setWrapS(GLuint wrap) { bind(); - wrapS_ = wrap; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS_); + mWrapS = wrap; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mWrapS); } inline void setWrapT(GLuint wrap) { bind(); - wrapT_ = wrap; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT_); + mWrapT = wrap; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mWrapT); } inline void bind() { - if (object_ == 0) + if (mObject == 0) { uploadToGL(); } - if (object_ != globalObject_) + if (mObject != gObject) { - glBindTexture(GL_TEXTURE_2D, object_); - globalObject_ = object_; + glBindTexture(GL_TEXTURE_2D, mObject); + gObject = mObject; } } - SDL_Surface* surface_; - unsigned width_; ///< Horizontal dimension of the image. - unsigned height_; ///< Vertical dimension. + Image mImage; + unsigned mWidth; ///< Horizontal dimension of the image. + unsigned mHeight; ///< Vertical dimension. + + GLuint mMode; ///< GL_RGB or GL_RGBA. + GLuint mMinFilter; ///< Minifcation filter. + GLuint mMagFilter; ///< Magnification filter. + GLuint mWrapS; ///< Wrapping behavior horizontally. + GLuint mWrapT; ///< Wrapping behavior vertically. - GLuint mode_; ///< Depth of the image, GL_RGB or GL_RGBA. - GLuint minFilter_; ///< Minifcation filter. - GLuint magFilter_; ///< Magnification filter. - GLuint wrapS_; ///< Wrapping behavior horizontally. - GLuint wrapT_; ///< Wrapping behavior vertically. + GLuint mObject; ///< GL texture handle. + static GLuint gObject; ///< Global GL texture handle. - GLuint object_; ///< GL texture handle. - static GLuint globalObject_; ///< Global GL texture handle. + Dispatch::Handler mDispatchHandler; }; -GLuint Texture::TextureImpl::globalObject_ = 0; +GLuint Texture::Impl::gObject = 0; Texture::Texture(const std::string& name) : // pass through - impl_(Texture::TextureImpl::retain(name), &Texture::TextureImpl::release) -{} + mImpl(Texture::Impl::getInstance(name)) {} /** @@ -399,7 +358,7 @@ Texture::Texture(const std::string& name) : void Texture::bind() const { // pass through - impl_->bind(); + mImpl->bind(); } @@ -410,52 +369,59 @@ void Texture::bind() const GLuint Texture::getObject() const { // pass through - return impl_->object_; + return mImpl->mObject; +} + + +void Texture::resetBind() +{ + glBindTexture(GL_TEXTURE_2D, 0); + Impl::gObject = 0; } unsigned Texture::getWidth() const { // pass through - return impl_->width_; + return mImpl->mWidth; } unsigned Texture::getHeight() const { // pass through - return impl_->height_; + return mImpl->mHeight; } void Texture::setMinFilter(GLuint filter) { // pass through - impl_->setMinFilter(filter); + mImpl->setMinFilter(filter); } void Texture::setMagFilter(GLuint filter) { // pass through - impl_->setMagFilter(filter); + mImpl->setMagFilter(filter); } void Texture::setWrapS(GLuint wrap) { // pass through - impl_->setWrapS(wrap); + mImpl->setWrapS(wrap); } void Texture::setWrapT(GLuint wrap) { // pass through - impl_->setWrapT(wrap); + mImpl->setWrapT(wrap); } -std::string Texture::getPathToResource(const std::string& name) +std::string Texture::getPath(const std::string& name) { - // TODO named resources must be png for now - return Resource::getPathToResource("textures/" + name + ".png"); + std::string path = Resource::getPath("textures/" + name + ".png"); + return path; }