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 ); 00087 void update( const Surface &surface, const Area &area ); 00089 void update( const Channel8u &surface, const Area &area ); 00090 00092 GLint getWidth() const; 00094 GLint getHeight() const; 00096 GLint getCleanWidth() const; 00098 GLint getCleanHeight() const; 00100 Vec2i getSize() const { return Vec2i( getWidth(), getHeight() ); } 00102 float getAspectRatio() const { return getWidth() / (float)getHeight(); } 00104 Area getBounds() const { return Area( 0, 0, getWidth(), getHeight() ); } 00106 Area getCleanBounds() const { return Area( 0, 0, getCleanWidth(), getCleanHeight() ); } 00108 bool hasAlpha() const; 00110 float getLeft() const; 00111 float getRight() const; 00112 float getTop() const; 00113 float getBottom() const; 00115 float getMaxU() const; 00116 float getMaxV() const; 00118 Rectf getAreaTexCoords( const Area &area ) const; 00120 GLint getInternalFormat() const; 00122 GLuint getId() const { return mObj->mTextureID; } 00124 GLenum getTarget() const { return mObj->mTarget; } 00126 bool isFlipped() const { return mObj->mFlipped; } 00128 void setFlipped( bool aFlipped = true ) { mObj->mFlipped = aFlipped; } 00129 00132 void enableAndBind() const; 00134 void disable() const; 00136 void bind( GLuint textureUnit = 0 ) const; 00138 void unbind( GLuint textureUnit = 0 ) const; 00139 00141 static Texture loadDds( IStreamRef ddsStream, Format format ); 00142 00144 static void SurfaceChannelOrderToDataFormatAndType( const SurfaceChannelOrder &sco, GLint *dataFormat, GLenum *type ); 00146 static bool dataFormatHasAlpha( GLint dataFormat ); 00148 static bool dataFormatHasColor( GLint dataFormat ); 00149 00151 Texture weakClone() const; 00152 00153 #if ! defined( CINDER_GLES ) 00154 00155 operator ImageSourceRef() const; 00156 #endif 00157 00158 struct Format { 00160 Format(); 00161 00163 void setTarget( GLenum target ) { mTarget = target; } 00165 #ifndef CINDER_GLES 00166 void setTargetRect() { mTarget = GL_TEXTURE_RECTANGLE_ARB; } 00167 #endif 00168 00170 void enableMipmapping( bool enableMipmapping = true ) { mMipmapping = enableMipmapping; } 00171 00173 void setInternalFormat( GLint internalFormat ) { mInternalFormat = internalFormat; } 00175 void setAutoInternalFormat() { mInternalFormat = -1; } 00176 00178 void setWrap( GLenum wrapS, GLenum wrapT ) { setWrapS( wrapS ); setWrapT( wrapT ); } 00181 void setWrapS( GLenum wrapS ) { mWrapS = wrapS; } 00184 void setWrapT( GLenum wrapT ) { mWrapT = wrapT; } 00187 void setMinFilter( GLenum minFilter ) { mMinFilter = minFilter; } 00190 void setMagFilter( GLenum magFilter ) { mMagFilter = magFilter; } 00191 00193 GLenum getTarget() const { return mTarget; } 00195 bool hasMipmapping() const { return mMipmapping; } 00196 00198 GLint getInternalFormat() const { return mInternalFormat; } 00200 bool isAutoInternalFormat() const { return mInternalFormat == -1; } 00201 00203 GLenum getWrapS() const { return mWrapS; } 00205 GLenum getWrapT() const { return mWrapT; } 00207 GLenum getMinFilter() const { return mMinFilter; } 00209 GLenum getMagFilter() const { return mMagFilter; } 00210 00211 protected: 00212 GLenum mTarget; 00213 GLenum mWrapS, mWrapT; 00214 GLenum mMinFilter, mMagFilter; 00215 bool mMipmapping; 00216 GLint mInternalFormat; 00217 00218 friend class Texture; 00219 }; 00220 00221 protected: 00222 void init( const unsigned char *data, int unpackRowLength, GLenum dataFormat, GLenum type, const Format &format ); 00223 void init( const float *data, GLint dataFormat, const Format &format ); 00224 void init( ImageSourceRef imageSource, const Format &format ); 00225 00226 struct Obj { 00227 Obj() : mWidth( -1 ), mHeight( -1 ), mCleanWidth( -1 ), mCleanHeight( -1 ), mInternalFormat( -1 ), mTextureID( 0 ), mFlipped( false ), mDeallocatorFunc( 0 ) {} 00228 Obj( int aWidth, int aHeight ) : mInternalFormat( -1 ), mWidth( aWidth ), mHeight( aHeight ), mCleanWidth( aWidth ), mCleanHeight( aHeight ), mFlipped( false ), mTextureID( 0 ), mDeallocatorFunc( 0 ) {} 00229 ~Obj(); 00230 00231 mutable GLint mWidth, mHeight, mCleanWidth, mCleanHeight; 00232 float mMaxU, mMaxV; 00233 mutable GLint mInternalFormat; 00234 GLenum mTarget; 00235 GLuint mTextureID; 00236 bool mDoNotDispose; 00237 bool mFlipped; 00238 void (*mDeallocatorFunc)(void *refcon); 00239 void *mDeallocatorRefcon; 00240 }; 00241 std::shared_ptr<Obj> mObj; 00242 00243 public: 00245 00246 typedef std::shared_ptr<Obj> Texture::*unspecified_bool_type; 00247 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &Texture::mObj; } 00248 void reset() { mObj.reset(); } 00250 }; 00251 00252 class TextureCache { 00253 public: 00254 TextureCache() {} 00255 TextureCache( const Surface8u &prototypeSurface, const Texture::Format &format ); 00256 00257 gl::Texture cache( const Surface8u &data ); 00258 00259 protected: 00260 struct Obj { 00261 Obj( const Surface8u &prototypeSurface, const Texture::Format &format ); 00262 00263 void markTextureAsFree( int id ); 00264 00265 int mWidth, mHeight; 00266 Texture::Format mFormat; 00267 00268 int mNextId; 00269 std::vector<std::pair<int,gl::Texture> > mTextures; 00270 00271 static void TextureCacheDeallocator( void *aDeallocatorRefcon ); 00272 }; 00273 00274 std::shared_ptr<Obj> mObj; 00275 00276 public: 00278 00279 typedef std::shared_ptr<Obj> TextureCache::*unspecified_bool_type; 00280 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &TextureCache::mObj; } 00281 void reset() { mObj.reset(); } 00283 }; 00284 00285 00286 class SurfaceConstraintsGLTexture : public SurfaceConstraints { 00287 public: 00288 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::BGRA : SurfaceChannelOrder::BGR; } 00289 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); } 00290 }; 00291 00292 class TextureDataExc : public std::exception { 00293 public: 00294 TextureDataExc( const std::string &log ) throw(); 00295 virtual const char* what() const throw() 00296 { 00297 return mMessage; 00298 } 00299 00300 private: 00301 char mMessage[16001]; 00302 GLint mShaderType; 00303 }; 00304 00305 00306 } } // namespace cinder::gl