/* 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_BUFFER
#define OSGCUDA_BUFFER 1


#include <osg/Image>
#include <osg/Array>
#include <osgCompute/Buffer>
#include <osgCuda/Export>

namespace osgCuda
{
    /**
    */
    class BufferStream : public osgCompute::BufferStream
    {
    public:
        void*							_devPtr;
        bool                            _devPtrAllocated;
        bool                            _syncDevice;
        void*							_hostPtr;
        bool                            _hostPtrAllocated;
        bool                            _syncHost;
        unsigned int                    _modifyCount;

        BufferStream();
        virtual ~BufferStream();

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

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

        META_Object(osgCuda,Buffer)

        virtual bool init();
        virtual void clear();

        virtual void* map( unsigned int mapping = osgCompute::MAP_DEVICE, unsigned int offset = 0, unsigned int hint = 0 );
        virtual void unmap( unsigned int hint = 0 );
        virtual bool setMemory( int value, unsigned int mapping = osgCompute::MAP_DEVICE, unsigned int offset = 0, unsigned int count = UINT_MAX, unsigned int hint = 0 );
        virtual bool resetMemory( unsigned int hint = 0 );

        virtual void setImage( osg::Image* image );
        virtual osg::Image* getImage();
        virtual const osg::Image* getImage() const;

        virtual void setArray( osg::Array* array );
        virtual osg::Array* getArray();
        virtual const osg::Array* getArray() const;

    protected:
        virtual ~Buffer() { clearLocal(); }
        void clearLocal();

        virtual void* mapStream( BufferStream& stream, unsigned int mapping, unsigned int offset );
        virtual void unmapStream( BufferStream& stream );
        bool setupStream( unsigned int mapping, BufferStream& stream );
        bool allocStream( unsigned int mapping, BufferStream& stream );
        bool syncStream( unsigned int mapping, BufferStream& stream );
        virtual osgCompute::BufferStream* newStream() const;
        void resetModifiedCounts() const;

    protected:
        mutable osg::ref_ptr<osg::Array>     _array;
        mutable osg::ref_ptr<osg::Image>     _image;

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

#endif //OSGCUDA_BUFFER
