/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSG_TEXTURE #define OSG_TEXTURE 1 #include #include #include #include #include #include #include #include #include #include #include // If not defined by gl.h use the definition found in: // http://oss.sgi.com/projects/ogl-sample/registry/EXT/texture_filter_anisotropic.txt #ifndef GL_TEXTURE_MAX_ANISOTROPY_EXT #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE #endif #ifndef GL_ARB_texture_compression #define GL_COMPRESSED_ALPHA_ARB 0x84E9 #define GL_COMPRESSED_LUMINANCE_ARB 0x84EA #define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB #define GL_COMPRESSED_INTENSITY_ARB 0x84EC #define GL_COMPRESSED_RGB_ARB 0x84ED #define GL_COMPRESSED_RGBA_ARB 0x84EE #define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF #define GL_TEXTURE_COMPRESSED_ARB 0x86A1 #define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2 #define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3 #endif #ifndef GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB #define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0 #endif #ifndef GL_EXT_texture_compression_s3tc #define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 #define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 #define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 #define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 #endif #ifndef GL_EXT_texture_compression_rgtc #define GL_COMPRESSED_RED_RGTC1_EXT 0x8DBB #define GL_COMPRESSED_SIGNED_RED_RGTC1_EXT 0x8DBC #define GL_COMPRESSED_RED_GREEN_RGTC2_EXT 0x8DBD #define GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT 0x8DBE #endif #ifndef GL_IMG_texture_compression_pvrtc #define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 #define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 #define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 #endif #ifndef GL_OES_compressed_ETC1_RGB8_texture #define GL_ETC1_RGB8_OES 0x8D64 #endif #ifndef GL_ARB_INTERNAL_TEXTURE_FORMAT #define GL_RGBA32F_ARB 0x8814 #define GL_RGB32F_ARB 0x8815 #define GL_ALPHA32F_ARB 0x8816 #define GL_INTENSITY32F_ARB 0x8817 #define GL_LUMINANCE32F_ARB 0x8818 #define GL_LUMINANCE_ALPHA32F_ARB 0x8819 #define GL_RGBA16F_ARB 0x881A #define GL_RGB16F_ARB 0x881B #define GL_ALPHA16F_ARB 0x881C #define GL_INTENSITY16F_ARB 0x881D #define GL_LUMINANCE16F_ARB 0x881E #define GL_LUMINANCE_ALPHA16F_ARB 0x881F #endif #ifndef GL_ARB_PIXEL_DATA #define GL_HALF_FLOAT_ARB 0x140B #endif #ifndef GL_NV_texture_shader #define GL_HILO_NV 0x86F4 #define GL_DSDT_NV 0x86F5 #define GL_DSDT_MAG_NV 0x86F6 #define GL_DSDT_MAG_VIB_NV 0x86F7 #define GL_HILO16_NV 0x86F8 #define GL_SIGNED_HILO_NV 0x86F9 #define GL_SIGNED_HILO16_NV 0x86FA #define GL_SIGNED_RGBA_NV 0x86FB #define GL_SIGNED_RGBA8_NV 0x86FC #define GL_SIGNED_RGB_NV 0x86FE #define GL_SIGNED_RGB8_NV 0x86FF #define GL_SIGNED_LUMINANCE_NV 0x8701 #define GL_SIGNED_LUMINANCE8_NV 0x8702 #define GL_SIGNED_LUMINANCE_ALPHA_NV 0x8703 #define GL_SIGNED_LUMINANCE8_ALPHA8_NV 0x8704 #define GL_SIGNED_ALPHA_NV 0x8705 #define GL_SIGNED_ALPHA8_NV 0x8706 #define GL_SIGNED_INTENSITY_NV 0x8707 #define GL_SIGNED_INTENSITY8_NV 0x8708 #define GL_DSDT8_NV 0x8709 #define GL_DSDT8_MAG8_NV 0x870A #define GL_DSDT8_MAG8_INTENSITY8_NV 0x870B #define GL_SIGNED_RGB_UNSIGNED_ALPHA_NV 0x870C #define GL_SIGNED_RGB8_UNSIGNED_ALPHA8_NV 0x870D #endif #ifndef GL_NV_float_buffer #define GL_FLOAT_R_NV 0x8880 #define GL_FLOAT_RG_NV 0x8881 #define GL_FLOAT_RGB_NV 0x8882 #define GL_FLOAT_RGBA_NV 0x8883 #define GL_FLOAT_R16_NV 0x8884 #define GL_FLOAT_R32_NV 0x8885 #define GL_FLOAT_RG16_NV 0x8886 #define GL_FLOAT_RG32_NV 0x8887 #define GL_FLOAT_RGB16_NV 0x8888 #define GL_FLOAT_RGB32_NV 0x8889 #define GL_FLOAT_RGBA16_NV 0x888A #define GL_FLOAT_RGBA32_NV 0x888B #endif #ifndef GL_NV_half_float #define GL_HALF_FLOAT_NV 0x140B #endif #ifndef GL_ATI_texture_float #define GL_RGBA_FLOAT32_ATI 0x8814 #define GL_RGB_FLOAT32_ATI 0x8815 #define GL_ALPHA_FLOAT32_ATI 0x8816 #define GL_INTENSITY_FLOAT32_ATI 0x8817 #define GL_LUMINANCE_FLOAT32_ATI 0x8818 #define GL_LUMINANCE_ALPHA_FLOAT32_ATI 0x8819 #define GL_RGBA_FLOAT16_ATI 0x881A #define GL_RGB_FLOAT16_ATI 0x881B #define GL_ALPHA_FLOAT16_ATI 0x881C #define GL_INTENSITY_FLOAT16_ATI 0x881D #define GL_LUMINANCE_FLOAT16_ATI 0x881E #define GL_LUMINANCE_ALPHA_FLOAT16_ATI 0x881F #endif #ifndef GL_MIRRORED_REPEAT_IBM #define GL_MIRRORED_REPEAT_IBM 0x8370 #endif #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif #ifndef GL_CLAMP #define GL_CLAMP 0x2900 #endif #ifndef GL_CLAMP_TO_BORDER_ARB #define GL_CLAMP_TO_BORDER_ARB 0x812D #endif #ifndef GL_INTENSITY // OpenGL ES1 and ES2 doesn't provide GL_INTENSITY #define GL_INTENSITY 0x8049 #endif #ifndef GL_GENERATE_MIPMAP_SGIS #define GL_GENERATE_MIPMAP_SGIS 0x8191 #define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192 #endif #ifndef GL_TEXTURE_3D #define GL_TEXTURE_3D 0x806F #endif #ifndef GL_TEXTURE_2D_ARRAY_EXT #define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A #define GL_TEXTURE_2D_ARRAY_EXT 0x8C1A #define GL_PROXY_TEXTURE_2D_ARRAY_EXT 0x8C1B #define GL_TEXTURE_BINDING_2D_ARRAY_EXT 0x8C1D #define GL_MAX_ARRAY_TEXTURE_LAYERS_EXT 0x88FF #define GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT 0x884E #define GL_SAMPLER_2D_ARRAY_EXT 0x8DC1 #define GL_SAMPLER_2D_ARRAY_SHADOW_EXT 0x8DC4 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 #endif #ifndef GL_TEXTURE_CUBE_MAP #define GL_TEXTURE_CUBE_MAP 0x8513 #define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 #define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 #define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 #define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A #define GL_PROXY_TEXTURE_CUBE_MAP 0x851B #define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C #endif #ifndef GL_TEXTURE_BINDING_3D #define GL_TEXTURE_BINDING_3D 0x806A #endif #ifndef GL_DEPTH_TEXTURE_MODE_ARB #define GL_DEPTH_TEXTURE_MODE_ARB 0x884B #endif #ifndef GL_TEXTURE_COMPARE_MODE_ARB #define GL_TEXTURE_COMPARE_MODE_ARB 0x884C #endif #ifndef GL_TEXTURE_COMPARE_FUNC_ARB #define GL_TEXTURE_COMPARE_FUNC_ARB 0x884D #endif #ifndef GL_COMPARE_R_TO_TEXTURE_ARB #define GL_COMPARE_R_TO_TEXTURE_ARB 0x884E #endif #ifndef TEXTURE_COMPARE_FAIL_VALUE_ARB #define TEXTURE_COMPARE_FAIL_VALUE_ARB 0x80BF #endif #if !defined( GL_MAX_TEXTURE_UNITS ) #define GL_MAX_TEXTURE_UNITS 0x84E2 #endif #ifndef GL_TEXTURE_DEPTH #define GL_TEXTURE_DEPTH 0x8071 #endif #ifndef GL_TEXTURE_2D_MULTISAMPLE #define GL_TEXTURE_2D_MULTISAMPLE 0x9100 #endif // Integer texture extension as in http://www.opengl.org/registry/specs/EXT/texture_integer.txt #ifndef GL_EXT_texture_integer #define GL_RGBA32UI_EXT 0x8D70 #define GL_RGB32UI_EXT 0x8D71 #define GL_ALPHA32UI_EXT 0x8D72 #define GL_INTENSITY32UI_EXT 0x8D73 #define GL_LUMINANCE32UI_EXT 0x8D74 #define GL_LUMINANCE_ALPHA32UI_EXT 0x8D75 #define GL_RGBA16UI_EXT 0x8D76 #define GL_RGB16UI_EXT 0x8D77 #define GL_ALPHA16UI_EXT 0x8D78 #define GL_INTENSITY16UI_EXT 0x8D79 #define GL_LUMINANCE16UI_EXT 0x8D7A #define GL_LUMINANCE_ALPHA16UI_EXT 0x8D7B #define GL_RGBA8UI_EXT 0x8D7C #define GL_RGB8UI_EXT 0x8D7D #define GL_ALPHA8UI_EXT 0x8D7E #define GL_INTENSITY8UI_EXT 0x8D7F #define GL_LUMINANCE8UI_EXT 0x8D80 #define GL_LUMINANCE_ALPHA8UI_EXT 0x8D81 #define GL_RGBA32I_EXT 0x8D82 #define GL_RGB32I_EXT 0x8D83 #define GL_ALPHA32I_EXT 0x8D84 #define GL_INTENSITY32I_EXT 0x8D85 #define GL_LUMINANCE32I_EXT 0x8D86 #define GL_LUMINANCE_ALPHA32I_EXT 0x8D87 #define GL_RGBA16I_EXT 0x8D88 #define GL_RGB16I_EXT 0x8D89 #define GL_ALPHA16I_EXT 0x8D8A #define GL_INTENSITY16I_EXT 0x8D8B #define GL_LUMINANCE16I_EXT 0x8D8C #define GL_LUMINANCE_ALPHA16I_EXT 0x8D8D #define GL_RGBA8I_EXT 0x8D8E #define GL_RGB8I_EXT 0x8D8F #define GL_ALPHA8I_EXT 0x8D90 #define GL_INTENSITY8I_EXT 0x8D91 #define GL_LUMINANCE8I_EXT 0x8D92 #define GL_LUMINANCE_ALPHA8I_EXT 0x8D93 #define GL_RED_INTEGER_EXT 0x8D94 #define GL_GREEN_INTEGER_EXT 0x8D95 #define GL_BLUE_INTEGER_EXT 0x8D96 #define GL_ALPHA_INTEGER_EXT 0x8D97 #define GL_RGB_INTEGER_EXT 0x8D98 #define GL_RGBA_INTEGER_EXT 0x8D99 #define GL_BGR_INTEGER_EXT 0x8D9A #define GL_BGRA_INTEGER_EXT 0x8D9B #define GL_LUMINANCE_INTEGER_EXT 0x8D9C #define GL_LUMINANCE_ALPHA_INTEGER_EXT 0x8D9D #define GL_RGBA_INTEGER_MODE_EXT 0x8D9E #endif namespace osg { /** Texture pure virtual base class that encapsulates OpenGL texture * functionality common to the various types of OSG textures. */ class OSG_EXPORT Texture : public osg::StateAttribute { public : Texture(); /** Copy constructor using CopyOp to manage deep vs shallow copy. */ Texture(const Texture& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY); virtual osg::Object* cloneType() const = 0; virtual osg::Object* clone(const CopyOp& copyop) const = 0; virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast(obj)!=NULL; } virtual const char* libraryName() const { return "osg"; } virtual const char* className() const { return "Texture"; } /** Fast alternative to dynamic_cast<> for determining if state attribute is a Texture.*/ virtual Texture* asTexture() { return this; } /** Fast alternative to dynamic_cast<> for determining if state attribute is a Texture.*/ virtual const Texture* asTexture() const { return this; } virtual Type getType() const { return TEXTURE; } virtual bool isTextureAttribute() const { return true; } virtual GLenum getTextureTarget() const = 0; virtual bool getModeUsage(StateAttribute::ModeUsage& usage) const { usage.usesTextureMode(getTextureTarget()); return true; } virtual int getTextureWidth() const { return 0; } virtual int getTextureHeight() const { return 0; } virtual int getTextureDepth() const { return 0; } enum WrapParameter { WRAP_S, WRAP_T, WRAP_R }; enum WrapMode { CLAMP = GL_CLAMP, CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE, CLAMP_TO_BORDER = GL_CLAMP_TO_BORDER_ARB, REPEAT = GL_REPEAT, MIRROR = GL_MIRRORED_REPEAT_IBM }; /** Sets the texture wrap mode. */ void setWrap(WrapParameter which, WrapMode wrap); /** Gets the texture wrap mode. */ WrapMode getWrap(WrapParameter which) const; /** Sets the border color. Only used when wrap mode is CLAMP_TO_BORDER. * The border color will be casted to the appropriate type to match the * internal pixel format of the texture. */ void setBorderColor(const Vec4d& color) { _borderColor = color; dirtyTextureParameters(); } /** Gets the border color. */ const Vec4d& getBorderColor() const { return _borderColor; } /** Sets the border width. */ void setBorderWidth(GLint width) { _borderWidth = width; dirtyTextureParameters(); } GLint getBorderWidth() const { return _borderWidth; } enum FilterParameter { MIN_FILTER, MAG_FILTER }; enum FilterMode { LINEAR = GL_LINEAR, LINEAR_MIPMAP_LINEAR = GL_LINEAR_MIPMAP_LINEAR, LINEAR_MIPMAP_NEAREST = GL_LINEAR_MIPMAP_NEAREST, NEAREST = GL_NEAREST, NEAREST_MIPMAP_LINEAR = GL_NEAREST_MIPMAP_LINEAR, NEAREST_MIPMAP_NEAREST = GL_NEAREST_MIPMAP_NEAREST }; /** Sets the texture filter mode. */ void setFilter(FilterParameter which, FilterMode filter); /** Gets the texture filter mode. */ FilterMode getFilter(FilterParameter which) const; /** Sets the maximum anisotropy value, default value is 1.0 for no * anisotropic filtering. If hardware does not support anisotropic * filtering, use normal filtering (equivalent to a max anisotropy * value of 1.0. Valid range is 1.0f upwards. The maximum value * depends on the graphics system. */ void setMaxAnisotropy(float anis); /** Gets the maximum anisotropy value. */ inline float getMaxAnisotropy() const { return _maxAnisotropy; } /** Sets the hardware mipmap generation hint. If enabled, it will * only be used if supported in the graphics system. */ inline void setUseHardwareMipMapGeneration(bool useHardwareMipMapGeneration) { _useHardwareMipMapGeneration = useHardwareMipMapGeneration; } /** Gets the hardware mipmap generation hint. */ inline bool getUseHardwareMipMapGeneration() const { return _useHardwareMipMapGeneration; } /** Sets whether or not the apply() function will unreference the image * data. If enabled, and the image data is only referenced by this * Texture, apply() will delete the image data. */ inline void setUnRefImageDataAfterApply(bool flag) { _unrefImageDataAfterApply = flag; } /** Gets whether or not apply() unreferences image data. */ inline bool getUnRefImageDataAfterApply() const { return _unrefImageDataAfterApply; } /** Sets whether to use client storage for the texture, if supported * by the graphics system. Note: If enabled, and the graphics system * supports it, the osg::Image(s) associated with this texture cannot * be deleted, so the UnRefImageDataAfterApply flag would be ignored. */ inline void setClientStorageHint(bool flag) { _clientStorageHint = flag; } /** Gets whether to use client storage for the texture. */ inline bool getClientStorageHint() const { return _clientStorageHint; } /** Sets whether to force the texture to resize images that have dimensions * that are not a power of two. If enabled, NPOT images will be resized, * whether or not NPOT textures are supported by the hardware. If disabled, * NPOT images will not be resized if supported by hardware. */ inline void setResizeNonPowerOfTwoHint(bool flag) { _resizeNonPowerOfTwoHint = flag; } /** Gets whether texture will force non power to two images to be resized. */ inline bool getResizeNonPowerOfTwoHint() const { return _resizeNonPowerOfTwoHint; } enum InternalFormatMode { USE_IMAGE_DATA_FORMAT, USE_USER_DEFINED_FORMAT, USE_ARB_COMPRESSION, USE_S3TC_DXT1_COMPRESSION, USE_S3TC_DXT3_COMPRESSION, USE_S3TC_DXT5_COMPRESSION, USE_PVRTC_2BPP_COMPRESSION, USE_PVRTC_4BPP_COMPRESSION, USE_ETC_COMPRESSION, USE_RGTC1_COMPRESSION, USE_RGTC2_COMPRESSION, USE_S3TC_DXT1c_COMPRESSION, USE_S3TC_DXT1a_COMPRESSION }; /** Sets the internal texture format mode. Note: If the texture format is * USE_IMAGE_DATA_FORMAT, USE_ARB_COMPRESSION, or USE_S3TC_COMPRESSION, * the internal format mode is set automatically and will overwrite the * previous _internalFormat. */ inline void setInternalFormatMode(InternalFormatMode mode) { _internalFormatMode = mode; } /** Gets the internal texture format mode. */ inline InternalFormatMode getInternalFormatMode() const { return _internalFormatMode; } /** Sets the internal texture format. Implicitly sets the * internalFormatMode to USE_USER_DEFINED_FORMAT. * The corresponding internal format type will be computed. */ inline void setInternalFormat(GLint internalFormat) { _internalFormatMode = USE_USER_DEFINED_FORMAT; _internalFormat = internalFormat; computeInternalFormatType(); } /** Gets the internal texture format. */ inline GLint getInternalFormat() const { if (_internalFormat==0) computeInternalFormat(); return _internalFormat; } /** Return true if the internal format is one of the compressed formats.*/ bool isCompressedInternalFormat() const; /** Sets the external source image format, used as a fallback when no osg::Image is attached to provide the source image format. */ inline void setSourceFormat(GLenum sourceFormat) { _sourceFormat = sourceFormat; } /** Gets the external source image format. */ inline GLenum getSourceFormat() const { return _sourceFormat; } /** Sets the external source data type, used as a fallback when no osg::Image is attached to provide the source image format.*/ inline void setSourceType(GLenum sourceType) { _sourceType = sourceType; } /** Gets the external source data type.*/ inline GLenum getSourceType() const { return _sourceType; } /** Texture type determined by the internal texture format */ enum InternalFormatType{ //! default OpenGL format (clamped values to [0,1) or [0,255]) NORMALIZED = 0x0, //! float values, Shader Model 3.0 (see ARB_texture_float) FLOAT = 0x1, //! Signed integer values (see EXT_texture_integer) SIGNED_INTEGER = 0x2, //! Unsigned integer value (see EXT_texture_integer) UNSIGNED_INTEGER = 0x4 }; /** Get the internal texture format type. */ inline InternalFormatType getInternalFormatType() const { return _internalFormatType; } class TextureObject; /** Returns a pointer to the TextureObject for the current context. */ inline TextureObject* getTextureObject(unsigned int contextID) const { return _textureObjectBuffer[contextID].get(); } inline void setTextureObject(unsigned int contextID, TextureObject* to) { _textureObjectBuffer[contextID] = to; } /** Forces a recompile on next apply() of associated OpenGL texture * objects. */ void dirtyTextureObject(); /** Returns true if the texture objects for all the required graphics * contexts are loaded. */ bool areAllTextureObjectsLoaded() const; /** Gets the dirty flag for the current contextID. */ inline unsigned int& getTextureParameterDirty(unsigned int contextID) const { return _texParametersDirtyList[contextID]; } /** Force a reset on next apply() of associated OpenGL texture * parameters. */ void dirtyTextureParameters(); /** Force a manual allocation of the mipmap levels on the next apply() call. * User is responsible for filling the mipmap levels with valid data. * The OpenGL's glGenerateMipmapEXT function is used to generate the mipmap levels. * If glGenerateMipmapEXT is not supported or texture's internal format is not supported * by the glGenerateMipmapEXT, then empty mipmap levels will * be allocated manually. The mipmap levels are also allocated if a non-mipmapped * min filter is used. */ void allocateMipmapLevels(); /** Sets GL_TEXTURE_COMPARE_MODE_ARB to GL_COMPARE_R_TO_TEXTURE_ARB * See http://oss.sgi.com/projects/ogl-sample/registry/ARB/shadow.txt. */ void setShadowComparison(bool flag) { _use_shadow_comparison = flag; } bool getShadowComparison() const { return _use_shadow_comparison; } enum ShadowCompareFunc { NEVER = GL_NEVER, LESS = GL_LESS, EQUAL = GL_EQUAL, LEQUAL = GL_LEQUAL, GREATER = GL_GREATER, NOTEQUAL = GL_NOTEQUAL, GEQUAL = GL_GEQUAL, ALWAYS = GL_ALWAYS }; /** Sets shadow texture comparison function. */ void setShadowCompareFunc(ShadowCompareFunc func) { _shadow_compare_func = func; } ShadowCompareFunc getShadowCompareFunc() const { return _shadow_compare_func; } enum ShadowTextureMode { LUMINANCE = GL_LUMINANCE, INTENSITY = GL_INTENSITY, ALPHA = GL_ALPHA }; /** Sets shadow texture mode after comparison. */ void setShadowTextureMode(ShadowTextureMode mode) { _shadow_texture_mode = mode; } ShadowTextureMode getShadowTextureMode() const { return _shadow_texture_mode; } /** Sets the TEXTURE_COMPARE_FAIL_VALUE_ARB texture parameter. See * http://oss.sgi.com/projects/ogl-sample/registry/ARB/shadow_ambient.txt. */ void setShadowAmbient(float shadow_ambient) { _shadow_ambient = shadow_ambient; } float getShadowAmbient() const { return _shadow_ambient; } /** Sets the texture image for the specified face. */ virtual void setImage(unsigned int face, Image* image) = 0; /** Gets the texture image for the specified face. */ virtual Image* getImage(unsigned int face) = 0; /** Gets the const texture image for specified face. */ virtual const Image* getImage(unsigned int face) const = 0; /** Gets the number of images that can be assigned to this Texture. */ virtual unsigned int getNumImages() const = 0; /** Set the PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/ void setReadPBuffer(GraphicsContext* context) { _readPBuffer = context; } /** Get the PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/ GraphicsContext* getReadPBuffer() { return _readPBuffer.get(); } /** Get the const PBuffer graphics context to read from when using PBuffers for RenderToTexture.*/ const GraphicsContext* getReadPBuffer() const { return _readPBuffer.get(); } /** Texture is a pure virtual base class, apply must be overridden. */ virtual void apply(State& state) const = 0; /** Calls apply(state) to compile the texture. */ virtual void compileGLObjects(State& state) const; /** Resize any per context GLObject buffers to specified size. */ virtual void resizeGLObjectBuffers(unsigned int maxSize); /** If State is non-zero, this function releases OpenGL objects for * the specified graphics context. Otherwise, releases OpenGL objects * for all graphics contexts. */ virtual void releaseGLObjects(State* state=0) const; /** Encapsulates queries of extension availability, obtains extension * function pointers, and provides convenience wrappers for * calling extension functions. */ class OSG_EXPORT Extensions : public osg::Referenced { public: Extensions(unsigned int contextID); void setMultiTexturingSupported(bool flag) { _isMultiTexturingSupported=flag; } bool isMultiTexturingSupported() const { return _isMultiTexturingSupported; } void setTextureFilterAnisotropicSupported(bool flag) { _isTextureFilterAnisotropicSupported=flag; } bool isTextureFilterAnisotropicSupported() const { return _isTextureFilterAnisotropicSupported; } void setTextureCompressionARBSupported(bool flag) { _isTextureCompressionARBSupported=flag; } bool isTextureCompressionARBSupported() const { return _isTextureCompressionARBSupported; } void setTextureCompressionS3TCSupported(bool flag) { _isTextureCompressionS3TCSupported=flag; } bool isTextureCompressionS3TCSupported() const { return _isTextureCompressionS3TCSupported; } void setTextureCompressionPVRTC2BPPSupported(bool flag) { _isTextureCompressionPVRTC2BPPSupported=flag; } bool isTextureCompressionPVRTC2BPPSupported() const { return _isTextureCompressionPVRTC2BPPSupported; } void setTextureCompressionPVRTC4BPPSupported(bool flag) { _isTextureCompressionPVRTC4BPPSupported=flag; } bool isTextureCompressionPVRTC4BPPSupported() const { return _isTextureCompressionPVRTC4BPPSupported; } void setTextureCompressionETCSupported(bool flag) { _isTextureCompressionETCSupported=flag; } bool isTextureCompressionETCSupported() const { return _isTextureCompressionETCSupported; } void setTextureCompressionRGTCSupported(bool flag) { _isTextureCompressionRGTCSupported=flag; } bool isTextureCompressionRGTCSupported() const { return _isTextureCompressionRGTCSupported; } void setTextureCompressionPVRTCSupported(bool flag) { _isTextureCompressionPVRTCSupported=flag; } bool isTextureCompressionPVRTCSupported() const { return _isTextureCompressionPVRTCSupported; } void setTextureMirroredRepeatSupported(bool flag) { _isTextureMirroredRepeatSupported=flag; } bool isTextureMirroredRepeatSupported() const { return _isTextureMirroredRepeatSupported; } void setTextureEdgeClampSupported(bool flag) { _isTextureEdgeClampSupported=flag; } bool isTextureEdgeClampSupported() const { return _isTextureEdgeClampSupported; } void setTextureBorderClampSupported(bool flag) { _isTextureBorderClampSupported=flag; } bool isTextureBorderClampSupported() const { return _isTextureBorderClampSupported; } void setGenerateMipMapSupported(bool flag) { _isGenerateMipMapSupported=flag; } bool isGenerateMipMapSupported() const { return _isGenerateMipMapSupported; } void setTextureMultisampledSupported(bool flag) { _isTextureMultisampledSupported=flag; } bool isTextureMultisampledSupported() const { return _isTextureMultisampledSupported; } void setShadowSupported(bool flag) { _isShadowSupported = flag; } bool isShadowSupported() const { return _isShadowSupported; } void setShadowAmbientSupported(bool flag) { _isShadowAmbientSupported = flag; } bool isShadowAmbientSupported() const { return _isShadowAmbientSupported; } void setTextureMaxLevelSupported(bool flag) { _isTextureMaxLevelSupported = flag; } bool isTextureMaxLevelSupported() const { return _isTextureMaxLevelSupported; } void setMaxTextureSize(GLint maxsize) { _maxTextureSize=maxsize; } GLint maxTextureSize() const { return _maxTextureSize; } void setNumTextureUnits(GLint nunits ) { _numTextureUnits=nunits; } GLint numTextureUnits() const { return _numTextureUnits; } bool isCompressedTexImage2DSupported() const { return _glCompressedTexImage2D!=0; } bool isCompressedTexSubImage2DSupported() const { return _glCompressedTexSubImage2D!=0; } bool isClientStorageSupported() const { return _isClientStorageSupported; } bool isNonPowerOfTwoTextureSupported(GLenum filter) const { return (filter==GL_LINEAR || filter==GL_NEAREST) ? _isNonPowerOfTwoTextureNonMipMappedSupported : _isNonPowerOfTwoTextureMipMappedSupported; } void setTextureIntegerSupported(bool flag) { _isTextureIntegerEXTSupported=flag; } bool isTextureIntegerSupported() const { return _isTextureIntegerEXTSupported; } void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) const { _glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); } void glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) const { _glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); } void glGetCompressedTexImage(GLenum target, GLint level, GLvoid *data) const { _glGetCompressedTexImage(target, level, data); } void glTexImage2DMultisample(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations) const { _glTexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations); } void glTexParameterIiv(GLenum target, GLenum pname, const GLint* data) const { _glTexParameterIiv(target, pname, data); } void glTexParameterIuiv(GLenum target, GLenum pname, const GLuint* data) const { _glTexParameterIuiv(target, pname, data); } protected: ~Extensions() {} typedef void (GL_APIENTRY * CompressedTexImage2DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data); typedef void (GL_APIENTRY * CompressedTexSubImage2DArbProc) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data); typedef void (GL_APIENTRY * GetCompressedTexImageArbProc) (GLenum target, GLint level, GLvoid *data); typedef void (GL_APIENTRY * TexImage2DMultisample)(GLenum target, GLsizei samples, GLint internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); typedef void (GL_APIENTRY * TexParameterIivProc)(GLenum target, GLenum pname, const GLint* data); typedef void (GL_APIENTRY * TexParameterIuivProc)(GLenum target, GLenum pname, const GLuint* data); CompressedTexImage2DArbProc _glCompressedTexImage2D; CompressedTexSubImage2DArbProc _glCompressedTexSubImage2D; GetCompressedTexImageArbProc _glGetCompressedTexImage; TexImage2DMultisample _glTexImage2DMultisample; TexParameterIivProc _glTexParameterIiv; TexParameterIuivProc _glTexParameterIuiv; bool _isMultiTexturingSupported; bool _isTextureFilterAnisotropicSupported; bool _isTextureCompressionARBSupported; bool _isTextureCompressionS3TCSupported; bool _isTextureCompressionPVRTC2BPPSupported; bool _isTextureCompressionPVRTC4BPPSupported; bool _isTextureCompressionETCSupported; bool _isTextureCompressionRGTCSupported; bool _isTextureCompressionPVRTCSupported; bool _isTextureMirroredRepeatSupported; bool _isTextureEdgeClampSupported; bool _isTextureBorderClampSupported; bool _isGenerateMipMapSupported; bool _isTextureMultisampledSupported; bool _isShadowSupported; bool _isShadowAmbientSupported; bool _isClientStorageSupported; bool _isNonPowerOfTwoTextureMipMappedSupported; bool _isNonPowerOfTwoTextureNonMipMappedSupported; bool _isTextureIntegerEXTSupported; bool _isTextureMaxLevelSupported; GLint _maxTextureSize; GLint _numTextureUnits; }; /** Gets the extension for the specified context. Creates the * Extensions object for that context if it doesn't exist. * Returns NULL if the Extensions object for the context doesn't * exist and the createIfNotInitalized flag is false. */ static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); /** Overrides Extensions objects across graphics contexts. Typically * used to ensure the same lowest common denominator of extensions * on systems with different graphics pipes. */ static void setExtensions(unsigned int contextID,Extensions* extensions); /** Determine whether the given internalFormat is a compressed * image format. */ static bool isCompressedInternalFormat(GLint internalFormat); /** Determine the size of a compressed image, given the internalFormat, * the width, the height, and the depth of the image. The block size * and the size are output parameters. */ static void getCompressedSize(GLenum internalFormat, GLint width, GLint height, GLint depth, GLint& blockSize, GLint& size); /** Helper method. Creates the texture, but doesn't set or use a * texture binding. Note: Don't call this method directly unless * you're implementing a subload callback. */ void applyTexImage2D_load(State& state, GLenum target, const Image* image, GLsizei width, GLsizei height,GLsizei numMipmapLevels) const; /** Helper method. Subloads images into the texture, but doesn't set * or use a texture binding. Note: Don't call this method directly * unless you're implementing a subload callback. */ void applyTexImage2D_subload(State& state, GLenum target, const Image* image, GLsizei width, GLsizei height, GLint inInternalFormat, GLsizei numMipmapLevels) const; /** Returned by mipmapBeforeTexImage() to indicate what * mipmapAfterTexImage() should do */ enum GenerateMipmapMode { GENERATE_MIPMAP_NONE, GENERATE_MIPMAP, GENERATE_MIPMAP_TEX_PARAMETER }; protected : virtual ~Texture(); virtual void computeInternalFormat() const = 0; /** Computes the internal format from Image parameters. */ void computeInternalFormatWithImage(const osg::Image& image) const; /** Computes the texture dimension for the given Image. */ void computeRequiredTextureDimensions(State& state, const osg::Image& image,GLsizei& width, GLsizei& height,GLsizei& numMipmapLevels) const; /** Computes the internal format type. */ void computeInternalFormatType() const; /** Helper method. Sets texture parameters. */ void applyTexParameters(GLenum target, State& state) const; /** Returns true if _useHardwareMipMapGeneration is true and either * glGenerateMipmapEXT() or GL_GENERATE_MIPMAP_SGIS are supported. */ bool isHardwareMipmapGenerationEnabled(const State& state) const; /** Returns true if the associated Image should be released and it's safe to do so. */ bool isSafeToUnrefImageData(const State& state) const { return (_unrefImageDataAfterApply && state.getMaxTexturePoolSize()==0 && areAllTextureObjectsLoaded()); } /** Helper methods to be called before and after calling * gl[Compressed][Copy]Tex[Sub]Image2D to handle generating mipmaps. */ GenerateMipmapMode mipmapBeforeTexImage(const State& state, bool hardwareMipmapOn) const; void mipmapAfterTexImage(State& state, GenerateMipmapMode beforeResult) const; /** Helper method to generate mipmap levels by calling of glGenerateMipmapEXT. * If it is not supported, then call the virtual allocateMipmap() method */ void generateMipmap(State& state) const; /** Allocate mipmap levels of the texture by subsequent calling of glTexImage* function. */ virtual void allocateMipmap(State& state) const = 0; /** Returns -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */ int compareTexture(const Texture& rhs) const; /** Returns -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */ int compareTextureObjects(const Texture& rhs) const; typedef buffered_value TexParameterDirtyList; mutable TexParameterDirtyList _texParametersDirtyList; mutable TexParameterDirtyList _texMipmapGenerationDirtyList; WrapMode _wrap_s; WrapMode _wrap_t; WrapMode _wrap_r; FilterMode _min_filter; FilterMode _mag_filter; float _maxAnisotropy; bool _useHardwareMipMapGeneration; bool _unrefImageDataAfterApply; bool _clientStorageHint; bool _resizeNonPowerOfTwoHint; Vec4d _borderColor; GLint _borderWidth; InternalFormatMode _internalFormatMode; mutable InternalFormatType _internalFormatType; mutable GLint _internalFormat; mutable GLenum _sourceFormat; mutable GLenum _sourceType; bool _use_shadow_comparison; ShadowCompareFunc _shadow_compare_func; ShadowTextureMode _shadow_texture_mode; float _shadow_ambient; public: struct OSG_EXPORT TextureProfile { inline TextureProfile(GLenum target): _target(target), _numMipmapLevels(0), _internalFormat(0), _width(0), _height(0), _depth(0), _border(0), _size(0) {} inline TextureProfile(GLenum target, GLint numMipmapLevels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border): _target(target), _numMipmapLevels(numMipmapLevels), _internalFormat(internalFormat), _width(width), _height(height), _depth(depth), _border(border), _size(0) { computeSize(); } #define LESSTHAN(A,B) if (A > TextureObjectList; class OSG_EXPORT TextureObjectSet : public Referenced { public: TextureObjectSet(TextureObjectManager* parent, const TextureProfile& profile); const TextureProfile& getProfile() const { return _profile; } void handlePendingOrphandedTextureObjects(); void deleteAllTextureObjects(); void discardAllTextureObjects(); void flushAllDeletedTextureObjects(); void discardAllDeletedTextureObjects(); void flushDeletedTextureObjects(double currentTime, double& availableTime); TextureObject* takeFromOrphans(Texture* texture); TextureObject* takeOrGenerate(Texture* texture); void moveToBack(TextureObject* to); void addToBack(TextureObject* to); void orphan(TextureObject* to); void remove(TextureObject* to); void moveToSet(TextureObject* to, TextureObjectSet* set); unsigned int size() const { return _profile._size * _numOfTextureObjects; } bool makeSpace(unsigned int& size); bool checkConsistency() const; TextureObjectManager* getParent() { return _parent; } unsigned int computeNumTextureObjectsInList() const; unsigned int getNumOfTextureObjects() const { return _numOfTextureObjects; } unsigned int getNumOrphans() const { return _orphanedTextureObjects.size(); } unsigned int getNumPendingOrphans() const { return _pendingOrphanedTextureObjects.size(); } protected: virtual ~TextureObjectSet(); OpenThreads::Mutex _mutex; TextureObjectManager* _parent; unsigned int _contextID; TextureProfile _profile; unsigned int _numOfTextureObjects; TextureObjectList _orphanedTextureObjects; TextureObjectList _pendingOrphanedTextureObjects; TextureObject* _head; TextureObject* _tail; }; class OSG_EXPORT TextureObjectManager : public osg::Referenced { public: TextureObjectManager(unsigned int contextID); unsigned int getContextID() const { return _contextID; } void setNumberActiveTextureObjects(unsigned int size) { _numActiveTextureObjects = size; } unsigned int& getNumberActiveTextureObjects() { return _numActiveTextureObjects; } unsigned int getNumberActiveTextureObjects() const { return _numActiveTextureObjects; } void setNumberOrphanedTextureObjects(unsigned int size) { _numOrphanedTextureObjects = size; } unsigned int& getNumberOrphanedTextureObjects() { return _numOrphanedTextureObjects; } unsigned int getNumberOrphanedTextureObjects() const { return _numOrphanedTextureObjects; } void setCurrTexturePoolSize(unsigned int size) { _currTexturePoolSize = size; } unsigned int& getCurrTexturePoolSize() { return _currTexturePoolSize; } unsigned int getCurrTexturePoolSize() const { return _currTexturePoolSize; } void setMaxTexturePoolSize(unsigned int size); unsigned int getMaxTexturePoolSize() const { return _maxTexturePoolSize; } bool hasSpace(unsigned int size) const { return (_currTexturePoolSize+size)<=_maxTexturePoolSize; } bool makeSpace(unsigned int size); TextureObject* generateTextureObject(const Texture* texture, GLenum target); TextureObject* generateTextureObject(const Texture* texture, GLenum target, GLint numMipmapLevels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border); void handlePendingOrphandedTextureObjects(); void deleteAllTextureObjects(); void discardAllTextureObjects(); void flushAllDeletedTextureObjects(); void discardAllDeletedTextureObjects(); void flushDeletedTextureObjects(double currentTime, double& availableTime); void releaseTextureObject(TextureObject* to); TextureObjectSet* getTextureObjectSet(const TextureProfile& profile); void newFrame(osg::FrameStamp* fs); void resetStats(); void reportStats(std::ostream& out); void recomputeStats(std::ostream& out) const; bool checkConsistency() const; unsigned int& getFrameNumber() { return _frameNumber; } unsigned int& getNumberFrames() { return _numFrames; } unsigned int& getNumberDeleted() { return _numDeleted; } double& getDeleteTime() { return _deleteTime; } unsigned int& getNumberGenerated() { return _numGenerated; } double& getGenerateTime() { return _generateTime; } unsigned int& getNumberApplied() { return _numApplied; } double& getApplyTime() { return _applyTime; } protected: typedef std::map< TextureProfile, osg::ref_ptr > TextureSetMap; unsigned int _contextID; unsigned int _numActiveTextureObjects; unsigned int _numOrphanedTextureObjects; unsigned int _currTexturePoolSize; unsigned int _maxTexturePoolSize; TextureSetMap _textureSetMap; unsigned int _frameNumber; unsigned int _numFrames; unsigned int _numDeleted; double _deleteTime; unsigned int _numGenerated; double _generateTime; unsigned int _numApplied; double _applyTime; }; static osg::ref_ptr& getTextureObjectManager(unsigned int contextID); static TextureObject* generateTextureObject(const Texture* texture, unsigned int contextID,GLenum target); static TextureObject* generateTextureObject(const Texture* texture, unsigned int contextID, GLenum target, GLint numMipmapLevels, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border); static void deleteAllTextureObjects(unsigned int contextID); static void discardAllTextureObjects(unsigned int contextID); static void flushAllDeletedTextureObjects(unsigned int contextID); static void discardAllDeletedTextureObjects(unsigned int contextID); static void flushDeletedTextureObjects(unsigned int contextID,double currentTime, double& availableTime); static void releaseTextureObject(unsigned int contextID, TextureObject* to); protected: typedef buffered_object< ref_ptr > TextureObjectBuffer; mutable TextureObjectBuffer _textureObjectBuffer; mutable ref_ptr _readPBuffer; }; } #endif