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 }
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
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.
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition: thread.h:109
A container for the various kinds of properties we might ask to have on a graphics window before we o...
bool get_supports_wgl_render_texture() const
Returns true if this particular GSG can render from a wglGraphicsBuffer directly into a texture,...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
A single graphics window for rendering OpenGL under Microsoft Windows.
PT(GraphicsPipe) wglGraphicsPipe
This function is passed to the GraphicsPipeSelection object to allow the user to make a default wglGr...
This is a base class for the various different classes that represent the result of a frame of render...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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.
A thread; that is, a lightweight process.
Definition: thread.h:46
bool pfnum_supports_pbuffer() const
Returns true if the gsg's pixel format is capable of supporting a pbuffer.
Encapsulates all the communication with a particular instance of a given rendering backend.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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:81
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
virtual std::string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.