Panda3D
Loading...
Searching...
No Matches
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
21TypeHandle wglGraphicsPipe::_type_handle;
22bool wglGraphicsPipe::_current_valid;
23HDC wglGraphicsPipe::_current_hdc;
24HGLRC wglGraphicsPipe::_current_hglrc;
25Thread *wglGraphicsPipe::_current_thread;
26
27/**
28 *
29 */
30wglGraphicsPipe::
31wglGraphicsPipe() {
32 _current_valid = false;
33}
34
35/**
36 *
37 */
38wglGraphicsPipe::
39~wglGraphicsPipe() {
40}
41
42/**
43 * a thin wrapper around wglMakeCurrent to avoid unnecessary OS-call overhead.
44 */
45bool wglGraphicsPipe::
46wgl_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 */
75get_interface_name() const {
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 */
83PT(GraphicsPipe) wglGraphicsPipe::
84pipe_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 */
92PT(GraphicsOutput) wglGraphicsPipe::
93make_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 */
231PT(GraphicsStateGuardian) wglGraphicsPipe::
232make_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 */
240std::string wglGraphicsPipe::
241format_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}
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
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.
This is a base class for the various different classes that represent the result of a frame of render...
An object to create GraphicsOutputs that share a particular 3-D API.
Encapsulates all the communication with a particular instance of a given rendering backend.
A lightweight class that represents a single element that may be timed and/or counted via stats.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition pStatTimer.h:30
A thread; that is, a lightweight process.
Definition thread.h:46
get_current_thread
Returns a pointer to the currently-executing Thread object.
Definition thread.h:109
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 window before we o...
An offscreen render buffer.
This graphics pipe represents the interface for creating OpenGL graphics windows on the various Windo...
virtual std::string get_interface_name() const
Returns the name of the rendering interface associated with this GraphicsPipe.
A tiny specialization on GLGraphicsStateGuardian to add some wgl-specific information.
bool pfnum_supports_pbuffer() const
Returns true if the gsg's pixel format is capable of supporting a pbuffer.
const FrameBufferProperties & get_fb_properties() const
Returns the properties of the pixel format that was chosen for this gsg.
A single graphics window for rendering OpenGL under Microsoft Windows.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.