Panda3D
|
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 00208 if (!support_rtt) { 00209 if (((flags&BF_rtt_cumulative)!=0)|| 00210 ((flags&BF_can_bind_every)!=0)) { 00211 // If we require Render-to-Texture, but can't be sure we 00212 // support it, bail. 00213 return NULL; 00214 } 00215 } 00216 00217 // Early failure - if we are sure that this buffer WONT 00218 // meet specs, we can bail out early. 00219 if ((flags & BF_fb_props_optional) == 0) { 00220 if ((fb_prop.get_aux_rgba() > 0)|| 00221 (fb_prop.get_aux_rgba() > 0)|| 00222 (fb_prop.get_aux_float() > 0)) { 00223 return NULL; 00224 } 00225 } 00226 // Early success - if we are sure that this buffer WILL 00227 // meet specs, we can precertify the window. 00228 if ((wglgsg != 0) && 00229 (wglgsg->is_valid()) && 00230 (!wglgsg->needs_reset()) && 00231 (wglgsg->pfnum_supports_pbuffer()) && 00232 (wglgsg->get_fb_properties().subsumes(fb_prop))&& 00233 (wglgsg->get_fb_properties().is_single_buffered())) { 00234 precertify = true; 00235 } 00236 return new wglGraphicsBuffer(engine, this, name, fb_prop, win_prop, 00237 flags, gsg, host); 00238 } 00239 00240 // Nothing else left to try. 00241 return NULL; 00242 } 00243 00244 //////////////////////////////////////////////////////////////////// 00245 // Function: wglGraphicsPipe::make_callback_gsg 00246 // Access: Protected, Virtual 00247 // Description: This is called when make_output() is used to create a 00248 // CallbackGraphicsWindow. If the GraphicsPipe can 00249 // construct a GSG that's not associated with any 00250 // particular window object, do so now, assuming the 00251 // correct graphics context has been set up externally. 00252 //////////////////////////////////////////////////////////////////// 00253 PT(GraphicsStateGuardian) wglGraphicsPipe:: 00254 make_callback_gsg(GraphicsEngine *engine) { 00255 return new wglGraphicsStateGuardian(engine, this, NULL); 00256 } 00257 00258 00259 //////////////////////////////////////////////////////////////////// 00260 // Function: wglGraphicsPipe::format_pfd_flags 00261 // Access: Private, Static 00262 // Description: Returns pfd_flags formatted as a string in a 00263 // user-friendly way. 00264 //////////////////////////////////////////////////////////////////// 00265 string wglGraphicsPipe:: 00266 format_pfd_flags(DWORD pfd_flags) { 00267 struct FlagDef { 00268 DWORD flag; 00269 const char *name; 00270 }; 00271 static FlagDef flag_def[] = { 00272 { PFD_DRAW_TO_WINDOW, "PFD_DRAW_TO_WINDOW" }, 00273 { PFD_DRAW_TO_BITMAP, "PFD_DRAW_TO_BITMAP" }, 00274 { PFD_SUPPORT_GDI, "PFD_SUPPORT_GDI" }, 00275 { PFD_SUPPORT_OPENGL, "PFD_SUPPORT_OPENGL" }, 00276 { PFD_GENERIC_ACCELERATED, "PFD_GENERIC_ACCELERATED" }, 00277 { PFD_GENERIC_FORMAT, "PFD_GENERIC_FORMAT" }, 00278 { PFD_NEED_PALETTE, "PFD_NEED_PALETTE" }, 00279 { PFD_NEED_SYSTEM_PALETTE, "PFD_NEED_SYSTEM_PALETTE" }, 00280 { PFD_DOUBLEBUFFER, "PFD_DOUBLEBUFFER" }, 00281 { PFD_STEREO, "PFD_STEREO" }, 00282 { PFD_SWAP_LAYER_BUFFERS, "PFD_SWAP_LAYER_BUFFERS" }, 00283 { PFD_SWAP_COPY, "PFD_SWAP_COPY" }, 00284 { PFD_SWAP_EXCHANGE, "PFD_SWAP_EXCHANGE" }, 00285 }; 00286 static const int num_flag_defs = sizeof(flag_def) / sizeof(FlagDef); 00287 00288 ostringstream out; 00289 00290 const char *sep = ""; 00291 bool got_any = false; 00292 for (int i = 0; i < num_flag_defs; i++) { 00293 if (pfd_flags & flag_def[i].flag) { 00294 out << sep << flag_def[i].name; 00295 pfd_flags &= ~flag_def[i].flag; 00296 sep = "|"; 00297 got_any = true; 00298 } 00299 } 00300 00301 if (pfd_flags != 0 || !got_any) { 00302 out << sep << hex << "0x" << pfd_flags << dec; 00303 } 00304 00305 return out.str(); 00306 }