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_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 }