00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/Cinder.h" 00026 #include "cinder/gl/gl.h" 00027 #include "cinder/Surface.h" 00028 #include "cinder/Rect.h" 00029 #include "cinder/Stream.h" 00030 00031 #include <vector> 00032 #include <utility> 00033 00034 namespace cinder { namespace gl { 00035 00048 class Texture { 00049 public: 00050 struct Format; 00051 00053 Texture() {} 00055 Texture( int aWidth, int aHeight, Format format = Format() ); 00057 Texture( const unsigned char *data, int dataFormat, int aWidth, int aHeight, Format format = Format() ); 00059 Texture( const Surface8u &surface, Format format = Format() ); 00061 Texture( const Surface32f &surface, Format format = Format() ); 00063 Texture( const Channel8u &channel, Format format = Format() ); 00065 Texture( const Channel32f &channel, Format format = Format() ); 00067 Texture( ImageSourceRef imageSource, Format format = Format() ); 00069 Texture( GLenum aTarget, GLuint aTextureID, int aWidth, int aHeight, bool aDoNotDispose ); 00070 00072 void setDoNotDispose( bool aDoNotDispose = true ) { mObj->mDoNotDispose = aDoNotDispose; } 00074 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon ); 00076 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); } 00079 void setWrapS( GLenum wrapS ); 00082 void setWrapT( GLenum wrapT ); 00085 void setMinFilter( GLenum minFilter ); 00088 void setMagFilter( GLenum magFilter ); 00089 00091 void setCleanTexCoords( float maxU, float maxV ); 00092 00094 void update( const Surface &surface ); 00097 void update( const Surface &surface, const Area &area ); 00099 void update( const Channel8u &surface, const Area &area ); 00100 00102 GLint getWidth() const; 00104 GLint getHeight() const; 00106 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00108 float getAspectRatio() const { return getWidth() / (float)getHeight(); } 00110 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); } 00112 bool hasAlpha() const; 00114 float getLeft() const; 00115 float getRight() const; 00116 float getTop() const; 00117 float getBottom() const; 00119 float getMaxU() const; 00120 float getMaxV() const; 00122 Rectf getAreaTexCoords( const Area &area ) const; 00124 GLint getInternalFormat() const; 00126 GLuint getTextureId() const { return mObj->mTextureID; } 00128 GLenum getTarget() const { return mObj->mTarget; } 00130 bool isFlipped() const { return mObj->mFlipped; } 00132 void setFlipped( bool aFlipped = true ) { mObj->mFlipped = aFlipped; } 00133 00136 void enableAndBind() const; 00138 void disable() const; 00140 void bind( GLuint textureUnit = 0 ) const; 00142 void unbind( GLuint textureUnit = 0 ) const; 00143 00145 static Texture loadDds( IStreamRef ddsStream, Format format ); 00146 00148 static void SurfaceChannelOrderToDataFormatAndType( const SurfaceChannelOrder &sco, GLint *dataFormat, GLenum *type ); 00150 static bool dataFormatHasAlpha( GLint dataFormat ); 00152 static bool dataFormatHasColor( GLint dataFormat ); 00153 00155 Texture weakClone() const; 00156 00157 #if ! defined( CINDER_GLES ) 00158 00159 operator ImageSourceRef() const; 00160 #endif 00161 00162 struct Format { 00164 Format(); 00165 00167 void setTarget( GLenum target ) { mTarget = target; } 00169 #ifndef CINDER_GLES 00170 void setTargetRect() { mTarget = GL_TEXTURE_RECTANGLE_ARB; } 00171 #endif 00172 00174 void enableMipmapping( bool enableMipmapping = true ) { mMipmapping = enableMipmapping; } 00175 00177 void setInternalFormat( GLint internalFormat ) { mInternalFormat = internalFormat; } 00179 void setAutoInternalFormat() { mInternalFormat = -1; } 00180 00182 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); } 00185 void setWrapS( GLenum wrapS ) { mWrapS = wrapS; } 00188 void setWrapT( GLenum wrapT ) { mWrapT = wrapT; } 00191 void setMinFilter( GLenum minFilter ) { mMinFilter = minFilter; } 00194 void setMagFilter( GLenum magFilter ) { mMagFilter = magFilter; } 00195 00197 GLenum getTarget() const { return mTarget; } 00199 bool hasMipmapping() const { return mMipmapping; } 00200 00202 GLint getInternalFormat() const { return mInternalFormat; } 00204 bool isAutoInternalFormat() const { return mInternalFormat == -1; } 00205 00207 GLenum getWrapS() const { return mWrapS; } 00209 GLenum getWrapT() const { return mWrapT; } 00211 GLenum getMinFilter() const { return mMinFilter; } 00213 GLenum getMagFilter() const { return mMagFilter; } 00214 00215 protected: 00216 GLenum mTarget; 00217 GLenum mWrapS, mWrapT; 00218 GLenum mMinFilter, mMagFilter; 00219 bool mMipmapping; 00220 GLint mInternalFormat; 00221 00222 friend class Texture; 00223 }; 00224 00225 protected: 00226 void init( const unsigned char *data, int unpackRowLength, GLenum dataFormat, GLenum type, const Format &format ); 00227 void init( const float *data, GLint dataFormat, const Format &format ); 00228 void init( ImageSourceRef imageSource, const Format &format ); 00229 00230 struct Obj { 00231 Obj() : mWidth( -1 ), mHeight( -1 ), mInternalFormat( -1 ), mTextureID( 0 ), mFlipped( false ), mDeallocatorFunc( 0 ) {} 00232 Obj( int aWidth, int aHeight ) : mInternalFormat( -1 ), mWidth( aWidth ), mHeight( aHeight ), mFlipped( false ), mTextureID( 0 ), mDeallocatorFunc( 0 ) {} 00233 ~Obj(); 00234 00235 mutable GLint mWidth, mHeight; 00236 float mMaxU, mMaxV; 00237 mutable GLint mInternalFormat; 00238 GLenum mTarget; 00239 GLuint mTextureID; 00240 bool mDoNotDispose; 00241 bool mFlipped; 00242 void (*mDeallocatorFunc)(void *refcon); 00243 void *mDeallocatorRefcon; 00244 }; 00245 shared_ptr<Obj> mObj; 00246 00247 public: 00249 00250 typedef shared_ptr<Obj> Texture::*unspecified_bool_type; 00251 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &Texture::mObj; } 00252 void reset() { mObj.reset(); } 00254 }; 00255 00256 class TextureCache { 00257 public: 00258 TextureCache() {} 00259 TextureCache( const Surface8u &prototypeSurface, const Texture::Format &format ); 00260 00261 gl::Texture cache( const Surface8u &data ); 00262 00263 protected: 00264 struct Obj { 00265 Obj( const Surface8u &prototypeSurface, const Texture::Format &format ); 00266 00267 void markTextureAsFree( int id ); 00268 00269 int mWidth, mHeight; 00270 Texture::Format mFormat; 00271 00272 int mNextId; 00273 std::vector<std::pair<int,gl::Texture> > mTextures; 00274 00275 static void TextureCacheDeallocator( void *aDeallocatorRefcon ); 00276 }; 00277 00278 shared_ptr<Obj> mObj; 00279 00280 public: 00282 00283 TextureCache( const TextureCache &other ) { mObj = other.mObj; } 00284 TextureCache& operator=( const TextureCache &other ) { mObj = other.mObj; return *this; } 00285 bool operator==( const TextureCache &other ) { return mObj == other.mObj; } 00286 typedef shared_ptr<Obj> TextureCache::*unspecified_bool_type; 00287 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &TextureCache::mObj; } 00288 void reset() { mObj.reset(); } 00290 }; 00291 00292 00293 class SurfaceConstraintsGLTexture : public SurfaceConstraints { 00294 public: 00295 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::BGRA : SurfaceChannelOrder::BGR; } 00296 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); } 00297 }; 00298 00299 class TextureDataExc : public std::exception { 00300 public: 00301 TextureDataExc( const std::string &log ) throw(); 00302 virtual const char* what() const throw() 00303 { 00304 return mMessage; 00305 } 00306 00307 private: 00308 char mMessage[16001]; 00309 GLint mShaderType; 00310 }; 00311 00312 00313 } } // namespace cinder::gl