Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Examples

pixmap-mixed.cc

Simple offscreen rendering example for mixing OpenGL and GDK rendering.

// -*- C++ -*-
/*
 * pixmap-mixed.cc:
 * Simple off-screen rendering example for mixing OpenGL and GDK rendering.
 *
 * written by Naofumi Yasufuku  <naofumi@users.sourceforge.net>
 */

#include <iostream>
#include <cstdlib>

#include <gtkmm.h>

#include <gtkglmm.h>

#ifdef G_OS_WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <windows.h>
#endif

#include <GL/gl.h>
#include <GL/glu.h>


//
// OpenGL frame buffer configuration utilities.
//

struct GLConfigUtil
{
  static void print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
                              const char* attrib_str,
                              int attrib,
                              bool is_boolean);

  static void examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig);
};

//
// Print a configuration attribute.
//
void GLConfigUtil::print_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig,
                                   const char* attrib_str,
                                   int attrib,
                                   bool is_boolean)
{
  int value;

  if (glconfig->get_attrib(attrib, value))
    {
      std::cout << attrib_str << " = ";
      if (is_boolean)
        std::cout << (value == true ? "true" : "false") << std::endl;
      else
        std::cout << value << std::endl;
    }
  else
    {
      std::cout << "*** Cannot get "
                << attrib_str
                << " attribute value\n";
    }
}

//
// Print configuration attributes.
//
void GLConfigUtil::examine_gl_attrib(const Glib::RefPtr<const Gdk::GL::Config>& glconfig)
{
  std::cout << "\nOpenGL visual configurations :\n\n";

  std::cout << "glconfig->is_rgba() = "
            << (glconfig->is_rgba() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->is_double_buffered() = "
            << (glconfig->is_double_buffered() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->is_stereo() = "
            << (glconfig->is_stereo() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->has_alpha() = "
            << (glconfig->has_alpha() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->has_depth_buffer() = "
            << (glconfig->has_depth_buffer() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->has_stencil_buffer() = "
            << (glconfig->has_stencil_buffer() ? "true" : "false")
            << std::endl;
  std::cout << "glconfig->has_accum_buffer() = "
            << (glconfig->has_accum_buffer() ? "true" : "false")
            << std::endl;

  std::cout << std::endl;

  print_gl_attrib(glconfig, "Gdk::GL::USE_GL",           Gdk::GL::USE_GL,           true);
  print_gl_attrib(glconfig, "Gdk::GL::BUFFER_SIZE",      Gdk::GL::BUFFER_SIZE,      false);
  print_gl_attrib(glconfig, "Gdk::GL::LEVEL",            Gdk::GL::LEVEL,            false);
  print_gl_attrib(glconfig, "Gdk::GL::RGBA",             Gdk::GL::RGBA,             true);
  print_gl_attrib(glconfig, "Gdk::GL::DOUBLEBUFFER",     Gdk::GL::DOUBLEBUFFER,     true);
  print_gl_attrib(glconfig, "Gdk::GL::STEREO",           Gdk::GL::STEREO,           true);
  print_gl_attrib(glconfig, "Gdk::GL::AUX_BUFFERS",      Gdk::GL::AUX_BUFFERS,      false);
  print_gl_attrib(glconfig, "Gdk::GL::RED_SIZE",         Gdk::GL::RED_SIZE,         false);
  print_gl_attrib(glconfig, "Gdk::GL::GREEN_SIZE",       Gdk::GL::GREEN_SIZE,       false);
  print_gl_attrib(glconfig, "Gdk::GL::BLUE_SIZE",        Gdk::GL::BLUE_SIZE,        false);
  print_gl_attrib(glconfig, "Gdk::GL::ALPHA_SIZE",       Gdk::GL::ALPHA_SIZE,       false);
  print_gl_attrib(glconfig, "Gdk::GL::DEPTH_SIZE",       Gdk::GL::DEPTH_SIZE,       false);
  print_gl_attrib(glconfig, "Gdk::GL::STENCIL_SIZE",     Gdk::GL::STENCIL_SIZE,     false);
  print_gl_attrib(glconfig, "Gdk::GL::ACCUM_RED_SIZE",   Gdk::GL::ACCUM_RED_SIZE,   false);
  print_gl_attrib(glconfig, "Gdk::GL::ACCUM_GREEN_SIZE", Gdk::GL::ACCUM_GREEN_SIZE, false);
  print_gl_attrib(glconfig, "Gdk::GL::ACCUM_BLUE_SIZE",  Gdk::GL::ACCUM_BLUE_SIZE,  false);
  print_gl_attrib(glconfig, "Gdk::GL::ACCUM_ALPHA_SIZE", Gdk::GL::ACCUM_ALPHA_SIZE, false);

  std::cout << std::endl;
}


//
// Simple OpenGL scene using GL::Pixmap.
//

class PixmapGLScene : public Gtk::DrawingArea
{
public:
  PixmapGLScene();
  virtual ~PixmapGLScene();

protected:
  // init OpenGL context
  void init_gl();

protected:
  virtual bool on_configure_event(GdkEventConfigure* event);
  virtual bool on_expose_event(GdkEventExpose* event);

protected:
  // OpenGL rendering stuff:
  Glib::RefPtr<Gdk::GL::Config> m_GLConfig;
  Glib::RefPtr<Gdk::GL::Context> m_GLContext;
  Glib::RefPtr<Gdk::Pixmap> m_Pixmap;
};

PixmapGLScene::PixmapGLScene()
  : m_GLConfig(0), m_GLContext(0), m_Pixmap(0)
{
  //
  // Configure OpenGL-capable visual.
  //

  // Try single-buffered visual
  m_GLConfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB    |
                                       Gdk::GL::MODE_DEPTH  |
                                       Gdk::GL::MODE_SINGLE);
  if (!m_GLConfig)
    {
      std::cerr << "*** Cannot find any OpenGL-capable visual.\n";
      std::exit(1);
    }

  // print frame buffer attributes.
  GLConfigUtil::examine_gl_attrib(m_GLConfig);

  //
  // Set OpenGL-capable colormap.
  //

  set_colormap(m_GLConfig->get_colormap());
}

PixmapGLScene::~PixmapGLScene()
{
}

void PixmapGLScene::init_gl()
{
  GLUquadricObj* qobj = gluNewQuadric();
  gluQuadricDrawStyle(qobj, GLU_FILL);
  glNewList(1, GL_COMPILE);
  gluSphere(qobj, 1.0, 20, 20);
  glEndList();

  static GLfloat light_diffuse[] = {1.0, 0.0, 0.0, 1.0};
  static GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);

  glClearColor(1.0, 1.0, 1.0, 1.0);
  glClearDepth(1.0);

  glViewport(0, 0, get_width(), get_height());

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(40.0, 1.0, 1.0, 10.0);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(0.0, 0.0, 3.0,
            0.0, 0.0, 0.0,
            0.0, 1.0, 0.0);
  glTranslatef(0.0, 0.0, -3.0);
}

bool PixmapGLScene::on_configure_event(GdkEventConfigure* event)
{
  //
  // Create an OpenGL off-screen rendering area.
  //

  m_Pixmap = Gdk::Pixmap::create(get_window(),
                                 get_width(), get_height(),
                                 m_GLConfig->get_depth());

  //
  // Set OpenGL-capability to the pixmap (invoke extension method).
  //

  Glib::RefPtr<Gdk::GL::Pixmap> glpixmap =
    Gdk::GL::ext(m_Pixmap).set_gl_capability(m_GLConfig);

  //
  // Create OpenGL rendering context (not direct).
  //

  if (!m_GLContext)
    m_GLContext = Gdk::GL::Context::create(glpixmap, false);

  //
  // GL calls.
  //

  // *** OpenGL BEGIN ***
  if (!glpixmap->gl_begin(m_GLContext))
    return false;

  static bool is_initialized = false;
  if (!is_initialized)
    {
      init_gl();
      is_initialized = true;
    }

  glViewport(0, 0, get_width(), get_height());

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // Sync.
  glpixmap->wait_gl();

  // GDK rendering.
  glpixmap->draw_rectangle(get_style()->get_fg_gc(get_state()),
                           true,
                           get_width()/10,
                           get_height()/10,
                           get_width()*8/10,
                           get_height()*8/10);

  // Sync.
  glpixmap->wait_gdk();

  glCallList(1);

  glFlush();

  glpixmap->gl_end();
  // *** OpenGL END ***

  return true;
}

bool PixmapGLScene::on_expose_event(GdkEventExpose* event)
{
  if (!m_Pixmap)
    return false;

  get_window()->draw_drawable(get_style()->get_fg_gc(get_state()),
                              m_Pixmap,
                              event->area.x, event->area.y,
                              event->area.x, event->area.y,
                              event->area.width, event->area.height);

  return true;
}


//
// The application class.
//

class Pixmap : public Gtk::Window
{
public:
  Pixmap();
  virtual ~Pixmap();

protected:
  // signal handlers:
  void on_button_quit_clicked();

protected:
  // member widgets:
  Gtk::VBox m_VBox;
  PixmapGLScene m_PixmapGLScene;
  Gtk::Button m_ButtonQuit;
};

Pixmap::Pixmap()
  : m_VBox(false, 0), m_ButtonQuit("Quit")
{
  //
  // Top-level window.
  //

  set_title("Pixmap");

  add(m_VBox);

  //
  // Simple OpenGL scene using GL::Pixmap.
  //

  m_PixmapGLScene.set_size_request(200, 200);

  m_VBox.pack_start(m_PixmapGLScene);

  //
  // Simple quit button.
  //

  m_ButtonQuit.signal_clicked().connect(
    sigc::mem_fun(*this, &Pixmap::on_button_quit_clicked));

  m_VBox.pack_start(m_ButtonQuit, Gtk::PACK_SHRINK, 0);

  //
  // Show window.
  //

  show_all();
}

Pixmap::~Pixmap()
{}

void Pixmap::on_button_quit_clicked()
{
  Gtk::Main::quit();
}


//
// Main.
//

int main(int argc, char** argv)
{
  Gtk::Main kit(argc, argv);

  //
  // Init gtkglextmm.
  //

  Gtk::GL::init(argc, argv);

  //
  // Query OpenGL extension version.
  //

  int major, minor;
  Gdk::GL::query_version(major, minor);
  std::cout << "OpenGL extension version - "
            << major << "." << minor << std::endl;

  //
  // Instantiate and run the application.
  //

  Pixmap pixmap;

  kit.run(pixmap);

  return 0;
}

Generated on Mon Feb 27 18:46:52 2006 for gtkglextmm by  doxygen 1.4.4