Panda3D
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 ////////////////////////////////////////////////////////////////////
94 PT(GraphicsPipe) wglGraphicsPipe::
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 ////////////////////////////////////////////////////////////////////
105 PT(GraphicsOutput) wglGraphicsPipe::
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 ////////////////////////////////////////////////////////////////////
247 PT(GraphicsStateGuardian) wglGraphicsPipe::
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.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
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...
const FrameBufferProperties & get_fb_properties() const
Returns the properties of the pixel format that was chosen for this gsg.
An offscreen render buffer.
bool pfnum_supports_pbuffer() const
Returns true if the gsg&#39;s pixel format is capable of supporting a pbuffer.
Encapsulates all the communication with a particular instance of a given rendering backend...
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
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...