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