Panda3D

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_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     // Early success - if we are sure that this buffer WILL
00180     // meet specs, we can precertify it.
00181     if ((wglgsg != 0) &&
00182         (wglgsg->is_valid()) &&
00183         (!wglgsg->needs_reset()) &&
00184         (wglgsg->_supports_framebuffer_object) &&
00185         (wglgsg->_glDrawBuffers != 0)&&
00186         (fb_prop.is_basic())) {
00187       precertify = true;
00188     }
00189     return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00190                                 flags, gsg, host);
00191   }
00192   
00193   // Third thing to try: a wglGraphicsBuffer
00194   
00195   if (retry == 2) {
00196     if (((flags&BF_require_parasite)!=0)||
00197         ((flags&BF_require_window)!=0)) {
00198       return NULL;
00199     }
00200 
00201     if (!support_rtt) {
00202       if (((flags&BF_rtt_cumulative)!=0)||
00203           ((flags&BF_can_bind_every)!=0)) {
00204         // If we require Render-to-Texture, but can't be sure we
00205         // support it, bail.
00206         return NULL;
00207       }
00208     }
00209 
00210     // Early failure - if we are sure that this buffer WONT
00211     // meet specs, we can bail out early.
00212     if ((flags & BF_fb_props_optional) == 0) {
00213       if ((fb_prop.get_aux_rgba() > 0)||
00214           (fb_prop.get_aux_rgba() > 0)||
00215           (fb_prop.get_aux_float() > 0)) {
00216         cerr << "b\n";
00217         return NULL;
00218       }
00219     }
00220     // Early success - if we are sure that this buffer WILL
00221     // meet specs, we can precertify the window.
00222     if ((wglgsg != 0) &&
00223         (wglgsg->is_valid()) &&
00224         (!wglgsg->needs_reset()) &&
00225         (wglgsg->pfnum_supports_pbuffer()) &&
00226         (wglgsg->get_fb_properties().subsumes(fb_prop))&&
00227         (wglgsg->get_fb_properties().is_single_buffered())) {
00228       cerr << "c\n";
00229       precertify = true;
00230     }
00231     cerr << "d\n";
00232     return new wglGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00233                                  flags, gsg, host);
00234   }
00235   
00236   // Nothing else left to try.
00237   return NULL;
00238 }
00239 
00240 
00241 ////////////////////////////////////////////////////////////////////
00242 //     Function: wglGraphicsPipe::format_pfd_flags
00243 //       Access: Private, Static
00244 //  Description: Returns pfd_flags formatted as a string in a
00245 //               user-friendly way.
00246 ////////////////////////////////////////////////////////////////////
00247 string wglGraphicsPipe::
00248 format_pfd_flags(DWORD pfd_flags) {
00249   struct FlagDef {
00250     DWORD flag;
00251     const char *name;
00252   };
00253   static FlagDef flag_def[] = {
00254     { PFD_DRAW_TO_WINDOW, "PFD_DRAW_TO_WINDOW" },
00255     { PFD_DRAW_TO_BITMAP, "PFD_DRAW_TO_BITMAP" },
00256     { PFD_SUPPORT_GDI, "PFD_SUPPORT_GDI" },
00257     { PFD_SUPPORT_OPENGL, "PFD_SUPPORT_OPENGL" },
00258     { PFD_GENERIC_ACCELERATED, "PFD_GENERIC_ACCELERATED" },
00259     { PFD_GENERIC_FORMAT, "PFD_GENERIC_FORMAT" },
00260     { PFD_NEED_PALETTE, "PFD_NEED_PALETTE" },
00261     { PFD_NEED_SYSTEM_PALETTE, "PFD_NEED_SYSTEM_PALETTE" },
00262     { PFD_DOUBLEBUFFER, "PFD_DOUBLEBUFFER" },
00263     { PFD_STEREO, "PFD_STEREO" },
00264     { PFD_SWAP_LAYER_BUFFERS, "PFD_SWAP_LAYER_BUFFERS" },
00265     { PFD_SWAP_COPY, "PFD_SWAP_COPY" },
00266     { PFD_SWAP_EXCHANGE, "PFD_SWAP_EXCHANGE" },
00267   };
00268   static const int num_flag_defs = sizeof(flag_def) / sizeof(FlagDef);
00269 
00270   ostringstream out;
00271 
00272   const char *sep = "";
00273   bool got_any = false;
00274   for (int i = 0; i < num_flag_defs; i++) {
00275     if (pfd_flags & flag_def[i].flag) {
00276       out << sep << flag_def[i].name;
00277       pfd_flags &= ~flag_def[i].flag;
00278       sep = "|";
00279       got_any = true;
00280     }
00281   }
00282 
00283   if (pfd_flags != 0 || !got_any) {
00284     out << sep << hex << "0x" << pfd_flags << dec;
00285   }
00286 
00287   return out.str();
00288 }
 All Classes Functions Variables Enumerations