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 //--------------------------------------------------------------------------------