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

# share-lists.cc

Simple display list sharing example.

    // -*- C++ -*-
    /*
     * share-lists.cc:
     * Simple display list sharing example.
     *
     * 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>

    //
    // Simple OpenGL scene base class.
    //

    class SimpleGLScene : public Gtk::GL::DrawingArea
    {
    public:
      explicit SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config);

      SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config,
                    const Glib::RefPtr<const Gdk::GL::Context>& share_list);

      virtual ~SimpleGLScene();

    protected:
      virtual void init_gl();

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

    public:
      // Gtk::Widget::realize() is protected, so that ...
      void realize() { Gtk::GL::DrawingArea::realize(); }

    public:
      void set_light_diffuse(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
      { m_LightDiffuse[0] = r; m_LightDiffuse[1] = g; m_LightDiffuse[2] = b; m_LightDiffuse[3] = a; }

      void set_light_position(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
      { m_LightPosition[0] = x; m_LightPosition[1] = y; m_LightPosition[2] = z; m_LightPosition[3] = w; }

    protected:
      GLfloat m_LightDiffuse[4];
      GLfloat m_LightPosition[4];

    };

    SimpleGLScene::SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config)
      : Gtk::GL::DrawingArea(config)
    {
      set_light_diffuse(1.0, 1.0, 1.0, 1.0);
      set_light_position(1.0, 1.0, 1.0, 0.0);
    }

    SimpleGLScene::SimpleGLScene(const Glib::RefPtr<const Gdk::GL::Config>& config,
                                 const Glib::RefPtr<const Gdk::GL::Context>& share_list)
      : Gtk::GL::DrawingArea(config, share_list)
    {
      set_light_diffuse(1.0, 1.0, 1.0, 1.0);
      set_light_position(1.0, 1.0, 1.0, 0.0);
    }

    SimpleGLScene::~SimpleGLScene()
    {
    }

    void SimpleGLScene::init_gl()
    {
      glLightfv(GL_LIGHT0, GL_DIFFUSE, m_LightDiffuse);
      glLightfv(GL_LIGHT0, GL_POSITION, m_LightPosition);
      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 SimpleGLScene::on_configure_event(GdkEventConfigure* event)
    {
      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return false;

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

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

      return true;
    }

    bool SimpleGLScene::on_expose_event(GdkEventExpose* event)
    {
      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return false;

      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

      glCallList(1);

      // Swap buffers.
      if (glwindow->is_double_buffered())
        glwindow->swap_buffers();
      else
        glFlush();

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

      return true;
    }

    //
    // SimpleGLSceneMain (creates display lists)
    //

    class SimpleGLSceneMain : public SimpleGLScene
    {
    public:
      explicit SimpleGLSceneMain(const Glib::RefPtr<const Gdk::GL::Config>& config);
      virtual ~SimpleGLSceneMain();

    protected:
      virtual void on_realize();

    };

    SimpleGLSceneMain::SimpleGLSceneMain(const Glib::RefPtr<const Gdk::GL::Config>& config)
      : SimpleGLScene(config)
    {
    }

    SimpleGLSceneMain::~SimpleGLSceneMain()
    {
    }

    void SimpleGLSceneMain::on_realize()
    {
      // We need to call the base on_realize()
      SimpleGLScene::on_realize();

      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return;

      // Create display list #1
      GLUquadricObj* qobj = gluNewQuadric();
      gluQuadricDrawStyle(qobj, GLU_FILL);
      glNewList(1, GL_COMPILE);
      gluSphere(qobj, 1.0, 20, 20);
      glEndList();

      // Initialize rendering context
      init_gl();

      glwindow->gl_end();
      // *** OpenGL END ***
    }

    //
    // SimpleGLSceneSub (shares display lists)
    //

    class SimpleGLSceneSub : public SimpleGLScene
    {
    public:
      SimpleGLSceneSub(const Glib::RefPtr<const Gdk::GL::Config>& config,
                       const Glib::RefPtr<const Gdk::GL::Context>& share_list);
      virtual ~SimpleGLSceneSub();

    protected:
      virtual void on_realize();

    };

    SimpleGLSceneSub::SimpleGLSceneSub(const Glib::RefPtr<const Gdk::GL::Config>& config,
                                       const Glib::RefPtr<const Gdk::GL::Context>& share_list)
      : SimpleGLScene(config, share_list)
    {
    }

    SimpleGLSceneSub::~SimpleGLSceneSub()
    {
    }

    void SimpleGLSceneSub::on_realize()
    {
      // We need to call the base on_realize()
      SimpleGLScene::on_realize();

      //
      // Get GL::Window.
      //

      Glib::RefPtr<Gdk::GL::Window> glwindow = get_gl_window();

      //
      // GL calls.
      //

      // *** OpenGL BEGIN ***
      if (!glwindow->gl_begin(get_gl_context()))
        return;

      // Initialize rendering context
      init_gl();

      glwindow->gl_end();
      // *** OpenGL END ***
    }

    //
    // The application class.
    //

    class Simple : public Gtk::Window
    {
    public:
      explicit Simple(const Glib::RefPtr<const Gdk::GL::Config>& config);
      virtual ~Simple();

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

    protected:
      // member widgets:
      Gtk::VBox m_VBox;
      SimpleGLScene *m_GLScene1;
      SimpleGLScene *m_GLScene2;
      SimpleGLScene *m_GLScene3;
      Gtk::Button m_ButtonQuit;
    };

    Simple::Simple(const Glib::RefPtr<const Gdk::GL::Config>& config)
      : m_VBox(false, 10), m_ButtonQuit("Quit")
    {
      //
      // Top-level window.
      //

      set_title("share-lists");

      // Get automatically redrawn if any of their children changed allocation.
      set_reallocate_redraws(true);
      // Set border width.
      set_border_width(10);

      add(m_VBox);

      //
      // OpenGL scene #1 (SimpleGLSceneMain: creates display lists)
      //

      m_GLScene1 = new SimpleGLSceneMain(config);
      m_GLScene1->set_size_request(120, 120);
      m_GLScene1->set_light_diffuse(1.0, 0.0, 0.0, 0.0); // red

      m_VBox.pack_start(*m_GLScene1);

      //
      // Get OpenGL rendering context.
      //

      m_GLScene1->realize();
      Glib::RefPtr<Gdk::GL::Context> glcontext = m_GLScene1->get_gl_context();

      //
      // OpenGL scene #2 (SimpleGLSceneSub: shares display lists)
      //

      m_GLScene2 = new SimpleGLSceneSub(config, glcontext);
      m_GLScene2->set_size_request(120, 120);
      m_GLScene2->set_light_diffuse(1.0, 1.0, 0.0, 0.0); // yellow

      m_VBox.pack_start(*m_GLScene2);

      //
      // OpenGL scene #3 (SimpleGLSceneSub: shares display lists)
      //

      m_GLScene3 = new SimpleGLSceneSub(config, glcontext);
      m_GLScene3->set_size_request(120, 120);
      m_GLScene3->set_light_diffuse(0.0, 1.0, 0.0, 0.0); // green

      m_VBox.pack_start(*m_GLScene3);

      //
      // Simple quit button.
      //

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

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

      //
      // Show window.
      //

      show_all();
    }

    Simple::~Simple()
    {
      delete m_GLScene1;
      delete m_GLScene2;
      delete m_GLScene3;
    }

    void Simple::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);

      //
      // Configure OpenGL-capable visual.
      //

      Glib::RefPtr<Gdk::GL::Config> glconfig;

      // Try double-buffered visual
      glconfig = Gdk::GL::Config::create(Gdk::GL::MODE_RGB    |
                                         Gdk::GL::MODE_DEPTH  |
                                         Gdk::GL::MODE_DOUBLE);
      if (!glconfig)
        {
          std::cerr << "*** Cannot find the double-buffered visual.\n"
                    << "*** Trying single-buffered visual.\n";

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

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

      Simple simple(glconfig);

      kit.run(simple);

      return 0;
    }