diff --git a/modules/gfx/src/offscreen_buffer.cc b/modules/gfx/src/offscreen_buffer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..278c77bb1fe85f7595716ecacd0d926064e8cdb0
--- /dev/null
+++ b/modules/gfx/src/offscreen_buffer.cc
@@ -0,0 +1,400 @@
+//------------------------------------------------------------------------------
+// This file is part of the OpenStructure project <www.openstructure.org>
+//
+// Copyright (C) 2008-2010 by the OpenStructure authors
+//
+// 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.0 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 Lesser General Public License for more
+// details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with this library; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+//------------------------------------------------------------------------------
+/*
+  Authors: Ansgar Philippsen, Marco Biasini
+*/
+
+#include <ost/log.hh>
+
+#include <ost/gfx/glext_include.hh>
+
+#include "offscreen_buffer.hh"
+
+#include <ost/gfx/scene.hh>
+
+namespace ost { namespace gfx {
+
+OffscreenBuffer& OffscreenBuffer::Instance()
+{
+  static OffscreenBuffer instance(500,500,8,8,8,8,24);
+  return instance;
+}
+
+bool OffscreenBuffer::Begin() 
+{
+  LOGN_DEBUG("switching to offscreen rendering");
+
+  if(active_) return true;
+  
+  glGetIntegerv(GL_VIEWPORT,old_vp_);
+#if defined(__linux__)
+
+  old_context_ = glXGetCurrentContext();
+
+  if(context_ != old_context_) {
+    old_dr1_ = glXGetCurrentDrawable();
+    old_dr2_ = glXGetCurrentReadDrawable();
+    
+    if(!glXMakeContextCurrent(dpy_, pbuffer_, pbuffer_, context_)) {
+      LOGN_ERROR("error switching to offscreen rendering context: glXMakeContextCurrent failed");
+      return false;
+    }
+  }
+#elif defined(__APPLE__)
+
+  old_context_=CGLGetCurrentContext();
+
+  if(context_ != old_context_) {
+    if (CGLError err=CGLSetCurrentContext(context_)) {
+      LOGN_ERROR("error switching to offscreen rendering context. "
+                 "CGLSetCurrentContext failed: " << CGLErrorString(err));
+      return false;
+    }
+  }
+#elif defined(_WIN32)
+  /*old_context_ = wglGetCurrentContext();
+  
+  if(context_ != old_context_) {
+    dev_context_=wglGetCurrentDC();
+    if (BOOL err=wglMakeCurrent(dev_context_, context_)) {
+      LOGN_ERROR("error switching to offscreen rendering context. "
+                 "wglMakeCurrent failed: ");
+      return false;
+    }
+  }
+  */
+#endif
+  active_=true;
+  return true;
+}
+
+bool OffscreenBuffer::End() 
+{
+  LOGN_DEBUG("switching back to normal rendering");
+
+  if(!active_) return true;
+
+#if defined(__linux__)
+
+  if(context_ != old_context_) {
+    // ignore error
+    glXMakeContextCurrent(dpy_, old_dr1_, old_dr2_, old_context_);
+  }
+
+#elif defined(__APPLE__)
+
+  if(context_!=old_context_) {
+    // ignore error
+    CGLSetCurrentContext(old_context_);
+  }
+  
+#elif defined(_WIN32)
+  /*
+  if(context_!=old_context_) {
+    old_dev_context_=wglGetCurrentDC();
+    wglMakeCurrent(old_dev_context_, old_context_);
+  }
+  */
+#endif  
+
+  Scene::Instance().SetViewport(old_vp_[2],old_vp_[3]);
+  active_=false;
+  return true;
+}
+
+bool OffscreenBuffer::Resize(unsigned int width, unsigned int height)
+{
+#if defined(__linux__)
+
+  std::vector<int> attrib_list;
+  attrib_list.push_back(GLX_PBUFFER_WIDTH);
+  attrib_list.push_back(width);
+  attrib_list.push_back(GLX_PBUFFER_HEIGHT);
+  attrib_list.push_back(height);
+  attrib_list.push_back(0);
+  
+  GLXPbuffer new_pbuffer = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
+
+  if(!new_pbuffer) {
+    LOGN_ERROR("offscreen rendering resize failed");
+    return false;
+  }
+  
+  GLXContext new_context = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
+                                               glXGetCurrentContext(), True);
+  
+  if(!new_context) {
+    LOGN_ERROR("offscreen rendering resize failed to get new context");
+    return false;
+  }
+
+  glXDestroyContext(dpy_, context_);
+  glXDestroyPbuffer(dpy_, pbuffer_);
+
+  context_=new_context;
+  pbuffer_=new_pbuffer;
+
+#elif defined(__APPLE__)
+  CGLPBufferObj      new_pbuffer;  
+  CGLError err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT,
+                                GL_RGBA, 0,  &new_pbuffer);
+  if (err) {
+    LOGN_ERROR("error resizing offscreen rendering context: "
+               "CGLCreatePBuffer failed: " << CGLErrorString(err));
+    return false;
+  }
+  GLint screen=0;
+  assert(CGLGetVirtualScreen(context_, &screen)==0);  
+  err=CGLSetPBuffer(context_, new_pbuffer, 0, 0, screen);
+  if (err) {
+    LOGN_ERROR("error resizing offscreen rendering context. "
+               "CGLSetPBuffer failed: " << CGLErrorString(err));
+    return false;
+  }
+  CGLDestroyPBuffer(pbuffer_);
+  pbuffer_=new_pbuffer;
+
+#elif defined(_WIN32)
+ /* int attribList[] = {0};
+  int format = 0;
+
+  HPBUFFERARB        new_pbuffer;
+  new_pbuffer = wglCreatePbufferARB(dev_context_, format, width, height, attribList);
+  if (new_pbuffer == NULL) 
+  {
+    LOGN_ERROR("Error resizing offscreen rendering context (wglCreatePbufferARB failed)\n");
+    return false;
+  }
+
+  dev_context_ = wglGetPbufferDCARB(new_pbuffer);
+  if (dev_context_ == NULL) 
+  {
+    LOGN_ERROR("Unable to retrieve handle to resized pbuffer device context\n");
+    return false;
+  }
+
+  context_ = wglCreateContext(dev_context_);
+  if (context_ == NULL) 
+  {
+    LOGN_ERROR("Unable to create a rendering context for the resized pbuffer\n");
+    return false;
+  }
+  //
+  //if (!wglShareLists(old_context_, context_)) 
+  //{
+  //  LOGN_ERROR("Unable to share data between resized rendering contexts\n");
+  //  return;
+  //}
+  */
+#endif
+  // nothing failed, set new width and height
+  width_=width;
+  height_=height;
+  return true;
+}
+
+bool OffscreenBuffer::IsValid() const
+{
+  return valid_;
+}
+
+bool OffscreenBuffer::IsActive() const
+{
+  return valid_;
+}
+
+OffscreenBuffer::OffscreenBuffer(int width, int height, int r_bits, 
+                                 int b_bits, int g_bits, 
+                                 int a_bits, int depth_bits):
+  width_(width), height_(height),valid_(false)
+{
+
+#if defined(__linux__)
+
+  if(getenv("DISPLAY")==NULL) {
+    LOGN_ERROR("error creating offscreen rendering context: missing DISPLAY environment variable");
+    return;
+  }
+  dpy_ = XOpenDisplay(getenv("DISPLAY"));
+  if(dpy_==NULL) {
+    LOGN_ERROR("error creating offscreen rendering context: XOpenDisplay failed");
+    return;
+  }
+
+  std::vector<int> attrib_list;
+  attrib_list.push_back(GLX_RENDER_TYPE);
+  attrib_list.push_back(GLX_RGBA_BIT);
+  attrib_list.push_back(GLX_DRAWABLE_TYPE);
+  attrib_list.push_back(GLX_PBUFFER_BIT);
+  attrib_list.push_back(GLX_DOUBLEBUFFER);
+  attrib_list.push_back(False);
+  attrib_list.push_back(GLX_DEPTH_SIZE);
+  attrib_list.push_back(depth_bits);
+  attrib_list.push_back(GLX_RED_SIZE);
+  attrib_list.push_back(r_bits);
+  attrib_list.push_back(GLX_GREEN_SIZE);
+  attrib_list.push_back(g_bits);
+  attrib_list.push_back(GLX_BLUE_SIZE);
+  attrib_list.push_back(b_bits);
+  attrib_list.push_back(GLX_ALPHA_SIZE);
+  attrib_list.push_back(a_bits);
+  attrib_list.push_back(0);
+
+  int nelem=0;
+  fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem);
+  if(fbconfig_==0 || nelem==0) {
+    LOGN_ERROR("error creating offscreen rendering context: glXChooseFBConfig failed");
+    return;
+  }
+
+  attrib_list.clear();
+  attrib_list.push_back(GLX_PBUFFER_WIDTH);
+  attrib_list.push_back(width);
+  attrib_list.push_back(GLX_PBUFFER_HEIGHT);
+  attrib_list.push_back(height);
+  attrib_list.push_back(0);
+  
+  pbuffer_ = glXCreatePbuffer(dpy_, fbconfig_[0], &attrib_list[0]);
+  if(!pbuffer_) {
+    LOGN_ERROR("error creating offscreen rendering context: glXCreatePBuffer failed");
+    return;
+  }
+
+  context_ = glXCreateNewContext(dpy_, fbconfig_[0], GLX_RGBA_TYPE, 
+                                 glXGetCurrentContext(), True);
+  if(!context_) {
+    LOGN_ERROR("error creating offscreen rendering context: glXCreateNewContext failed");
+    return;
+  }
+
+#elif defined(__APPLE__)                                   
+  CGLPixelFormatAttribute attributes[]={
+    kCGLPFAPBuffer,
+    kCGLPFAColorSize, CGLPixelFormatAttribute(8),
+    kCGLPFAAlphaSize, CGLPixelFormatAttribute(8),
+    kCGLPFADepthSize, CGLPixelFormatAttribute(24),
+    CGLPixelFormatAttribute(0)
+  };
+  GLint npix=0;
+  CGLError err=CGLChoosePixelFormat(attributes, &pix_format_, &npix);
+  if(err) {
+    LOGN_ERROR("error creating offscreen rendering context. "
+               "CGLChoosePixFormat failed:" << CGLErrorString(err));
+    return;
+  }
+  // if a context exists, share resources such as shader programs and display
+  // lists.
+  err=CGLCreateContext(pix_format_, CGLGetCurrentContext(), &context_);
+  if(err) {
+    LOGN_ERROR("error creating offscreen rendering context. "
+               "CGLCreateContext failed" << CGLErrorString(err));
+    return;
+  }
+  err=CGLCreatePBuffer(width, height, GL_TEXTURE_RECTANGLE_EXT, GL_RGBA, 0, 
+                       &pbuffer_);
+  if (err) {
+    LOGN_ERROR("error creating offscreen rendering context. "
+               "CGLCreatePBuffer failed: " << CGLErrorString(err));
+    return;
+  }
+  GLint screen=0;
+  assert(CGLGetVirtualScreen(context_, &screen)==0);  
+  err=CGLSetPBuffer(context_, pbuffer_, 0, 0, screen);
+  if (err) {
+    LOGN_ERROR("error creating offscreen rendering context. "
+               "CGLSetPBuffer failed: " << CGLErrorString(err));
+    return;
+  }
+
+#elif defined(_WIN32)
+  /*    
+  // store current windows device and rendering context
+  dev_context_ = wglGetCurrentDC();
+  context_ = wglGetCurrentContext();
+
+  int format = 0;
+  unsigned int nformats;
+  int attribList[] = 
+  {
+      WGL_RED_BITS_ARB,               32,
+      WGL_GREEN_BITS_ARB,             32,
+      WGL_BLUE_BITS_ARB,              32,
+      WGL_ALPHA_BITS_ARB,             32,
+      WGL_STENCIL_BITS_ARB,           8,
+      WGL_DEPTH_BITS_ARB,             24,
+      WGL_FLOAT_COMPONENTS_NV,        true,
+      WGL_DRAW_TO_PBUFFER_ARB,        true,
+      0,
+  };
+
+  wglChoosePixelFormatARB(dev_context_, attribList, NULL, 1, &format, &nformats);
+  if (nformats == 0)
+  {
+    LOGN_ERROR("Unable to find any RGBA32 floating point pixel formats\n");
+    return;
+  }
+
+  // clear attribute list
+  //attribList[0] = 0;
+  
+  int attribs[] = {
+      WGL_RED_BITS_ARB,               8,
+      WGL_GREEN_BITS_ARB,             8,
+      WGL_BLUE_BITS_ARB,              8,
+      WGL_ALPHA_BITS_ARB,             8,
+      WGL_STENCIL_BITS_ARB,           8,
+      WGL_DEPTH_BITS_ARB,             24,
+      0,
+  };
+
+  pbuffer_ = wglCreatePbufferARB(dev_context_, format, width, height, attribs);
+  if (pbuffer_ == NULL) 
+  {
+    LOGN_ERROR("Unable to create floating point pbuffer (wglCreatePbufferARB failed)\n");
+    return;
+  }
+
+  old_dev_context_ = wglGetPbufferDCARB(pbuffer_);
+  if (dev_context_ == NULL) 
+  {
+    LOGN_ERROR("Unable to retrieve handle to pbuffer device context\n");
+    return;
+  }
+
+  context_ = wglCreateContext(dev_context_);
+  if (context_ == NULL) 
+  {
+    LOGN_ERROR("Unable to create a rendering context for the pbuffer\n");
+    return;
+  }
+  
+  if (!wglShareLists(old_context_, context_)) 
+  {
+    LOGN_ERROR("Unable to share data between rendering contexts\n");
+    return;
+  }
+*/
+#endif
+
+  // nothing failed, all is good
+  valid_=true;
+  active_=false;
+} 
+
+}}