Panda3D
 All Classes Functions Variables Enumerations
wglGraphicsPipe.cxx
00001 // Filename: wglGraphicsPipe.cxx
00002 // Created by:  drose (20Dec02)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) Carnegie Mellon University.  All rights reserved.
00008 //
00009 // All use of this software is subject to the terms of the revised BSD
00010 // license.  You should have received a copy of this license along
00011 // with this source code in a file named "LICENSE."
00012 //
00013 ////////////////////////////////////////////////////////////////////
00014 
00015 #include "wglGraphicsPipe.h"
00016 #include "config_wgldisplay.h"
00017 #include "config_windisplay.h"
00018 #include "wglGraphicsWindow.h"
00019 #include "wglGraphicsBuffer.h"
00020 
00021 typedef enum {Software, MCD, ICD} OGLDriverType;
00022 
00023 TypeHandle wglGraphicsPipe::_type_handle;
00024 bool    wglGraphicsPipe::_current_valid;
00025 HDC     wglGraphicsPipe::_current_hdc;
00026 HGLRC   wglGraphicsPipe::_current_hglrc;
00027   
00028 ////////////////////////////////////////////////////////////////////
00029 //     Function: wglGraphicsPipe::Constructor
00030 //       Access: Public
00031 //  Description: 
00032 ////////////////////////////////////////////////////////////////////
00033 wglGraphicsPipe::
00034 wglGraphicsPipe() {
00035   _current_valid = false;
00036 }
00037 
00038 ////////////////////////////////////////////////////////////////////
00039 //     Function: wglGraphicsPipe::Destructor
00040 //       Access: Public, Virtual
00041 //  Description: 
00042 ////////////////////////////////////////////////////////////////////
00043 wglGraphicsPipe::
00044 ~wglGraphicsPipe() {
00045 }
00046 
00047 ////////////////////////////////////////////////////////////////////
00048 //     Function: wglGraphicsWindow::wgl_make_current
00049 //       Access: Private, Static
00050 //  Description: a thin wrapper around wglMakeCurrent to avoid
00051 //               unnecessary OS-call overhead.
00052 ////////////////////////////////////////////////////////////////////
00053 void wglGraphicsPipe::
00054 wgl_make_current(HDC hdc, HGLRC hglrc, PStatCollector *collector) {
00055   if ((_current_valid) &&
00056       (_current_hdc == hdc) &&
00057       (_current_hglrc == hglrc)) {
00058     return;
00059   }
00060   _current_valid = true;
00061   _current_hdc = hdc;
00062   _current_hglrc = hglrc;
00063   BOOL res;
00064   if (collector) {
00065     PStatTimer timer(*collector);
00066     res = wglMakeCurrent(hdc, hglrc);
00067   } else {
00068     res = wglMakeCurrent(hdc, hglrc);
00069   }
00070 }
00071 
00072 ////////////////////////////////////////////////////////////////////
00073 //     Function: wglGraphicsPipe::get_interface_name
00074 //       Access: Published, Virtual
00075 //  Description: Returns the name of the rendering interface
00076 //               associated with this GraphicsPipe.  This is used to
00077 //               present to the user to allow him/her to choose
00078 //               between several possible GraphicsPipes available on a
00079 //               particular platform, so the name should be meaningful
00080 //               and unique for a given platform.
00081 ////////////////////////////////////////////////////////////////////
00082 string wglGraphicsPipe::
00083 get_interface_name() const {
00084   return "OpenGL";
00085 }
00086 
00087 ////////////////////////////////////////////////////////////////////
00088 //     Function: wglGraphicsPipe::pipe_constructor
00089 //       Access: Public, Static
00090 //  Description: This function is passed to the GraphicsPipeSelection
00091 //               object to allow the user to make a default
00092 //               wglGraphicsPipe.
00093 ////////////////////////////////////////////////////////////////////
00094 PT(GraphicsPipe) wglGraphicsPipe::
00095 pipe_constructor() {
00096   return new wglGraphicsPipe;
00097 }
00098 
00099 ////////////////////////////////////////////////////////////////////
00100 //     Function: wglGraphicsPipe::make_output
00101 //       Access: Protected, Virtual
00102 //  Description: Creates a new window or buffer on the pipe, if possible.
00103 //               This routine is only called from GraphicsEngine::make_output.
00104 ////////////////////////////////////////////////////////////////////
00105 PT(GraphicsOutput) wglGraphicsPipe::
00106 make_output(const string &name,
00107             const FrameBufferProperties &fb_prop,
00108             const WindowProperties &win_prop,
00109             int flags,
00110             GraphicsEngine *engine,
00111             GraphicsStateGuardian *gsg,
00112             GraphicsOutput *host,
00113             int retry,
00114             bool &precertify) {
00115   
00116   if (!_is_valid) {
00117     return NULL;
00118   }
00119 
00120   wglGraphicsStateGuardian *wglgsg = 0;
00121   if (gsg != 0) {
00122     DCAST_INTO_R(wglgsg, gsg, NULL);
00123   }
00124 
00125   bool support_rtt;
00126   support_rtt = false;
00127   if (wglgsg) {
00128      support_rtt = 
00129       wglgsg -> get_supports_wgl_render_texture() && 
00130       support_render_texture;
00131   }
00132 
00133   // First thing to try: a wglGraphicsWindow
00134 
00135   if (retry == 0) {
00136     if (((flags&BF_require_parasite)!=0)||
00137         ((flags&BF_refuse_window)!=0)||
00138         ((flags&BF_resizeable)!=0)||
00139         ((flags&BF_size_track_host)!=0)||
00140         ((flags&BF_rtt_cumulative)!=0)||
00141         ((flags&BF_can_bind_color)!=0)||
00142         ((flags&BF_can_bind_every)!=0)) {
00143       return NULL;
00144     }
00145     if ((flags & BF_fb_props_optional)==0) {
00146       if ((fb_prop.get_aux_rgba() > 0)||
00147           (fb_prop.get_aux_hrgba() > 0)||
00148           (fb_prop.get_aux_float() > 0)) {
00149         return NULL;
00150       }
00151     }
00152     return new wglGraphicsWindow(engine, this, name, fb_prop, win_prop,
00153                                  flags, gsg, host);
00154   }
00155   
00156   // Second thing to try: a GLGraphicsBuffer
00157   
00158   if (retry == 1) {
00159     if ((!gl_support_fbo)||
00160         (host==0)||
00161         ((flags&BF_require_parasite)!=0)||
00162         ((flags&BF_require_window)!=0)) {
00163       return NULL;
00164     }
00165     // Early failure - if we are sure that this buffer WONT
00166     // meet specs, we can bail out early.
00167     int _fbo_multisample = 0;
00168     if (!ConfigVariableBool("framebuffer-object-multisample", false, PRC_DESC("Enabled Multisample."))) {
00169         _fbo_multisample = 16;
00170     }
00171     if ((flags & BF_fb_props_optional)==0) {
00172       if ((fb_prop.get_indexed_color() > 0)||
00173           (fb_prop.get_back_buffers() > 0)||
00174           (fb_prop.get_accum_bits() > 0)||
00175           (fb_prop.get_multisamples() > _fbo_multisample)) {
00176         return NULL;
00177       }
00178     }
00179     if ((wglgsg != 0) &&
00180         (wglgsg->is_valid()) &&
00181         (!wglgsg->needs_reset()) &&
00182   !wglgsg->_supports_framebuffer_object) {
00183       return NULL;
00184     }
00185 
00186     // Early success - if we are sure that this buffer WILL
00187     // meet specs, we can precertify it.
00188     if ((wglgsg != 0) &&
00189         (wglgsg->is_valid()) &&
00190         (!wglgsg->needs_reset()) &&
00191         (wglgsg->_supports_framebuffer_object) &&
00192         (wglgsg->_glDrawBuffers != 0)&&
00193         (fb_prop.is_basic())) {
00194       precertify = true;
00195     }
00196     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00197                                 flags, gsg, host);
00198   }
00199   
00200   // Third thing to try: a wglGraphicsBuffer
00201   
00202   if (retry == 2) {
00203     if (((flags&BF_require_parasite)!=0)||
00204         ((flags&BF_require_window)!=0)) {
00205       return NULL;
00206     }
00207     if ((wglgsg != 0) &&
00208         (wglgsg->is_valid()) &&
00209         (!wglgsg->needs_reset()) &&
00210   !wglgsg->_supports_pbuffer) {
00211       return NULL;
00212     }
00213 
00214     if (!support_rtt) {
00215       if (((flags&BF_rtt_cumulative)!=0)||
00216           ((flags&BF_can_bind_every)!=0)) {
00217         // If we require Render-to-Texture, but can't be sure we
00218         // support it, bail.
00219         return NULL;
00220       }
00221     }
00222 
00223     // Early failure - if we are sure that this buffer WONT
00224     // meet specs, we can bail out early.
00225     if ((flags & BF_fb_props_optional) == 0) {
00226       if ((fb_prop.get_aux_rgba() > 0)||
00227           (fb_prop.get_aux_rgba() > 0)||
00228           (fb_prop.get_aux_float() > 0)) {
00229         return NULL;
00230       }
00231     }
00232     // Early success - if we are sure that this buffer WILL
00233     // meet specs, we can precertify the window.
00234     if ((wglgsg != 0) &&
00235         (wglgsg->is_valid()) &&
00236         (!wglgsg->needs_reset()) &&
00237         (wglgsg->pfnum_supports_pbuffer()) &&
00238         (wglgsg->get_fb_properties().subsumes(fb_prop))&&
00239         (wglgsg->get_fb_properties().is_single_buffered())) {
00240       precertify = true;
00241     }
00242     return new wglGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00243                                  flags, gsg, host);
00244   }
00245   
00246   // Nothing else left to try.
00247   return NULL;
00248 }
00249 
00250 ////////////////////////////////////////////////////////////////////
00251 //     Function: wglGraphicsPipe::make_callback_gsg
00252 //       Access: Protected, Virtual
00253 //  Description: This is called when make_output() is used to create a
00254 //               CallbackGraphicsWindow.  If the GraphicsPipe can
00255 //               construct a GSG that's not associated with any
00256 //               particular window object, do so now, assuming the
00257 //               correct graphics context has been set up externally.
00258 ////////////////////////////////////////////////////////////////////
00259 PT(GraphicsStateGuardian) wglGraphicsPipe::
00260 make_callback_gsg(GraphicsEngine *engine) {
00261   return new wglGraphicsStateGuardian(engine, this, NULL);
00262 }
00263 
00264 
00265 ////////////////////////////////////////////////////////////////////
00266 //     Function: wglGraphicsPipe::format_pfd_flags
00267 //       Access: Private, Static
00268 //  Description: Returns pfd_flags formatted as a string in a
00269 //               user-friendly way.
00270 ////////////////////////////////////////////////////////////////////
00271 string wglGraphicsPipe::
00272 format_pfd_flags(DWORD pfd_flags) {
00273   struct FlagDef {
00274     DWORD flag;
00275     const char *name;
00276   };
00277   static FlagDef flag_def[] = {
00278     { PFD_DRAW_TO_WINDOW, "PFD_DRAW_TO_WINDOW" },
00279     { PFD_DRAW_TO_BITMAP, "PFD_DRAW_TO_BITMAP" },
00280     { PFD_SUPPORT_GDI, "PFD_SUPPORT_GDI" },
00281     { PFD_SUPPORT_OPENGL, "PFD_SUPPORT_OPENGL" },
00282     { PFD_GENERIC_ACCELERATED, "PFD_GENERIC_ACCELERATED" },
00283     { PFD_GENERIC_FORMAT, "PFD_GENERIC_FORMAT" },
00284     { PFD_NEED_PALETTE, "PFD_NEED_PALETTE" },
00285     { PFD_NEED_SYSTEM_PALETTE, "PFD_NEED_SYSTEM_PALETTE" },
00286     { PFD_DOUBLEBUFFER, "PFD_DOUBLEBUFFER" },
00287     { PFD_STEREO, "PFD_STEREO" },
00288     { PFD_SWAP_LAYER_BUFFERS, "PFD_SWAP_LAYER_BUFFERS" },
00289     { PFD_SWAP_COPY, "PFD_SWAP_COPY" },
00290     { PFD_SWAP_EXCHANGE, "PFD_SWAP_EXCHANGE" },
00291   };
00292   static const int num_flag_defs = sizeof(flag_def) / sizeof(FlagDef);
00293 
00294   ostringstream out;
00295 
00296   const char *sep = "";
00297   bool got_any = false;
00298   for (int i = 0; i < num_flag_defs; i++) {
00299     if (pfd_flags & flag_def[i].flag) {
00300       out << sep << flag_def[i].name;
00301       pfd_flags &= ~flag_def[i].flag;
00302       sep = "|";
00303       got_any = true;
00304     }
00305   }
00306 
00307   if (pfd_flags != 0 || !got_any) {
00308     out << sep << hex << "0x" << pfd_flags << dec;
00309   }
00310 
00311   return out.str();
00312 }
 All Classes Functions Variables Enumerations