OpenSceneGraph/examples/osgmemorytest/osgmemorytest.cpp

450 lines
15 KiB
C++
Raw Normal View History

/* OpenSceneGraph example, osganimate.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <osg/Notify>
#include <osg/ArgumentParser>
#include <osg/Texture1D>
#include <osg/Texture2D>
#include <osg/Texture3D>
#include <osg/Geometry>
#include <osgViewer/Viewer>
#include <stdio.h>
class MemoryTest : public osg::Referenced
{
public:
};
2008-11-11 20:50:51 +08:00
class GLObject : public osg::Referenced
{
public:
virtual void apply(osg::RenderInfo& renderInfo) = 0;
};
2008-11-11 20:50:51 +08:00
class GLMemoryTest : public MemoryTest
{
public:
2008-11-11 20:50:51 +08:00
virtual GLObject* allocate() = 0;
};
/////////////////////////////////////////////////////////////////////////
//
2008-11-11 20:50:51 +08:00
// Context test
class ContextTest : public MemoryTest
{
public:
2008-11-11 20:50:51 +08:00
ContextTest(int width, int height, bool pbuffer):
_width(width),
2008-11-11 20:50:51 +08:00
_height(height),
_pbuffer(pbuffer) {}
virtual osg::GraphicsContext* allocate()
{
osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
traits->width = _width;
traits->height = _height;
2008-11-11 20:50:51 +08:00
traits->windowDecoration = true;
traits->pbuffer = _pbuffer;
2008-11-11 20:50:51 +08:00
osg::ref_ptr<osg::GraphicsContext> window = osg::GraphicsContext::createGraphicsContext(traits.get());
if (window.valid())
{
2008-11-11 20:50:51 +08:00
if (window->realize())
{
2008-11-11 20:50:51 +08:00
return window.release();
}
else
{
2008-11-11 20:50:51 +08:00
if (_pbuffer) throw "Failed to realize PixelBuffer";
else throw "Failed to realize GraphicsWindow";
}
}
else
{
2008-11-11 20:50:51 +08:00
if (_pbuffer) throw "Failed to create PixelBuffer";
else throw "Failed to create GraphicsWindow";
}
return 0;
}
protected:
int _width;
int _height;
2008-11-11 20:50:51 +08:00
bool _pbuffer;
};
2008-11-11 20:50:51 +08:00
////////////////////////////////////////////////////////////////////////
//
2008-11-11 20:50:51 +08:00
// Wrap StateAttribute
class StateAttributeObject : public GLObject
{
public:
2008-11-11 20:50:51 +08:00
StateAttributeObject(osg::StateAttribute* sa): _attribute(sa) {}
void apply(osg::RenderInfo& renderInfo)
{
_attribute->apply(*renderInfo.getState());
if (renderInfo.getState()->checkGLErrors(_attribute.get()))
{
2008-11-11 20:50:51 +08:00
throw "OpenGL error";
}
}
2008-11-11 20:50:51 +08:00
osg::ref_ptr<osg::StateAttribute> _attribute;
};
/////////////////////////////////////////////////////////////////////////
//
2008-11-11 20:50:51 +08:00
// Texture test
class TextureTest : public GLMemoryTest
{
public:
2008-11-11 20:50:51 +08:00
TextureTest(int width=256, int height=256, int depth=1):
_width(width),
_height(height),
_depth(depth) {}
2008-11-11 20:50:51 +08:00
virtual GLObject* allocate()
{
if (_depth>1)
{
osg::ref_ptr<osg::Image> image = new osg::Image;
image->allocateImage(_width, _height, _depth, GL_RGBA, GL_UNSIGNED_BYTE);
osg::ref_ptr<osg::Texture3D> texture = new osg::Texture3D;
texture->setImage(image.get());
2008-11-11 20:50:51 +08:00
texture->setResizeNonPowerOfTwoHint(false);
2008-11-11 20:50:51 +08:00
return new StateAttributeObject(texture.get());
}
if (_height>1)
{
osg::ref_ptr<osg::Image> image = new osg::Image;
image->allocateImage(_width, _height, 1, GL_RGBA, GL_UNSIGNED_BYTE);
osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
texture->setImage(image.get());
2008-11-11 20:50:51 +08:00
texture->setResizeNonPowerOfTwoHint(false);
2008-11-11 20:50:51 +08:00
return new StateAttributeObject(texture.get());
}
if (_width>1)
{
osg::ref_ptr<osg::Image> image = new osg::Image;
image->allocateImage(_width, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE);
osg::ref_ptr<osg::Texture1D> texture = new osg::Texture1D;
texture->setImage(image.get());
2008-11-11 20:50:51 +08:00
texture->setResizeNonPowerOfTwoHint(false);
2008-11-11 20:50:51 +08:00
return new StateAttributeObject(texture.get());
}
else
{
2008-11-11 20:50:51 +08:00
throw "Invalid texture size of 0,0,0";
}
2008-11-11 20:50:51 +08:00
return 0;
}
protected:
2008-11-11 20:50:51 +08:00
int _width;
int _height;
int _depth;
};
2008-11-11 20:50:51 +08:00
/////////////////////////////////////////////////////////////////////////
//
// FrameBufferObject test
2008-11-11 20:50:51 +08:00
class FboTest : public GLMemoryTest
{
public:
FboTest(int width=1024, int height=1024, int depth=2):
_width(width),
_height(height),
_depth(depth) {}
virtual GLObject* allocate()
{
2008-11-11 20:50:51 +08:00
osg::ref_ptr<osg::FrameBufferObject> fbo = new osg::FrameBufferObject;
if (_depth>=1) fbo->setAttachment(osg::Camera::COLOR_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(_width, _height, GL_RGBA)));
if (_depth>=2) fbo->setAttachment(osg::Camera::DEPTH_BUFFER, osg::FrameBufferAttachment(new osg::RenderBuffer(_width, _height, GL_DEPTH_COMPONENT24)));
return new StateAttributeObject(fbo.get());
}
2008-11-11 20:50:51 +08:00
protected:
int _width;
int _height;
int _depth;
};
////////////////////////////////////////////////////////////////////////
//
// Wrap Drawable
class DrawableObject : public GLObject
{
public:
DrawableObject(osg::Drawable* drawable): _drawable(drawable) {}
void apply(osg::RenderInfo& renderInfo)
{
_drawable->draw(renderInfo);
if (renderInfo.getState()->checkGLErrors("Drawable"))
{
throw "OpenGL error";
}
}
osg::ref_ptr<osg::Drawable> _drawable;
};
/////////////////////////////////////////////////////////////////////////
//
// Geometry test
class GeometryTest : public GLMemoryTest
{
public:
enum GLObjectType
{
VERTEX_ARRAY,
DISPLAY_LIST,
VERTEX_BUFFER_OBJECT
};
GeometryTest(GLObjectType type, int width=64, int height=64):
_glObjectType(type),
_width(width),
_height(height) {}
virtual GLObject* allocate()
{
unsigned int numVertices = _width * _height;
osg::Vec3Array* vertices = new osg::Vec3Array(numVertices);
for(unsigned int j=0; j<_height; ++j)
{
for(unsigned i=0; i<_width; ++i)
{
(*vertices)[i+j*_width].set(float(i),float(j),0.0f);
}
}
unsigned int numIndices = (_width-1) * (_height-1) * 4;
osg::DrawElementsUShort* quads = new osg::DrawElementsUShort(GL_QUADS);
quads->reserve(numIndices);
for(unsigned int j=0; j<_height-1; ++j)
{
for(unsigned i=0; i<_width-1; ++i)
{
quads->push_back(i + j*_width);
quads->push_back(i+1 + j*_width);
quads->push_back(i+1 + (j+1)*_width);
quads->push_back(i + (j+1)*_width);
}
}
osg::Geometry* geometry = new osg::Geometry;
geometry->setVertexArray(vertices);
geometry->addPrimitiveSet(quads);
switch(_glObjectType)
{
case(VERTEX_ARRAY):
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(false);
break;
case(DISPLAY_LIST):
geometry->setUseDisplayList(true);
geometry->setUseVertexBufferObjects(false);
break;
case(VERTEX_BUFFER_OBJECT):
geometry->setUseDisplayList(false);
geometry->setUseVertexBufferObjects(true);
break;
}
return new DrawableObject(geometry);
}
protected:
GLObjectType _glObjectType;
int _width;
int _height;
};
int main( int argc, char **argv )
{
osg::ArgumentParser arguments(&argc,argv);
typedef std::list< osg::ref_ptr<MemoryTest> > Tests;
Tests tests;
int width, height, depth;
2008-11-11 20:50:51 +08:00
while(arguments.read("--pbuffer",width,height)) { tests.push_back(new ContextTest(width, height, true)); }
while(arguments.read("--pbuffer")) { tests.push_back(new ContextTest(512, 512, true)); }
2008-11-11 20:50:51 +08:00
while(arguments.read("--window",width,height)) { tests.push_back(new ContextTest(width, height, false)); }
while(arguments.read("--window")) { tests.push_back(new ContextTest(512,512, false)); }
while(arguments.read("--texture",width,height,depth)) { tests.push_back(new TextureTest(width,height,depth)); }
while(arguments.read("--texture",width,height)) { tests.push_back(new TextureTest(width,height,1)); }
while(arguments.read("--texture",width)) { tests.push_back(new TextureTest(width,1,1)); }
2008-11-11 20:50:51 +08:00
while(arguments.read("--fbo",width,height,depth)) { tests.push_back(new FboTest(width,height,depth)); }
while(arguments.read("--fbo",width,height)) { tests.push_back(new FboTest(width,height,2)); }
while(arguments.read("--fbo")) { tests.push_back(new FboTest(1024,1024,2)); }
while(arguments.read("--geometry",width,height)) { tests.push_back(new GeometryTest(GeometryTest::DISPLAY_LIST,width,height)); }
while(arguments.read("--geometry")) { tests.push_back(new GeometryTest(GeometryTest::DISPLAY_LIST,64,64)); }
while(arguments.read("--geometry-vbo",width,height)) { tests.push_back(new GeometryTest(GeometryTest::VERTEX_BUFFER_OBJECT,width,height)); }
while(arguments.read("--geometry-vbo")) { tests.push_back(new GeometryTest(GeometryTest::VERTEX_BUFFER_OBJECT,64,64)); }
while(arguments.read("--geometry-va",width,height)) { tests.push_back(new GeometryTest(GeometryTest::VERTEX_ARRAY,width,height)); }
while(arguments.read("--geometry-va")) { tests.push_back(new GeometryTest(GeometryTest::VERTEX_ARRAY,64,64)); }
unsigned int sleepTime = 0;
while(arguments.read("--delay",sleepTime)) {}
2008-11-11 20:50:51 +08:00
int maxNumContextIterations = 1;
while(arguments.read("-c",maxNumContextIterations)) {}
int maxNumGLIterations = 1000;
while(arguments.read("-g",maxNumGLIterations)) {}
typedef std::list< osg::ref_ptr<GLMemoryTest> > GLMemoryTests;
typedef std::list< osg::ref_ptr<ContextTest> > ContextTests;
ContextTests contextTests;
GLMemoryTests glMemoryTests;
for(Tests::iterator itr = tests.begin();
itr != tests.end();
++itr)
{
MemoryTest* test = itr->get();
if (dynamic_cast<GLMemoryTest*>(test)!=0)
{
glMemoryTests.push_back(dynamic_cast<GLMemoryTest*>(test));
}
else if (dynamic_cast<ContextTest*>(test)!=0)
{
contextTests.push_back(dynamic_cast<ContextTest*>(test));
}
}
typedef std::list< osg::ref_ptr<osg::GraphicsContext> > Contexts;
2008-11-11 20:50:51 +08:00
typedef std::list< osg::ref_ptr<GLObject> > GLObjects;
Contexts allocatedContexts;
2008-11-11 20:50:51 +08:00
GLObjects glObjects;
2008-11-12 00:21:04 +08:00
osg::Timer_t startTick = osg::Timer::instance()->tick();
int numContextIterations = 0;
2008-11-11 20:50:51 +08:00
int numGLObjectIterations = 0;
int numGLObjectsApplied = 0;
try
{
2008-11-11 20:50:51 +08:00
for(; numGLObjectIterations<maxNumGLIterations; ++numGLObjectIterations)
{
for(GLMemoryTests::iterator itr = glMemoryTests.begin();
itr != glMemoryTests.end();
++itr)
{
osg::ref_ptr<GLObject> glObject = (*itr)->allocate();
if (glObject.valid()) glObjects.push_back(glObject.get());
}
}
for(;numContextIterations<maxNumContextIterations; ++numContextIterations)
{
printf("iteration %i\n",numContextIterations);
for(ContextTests::iterator itr = contextTests.begin();
itr != contextTests.end();
++itr)
{
osg::ref_ptr<osg::GraphicsContext> context = (*itr)->allocate();
if (context.valid())
{
2008-11-11 20:50:51 +08:00
allocatedContexts.push_back(context);
context->makeCurrent();
osg::RenderInfo renderInfo;
renderInfo.setState(context->getState());
2008-11-11 20:50:51 +08:00
for(GLObjects::iterator gitr = glObjects.begin();
gitr != glObjects.end();
++gitr)
{
if (sleepTime>0) OpenThreads::Thread::microSleep( sleepTime );
printf("%i ",numGLObjectsApplied);fflush(stdout);
(*gitr)->apply(renderInfo);
2008-11-11 20:50:51 +08:00
++numGLObjectsApplied;
}
context->releaseContext();
printf("\n\n"); fflush(stdout);
}
}
}
}
catch(const char* errorString)
{
2008-11-12 00:21:04 +08:00
printf("\nException caught, contexts completed = %i, gl objects successfully applied = %i, error = %s\n\n",numContextIterations, numGLObjectsApplied, errorString);
return 1;
}
catch(...)
{
2008-11-12 00:21:04 +08:00
printf("\nException caught, contexts completed = %i, gl objects successfully applied = %i\n\n",numContextIterations, numGLObjectsApplied);
return 1;
}
2008-11-12 00:21:04 +08:00
osg::Timer_t endTick = osg::Timer::instance()->tick();
printf("\nSuccessful completion, contexts created = %i, gl objects applied = %i\n",numContextIterations, numGLObjectsApplied);
printf("Duration = %f seconds.\n\n",osg::Timer::instance()->delta_s(startTick, endTick));
2008-11-12 00:21:04 +08:00
return 0;
}