core/vgui/internals/vgui_overlay_helper.cxx
Go to the documentation of this file.
00001 // This is core/vgui/internals/vgui_overlay_helper.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author fsm
00008 
00009 #include "vgui_overlay_helper.h"
00010 
00011 #include <vcl_cassert.h>
00012 #include <vcl_iostream.h>
00013 
00014 #include <vgui/vgui_event.h>
00015 #include <vgui/vgui_macro.h>
00016 #include <vgui/vgui_utils.h>
00017 #include <vgui/vgui_adaptor.h>
00018 #include <vgui/internals/vgui_accelerate.h>
00019 
00020 #define trace if (true) { } else vcl_cerr
00021 
00022 vgui_overlay_helper::vgui_overlay_helper(vgui_adaptor *a)
00023   : adaptor(a)
00024   //, aux_buffer_is_back_buffer(true)
00025   , last_draw_was_overlay(false)
00026   , overlay_redraw_posted(false)
00027 {
00028   trace << "vgui_overlay_helper created\n";
00029   assert(adaptor);
00030 
00031   // check that this GL state is double buffered :
00032   adaptor->make_current();
00033   {
00034     GLboolean isdouble = 0;
00035     glGetBooleanv(GL_DOUBLEBUFFER, &isdouble);
00036     if (!isdouble) {
00037       vgui_macro_warning << "current GL state is not double buffered\n";
00038       return;
00039     }
00040   }
00041 }
00042 
00043 vgui_overlay_helper::~vgui_overlay_helper() {
00044   adaptor = 0;
00045 }
00046 
00047 //--------------------------------------------------------------------------------
00048 
00049 // this could be inlined
00050 bool vgui_overlay_helper::dispatch(vgui_event const &e) {
00051   if (e.type == vgui_DRAW)
00052     return dispatch_draw(e);
00053 
00054   else if (e.type == vgui_DRAW_OVERLAY)
00055     return dispatch_overlay_draw(e);
00056 
00057   else
00058     return dispatch_other(e);
00059 }
00060 
00061 bool vgui_overlay_helper::dispatch_draw(vgui_event const &e) {
00062   //vgui_macro_warning << "emulation normal redisplay" << endl;
00063   assert(e.type == vgui_DRAW);
00064 
00065   // First perform the normal draw :
00066   last_draw_was_overlay = false;
00067   bool f = adaptor->dispatch_to_tableau(e);
00068   adaptor->swap_buffers(); // should this be moved further down?
00069 
00070   // It is up to tableaux to post overlay redraws when receiving
00071   // vgui_DRAW events, so if any overlays need to be drawn, we
00072   // should know at this point.
00073   if (overlay_redraw_posted) {
00074     vgui_event oe(vgui_DRAW_OVERLAY);
00075     f = dispatch_overlay_draw(oe);
00076   }
00077 
00078   return f;
00079 }
00080 
00081 bool vgui_overlay_helper::dispatch_other(vgui_event const &e) {
00082   //vgui_macro_warning << "emulation other dispatch" << endl;
00083   assert(e.type != vgui_DRAW && e.type != vgui_DRAW_OVERLAY);
00084 
00085   // dispatch
00086   bool f = adaptor->dispatch_to_tableau(e);
00087 
00088   // cf dispatch_draw
00089   if (overlay_redraw_posted) {
00090     vgui_event oe(vgui_DRAW_OVERLAY);
00091     f = dispatch_overlay_draw(oe);
00092   }
00093 
00094   return f;
00095 }
00096 
00097 bool vgui_overlay_helper::dispatch_overlay_draw(vgui_event const &e) {
00098   //vgui_macro_warning << "emulation overlay redisplay" << endl;
00099   assert(e.type == vgui_DRAW_OVERLAY);
00100 
00101   // If the last draw was a normal draw we need to snapshot the
00102   // frame buffer before drawing the overlays.
00103   if (!last_draw_was_overlay) {
00104     trace << "snapshot\n";
00105     if (vgui_accelerate::instance()->vgui_copy_back_to_aux())
00106       aux_buffer_is_back_buffer = false;
00107     else {
00108       vgui_utils::copy_front_to_back();
00109       aux_buffer_is_back_buffer = true;
00110     }
00111   }
00112   // Else, the last draw was an overlay draw, so we need to repair
00113   // the damage before drawing the new overlays.
00114   else {
00115     trace << "revert\n";
00116     if (!aux_buffer_is_back_buffer)
00117       vgui_accelerate::instance()->vgui_copy_aux_to_back();
00118     else
00119       vgui_utils::copy_back_to_front();
00120   }
00121 
00122 
00123   // enter "overlay mode"
00124   if (!aux_buffer_is_back_buffer)
00125     glDrawBuffer(GL_BACK);
00126   else
00127     glDrawBuffer(GL_FRONT);
00128 
00129 
00130   // get tableau to draw its overlays.
00131   bool f = adaptor->dispatch_to_tableau(e);
00132 
00133 
00134   // With an auxiliary buffer (Mesa), we now need to blit the overlays
00135   // rendered in the back buffer onto the screen.
00136   if (!aux_buffer_is_back_buffer)
00137     adaptor->swap_buffers();
00138 
00139 
00140   // update state
00141   last_draw_was_overlay = true;  // remember this for later.
00142   overlay_redraw_posted = false; // overlay draw no longer pending.
00143 
00144 
00145   // leave "overlay mode"
00146   if (aux_buffer_is_back_buffer)
00147     glDrawBuffer(GL_BACK);
00148 
00149   return f;
00150 }
00151 
00152 //--------------------------------------------------------------------------------