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 GLint getCleanWidth() const; 00108 GLint getCleanHeight() const; 00110 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00112 float getAspectRatio() const { return getWidth() / (float)getHeight(); } 00114 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); } 00116 Area getCleanBounds() const { return Area( 0, 0, getCleanWidth(), getCleanHeight() ); } 00118 bool hasAlpha() const; 00120 float getLeft() const; 00121 float getRight() const; 00122 float getTop() const; 00123 float getBottom() const; 00125 float getMaxU() const; 00126 float getMaxV() const; 00128 Rectf getAreaTexCoords( const Area &area ) const; 00130 GLint getInternalFormat() const; 00132 GLuint getTextureId() const { return mObj->mTextureID; } 00134 GLenum getTarget() const { return mObj->mTarget; } 00136 bool isFlipped() const { return mObj->mFlipped; } 00138 void setFlipped( bool aFlipped = true ) { mObj->mFlipped = aFlipped; } 00139 00142 void enableAndBind() const; 00144 void disable() const; 00146 void bind( GLuint textureUnit = 0 ) const; 00148 void unbind( GLuint textureUnit = 0 ) const; 00149 00151 static Texture loadDds( IStreamRef ddsStream, Format format ); 00152 00154 static void SurfaceChannelOrderToDataFormatAndType( const SurfaceChannelOrder &sco, GLint *dataFormat, GLenum *type ); 00156 static bool dataFormatHasAlpha( GLint dataFormat ); 00158 static bool dataFormatHasColor( GLint dataFormat ); 00159 00161 Texture weakClone() const; 00162 00163 #if ! defined( CINDER_GLES ) 00164 00165 operator ImageSourceRef() const; 00166 #endif 00167 00168 struct Format { 00170 Format(); 00171 00173 void setTarget( GLenum target ) { mTarget = target; } 00175 #ifndef CINDER_GLES 00176 void setTargetRect() { mTarget = GL_TEXTURE_RECTANGLE_ARB; } 00177 #endif 00178 00180 void enableMipmapping( bool enableMipmapping = true ) { mMipmapping = enableMipmapping; } 00181 00183 void setInternalFormat( GLint internalFormat ) { mInternalFormat = internalFormat; } 00185 void setAutoInternalFormat() { mInternalFormat = -1; } 00186 00188 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); } 00191 void setWrapS( GLenum wrapS ) { mWrapS = wrapS; } 00194 void setWrapT( GLenum wrapT ) { mWrapT = wrapT; } 00197 void setMinFilter( GLenum minFilter ) { mMinFilter = minFilter; } 00200 void setMagFilter( GLenum magFilter ) { mMagFilter = magFilter; } 00201 00203 GLenum getTarget() const { return mTarget; } 00205 bool hasMipmapping() const { return mMipmapping; } 00206 00208 GLint getInternalFormat() const { return mInternalFormat; } 00210 bool isAutoInternalFormat() const { return mInternalFormat == -1; } 00211 00213 GLenum getWrapS() const { return mWrapS; } 00215 GLenum getWrapT() const { return mWrapT; } 00217 GLenum getMinFilter() const { return mMinFilter; } 00219 GLenum getMagFilter() const { return mMagFilter; } 00220 00221 protected: 00222 GLenum mTarget; 00223 GLenum mWrapS, mWrapT; 00224 GLenum mMinFilter, mMagFilter; 00225 bool mMipmapping; 00226 GLint mInternalFormat; 00227 00228 friend class Texture; 00229 }; 00230 00231 protected: 00232 void init( const unsigned char *data, int unpackRowLength, GLenum dataFormat, GLenum type, const Format &format ); 00233 void init( const float *data, GLint dataFormat, const Format &format ); 00234 void init( ImageSourceRef imageSource, const Format &format ); 00235 00236 struct Obj { 00237 Obj() : mWidth( -1 ), mHeight( -1 ), mCleanWidth( -1 ), mCleanHeight( -1 ), mInternalFormat( -1 ), mTextureID( 0 ), mFlipped( false ), mDeallocatorFunc( 0 ) {} 00238 Obj( int aWidth, int aHeight ) : mInternalFormat( -1 ), mWidth( aWidth ), mHeight( aHeight ), mCleanWidth( aWidth ), mCleanHeight( aHeight ), mFlipped( false ), mTextureID( 0 ), mDeallocatorFunc( 0 ) {} 00239 ~Obj(); 00240 00241 mutable GLint mWidth, mHeight, mCleanWidth, mCleanHeight; 00242 float mMaxU, mMaxV; 00243 mutable GLint mInternalFormat; 00244 GLenum mTarget; 00245 GLuint mTextureID; 00246 bool mDoNotDispose; 00247 bool mFlipped; 00248 void (*mDeallocatorFunc)(void *refcon); 00249 void *mDeallocatorRefcon; 00250 }; 00251 shared_ptr<Obj> mObj; 00252 00253 public: 00255 00256 typedef shared_ptr<Obj> Texture::*unspecified_bool_type; 00257 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &Texture::mObj; } 00258 void reset() { mObj.reset(); } 00260 }; 00261 00262 class TextureCache { 00263 public: 00264 TextureCache() {} 00265 TextureCache( const Surface8u &prototypeSurface, const Texture::Format &format ); 00266 00267 gl::Texture cache( const Surface8u &data ); 00268 00269 protected: 00270 struct Obj { 00271 Obj( const Surface8u &prototypeSurface, const Texture::Format &format ); 00272 00273 void markTextureAsFree( int id ); 00274 00275 int mWidth, mHeight; 00276 Texture::Format mFormat; 00277 00278 int mNextId; 00279 std::vector<std::pair<int,gl::Texture> > mTextures; 00280 00281 static void TextureCacheDeallocator( void *aDeallocatorRefcon ); 00282 }; 00283 00284 shared_ptr<Obj> mObj; 00285 00286 public: 00288 00289 TextureCache( const TextureCache &other ) { mObj = other.mObj; } 00290 TextureCache& operator=( const TextureCache &other ) { mObj = other.mObj; return *this; } 00291 bool operator==( const TextureCache &other ) { return mObj == other.mObj; } 00292 typedef shared_ptr<Obj> TextureCache::*unspecified_bool_type; 00293 operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &TextureCache::mObj; } 00294 void reset() { mObj.reset(); } 00296 }; 00297 00298 00299 class SurfaceConstraintsGLTexture : public SurfaceConstraints { 00300 public: 00301 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::BGRA : SurfaceChannelOrder::BGR; } 00302 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); } 00303 }; 00304 00305 class TextureDataExc : public std::exception { 00306 public: 00307 TextureDataExc( const std::string &log ) throw(); 00308 virtual const char* what() const throw() 00309 { 00310 return mMessage; 00311 } 00312 00313 private: 00314 char mMessage[16001]; 00315 GLint mShaderType; 00316 }; 00317 00318 00319 } } // namespace cinder::gl