Texture2DArray 11.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230
/* -*-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_TEXTURE2DARRAY
#define OSG_TEXTURE2DARRAY 1

#include <osg/Texture>
#include <list>

namespace osg {

/** Texture2DArray state class which encapsulates OpenGL 2D array texture functionality. 
 * Texture arrays were introduced with Shader Model 4.0 hardware.
 * 
 * A 2D texture array does contain textures sharing the same properties (e.g. size, bitdepth,...)
 * in a layered structure. See http://www.opengl.org/registry/specs/EXT/texture_array.txt for more info.
 */
class OSG_EXPORT Texture2DArray : public Texture
{

    public :
        
        Texture2DArray();

        /** Copy constructor using CopyOp to manage deep vs shallow copy. */
        Texture2DArray(const Texture2DArray& cm,const CopyOp& copyop=CopyOp::SHALLOW_COPY);

        META_StateAttribute(osg, Texture2DArray, TEXTURE);
        
        /** Return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs. */
        virtual int compare(const StateAttribute& rhs) const;

        virtual GLenum getTextureTarget() const { return GL_TEXTURE_2D_ARRAY_EXT; }

        /** Set the texture image for specified layer. */
        virtual void setImage(unsigned int layer, Image* image);

        /** Get the texture image for specified layer. */
        virtual Image* getImage(unsigned int layer);

        /** Get the const texture image for specified layer. */
        virtual const Image* getImage(unsigned int layer) const;

        /** Get the number of images that are assigned to the Texture. 
         * The number is equal to the texture depth. To get the maximum possible
         * image/layer count, you have to use the extension subclass, since it provides
         * graphic context dependent information.
         */
        virtual unsigned int getNumImages() const { return getTextureDepth(); } 

        /** Check how often was a certain layer in the given context modified */
        inline unsigned int& getModifiedCount(unsigned int layer, unsigned int contextID) const
        {
            // get the modified count for the current contextID.
            return _modifiedCount[layer][contextID];
        }

        /** Set the texture width and height. If width or height are zero then
          * the respective size value is calculated from the source image sizes.
          * Depth parameter specifies the number of layers to be used.
        */
        void setTextureSize(int width, int height, int depth);

        void setTextureWidth(int width) { _textureWidth=width; }
        void setTextureHeight(int height) { _textureHeight=height; }
        void setTextureDepth(int depth);

        virtual int getTextureWidth() const { return _textureWidth; }
        virtual int getTextureHeight() const { return _textureHeight; }
        virtual int getTextureDepth() const { return _textureDepth; }

        class OSG_EXPORT SubloadCallback : public Referenced
        {
            public:
                virtual void load(const Texture2DArray& texture,State& state) const = 0;
                virtual void subload(const Texture2DArray& texture,State& state) const = 0;
        };
        
        
        void setSubloadCallback(SubloadCallback* cb) { _subloadCallback = cb;; }
        
        SubloadCallback* getSubloadCallback() { return _subloadCallback.get(); }

        const SubloadCallback* getSubloadCallback() const { return _subloadCallback.get(); }
        
        

        /** Set the number of mip map levels the the texture has been created with.
          * Should only be called within an osg::Texture::apply() and custom OpenGL texture load.
        */
        void setNumMipmapLevels(unsigned int num) const { _numMipmapLevels=num; }

        /** Get the number of mip map levels the the texture has been created with. */
        unsigned int getNumMipmapLevels() const { return _numMipmapLevels; }        

        /** Copies a two-dimensional texture subimage, as per
          * glCopyTexSubImage3D. Updates a portion of an existing OpenGL
          * texture object from the current OpenGL background framebuffer
          * contents at position \a x, \a y with width \a width and height
          * \a height. Loads framebuffer data into the texture using offsets
          * \a xoffset and \a yoffset. \a zoffset specifies the layer of the texture 
          * array to which the result is copied. 
          */
        void copyTexSubImage2DArray(State& state, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height );

        /** Bind the texture if already compiled. Otherwise recompile.
        */
        virtual void apply(State& state) const;
        

        /** Extensions class which encapsulates the querying of extensions and
          * associated function pointers, and provides convenience wrappers to 
          * check for the extensions or use the associated functions.
        */
        class OSG_EXPORT Extensions : public osg::Referenced
        {
            public:
                Extensions(unsigned int contextID);

                Extensions(const Extensions& rhs);
                
                void lowestCommonDenominator(const Extensions& rhs);
                
                void setupGLExtensions(unsigned int contextID);

                void setTexture2DArraySupported(bool flag) { _isTexture2DArraySupported=flag; }
                bool isTexture2DArraySupported() const { return _isTexture2DArraySupported; }
                
                void setTexture3DSupported(bool flag) { _isTexture3DSupported=flag; }
                bool isTexture3DSupported() const { return _isTexture3DSupported; }

                void setMaxLayerCount(GLint count) { _maxLayerCount = count; }
                GLint maxLayerCount() const { return _maxLayerCount; }
                
                void setMax2DSize(GLint size) { _max2DSize = size; }
                GLint max2DSize() const { return _max2DSize; }
                
                void glTexImage3D( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) const;

                void glTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) const;
                
                void glCopyTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height ) const;
                
                bool isCompressedTexImage3DSupported() const { return _glCompressedTexImage3D!=0; }
                void glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) const;

                bool isCompressedTexSubImage3DSupported() const { return _glCompressedTexSubImage3D!=0; }
                void glCompressedTexSubImage3D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data ) const;

            protected:

                ~Extensions() {}
                
                bool    _isTexture2DArraySupported;
                bool    _isTexture3DSupported;
                
                GLint   _maxLayerCount;
                GLint   _max2DSize;

                typedef void (GL_APIENTRY * GLTexImage3DProc)      ( GLenum target, GLint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
                typedef void (GL_APIENTRY * GLTexSubImage3DProc)   ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
                typedef void (GL_APIENTRY * CompressedTexImage3DArbProc) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
                typedef void (GL_APIENTRY * CompressedTexSubImage3DArbProc) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
                typedef void (GL_APIENTRY * GLCopyTexSubImageProc) ( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height );

                GLTexImage3DProc                _glTexImage3D;
                GLTexSubImage3DProc             _glTexSubImage3D;
                CompressedTexImage3DArbProc     _glCompressedTexImage3D;
                CompressedTexSubImage3DArbProc  _glCompressedTexSubImage3D;
                GLCopyTexSubImageProc           _glCopyTexSubImage3D;
                
        };
        
        /** Function to call to get the extension of a specified context.
          * If the Extension object for that context has not yet been created
          * and the 'createIfNotInitalized' flag been set to false then returns NULL.
          * If 'createIfNotInitalized' is true then the Extensions object is 
          * automatically created. However, in this case the extension object will
          * only be created with the graphics context associated with ContextID.
        */
        static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized);

        /** The setExtensions method allows users to override the extensions across graphics contexts.
          * Typically used when you have different extensions supported across graphics pipes
          * but need to ensure that they all use the same low common denominator extensions.
        */
        static void setExtensions(unsigned int contextID,Extensions* extensions);


    protected :

        virtual ~Texture2DArray();
        
        bool imagesValid() const;
        
        virtual void computeInternalFormat() const;
        void allocateMipmap(State& state) const;

        void applyTexImage2DArray_subload(State& state, Image* image, GLsizei inwidth, GLsizei inheight, GLsizei indepth, GLint inInternalFormat, GLsizei& numMipmapLevels) const;

        /**
         * Use std::vector to encapsulate referenced pointers to images of different layers.
         * Vectors gives us a random access iterator. The overhead of non-used elements is negligible */
        std::vector<ref_ptr<Image> > _images;

        // subloaded images can have different texture and image sizes.
        mutable GLsizei _textureWidth, _textureHeight, _textureDepth;
        
        // number of mip map levels the the texture has been created with,        
        mutable GLsizei _numMipmapLevels;

        ref_ptr<SubloadCallback> _subloadCallback;

        typedef buffered_value<unsigned int> ImageModifiedCount;
        mutable std::vector<ImageModifiedCount> _modifiedCount;
};

}

#endif