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 00038 class Texture { 00039 public: 00040 struct Format; 00041 00043 Texture() {} 00045 Texture( int aWidth, int aHeight, Format format = Format() ); 00047 Texture( const unsigned char *data, int dataFormat, int aWidth, int aHeight, Format format = Format() ); 00049 Texture( const Surface8u &surface, Format format = Format() ); 00051 Texture( const Surface32f &surface, Format format = Format() ); 00053 Texture( const Channel8u &channel, Format format = Format() ); 00055 Texture( const Channel32f &channel, Format format = Format() ); 00057 Texture( ImageSourceRef imageSource, Format format = Format() ); 00059 Texture( GLenum aTarget, GLuint aTextureID, int aWidth, int aHeight, bool aDoNotDispose ); 00060 00062 void setDoNotDispose( bool aDoNotDispose = true ) { mObj->mDoNotDispose = aDoNotDispose; } 00064 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon ); 00066 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); } 00069 void setWrapS( GLenum wrapS ); 00072 void setWrapT( GLenum wrapT ); 00075 void setMinFilter( GLenum minFilter ); 00078 void setMagFilter( GLenum magFilter ); 00079 00081 void setCleanTexCoords( float maxU, float maxV ); 00082 00084 void update( const Surface &surface ); 00086 void update( const Surface32f &surface ); 00089 void update( const Surface &surface, const Area &area ); 00091 void update( const Channel32f &channel ); 00093 void update( const Channel8u &channel, const Area &area ); 00094 00096 GLint getWidth() const; 00098 GLint getHeight() const; 00100 GLint getCleanWidth() const; 00102 GLint getCleanHeight() const; 00104 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00106 float getAspectRatio() const { return getWidth() / (float)getHeight(); } 00108 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); } 00110 Area getCleanBounds() const { return Area( 0, 0, getCleanWidth(), getCleanHeight() ); } 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 getId() 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 ), mCleanWidth( -1 ), mCleanHeight( -1 ), mInternalFormat( -1 ), mTextureID( 0 ), mFlipped( false ), mDeallocatorFunc( 0 ) {} 00232 Obj( int aWidth, int aHeight ) : mInternalFormat( -1 ), mWidth( aWidth ), mHeight( aHeight ), mCleanWidth( aWidth ), mCleanHeight( aHeight ), mFlipped( false ), mTextureID( 0 ), mDeallocatorFunc( 0 ) {} 00233 ~Obj(); 00234 00235 mutable GLint mWidth, mHeight, mCleanWidth, mCleanHeight; 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 std::shared_ptr<Obj> mObj; 00246 00247 public: 00249 00250 typedef std::shared_ptr<Obj> Texture::*unspecified_bool_type; 00251 operator unspecified_bool_type() const { 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 std::shared_ptr<Obj> mObj; 00279 00280 public: 00282 00283 typedef std::shared_ptr<Obj> TextureCache::*unspecified_bool_type; 00284 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &TextureCache::mObj; } 00285 void reset() { mObj.reset(); } 00287 }; 00288 00289 00290 class SurfaceConstraintsGLTexture : public SurfaceConstraints { 00291 public: 00292 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::BGRA : SurfaceChannelOrder::BGR; } 00293 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); } 00294 }; 00295 00296 class TextureDataExc : public std::exception { 00297 public: 00298 TextureDataExc( const std::string &log ) throw(); 00299 virtual const char* what() const throw() 00300 { 00301 return mMessage; 00302 } 00303 00304 private: 00305 char mMessage[16001]; 00306 GLint mShaderType; 00307 }; 00308 00309 00310 } } // namespace cinder::gl