diff --git a/cmake_support/FindMesa.cmake b/cmake_support/FindMesa.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6b1c33d79271caa0ba33bec3f1fafe011c2267d8 --- /dev/null +++ b/cmake_support/FindMesa.cmake @@ -0,0 +1,37 @@ +set(OPENGL_FOUND FALSE) + +if (OPENGL_INCLUDE_DIR) + + # in cache already + set(OPENGL_FOUND TRUE) + +else (OPENGL_INCLUDE_DIR) + + if(DEFINED MESA_PREFIX) + set(_MESA_PREFIX ${MESA_PREFIX}) + elseif(DEFINED ENV{MESA_PREFIX}) + set(_MESA_PREFIX $ENV{MESA_PREFIX}) + else() + message(FATAL_ERROR "no MESA_PREFIX given or found in environment") + endif() + + if(DEFINED _MESA_PREFIX) + set(OPENGL_INCLUDE_DIR "${_MESA_PREFIX}/include" CACHE PATH "Mesa include") + set(OPENGL_LIBRARY_DIR "${_MESA_PREFIX}/lib" CACHE PATH "Mesa lib") + set(OPENGL_gl_LIBRARY "${_MESA_PREFIX}/lib/libGL.so" CACHE PATH "Mesa gl lib") + set(OPENGL_glu_LIBRARY "${_MESA_PREFIX}/lib/libGLU.so" CACHE PATH "Mesa glu lib") + + set(OPENGL_LIBRARIES ${_MESA_PREFIX}/lib/libGL.so ${_MESA_PREFIX}/lib/libGLU.so ${_MESA_PREFIX}/lib/libOSMesa.so CACHE PATH "Mesa libs") + set(OPENGL_FOUND TRUE) + message(STATUS "Found Mesa include dir: ${OPENGL_INCLUDE_DIR}") + message(STATUS "Found Mesa lib dir: ${OPENGL_LIBRARY_DIR}") + message(STATUS "Using Mesa libs: ${OPENGL_LIBRARIES}") + endif() + +endif() + +if(NOT OPENGL_FOUND) + message(FATAL_ERROR "no Mesa found, please provide the correct location with MESA_PREFIX") +endif() + +mark_as_advanced (OPENGL_INCLUDE_DIR) diff --git a/modules/gfx/src/impl/mesa_offscreen_buffer.cc b/modules/gfx/src/impl/mesa_offscreen_buffer.cc new file mode 100644 index 0000000000000000000000000000000000000000..39ed73b5cfd090c4f451e0881364e9ba5778e05b --- /dev/null +++ b/modules/gfx/src/impl/mesa_offscreen_buffer.cc @@ -0,0 +1,214 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 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 +//------------------------------------------------------------------------------ + +/* + Author: Ansgar Philippsen +*/ + +#include <ost/log.hh> +#include <ost/gfx/offscreen_buffer.hh> +#include <ost/gfx/scene.hh> + +namespace ost { namespace gfx { + +static XVisualInfo* get_visinfo(Display* dpy, bool use_accum) +{ + int buf[64]; + unsigned int bufc=0; + int d[]={16,12,8,6,4,1}; + int c[]={16,12,8,6,5,4,2,1}; + int a[]={8,4}; + XVisualInfo *vis=NULL; + + buf[bufc++]=GLX_RGBA; + buf[bufc++]=GLX_DEPTH_SIZE; + unsigned int depthi=bufc++; + buf[bufc++]=GLX_RED_SIZE; + unsigned int redi=bufc++; + buf[bufc++]=GLX_BLUE_SIZE; + unsigned int bluei=bufc++; + buf[bufc++]=GLX_GREEN_SIZE; + unsigned int greeni=bufc++; + unsigned int accumi=0; + if(use_accum) { + buf[bufc++]=GLX_ACCUM_RED_SIZE; + accumi=bufc++; + buf[bufc++]=GLX_ACCUM_BLUE_SIZE; + bufc++; + buf[bufc++]=GLX_ACCUM_GREEN_SIZE; + bufc++; + } + buf[bufc++]=None; + + for(unsigned int j=0;j<sizeof(c)/sizeof(int);j++) { + for(unsigned int i=0;i<sizeof(d)/sizeof(int);i++) { + buf[depthi]=d[i]; + buf[redi]=c[j]; + buf[bluei]=c[j]; + buf[greeni]=c[j]; + if(use_accum) { + for(unsigned int k=0;k<sizeof(a)/sizeof(int);k++) { + buf[accumi+0]=a[k]; + buf[accumi+2]=a[k]; + buf[accumi+4]=a[k]; + vis=glXChooseVisual(dpy,DefaultScreen(dpy),buf); + if(vis) return vis; + } + } else { + vis=glXChooseVisual(dpy,DefaultScreen(dpy),buf); + if(vis) return vis; + } + } + } + return NULL; +} + +static void create_error(const std::string& m) +{ + LOG_ERROR("error creating offscreen rendering context: " << m); +} + +OffscreenBuffer::OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared): + width_(width), height_(height), valid_(false), active_(false) +{ + LOG_DEBUG("offscreen buffer: checking for DISPLAY"); + if(getenv("DISPLAY")==NULL) { + create_error("missing DISPLAY environment variable"); + return; + } + + LOG_DEBUG("offscreen buffer: XOpenDisplay"); + dpy_ = XOpenDisplay(getenv("DISPLAY")); + if(dpy_==NULL) { + create_error("XOpenDisplay() failed"); + return; + } + +#if 0 + 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_PIXMAP_BIT); + attrib_list.push_back(GLX_DOUBLEBUFFER); + attrib_list.push_back(False); + attrib_list.push_back(GLX_DEPTH_SIZE); + attrib_list.push_back(f.dbits); + attrib_list.push_back(GLX_RED_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_GREEN_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_BLUE_SIZE); + attrib_list.push_back(f.cbits); + attrib_list.push_back(GLX_ALPHA_SIZE); + attrib_list.push_back(f.abits); + attrib_list.push_back(0); + + int nelem=0; + LOG_DEBUG("offscreen buffer: glXChooseFBConfig"); + fbconfig_ =glXChooseFBConfig(dpy_,0,&attrib_list[0],&nelem); + if(fbconfig_==0 || nelem==0) { + create_error("glXChooseFBConfig failed"); + return; + } + +#else + + visinfo_ = get_visinfo(dpy_,true); + if(!visinfo_) { + create_error("get_visinfo() failed"); + return; + } + + context_=glXCreateContext(dpy_, visinfo_, 0, False); + if(!context_) { + create_error("glxCreateContext() failed"); + return; + } + + pm_=XCreatePixmap(dpy_,RootWindow(dpy_,DefaultScreen(dpy_)), + width_,height_,visinfo_->depth); + if(!pm_) { + create_error("XCreatePixmap() failed"); + return; + } + + glxpm_=glXCreateGLXPixmap(dpy_, visinfo_, pm_); + if(!glxpm_) { + create_error("glXCreateGLXPixmap() failed"); + return; + } + +#endif + + valid_=true; +} + +OffscreenBuffer::~OffscreenBuffer() +{ + if(valid_) { + glXDestroyGLXPixmap(dpy_,glxpm_); + XFreePixmap(dpy_,pm_); + glXDestroyContext(dpy_,context_); + valid_=false; + } +} + +bool OffscreenBuffer::Resize(unsigned int width, unsigned int height) +{ + width_=width; + height_=height; + + if(pm_) { + XFreePixmap(dpy_,pm_); + } + pm_=XCreatePixmap(dpy_,RootWindow(dpy_,DefaultScreen(dpy_)), + width_,height_,visinfo_->depth); + if(!pm_) { + create_error("XCreatePixmap() failed"); + return false; + } + + if(glxpm_) { + glXDestroyGLXPixmap(dpy_,glxpm_); + } + glxpm_=glXCreateGLXPixmap(dpy_, visinfo_, pm_); + if(!glxpm_) { + create_error("glXCreateGLXPixmap() failed"); + return false; + } + + if(active_) { + MakeActive(); + } + + return true; +} + +bool OffscreenBuffer::MakeActive() +{ + if(glXMakeCurrent(dpy_,glxpm_,context_)==False) { + LOG_ERROR("error activating offscreen rendering: glXMakeCurrent() failed"); + return false; + } + active_=true; + return true; +} + +}} // ns diff --git a/modules/gfx/src/impl/mesa_offscreen_buffer.hh b/modules/gfx/src/impl/mesa_offscreen_buffer.hh new file mode 100644 index 0000000000000000000000000000000000000000..5ed38b942e7ab7a8b5c41924d1f3f2fcb7a44e24 --- /dev/null +++ b/modules/gfx/src/impl/mesa_offscreen_buffer.hh @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +// This file is part of the OpenStructure project <www.openstructure.org> +// +// Copyright (C) 2008-2011 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 +//------------------------------------------------------------------------------ +#ifndef OST_GFX_MESA_OFFSCREEN_BUFFER_HH +#define OST_GFX_MESA_OFFSCREEN_BUFFER_HH + +#include <stack> +#include <ost/gfx/glext_include.hh> +#include <GL/glx.h> + +namespace ost { namespace gfx { + +/* + mesa implementation for offscreen buffers + + Author: Ansgar Philippsen +*/ + +class OffscreenBuffer +{ +public: + OffscreenBuffer(unsigned int width, unsigned int height, const OffscreenBufferFormat& f, bool shared=true); + ~OffscreenBuffer(); + + bool Resize(unsigned int w, unsigned int h); + + bool MakeActive(); + + bool IsActive() {return active_;} + + bool IsValid() {return valid_;} + +private: + int width_; + int height_; + bool valid_; + bool active_; + + Display* dpy_; + XVisualInfo* visinfo_; + Pixmap pm_; + GLXPixmap glxpm_; + GLXContext context_; + GLXFBConfig* fbconfig_; +}; + +}} // ns + +#endif