Added osg::BufferObject and a made a number associated to accomodate this

new class. osg::BufferObject wraps up OpenGL pixel and array buffer objects.
Currently implementation is work in progress.
This commit is contained in:
Robert Osfield
2005-02-09 10:39:45 +00:00
parent 1a9b5ddbbf
commit 117c791a3b
34 changed files with 1017 additions and 253 deletions

371
src/osg/BufferObject.cpp Normal file
View File

@@ -0,0 +1,371 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
*/
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <osg/BufferObject>
#include <osg/Notify>
#include <osg/GLExtensions>
#include <osg/Timer>
#include <osg/Image>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
using namespace osg;
// static cache of deleted display lists which can only
// by completely deleted once the appropriate OpenGL context
// is set. Used osg::BufferObject::deleteDisplayList(..) and flushDeletedBufferObjects(..) below.
typedef std::multimap<unsigned int,GLuint> DisplayListMap;
typedef std::map<unsigned int,DisplayListMap> DeletedBufferObjectCache;
static OpenThreads::Mutex s_mutex_deletedBufferObjectCache;
static DeletedBufferObjectCache s_deletedBufferObjectCache;
void BufferObject::deleteBufferObject(unsigned int contextID,GLuint globj)
{
if (globj!=0)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
// insert the globj into the cache for the appropriate context.
s_deletedBufferObjectCache[contextID].insert(DisplayListMap::value_type(0,globj));
}
}
/** flush all the cached display list which need to be deleted
* in the OpenGL context related to contextID.*/
void BufferObject::flushDeletedBufferObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
{
// if no time available don't try to flush objects.
if (availableTime<=0.0) return;
const osg::Timer& timer = *osg::Timer::instance();
osg::Timer_t start_tick = timer.tick();
double elapsedTime = 0.0;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedBufferObjectCache);
DeletedBufferObjectCache::iterator citr = s_deletedBufferObjectCache.find(contextID);
if (citr!=s_deletedBufferObjectCache.end())
{
const Extensions* extensions = getExtensions(contextID,true);
unsigned int noDeleted = 0;
DisplayListMap& dll = citr->second;
DisplayListMap::iterator ditr=dll.begin();
for(;
ditr!=dll.end() && elapsedTime<availableTime;
++ditr)
{
extensions->glDeleteBuffers(1,&(ditr->second));
elapsedTime = timer.delta_s(start_tick,timer.tick());
++noDeleted;
}
if (ditr!=dll.begin()) dll.erase(dll.begin(),ditr);
if (noDeleted!=0) notify(osg::INFO)<<"Number VBOs deleted = "<<noDeleted<<std::endl;
}
}
availableTime -= elapsedTime;
}
BufferObject::BufferObject():
_target(0),
_usage(0),
_totalSize(0)
{
}
BufferObject::BufferObject(const BufferObject& bo,const CopyOp& copyop):
Object(bo,copyop)
{
}
BufferObject::~BufferObject()
{
releaseBuffer(0);
}
void BufferObject::releaseBuffer(State* state) const
{
if (state)
{
unsigned int contextID = state->getContextID();
if (_bufferObjectList[contextID])
{
deleteBufferObject(contextID,_bufferObjectList[contextID]);
_bufferObjectList[contextID] = 0;
}
}
else
{
for(unsigned int contextID=0;contextID<_bufferObjectList.size();++contextID)
{
if (_bufferObjectList[contextID])
{
deleteBufferObject(contextID,_bufferObjectList[contextID]);
_bufferObjectList[contextID] = 0;
}
}
}
}
//////////////////////////////////////////////////////////////////////////////
//
// Extension support
//
typedef buffered_value< ref_ptr<BufferObject::Extensions> > BufferedExtensions;
static BufferedExtensions s_extensions;
BufferObject::Extensions* BufferObject::getExtensions(unsigned int contextID,bool createIfNotInitalized)
{
if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new BufferObject::Extensions;
return s_extensions[contextID].get();
}
void BufferObject::setExtensions(unsigned int contextID,Extensions* extensions)
{
s_extensions[contextID] = extensions;
}
BufferObject::Extensions::Extensions()
{
setupGLExtenions();
}
BufferObject::Extensions::Extensions(const Extensions& rhs):
Referenced()
{
_glGenBuffers = rhs._glGenBuffers;
_glBindBuffer = rhs._glBindBuffer;
_glBufferData = rhs._glBufferData;
_glBufferSubData = rhs._glBufferSubData;
_glDeleteBuffers = rhs._glDeleteBuffers;
_glIsBuffer = rhs._glIsBuffer;
_glGetBufferSubData = rhs._glGetBufferSubData;
_glMapBuffer = rhs._glMapBuffer;
_glUnmapBuffer = rhs._glUnmapBuffer;
_glGetBufferParameteriv = rhs._glGetBufferParameteriv;
_glGetBufferPointerv = rhs._glGetBufferPointerv;
}
void BufferObject::Extensions::lowestCommonDenominator(const Extensions& rhs)
{
if (!rhs._glGenBuffers) _glGenBuffers = rhs._glGenBuffers;
if (!rhs._glBindBuffer) _glBindBuffer = rhs._glBindBuffer;
if (!rhs._glBufferData) _glBufferData = rhs._glBufferData;
if (!rhs._glBufferSubData) _glBufferSubData = rhs._glBufferSubData;
if (!rhs._glDeleteBuffers) _glDeleteBuffers = rhs._glDeleteBuffers;
if (!rhs._glIsBuffer) _glIsBuffer = rhs._glIsBuffer;
if (!rhs._glGetBufferSubData) _glGetBufferSubData = rhs._glGetBufferSubData;
if (!rhs._glMapBuffer) _glMapBuffer = rhs._glMapBuffer;
if (!rhs._glUnmapBuffer) _glUnmapBuffer = rhs._glUnmapBuffer;
if (!rhs._glGetBufferParameteriv) _glGetBufferParameteriv = rhs._glGetBufferParameteriv;
if (!rhs._glGetBufferParameteriv) _glGetBufferPointerv = rhs._glGetBufferPointerv;
}
void BufferObject::Extensions::setupGLExtenions()
{
_glGenBuffers = ((GenBuffersProc)osg::getGLExtensionFuncPtr("glGenBuffers","glGenBuffersARB"));
_glBindBuffer = ((BindBufferProc)osg::getGLExtensionFuncPtr("glBindBuffer","glBindBufferARB"));
_glBufferData = ((BufferDataProc)osg::getGLExtensionFuncPtr("glBufferData","glBufferDataARB"));
_glBufferSubData = ((BufferSubDataProc)osg::getGLExtensionFuncPtr("glBufferSubData","glBufferSubDataARB"));
_glDeleteBuffers = ((DeleteBuffersProc)osg::getGLExtensionFuncPtr("glDeleteBuffers","glDeleteBuffersARB"));
_glIsBuffer = ((IsBufferProc)osg::getGLExtensionFuncPtr("glIsBuffer","glIsBufferARB"));
_glGetBufferSubData = ((GetBufferSubDataProc)osg::getGLExtensionFuncPtr("glGetBufferSubData","glGetBufferSubDataARB"));
_glMapBuffer = ((MapBufferProc)osg::getGLExtensionFuncPtr("glMapBuffer","glMapBufferARB"));
_glUnmapBuffer = ((UnmapBufferProc)osg::getGLExtensionFuncPtr("glUnmapBuffer","glUnmapBufferARB"));
_glGetBufferParameteriv = ((GetBufferParameterivProc)osg::getGLExtensionFuncPtr("glGetBufferParameteriv","glGetBufferParameterivARB"));
_glGetBufferPointerv = ((GetBufferPointervProc)osg::getGLExtensionFuncPtr("glGetBufferPointerv","glGetBufferPointervARB"));
}
void BufferObject::Extensions::glGenBuffers(GLsizei n, GLuint *buffers) const
{
if (_glGenBuffers) _glGenBuffers(n, buffers);
else notify(WARN)<<"Error: glGenBuffers not supported by OpenGL driver"<<std::endl;
}
void BufferObject::Extensions::glBindBuffer(GLenum target, GLuint buffer) const
{
if (_glBindBuffer) _glBindBuffer(target, buffer);
else notify(WARN)<<"Error: glBindBuffer not supported by OpenGL driver"<<std::endl;
}
void BufferObject::Extensions::glBufferData(GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const
{
if (_glBufferData) _glBufferData(target, size, data, usage);
else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
}
void BufferObject::Extensions::glBufferSubData(GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const
{
if (_glBufferSubData) _glBufferSubData(target, offset, size, data);
else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
}
void BufferObject::Extensions::glDeleteBuffers(GLsizei n, const GLuint *buffers) const
{
if (_glDeleteBuffers) _glDeleteBuffers(n, buffers);
else notify(WARN)<<"Error: glBufferData not supported by OpenGL driver"<<std::endl;
}
GLboolean BufferObject::Extensions::glIsBuffer (GLuint buffer) const
{
if (_glIsBuffer) return _glIsBuffer(buffer);
else
{
notify(WARN)<<"Error: glIsBuffer not supported by OpenGL driver"<<std::endl;
return GL_FALSE;
}
}
void BufferObject::Extensions::glGetBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data) const
{
if (_glGetBufferSubData) _glGetBufferSubData(target,offset,size,data);
else notify(WARN)<<"Error: glGetBufferSubData not supported by OpenGL driver"<<std::endl;
}
GLvoid* BufferObject::Extensions::glMapBuffer (GLenum target, GLenum access) const
{
if (_glMapBuffer) return _glMapBuffer(target,access);
else
{
notify(WARN)<<"Error: glMapBuffer not supported by OpenGL driver"<<std::endl;
return 0;
}
}
GLboolean BufferObject::Extensions::glUnmapBuffer (GLenum target) const
{
if (_glUnmapBuffer) return _glUnmapBuffer(target);
else
{
notify(WARN)<<"Error: glUnmapBuffer not supported by OpenGL driver"<<std::endl;
return GL_FALSE;
}
}
void BufferObject::Extensions::glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) const
{
if (_glGetBufferParameteriv) _glGetBufferParameteriv(target,pname,params);
else notify(WARN)<<"Error: glGetBufferParameteriv not supported by OpenGL driver"<<std::endl;
}
void BufferObject::Extensions::glGetBufferPointerv (GLenum target, GLenum pname, GLvoid* *params) const
{
if (_glGetBufferPointerv) _glGetBufferPointerv(target,pname,params);
else notify(WARN)<<"Error: glGetBufferPointerv not supported by OpenGL driver"<<std::endl;
}
PixelBufferObject::PixelBufferObject(osg::Image* image):
BufferObject()
{
_target = GL_PIXEL_UNPACK_BUFFER_ARB;
_usage = GL_STREAM_DRAW_ARB;
_bufferEntryImagePair.second = image;
}
/** Copy constructor using CopyOp to manage deep vs shallow copy.*/
PixelBufferObject::PixelBufferObject(const PixelBufferObject& buffer,const CopyOp& copyop):
BufferObject(buffer,copyop),
_bufferEntryImagePair(buffer._bufferEntryImagePair)
{
}
PixelBufferObject::~PixelBufferObject()
{
}
void PixelBufferObject::setImage(osg::Image* image)
{
_bufferEntryImagePair.second = image;
}
bool PixelBufferObject::needsCompile(unsigned int contextID) const
{
if (!_bufferEntryImagePair.second)
return false;
if (_bufferEntryImagePair.first.modifiedCount[contextID]!=_bufferEntryImagePair.second->getModifiedCount())
return true;
if (_bufferObjectList[contextID]==0) return true;
return false;
}
void PixelBufferObject::compileBuffer(State& state) const
{
unsigned int contextID = state.getContextID();
if (!needsCompile(contextID)) return;
Extensions* extensions = getExtensions(contextID,true);
osg::Image* image = _bufferEntryImagePair.second;
GLuint& pbo = buffer(contextID);
if (pbo==0)
{
// building for the first time.
extensions->glGenBuffers(1, &pbo);
extensions->glBindBuffer(_target, pbo);
_totalSize = image->getTotalSizeInBytes();
extensions->glBufferData(_target, _totalSize, NULL,
_usage);
}
else
{
extensions->glBindBuffer(_target, pbo);
if (_totalSize != image->getTotalSizeInBytes())
{
_totalSize = image->getTotalSizeInBytes();
extensions->glBufferData(_target, _totalSize, NULL,
_usage);
}
}
// osg::Timer_t start_tick = osg::Timer::instance()->tick();
void* pboMemory = extensions->glMapBuffer(_target,
GL_WRITE_ONLY_ARB);
memcpy(pboMemory, image->data(), _totalSize);
// Unmap the texture image buffer
extensions->glUnmapBuffer(_target);
extensions->glBindBuffer(_target, 0);
_bufferEntryImagePair.first.modifiedCount[contextID] = image->getModifiedCount();
// osg::notify(osg::NOTICE)<<"pbo _totalSize="<<_totalSize<<std::endl;
// osg::notify(osg::NOTICE)<<"pbo "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
}

View File

@@ -497,7 +497,7 @@ void Drawable::setUpdateCallback(UpdateCallback* ac)
}
}
struct ComputeBound : public Drawable::PrimitiveFunctor
struct ComputeBound : public PrimitiveFunctor
{
ComputeBound():_vertices(0) {}

View File

@@ -11,6 +11,7 @@ CXXFILES =\
Billboard.cpp\
BoundingBox.cpp\
BoundingSphere.cpp\
BufferObject.cpp\
BlendColor.cpp\
BlendFunc.cpp\
BlendEquation.cpp\

View File

@@ -41,7 +41,7 @@ Image::Image()
_allocationMode = USE_NEW_DELETE;
_data = (unsigned char *)0L;
_modifiedTag = 0;
_modifiedCount = 0;
}
Image::Image(const Image& image,const CopyOp& copyop):
@@ -53,7 +53,7 @@ Image::Image(const Image& image,const CopyOp& copyop):
_dataType(image._dataType),
_packing(image._packing),
_data(0L),
_modifiedTag(image._modifiedTag),
_modifiedCount(image._modifiedCount),
_mipmapData(image._mipmapData)
{
if (image._data)
@@ -91,7 +91,7 @@ int Image::compare(const Image& rhs) const
COMPARE_StateAttribute_Parameter(_pixelFormat)
COMPARE_StateAttribute_Parameter(_dataType)
COMPARE_StateAttribute_Parameter(_packing)
COMPARE_StateAttribute_Parameter(_modifiedTag)
COMPARE_StateAttribute_Parameter(_modifiedCount)
if (_data<rhs._data) return -1;
if (_data>rhs._data) return 1;
@@ -379,7 +379,7 @@ void Image::allocateImage(int s,int t,int r,
_internalTextureFormat = 0;
}
++_modifiedTag;
++_modifiedCount;
}
void Image::setImage(int s,int t,int r,
@@ -403,7 +403,7 @@ void Image::setImage(int s,int t,int r,
_packing = packing;
++_modifiedTag;
++_modifiedCount;
}
@@ -523,7 +523,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
extensions->glGetCompressedTexImage(textureMode, i, getMipmapData(i));
}
++_modifiedTag;
++_modifiedCount;
}
else
@@ -576,7 +576,7 @@ void Image::readImageFromCurrentTexture(unsigned int contextID, bool copyMipMaps
glGetTexImage(textureMode,i,_pixelFormat,_dataType,getMipmapData(i));
}
++_modifiedTag;
++_modifiedCount;
}
}
@@ -639,7 +639,7 @@ void Image::scaleImage(int s,int t,int r, GLenum newDataType)
notify(WARN) << "Error Image::scaleImage() did not succeed : errorString = "<<gluErrorString((GLenum)status)<<std::endl;
}
++_modifiedTag;
++_modifiedCount;
}
void Image::copySubImage(int s_offset,int t_offset,int r_offset,osg::Image* source)
@@ -729,7 +729,7 @@ void Image::flipHorizontal()
}
}
++_modifiedTag;
++_modifiedCount;
}
void flipImageVertical(unsigned char* top, unsigned char* bottom, unsigned int rowSize)
@@ -813,7 +813,7 @@ void Image::flipVertical()
}
}
++_modifiedTag;
++_modifiedCount;
}

View File

@@ -20,6 +20,9 @@ ImageStream::ImageStream():
_loopingMode(LOOPING)
{
setDataVariance(DYNAMIC);
#if 1
setPixelBufferObject(new PixelBufferObject(this));
#endif
}
ImageStream::ImageStream(const ImageStream& image,const CopyOp& copyop):

View File

@@ -11,6 +11,7 @@
* OpenSceneGraph Public License for more details.
*/
#include <osg/PrimitiveSet>
#include <osg/BufferObject>
using namespace osg;
@@ -19,12 +20,12 @@ void DrawArrays::draw(State&, bool) const
glDrawArrays(_mode,_first,_count);
}
void DrawArrays::accept(Drawable::PrimitiveFunctor& functor) const
void DrawArrays::accept(PrimitiveFunctor& functor) const
{
functor.drawArrays(_mode,_first,_count);
}
void DrawArrays::accept(Drawable::PrimitiveIndexFunctor& functor) const
void DrawArrays::accept(PrimitiveIndexFunctor& functor) const
{
functor.drawArrays(_mode,_first,_count);
}
@@ -41,7 +42,7 @@ void DrawArrayLengths::draw(State&, bool) const
}
}
void DrawArrayLengths::accept(Drawable::PrimitiveFunctor& functor) const
void DrawArrayLengths::accept(PrimitiveFunctor& functor) const
{
GLint first = _first;
for(VectorSizei::const_iterator itr=begin();
@@ -53,7 +54,7 @@ void DrawArrayLengths::accept(Drawable::PrimitiveFunctor& functor) const
}
}
void DrawArrayLengths::accept(Drawable::PrimitiveIndexFunctor& functor) const
void DrawArrayLengths::accept(PrimitiveIndexFunctor& functor) const
{
GLint first = _first;
for(VectorSizei::const_iterator itr=begin();
@@ -83,7 +84,7 @@ DrawElementsUByte::~DrawElementsUByte()
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
BufferObject::deleteBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
@@ -93,7 +94,7 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true);
const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true);
GLuint& buffer = _vboList[state.getContextID()];
if (!buffer)
@@ -116,12 +117,12 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const
}
}
void DrawElementsUByte::accept(Drawable::PrimitiveFunctor& functor) const
void DrawElementsUByte::accept(PrimitiveFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUByte::accept(Drawable::PrimitiveIndexFunctor& functor) const
void DrawElementsUByte::accept(PrimitiveIndexFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
@@ -143,7 +144,7 @@ DrawElementsUShort::~DrawElementsUShort()
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
BufferObject::deleteBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
@@ -153,7 +154,7 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true);
const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true);
GLuint& buffer = _vboList[state.getContextID()];
if (!buffer)
@@ -167,8 +168,8 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer);
}
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, 0);
extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, 0);
}
else
{
@@ -176,12 +177,12 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const
}
}
void DrawElementsUShort::accept(Drawable::PrimitiveFunctor& functor) const
void DrawElementsUShort::accept(PrimitiveFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUShort::accept(Drawable::PrimitiveIndexFunctor& functor) const
void DrawElementsUShort::accept(PrimitiveIndexFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
@@ -203,7 +204,7 @@ DrawElementsUInt::~DrawElementsUInt()
{
if (_vboList[i] != 0)
{
Drawable::deleteVertexBufferObject(i,_vboList[i]);
BufferObject::deleteBufferObject(i,_vboList[i]);
_vboList[i] = 0;
}
}
@@ -213,7 +214,7 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
{
if (useVertexBufferObjects)
{
const Drawable::Extensions* extensions = Drawable::getExtensions(state.getContextID(), true);
const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true);
GLuint& buffer = _vboList[state.getContextID()];
if (!buffer)
@@ -236,12 +237,12 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const
}
}
void DrawElementsUInt::accept(Drawable::PrimitiveFunctor& functor) const
void DrawElementsUInt::accept(PrimitiveFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}
void DrawElementsUInt::accept(Drawable::PrimitiveIndexFunctor& functor) const
void DrawElementsUInt::accept(PrimitiveIndexFunctor& functor) const
{
if (!empty()) functor.drawElements(_mode,size(),&front());
}

View File

@@ -1303,7 +1303,7 @@ class PrimitiveShapeVisitor : public ConstShapeVisitor
{
public:
PrimitiveShapeVisitor(Drawable::PrimitiveFunctor& functor,const TessellationHints* hints):
PrimitiveShapeVisitor(PrimitiveFunctor& functor,const TessellationHints* hints):
_functor(functor),
_hints(hints) {}
@@ -1320,7 +1320,7 @@ class PrimitiveShapeVisitor : public ConstShapeVisitor
virtual void apply(const CompositeShape&);
Drawable::PrimitiveFunctor& _functor;
PrimitiveFunctor& _functor;
const TessellationHints* _hints;
};

View File

@@ -1026,6 +1026,23 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
}
bool useHardwareMipMapGeneration = !image->isMipmap() && _useHardwareMipMapGeneration && generateMipMapSupported;
unsigned int dataMinusOffset=0;
unsigned int dataPlusOffset=0;
const PixelBufferObject* pbo = image->getPixelBufferObject();
if (pbo && pbo->isBufferObjectSupported(contextID) && !needImageRescale)
{
pbo->compileBuffer(state);
pbo->bindBuffer(contextID);
dataMinusOffset = (unsigned int) data;
dataPlusOffset=pbo->offset(); // -dataMinusOffset+dataPlusOffset
}
else
{
pbo = 0;
}
if( _min_filter == LINEAR || _min_filter == NEAREST || useHardwareMipMapGeneration)
{
@@ -1045,7 +1062,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
inwidth, inheight,
(GLenum)image->getPixelFormat(),
(GLenum)image->getDataType(),
data );
data - dataMinusOffset+dataPlusOffset);
}
else if (extensions->isCompressedTexImage2DSupported())
@@ -1058,7 +1075,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
inwidth, inheight,
(GLenum)image->getPixelFormat(),
size,
data );
data + -dataMinusOffset+dataPlusOffset );
}
if (hardwareMipMapOn) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS,GL_FALSE);
@@ -1087,7 +1104,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
width, height,
(GLenum)image->getPixelFormat(),
(GLenum)image->getDataType(),
image->getMipmapData(k));
image->getMipmapData(k) -dataMinusOffset+dataPlusOffset);
width >>= 1;
height >>= 1;
@@ -1112,7 +1129,7 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
width, height,
(GLenum)image->getPixelFormat(),
size,
image->getMipmapData(k));
image->getMipmapData(k) -dataMinusOffset+dataPlusOffset);
//state.checkGLErrors("after extensions->glCompressedTexSubImage2D(");
@@ -1196,6 +1213,11 @@ void Texture::applyTexImage2D_subload(State& state, GLenum target, const Image*
}
}
if (pbo)
{
pbo->unbindBuffer(contextID);
}
if (needImageRescale)
{
// clean up the resized image.

View File

@@ -80,7 +80,7 @@ void Texture1D::setImage(Image* image)
dirtyTextureObject();
_image = image;
_modifiedTag.setAllElementsTo(0);
_modifiedCount.setAllElementsTo(0);
}
@@ -105,12 +105,12 @@ void Texture1D::apply(State& state) const
{
_subloadCallback->subload(*this,state);
}
else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag())
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage1D(GL_TEXTURE_1D,_image.get(),state, _textureWidth, _numMipmapLevels);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
}
}
@@ -149,8 +149,8 @@ void Texture1D::apply(State& state) const
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,1,1,0);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded() && _image->getDataVariance()==STATIC)
{

View File

@@ -92,7 +92,7 @@ int Texture2D::compare(const StateAttribute& sa) const
void Texture2D::setImage(Image* image)
{
_image = image;
_modifiedTag.setAllElementsTo(0);
_modifiedCount.setAllElementsTo(0);
}
@@ -119,13 +119,13 @@ void Texture2D::apply(State& state) const
{
_subloadCallback->subload(*this,state);
}
else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag())
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage2D_subload(state,GL_TEXTURE_2D,_image.get(),
_textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
getModifiedCount(contextID) = _image->getModifiedCount();
}
@@ -184,7 +184,7 @@ void Texture2D::apply(State& state) const
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
getModifiedCount(contextID) = _image->getModifiedCount();
if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded() && _image->getDataVariance()==STATIC)

View File

@@ -88,7 +88,7 @@ void Texture3D::setImage(Image* image)
// delete old texture objects.
dirtyTextureObject();
_modifiedTag.setAllElementsTo(0);
_modifiedCount.setAllElementsTo(0);
_image = image;
}
@@ -170,12 +170,12 @@ void Texture3D::apply(State& state) const
{
_subloadCallback->subload(*this,state);
}
else if (_image.get() && getModifiedTag(contextID) != _image->getModifiedTag())
else if (_image.get() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage3D(GL_TEXTURE_3D,_image.get(),state, _textureWidth, _textureHeight, _textureDepth,_numMipmapLevels);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
}
}
@@ -219,8 +219,8 @@ void Texture3D::apply(State& state) const
textureObject->setAllocated(_numMipmapLevels,_internalFormat,_textureWidth,_textureHeight,_textureDepth,0);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
if (_unrefImageDataAfterApply && areAllTextureObjectsLoaded() && _image->getDataVariance()==STATIC)
{

View File

@@ -108,12 +108,12 @@ TextureCubeMap::TextureCubeMap(const TextureCubeMap& text,const CopyOp& copyop):
_images[4] = copyop(text._images[4].get());
_images[5] = copyop(text._images[5].get());
_modifiedTag[0].setAllElementsTo(0);
_modifiedTag[1].setAllElementsTo(0);
_modifiedTag[2].setAllElementsTo(0);
_modifiedTag[3].setAllElementsTo(0);
_modifiedTag[4].setAllElementsTo(0);
_modifiedTag[5].setAllElementsTo(0);
_modifiedCount[0].setAllElementsTo(0);
_modifiedCount[1].setAllElementsTo(0);
_modifiedCount[2].setAllElementsTo(0);
_modifiedCount[3].setAllElementsTo(0);
_modifiedCount[4].setAllElementsTo(0);
_modifiedCount[5].setAllElementsTo(0);
}
@@ -167,7 +167,7 @@ int TextureCubeMap::compare(const StateAttribute& sa) const
void TextureCubeMap::setImage( unsigned int face, Image* image)
{
_images[face] = image;
_modifiedTag[face].setAllElementsTo(0);
_modifiedCount[face].setAllElementsTo(0);
}
Image* TextureCubeMap::getImage(unsigned int face)
@@ -223,10 +223,10 @@ void TextureCubeMap::apply(State& state) const
for (int n=0; n<6; n++)
{
const osg::Image* image = _images[n].get();
if (image && getModifiedTag((Face)n,contextID) != image->getModifiedTag())
if (image && getModifiedCount((Face)n,contextID) != image->getModifiedCount())
{
applyTexImage2D_subload( state, faceTarget[n], _images[n].get(), _textureWidth, _textureHeight, _internalFormat, _numMipmapLevels);
getModifiedTag((Face)n,contextID) = image->getModifiedTag();
getModifiedCount((Face)n,contextID) = image->getModifiedCount();
}
}
}
@@ -278,7 +278,7 @@ void TextureCubeMap::apply(State& state) const
{
applyTexImage2D_load( state, faceTarget[n], image, _textureWidth, _textureHeight, _numMipmapLevels);
}
getModifiedTag((Face)n,contextID) = image->getModifiedTag();
getModifiedCount((Face)n,contextID) = image->getModifiedCount();
}

View File

@@ -17,6 +17,8 @@
#include <osg/GLU>
#include <osg/Notify>
#include <osg/Timer>
#ifndef GL_UNPACK_CLIENT_STORAGE_APPLE
#define GL_UNPACK_CLIENT_STORAGE_APPLE 0x85B2
#endif
@@ -143,12 +145,12 @@ void TextureRectangle::apply(State& state) const
{
_subloadCallback->subload(*this, state);
}
else if (_image.valid() && getModifiedTag(contextID) != _image->getModifiedTag())
else if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount())
{
applyTexImage_subload(GL_TEXTURE_RECTANGLE, _image.get(), state, _textureWidth, _textureHeight, _internalFormat);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = _image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = _image->getModifiedCount();
}
}
else if (_subloadCallback.valid())
@@ -221,8 +223,8 @@ void TextureRectangle::applyTexImage_load(GLenum target, Image* image, State& st
const unsigned int contextID = state.getContextID();
const Extensions* extensions = getExtensions(contextID,true);
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = image->getModifiedCount();
// compute the internal texture format, sets _internalFormat.
computeInternalFormat();
@@ -240,13 +242,35 @@ void TextureRectangle::applyTexImage_load(GLenum target, Image* image, State& st
#endif
}
unsigned int dataMinusOffset=0;
unsigned int dataPlusOffset=0;
const PixelBufferObject* pbo = image->getPixelBufferObject();
if (pbo && pbo->isBufferObjectSupported(contextID))
{
pbo->compileBuffer(state);
pbo->bindBuffer(contextID);
dataMinusOffset=(unsigned int)image->data();
dataPlusOffset=pbo->offset(); // -dataMinusOffset+dataPlusOffset
}
else
{
pbo = 0;
}
// UH: ignoring compressed for now.
glTexImage2D(target, 0, _internalFormat,
image->s(), image->t(), 0,
(GLenum)image->getPixelFormat(),
(GLenum)image->getDataType(),
image->data());
image->data() + -dataMinusOffset+dataPlusOffset);
if (pbo)
{
pbo->unbindBuffer(contextID);
}
inwidth = image->s();
inheight = image->t();
@@ -273,21 +297,56 @@ void TextureRectangle::applyTexImage_subload(GLenum target, Image* image, State&
// current OpenGL context.
const unsigned int contextID = state.getContextID();
// update the modified tag to show that it is upto date.
getModifiedTag(contextID) = image->getModifiedTag();
// update the modified count to show that it is upto date.
getModifiedCount(contextID) = image->getModifiedCount();
// compute the internal texture format, sets _internalFormat.
computeInternalFormat();
glPixelStorei(GL_UNPACK_ALIGNMENT, image->getPacking());
#define DO_TIMING
#ifdef DO_TIMING
osg::Timer_t start_tick = osg::Timer::instance()->tick();
osg::notify(osg::NOTICE)<<"glTexSubImage2D pixelFormat = "<<std::hex<<image->getPixelFormat()<<std::dec<<std::endl;
#endif
unsigned int dataMinusOffset=0;
unsigned int dataPlusOffset=0;
const PixelBufferObject* pbo = image->getPixelBufferObject();
if (pbo && pbo->isBufferObjectSupported(contextID))
{
pbo->compileBuffer(state);
pbo->bindBuffer(contextID);
dataMinusOffset=(unsigned int)image->data();
dataPlusOffset=pbo->offset(); // -dataMinusOffset+dataPlusOffset
#ifdef DO_TIMING
osg::notify(osg::NOTICE)<<"after PBO "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
#endif
}
else
{
pbo = 0;
}
// UH: ignoring compressed for now.
glTexSubImage2D(target, 0,
0,0,
image->s(), image->t(),
(GLenum)image->getPixelFormat(),
(GLenum)image->getDataType(),
image->data());
image->data() + -dataMinusOffset+dataPlusOffset);
if (pbo)
{
pbo->unbindBuffer(contextID);
}
#ifdef DO_TIMING
osg::notify(osg::NOTICE)<<"glTexSubImage2D "<<osg::Timer::instance()->delta_m(start_tick,osg::Timer::instance()->tick())<<"ms"<<std::endl;
#endif
}

View File

@@ -111,14 +111,14 @@ Node* osgDB::readNodeFiles(std::vector<std::string>& commandLine,const ReaderWri
Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments,const ReaderWriter::Options* options)
{
typedef std::vector<osg::Node*> NodeList;
typedef std::vector< osg::ref_ptr<osg::Node> > NodeList;
NodeList nodeList;
std::string filename;
while (arguments.read("--image",filename))
{
osg::Image* image = readImageFile(filename.c_str(), options);
if (image) nodeList.push_back(osg::createGeodeForImage(image));
osg::ref_ptr<osg::Image> image = readImageFile(filename.c_str(), options);
if (image.valid()) nodeList.push_back(osg::createGeodeForImage(image.get()));
}
while (arguments.read("--dem",filename))
@@ -156,7 +156,7 @@ Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments,const ReaderWriter::Op
if (nodeList.size()==1)
{
return nodeList.front();
return nodeList.front().release();
}
else // size >1
{
@@ -165,7 +165,7 @@ Node* osgDB::readNodeFiles(osg::ArgumentParser& arguments,const ReaderWriter::Op
itr!=nodeList.end();
++itr)
{
group->addChild(*itr);
group->addChild((*itr).get());
}
return group;

View File

@@ -51,7 +51,7 @@ void Image::write(DataOutputStream* out)
out->writeInt(getPacking());
// Write modified tag.
out->writeInt(getModifiedTag());
out->writeInt(getModifiedCount());
// Write mipmapdata vector
int size = _mipmapData.size();
@@ -103,7 +103,7 @@ void Image::read(DataInputStream* in)
unsigned int packing = (unsigned int)in->readInt();
// Read modified tag.
setModifiedTag((unsigned int)in->readInt());
setModifiedCount((unsigned int)in->readInt());
// Read mipmapdata vector
int size = in->readInt();

View File

@@ -164,13 +164,13 @@ void MpegImageStream::load(const char* fileName)
// Allocate image data
// maybe use BGR888 and save some conversion somewhere?
unsigned char* data = new unsigned char [s * t * 3];
_videoWriteData = new unsigned char [s * t * 3];
// maybe use BGRA888 and save some conversion somewhere?
unsigned char* data = new unsigned char [s * t * 4];
_videoWriteData = new unsigned char [s * t * 4];
setImage(s, t, 0,
setImage(s, t, 1,
GL_RGB,
GL_RGB, GL_UNSIGNED_BYTE, data,
GL_BGRA, GL_UNSIGNED_BYTE, data,
osg::Image::USE_NEW_DELETE);
@@ -196,7 +196,7 @@ void MpegImageStream::swapData()
for (int i = 0; i < t(); i++)
{
_rows[t()-i-1] = dp;
dp += (s() * 3);
dp += (s() * 4);
}
}
@@ -279,7 +279,7 @@ void MpegImageStream::run()
mpeg3_read_frame(mpg, _rows,
0, 0, _s, _t,
_s, _t,
MPEG3_RGB888, str);
MPEG3_RGBA8888, str);
swapData();

View File

@@ -1,7 +1,7 @@
// (C) Robert Osfield, Feb 2004.
// GPL'd.
#include <osg/Image>
#include <osg/ImageStream>
#include <osg/Notify>
#include <osg/Geode>
#include <osg/GL>
@@ -23,8 +23,9 @@ static void my_render_frame(uint32_t width, uint32_t height, void* data, void* u
{
osg::Image* imageStream = (osg::Image*) userData;
GLenum pixelFormat = GL_BGR;
GLenum pixelFormat = GL_BGRA;
#if 0
if (!ready)
{
imageStream->allocateImage(width,height,1,pixelFormat,GL_UNSIGNED_BYTE,1);
@@ -39,14 +40,14 @@ static void my_render_frame(uint32_t width, uint32_t height, void* data, void* u
imageStream->dirty();
/*
#else
imageStream->setImage(width,height,1,
GL_RGB,
pixelFormat,GL_UNSIGNED_BYTE,
(unsigned char *)data,
osg::Image::NO_DELETE,
1);
*/
#endif
ready = 1;
}
@@ -99,12 +100,12 @@ class ReaderWriterXine : public osgDB::ReaderWriter
osg::notify(osg::NOTICE)<<"ReaderWriterXine::readImage "<< file<< std::endl;
//XineImageStream* imageStream = new XineImageStream(file.c_str());
osg::Image* imageStream = new osg::Image;
osg::Image* imageStream = new osg::ImageStream;
// create visual
rgbout_visual_info_t* visual = new rgbout_visual_info_t;
visual->levels = PXLEVEL_ALL;
visual->format = PX_BGR24;
visual->format = PX_RGB32;
visual->user_data = imageStream;
visual->callback = my_render_frame;

View File

@@ -866,7 +866,7 @@ void Text::accept(osg::Drawable::ConstAttributeFunctor& af) const
}
}
void Text::accept(osg::Drawable::PrimitiveFunctor& pf) const
void Text::accept(osg::PrimitiveFunctor& pf) const
{
for(TextureGlyphQuadMap::const_iterator titr=_textureGlyphQuadMap.begin();
titr!=_textureGlyphQuadMap.end();