include/cinder/gl/Texture.h
Go to the documentation of this file.
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 
00036 class Texture;
00037 typedef std::shared_ptr<Texture>    TextureRef;
00038 
00041 class Texture {
00042   public:
00043     struct Format;
00044 
00045     // Create analogs for constructors
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 } } // namespace cinder::gl