/* osgCompute - Copyright (C) 2008-2009 SVT Group
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* 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
* GNU Lesse General Public License for more details.
*
* The full license is in LICENSE file included with this distribution.
*/

#ifndef OSGCUDA_TEXTURE
#define OSGCUDA_TEXTURE 1

#include <osgCompute/Buffer>
#include <osgCuda/Export>

namespace osg
{
	class Texture;
	class Image;
}

namespace osgCuda
{
#define META_Texture( libraryname, classname )                            \
    META_Buffer( libraryname, classname )                                 \
    virtual osg::Texture* asTexture() { return this; }                    \
    virtual const osg::Texture* asTexture() const { return this; }

    /**
    */
    class LIBRARY_EXPORT TextureStream : public osgCompute::BufferStream
    {
    public:
        void*					 _hostPtr;
        bool                     _hostPtrAllocated;
        bool                     _syncHost;
        void*					 _devPtr;
        bool                     _syncDevice;
        GLuint                   _bo;
        bool                     _boRegistered;
        unsigned int             _modifyCount;

        TextureStream();
        virtual ~TextureStream();

    private:
        // not allowed to call copy-constructor or copy-operator
        TextureStream( const TextureStream& ) {}
        TextureStream& operator=( const TextureStream& ) { return *this; }
    };

    /**
    */
    class LIBRARY_EXPORT Texture : public osgCompute::Buffer
    {
    public:
        Texture();

        virtual bool init();

        virtual osg::Texture* asTexture() = 0;
        virtual const osg::Texture* asTexture() const = 0;

        virtual bool setMemory( const osgCompute::Context& context, int value, unsigned int mapping, unsigned int offset = 0, unsigned int count = UINT_MAX ) const;
        virtual void* map( const osgCompute::Context& context, unsigned int mapping ) const;
        virtual void unmap( const osgCompute::Context& context ) const;

        virtual osg::Image* getImagePtr();
        virtual const osg::Image* getImagePtr() const;

        inline void setIsRenderTarget( bool isRenderTarget );
        inline bool getIsRenderTarget() const;

        virtual void clear();
    protected:
        virtual ~Texture();
        void clearLocal();

        virtual bool initDimension();

        virtual void* mapStream( TextureStream& stream, unsigned int mapping ) const;
        virtual void unmapStream( TextureStream& stream ) const;

        bool setupStream( unsigned int mapping, TextureStream& stream ) const;
        bool allocStream( unsigned int mapping, TextureStream& stream ) const;
        bool syncStream( unsigned int mapping, TextureStream& stream ) const;

        virtual void syncModifiedCounter( const osgCompute::Context& context ) const = 0;
        virtual bool allocPBO( TextureStream& stream ) const = 0;
        virtual void syncPBO( TextureStream& stream ) const = 0;
        virtual void syncTexture( TextureStream& stream ) const = 0;

        virtual void clear( const osgCompute::Context& context ) const;

        bool    _isRenderTarget;

    private:
        // copy constructor and operator should not be called
        Texture( const Texture& , const osg::CopyOp& ) {}
        Texture& operator=(const Texture&) { return (*this); }
    };

	//------------------------------------------------------------------------------
	inline bool Texture::getIsRenderTarget() const
	{
		return _isRenderTarget;
	}

	//------------------------------------------------------------------------------
	inline void Texture::setIsRenderTarget( bool isRenderTarget )
	{
		_isRenderTarget = isRenderTarget;
	}
}


#endif //OSGCUDA_TEXTURE
