00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
00036 class Texture;
00037 typedef std::shared_ptr<Texture> TextureRef;
00038
00041 class Texture {
00042 public:
00043 struct Format;
00044
00045
00047 static TextureRef create( int width, int height, Format format = Format() ) { return std::make_shared<Texture>( width, height, format ); }
00049 static TextureRef create( const unsigned char *data, int dataFormat, int width, int height, Format format = Format() ) { return std::make_shared<Texture>( data, dataFormat, width, height, format ); }
00051 static TextureRef create( const Surface8u &surface, Format format = Format() ) { return std::make_shared<Texture>( surface, format ); }
00053 static TextureRef create( const Surface32f &surface, Format format = Format() ) { return std::make_shared<Texture>( surface, format ); }
00055 static TextureRef create( const Channel8u &channel, Format format = Format() ) { return std::make_shared<Texture>( channel, format ); }
00057 static TextureRef create( const Channel32f &channel, Format format = Format() ) { return std::make_shared<Texture>( channel, format ); }
00059 static TextureRef create( ImageSourceRef imageSource, Format format = Format() ) { return std::make_shared<Texture>( imageSource, format ); }
00061 static TextureRef create( GLenum target, GLuint textureId, int width, int height, bool doNotDispose ) { return std::make_shared<Texture>( target, textureId, width, height, doNotDispose ); }
00062
00063 public:
00065 Texture() {}
00067 Texture( int aWidth, int aHeight, Format format = Format() );
00069 Texture( const unsigned char *data, int dataFormat, int aWidth, int aHeight, Format format = Format() );
00071 Texture( const Surface8u &surface, Format format = Format() );
00073 Texture( const Surface32f &surface, Format format = Format() );
00075 Texture( const Channel8u &channel, Format format = Format() );
00077 Texture( const Channel32f &channel, Format format = Format() );
00079 Texture( ImageSourceRef imageSource, Format format = Format() );
00081 Texture( GLenum aTarget, GLuint aTextureID, int aWidth, int aHeight, bool aDoNotDispose );
00082
00083 public:
00085 void setDoNotDispose( bool aDoNotDispose = true ) { mObj->mDoNotDispose = aDoNotDispose; }
00087 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon );
00089 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); }
00092 void setWrapS( GLenum wrapS );
00095 void setWrapT( GLenum wrapT );
00098 void setMinFilter( GLenum minFilter );
00101 void setMagFilter( GLenum magFilter );
00102
00104 void setCleanTexCoords( float maxU, float maxV );
00105
00107 void update( const Surface &surface );
00109 void update( const Surface32f &surface );
00112 void update( const Surface &surface, const Area &area );
00114 void update( const Channel32f &channel );
00116 void update( const Channel8u &channel, const Area &area );
00117
00119 GLint getWidth() const;
00121 GLint getHeight() const;
00123 GLint getCleanWidth() const;
00125 GLint getCleanHeight() const;
00127 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); }
00129 float getAspectRatio() const { return getWidth() / (float)getHeight(); }
00131 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); }
00133 Area getCleanBounds() const { return Area( 0, 0, getCleanWidth(), getCleanHeight() ); }
00135 bool hasAlpha() const;
00137 float getLeft() const;
00138 float getRight() const;
00139 float getTop() const;
00140 float getBottom() const;
00142 float getMaxU() const;
00143 float getMaxV() const;
00145 Rectf getAreaTexCoords( const Area &area ) const;
00147 GLint getInternalFormat() const;
00149 GLuint getId() const { return mObj->mTextureID; }
00151 GLenum getTarget() const { return mObj->mTarget; }
00153 bool isFlipped() const { return mObj->mFlipped; }
00155 void setFlipped( bool aFlipped = true ) { mObj->mFlipped = aFlipped; }
00156
00159 void enableAndBind() const;
00161 void disable() const;
00163 void bind( GLuint textureUnit = 0 ) const;
00165 void unbind( GLuint textureUnit = 0 ) const;
00166
00168 static Texture loadDds( IStreamRef ddsStream, Format format );
00169
00171 static void SurfaceChannelOrderToDataFormatAndType( const SurfaceChannelOrder &sco, GLint *dataFormat, GLenum *type );
00173 static bool dataFormatHasAlpha( GLint dataFormat );
00175 static bool dataFormatHasColor( GLint dataFormat );
00176
00178 Texture weakClone() const;
00179
00180 #if ! defined( CINDER_GLES )
00181
00182 operator ImageSourceRef() const;
00183 #endif
00184
00185 struct Format {
00187 Format();
00188
00190 void setTarget( GLenum target ) { mTarget = target; }
00192 #ifndef CINDER_GLES
00193 void setTargetRect() { mTarget = GL_TEXTURE_RECTANGLE_ARB; }
00194 #endif
00195
00197 void enableMipmapping( bool enableMipmapping = true ) { mMipmapping = enableMipmapping; }
00198
00200 void setInternalFormat( GLint internalFormat ) { mInternalFormat = internalFormat; }
00202 void setAutoInternalFormat() { mInternalFormat = -1; }
00203
00205 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); }
00208 void setWrapS( GLenum wrapS ) { mWrapS = wrapS; }
00211 void setWrapT( GLenum wrapT ) { mWrapT = wrapT; }
00214 void setMinFilter( GLenum minFilter ) { mMinFilter = minFilter; }
00217 void setMagFilter( GLenum magFilter ) { mMagFilter = magFilter; }
00218
00220 GLenum getTarget() const { return mTarget; }
00222 bool hasMipmapping() const { return mMipmapping; }
00223
00225 GLint getInternalFormat() const { return mInternalFormat; }
00227 bool isAutoInternalFormat() const { return mInternalFormat == -1; }
00228
00230 GLenum getWrapS() const { return mWrapS; }
00232 GLenum getWrapT() const { return mWrapT; }
00234 GLenum getMinFilter() const { return mMinFilter; }
00236 GLenum getMagFilter() const { return mMagFilter; }
00237
00238 protected:
00239 GLenum mTarget;
00240 GLenum mWrapS, mWrapT;
00241 GLenum mMinFilter, mMagFilter;
00242 bool mMipmapping;
00243 GLint mInternalFormat;
00244
00245 friend class Texture;
00246 };
00247
00248 protected:
00249 void init( const unsigned char *data, int unpackRowLength, GLenum dataFormat, GLenum type, const Format &format );
00250 void init( const float *data, GLint dataFormat, const Format &format );
00251 void init( ImageSourceRef imageSource, const Format &format );
00252
00253 struct Obj {
00254 Obj() : mWidth( -1 ), mHeight( -1 ), mCleanWidth( -1 ), mCleanHeight( -1 ), mInternalFormat( -1 ), mTextureID( 0 ), mFlipped( false ), mDeallocatorFunc( 0 ) {}
00255 Obj( int aWidth, int aHeight ) : mInternalFormat( -1 ), mWidth( aWidth ), mHeight( aHeight ), mCleanWidth( aWidth ), mCleanHeight( aHeight ), mFlipped( false ), mTextureID( 0 ), mDeallocatorFunc( 0 ) {}
00256 ~Obj();
00257
00258 mutable GLint mWidth, mHeight, mCleanWidth, mCleanHeight;
00259 float mMaxU, mMaxV;
00260 mutable GLint mInternalFormat;
00261 GLenum mTarget;
00262 GLuint mTextureID;
00263 bool mDoNotDispose;
00264 bool mFlipped;
00265 void (*mDeallocatorFunc)(void *refcon);
00266 void *mDeallocatorRefcon;
00267 };
00268 std::shared_ptr<Obj> mObj;
00269
00270 public:
00272
00273 typedef std::shared_ptr<Obj> Texture::*unspecified_bool_type;
00274 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &Texture::mObj; }
00275 void reset() { mObj.reset(); }
00277 };
00278
00279 class TextureCache {
00280 public:
00281 TextureCache() {}
00282 TextureCache( const Surface8u &prototypeSurface, const Texture::Format &format );
00283
00284 gl::Texture cache( const Surface8u &data );
00285
00286 protected:
00287 struct Obj {
00288 Obj( const Surface8u &prototypeSurface, const Texture::Format &format );
00289
00290 void markTextureAsFree( int id );
00291
00292 int mWidth, mHeight;
00293 Texture::Format mFormat;
00294
00295 int mNextId;
00296 std::vector<std::pair<int,gl::Texture> > mTextures;
00297
00298 static void TextureCacheDeallocator( void *aDeallocatorRefcon );
00299 };
00300
00301 std::shared_ptr<Obj> mObj;
00302
00303 public:
00305
00306 typedef std::shared_ptr<Obj> TextureCache::*unspecified_bool_type;
00307 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &TextureCache::mObj; }
00308 void reset() { mObj.reset(); }
00310 };
00311
00312
00313 class SurfaceConstraintsGLTexture : public SurfaceConstraints {
00314 public:
00315 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::BGRA : SurfaceChannelOrder::BGR; }
00316 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); }
00317 };
00318
00319 class TextureDataExc : public std::exception {
00320 public:
00321 TextureDataExc( const std::string &log ) throw();
00322 virtual const char* what() const throw()
00323 {
00324 return mMessage;
00325 }
00326
00327 private:
00328 char mMessage[16001];
00329 GLint mShaderType;
00330 };
00331
00332
00333 } }