Panda3D
 All Classes Functions Variables Enumerations
wglGraphicsPipe.cxx
1 // Filename: wglGraphicsPipe.cxx
2 // Created by: drose (20Dec02)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "wglGraphicsPipe.h"
16 #include "config_wgldisplay.h"
17 #include "config_windisplay.h"
18 #include "wglGraphicsWindow.h"
19 #include "wglGraphicsBuffer.h"
20 
21 typedef enum {Software, MCD, ICD} OGLDriverType;
22 
23 TypeHandle wglGraphicsPipe::_type_handle;
24 bool wglGraphicsPipe::_current_valid;
25 HDC wglGraphicsPipe::_current_hdc;
26 HGLRC wglGraphicsPipe::_current_hglrc;
27 
28 ////////////////////////////////////////////////////////////////////
29 // Function: wglGraphicsPipe::Constructor
30 // Access: Public
31 // Description:
32 ////////////////////////////////////////////////////////////////////
33 wglGraphicsPipe::
34 wglGraphicsPipe() {
35  _current_valid = false;
36 }
37 
38 ////////////////////////////////////////////////////////////////////
39 // Function: wglGraphicsPipe::Destructor
40 // Access: Public, Virtual
41 // Description:
42 ////////////////////////////////////////////////////////////////////
43 wglGraphicsPipe::
44 ~wglGraphicsPipe() {
45 }
46 
47 ////////////////////////////////////////////////////////////////////
48 // Function: wglGraphicsWindow::wgl_make_current
49 // Access: Private, Static
50 // Description: a thin wrapper around wglMakeCurrent to avoid
51 // unnecessary OS-call overhead.
52 ////////////////////////////////////////////////////////////////////
53 void wglGraphicsPipe::
54 wgl_make_current(HDC hdc, HGLRC hglrc, PStatCollector *collector) {
55  if ((_current_valid) &&
56  (_current_hdc == hdc) &&
57  (_current_hglrc == hglrc)) {
58  return;
59  }
60  _current_valid = true;
61  _current_hdc = hdc;
62  _current_hglrc = hglrc;
63  BOOL res;
64  if (collector) {
65  PStatTimer timer(*collector);
66  res = wglMakeCurrent(hdc, hglrc);
67  } else {
68  res = wglMakeCurrent(hdc, hglrc);
69  }
70 }
71 
72 ////////////////////////////////////////////////////////////////////
73 // Function: wglGraphicsPipe::get_interface_name
74 // Access: Published, Virtual
75 // Description: Returns the name of the rendering interface
76 // associated with this GraphicsPipe. This is used to
77 // present to the user to allow him/her to choose
78 // between several possible GraphicsPipes available on a
79 // particular platform, so the name should be meaningful
80 // and unique for a given platform.
81 ////////////////////////////////////////////////////////////////////
82 string wglGraphicsPipe::
84  return "OpenGL";
85 }
86 
87 ////////////////////////////////////////////////////////////////////
88 // Function: wglGraphicsPipe::pipe_constructor
89 // Access: Public, Static
90 // Description: This function is passed to the GraphicsPipeSelection
91 // object to allow the user to make a default
92 // wglGraphicsPipe.
93 ////////////////////////////////////////////////////////////////////
95 pipe_constructor() {
96  return new wglGraphicsPipe;
97 }
98 
99 ////////////////////////////////////////////////////////////////////
100 // Function: wglGraphicsPipe::make_output
101 // Access: Protected, Virtual
102 // Description: Creates a new window or buffer on the pipe, if possible.
103 // This routine is only called from GraphicsEngine::make_output.
104 ////////////////////////////////////////////////////////////////////
106 make_output(const string &name,
107  const FrameBufferProperties &fb_prop,
108  const WindowProperties &win_prop,
109  int flags,
110  GraphicsEngine *engine,
112  GraphicsOutput *host,
113  int retry,
114  bool &precertify) {
115 
116  if (!_is_valid) {
117  return NULL;
118  }
119 
120  wglGraphicsStateGuardian *wglgsg = 0;
121  if (gsg != 0) {
122  DCAST_INTO_R(wglgsg, gsg, NULL);
123  }
124 
125  bool support_rtt;
126  support_rtt = false;
127  if (wglgsg) {
128  support_rtt =
129  wglgsg -> get_supports_wgl_render_texture() &&
130  support_render_texture;
131  }
132 
133  // First thing to try: a wglGraphicsWindow
134 
135  if (retry == 0) {
136  if (((flags&BF_require_parasite)!=0)||
137  ((flags&BF_refuse_window)!=0)||
138  ((flags&BF_resizeable)!=0)||
139  ((flags&BF_size_track_host)!=0)||
140  ((flags&BF_rtt_cumulative)!=0)||
141  ((flags&BF_can_bind_color)!=0)||
142  ((flags&BF_can_bind_every)!=0)||
143  ((flags&BF_can_bind_layered)!=0)) {
144  return NULL;
145  }
146  if ((flags & BF_fb_props_optional)==0) {
147  if ((fb_prop.get_aux_rgba() > 0)||
148  (fb_prop.get_aux_hrgba() > 0)||
149  (fb_prop.get_aux_float() > 0)) {
150  return NULL;
151  }
152  }
153  return new wglGraphicsWindow(engine, this, name, fb_prop, win_prop,
154  flags, gsg, host);
155  }
156 
157  // Second thing to try: a GLGraphicsBuffer
158 
159  if (retry == 1) {
160  if (!gl_support_fbo || host == NULL ||
161  (flags & (BF_require_parasite | BF_require_window)) != 0) {
162  return NULL;
163  }
164  // Early failure - if we are sure that this buffer WONT
165  // meet specs, we can bail out early.
166  if ((flags & BF_fb_props_optional) == 0) {
167  if (fb_prop.get_indexed_color() ||
168  fb_prop.get_back_buffers() > 0 ||
169  fb_prop.get_accum_bits() > 0) {
170  return NULL;
171  }
172  }
173  if (wglgsg != NULL && wglgsg->is_valid() && !wglgsg->needs_reset()) {
174  if (!wglgsg->_supports_framebuffer_object ||
175  wglgsg->_glDrawBuffers == NULL) {
176  return NULL;
177  } else {
178  // Early success - if we are sure that this buffer WILL
179  // meet specs, we can precertify it.
180  precertify = true;
181  }
182  }
183  return new GLGraphicsBuffer(engine, this, name, fb_prop, win_prop,
184  flags, gsg, host);
185  }
186 
187  // Third thing to try: a wglGraphicsBuffer
188 
189  if (retry == 2) {
190  if (((flags&BF_require_parasite)!=0)||
191  ((flags&BF_require_window)!=0)||
192  ((flags&BF_can_bind_layered)!=0)) {
193  return NULL;
194  }
195  if ((wglgsg != 0) &&
196  (wglgsg->is_valid()) &&
197  (!wglgsg->needs_reset()) &&
198  !wglgsg->_supports_pbuffer) {
199  return NULL;
200  }
201 
202  if (!support_rtt) {
203  if (((flags&BF_rtt_cumulative)!=0)||
204  ((flags&BF_can_bind_every)!=0)) {
205  // If we require Render-to-Texture, but can't be sure we
206  // support it, bail.
207  return NULL;
208  }
209  }
210 
211  // Early failure - if we are sure that this buffer WONT
212  // meet specs, we can bail out early.
213  if ((flags & BF_fb_props_optional) == 0) {
214  if ((fb_prop.get_aux_rgba() > 0)||
215  (fb_prop.get_aux_rgba() > 0)||
216  (fb_prop.get_aux_float() > 0)) {
217  return NULL;
218  }
219  }
220  // Early success - if we are sure that this buffer WILL
221  // meet specs, we can precertify the window.
222  if ((wglgsg != 0) &&
223  (wglgsg->is_valid()) &&
224  (!wglgsg->needs_reset()) &&
225  (wglgsg->pfnum_supports_pbuffer()) &&
226  (wglgsg->get_fb_properties().subsumes(fb_prop))&&
227  (wglgsg->get_fb_properties().is_single_buffered())) {
228  precertify = true;
229  }
230  return new wglGraphicsBuffer(engine, this, name, fb_prop, win_prop,
231  flags, gsg, host);
232  }
233 
234  // Nothing else left to try.
235  return NULL;
236 }
237 
238 ////////////////////////////////////////////////////////////////////
239 // Function: wglGraphicsPipe::make_callback_gsg
240 // Access: Protected, Virtual
241 // Description: This is called when make_output() is used to create a
242 // CallbackGraphicsWindow. If the GraphicsPipe can
243 // construct a GSG that's not associated with any
244 // particular window object, do so now, assuming the
245 // correct graphics context has been set up externally.
246 ////////////////////////////////////////////////////////////////////
248 make_callback_gsg(GraphicsEngine *engine) {
249  return new wglGraphicsStateGuardian(engine, this, NULL);
250 }
251 
252 
253 ////////////////////////////////////////////////////////////////////
254 // Function: wglGraphicsPipe::format_pfd_flags
255 // Access: Private, Static
256 // Description: Returns pfd_flags formatted as a string in a
257 // user-friendly way.
258 ////////////////////////////////////////////////////////////////////
259 string wglGraphicsPipe::
260 format_pfd_flags(DWORD pfd_flags) {
261  struct FlagDef {
262  DWORD flag;
263  const char *name;
264  };
265  static FlagDef flag_def[] = {
266  { PFD_DRAW_TO_WINDOW, "PFD_DRAW_TO_WINDOW" },
267  { PFD_DRAW_TO_BITMAP, "PFD_DRAW_TO_BITMAP" },
268  { PFD_SUPPORT_GDI, "PFD_SUPPORT_GDI" },
269  { PFD_SUPPORT_OPENGL, "PFD_SUPPORT_OPENGL" },
270  { PFD_GENERIC_ACCELERATED, "PFD_GENERIC_ACCELERATED" },
271  { PFD_GENERIC_FORMAT, "PFD_GENERIC_FORMAT" },
272  { PFD_NEED_PALETTE, "PFD_NEED_PALETTE" },
273  { PFD_NEED_SYSTEM_PALETTE, "PFD_NEED_SYSTEM_PALETTE" },
274  { PFD_DOUBLEBUFFER, "PFD_DOUBLEBUFFER" },
275  { PFD_STEREO, "PFD_STEREO" },
276  { PFD_SWAP_LAYER_BUFFERS, "PFD_SWAP_LAYER_BUFFERS" },
277  { PFD_SWAP_COPY, "PFD_SWAP_COPY" },
278  { PFD_SWAP_EXCHANGE, "PFD_SWAP_EXCHANGE" },
279  };
280  static const int num_flag_defs = sizeof(flag_def) / sizeof(FlagDef);
281 
282  ostringstream out;
283 
284  const char *sep = "";
285  bool got_any = false;
286  for (int i = 0; i < num_flag_defs; i++) {
287  if (pfd_flags & flag_def[i].flag) {
288  out << sep << flag_def[i].name;
289  pfd_flags &= ~flag_def[i].flag;
290  sep = "|";
291  got_any = true;
292  }
293  }
294 
295  if (pfd_flags != 0 || !got_any) {
296  out << sep << hex << "0x" << pfd_flags << dec;
297  }
298 
299  return out.str();
300 }
virtual string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.
bool pfnum_supports_pbuffer() const
Returns true if the gsg&#39;s pixel format is capable of supporting a pbuffer.
bool get_supports_wgl_render_texture() const
Returns true if this particular GSG can render from a wglGraphicsBuffer directly into a texture...
const FrameBufferProperties & get_fb_properties() const
Returns the properties of the pixel format that was chosen for this gsg.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
A lightweight class that represents a single element that may be timed and/or counted via stats...
A container for the various kinds of properties we might ask to have on a graphics window before we o...
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
A single graphics window for rendering OpenGL under Microsoft Windows.
This is a base class for the various different classes that represent the result of a frame of render...
This graphics pipe represents the interface for creating OpenGL graphics windows on the various Windo...
An offscreen render buffer.
Encapsulates all the communication with a particular instance of a given rendering backend...
This class is the main interface to controlling the render process.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...