Threaded Rendering
// threaded rendering with vrui
// sean whalen, 03-2009 (updated 09-2009)
#include <stdlib.h>
#include <vector>
#include <Geometry/Random.h>
#include <GL/GLContextData.h>
#include <GL/GLGeometryWrappers.h>
#include <Threads/Mutex.h>
#include <Threads/Thread.h>
#include <Vrui/Vrui.h>
#include <Vrui/Application.h>
#include <Vrui/Geometry.h>
#define RADIUS 10
#define NUM_POINTS 12
using namespace std;
class ThreadExample : public Vrui::Application, public GLObject
{
private:
struct DataItem : public GLObject::DataItem
{
GLuint displayList;
int displayListVersion;
DataItem()
{
displayList = glGenLists(1);
displayListVersion = 0;
}
~DataItem()
{
glDeleteLists(displayList, 1);
}
};
int displayListVersion;
vector<Vrui::Point> pointsWrite;
vector<Vrui::Point> pointsRead;
Vrui::Point min;
Vrui::Point max;
Threads::Thread layoutThread;
Threads::Mutex mutex;
bool stopped;
public:
ThreadExample(int, char**, char**);
~ThreadExample();
void display(GLContextData&) const;
void frame();
void initContext(GLContextData&) const;
void* threadMethod();
};
ThreadExample::ThreadExample(int argc, char** argv, char** appDefaults)
: Vrui::Application(argc, argv, appDefaults)
{
displayListVersion = 0;
min = Vrui::Point(-RADIUS, -RADIUS, -RADIUS);
max = Vrui::Point(RADIUS, RADIUS, RADIUS);
for(int i = 0; i < NUM_POINTS; i++)
{
Vrui::Point p = Geometry::randPointUniformCO(min, max);
pointsWrite.push_back(p);
}
Vrui::setNavigationTransformation(Vrui::Point(0, 0, 0), 25.0);
stopped = false;
layoutThread.start(this, &ThreadExample::threadMethod);
}
ThreadExample::~ThreadExample()
{
stopped = true;
}
void ThreadExample::initContext(GLContextData& contextData) const
{
DataItem* dataItem = new DataItem;
contextData.addDataItem(this, dataItem);
}
void ThreadExample::display(GLContextData& contextData) const
{
DataItem* dataItem = contextData.retrieveDataItem<DataItem>(this);
glPointSize(3);
if(dataItem->displayListVersion != displayListVersion)
{
glNewList(dataItem->displayList, GL_COMPILE);
glBegin(GL_POINTS);
glColor3f(0, 255, 0);
for(int i = 0; i < NUM_POINTS; i++)
{
glVertex(pointsRead[i]);
}
glEnd();
glEndList();
dataItem->displayListVersion = displayListVersion;
}
glCallList(dataItem->displayList);
}
void ThreadExample::frame()
{
mutex.lock();
pointsRead = pointsWrite;
displayListVersion++;
mutex.unlock();
Vrui::requestUpdate();
}
void* ThreadExample::threadMethod()
{
while(!stopped)
{
mutex.lock();
for(int i = 0; i < NUM_POINTS; i++)
{
pointsWrite[i] = Geometry::randPointUniformCO(min, max);
}
mutex.unlock();
}
return 0;
}
int main(int argc, char** argv)
{
char** appDefaults = 0;
ThreadExample app(argc, argv, appDefaults);
app.run();
return 0;
}