Panda3D

glxGraphicsWindow.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 glxGraphicsWindow.cxx
10 * @author mike
11 * @date 1997-01-09
12 */
13
14 #include "glxGraphicsWindow.h"
15 #include "glxGraphicsStateGuardian.h"
16 #include "config_glxdisplay.h"
17 #include "glxGraphicsPipe.h"
18
19 #include "graphicsPipe.h"
20 #include "keyboardButton.h"
21 #include "mouseButton.h"
22 #include "glgsg.h"
23 #include "clockObject.h"
24 #include "pStatTimer.h"
25 #include "textEncoder.h"
26 #include "throw_event.h"
27 #include "lightReMutexHolder.h"
28
29 #include <errno.h>
30 #include <sys/time.h>
31
32 TypeHandle glxGraphicsWindow::_type_handle;
33
34 /**
35 *
36 */
37 glxGraphicsWindow::
38 glxGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
39 const std::string &name,
40 const FrameBufferProperties &fb_prop,
41 const WindowProperties &win_prop,
42 int flags,
43 GraphicsStateGuardian *gsg,
44 GraphicsOutput *host) :
45 x11GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
46 {
47 }
48
49 /**
50 * This function will be called within the draw thread before beginning
51 * rendering for a given frame. It should do whatever setup is required, and
52 * return true if the frame should be rendered, or false if it should be
53 * skipped.
54 */
55 bool glxGraphicsWindow::
56 begin_frame(FrameMode mode, Thread *current_thread) {
57 PStatTimer timer(_make_current_pcollector, current_thread);
58
59 begin_frame_spam(mode);
60 if (_gsg == nullptr) {
61 return false;
62 }
63 if (_awaiting_configure) {
64 // Don't attempt to draw while we have just reconfigured the window and we
65 // haven't got the notification back yet.
66 return false;
67 }
68
69 glxGraphicsStateGuardian *glxgsg;
70 DCAST_INTO_R(glxgsg, _gsg, false);
71 {
72 LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
73
74 if (glXGetCurrentDisplay() == _display &&
75 glXGetCurrentDrawable() == _xwindow &&
76 glXGetCurrentContext() == glxgsg->_context) {
77 // No need to make the context current again. Short-circuit this
78 // possibly-expensive call.
79 } else {
80 // Need to set the context.
81 glXMakeCurrent(_display, _xwindow, glxgsg->_context);
82 }
83 }
84
85 // Now that we have made the context current to a window, we can reset the
86 // GSG state if this is the first time it has been used. (We can't just
87 // call reset() when we construct the GSG, because reset() requires having a
88 // current context.)
89 glxgsg->reset_if_new();
90
91 if (mode == FM_render) {
92 glxgsg->push_group_marker(std::string("glxGraphicsWindow ") + get_name());
93 // begin_render_texture();
94 clear_cube_map_selection();
95 }
96
97 _gsg->set_current_properties(&get_fb_properties());
98 return _gsg->begin_frame(current_thread);
99 }
100
101
102 /**
103 * This function will be called within the draw thread after rendering is
104 * completed for a given frame. It should do whatever finalization is
105 * required.
106 */
107 void glxGraphicsWindow::
108 end_frame(FrameMode mode, Thread *current_thread) {
109 end_frame_spam(mode);
110 nassertv(_gsg != nullptr);
111
112 if (mode == FM_render) {
113 // end_render_texture();
114 copy_to_textures();
115 }
116
117 _gsg->end_frame(current_thread);
118
119 if (mode == FM_render) {
120 trigger_flip();
121 clear_cube_map_selection();
122
123 glxGraphicsStateGuardian *glxgsg;
124 DCAST_INTO_V(glxgsg, _gsg);
125 glxgsg->pop_group_marker();
126 }
127 }
128
129 /**
130 * This function will be called within the draw thread after begin_flip() has
131 * been called on all windows, to finish the exchange of the front and back
132 * buffers.
133 *
134 * This should cause the window to wait for the flip, if necessary.
135 */
136 void glxGraphicsWindow::
137 end_flip() {
138 if (_gsg != nullptr && _flip_ready) {
139
140 // It doesn't appear to be necessary to ensure the graphics context is
141 // current before flipping the windows, and insisting on doing so can be a
142 // significant performance hit.
143
144 // make_current();
145
146 LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
147 glXSwapBuffers(_display, _xwindow);
148 }
149 GraphicsWindow::end_flip();
150 }
151
152 /**
153 * Closes the window right now. Called from the window thread.
154 */
155 void glxGraphicsWindow::
156 close_window() {
157 LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
158
159 if (_gsg != nullptr) {
160 glXMakeCurrent(_display, None, nullptr);
161 _gsg.clear();
162 }
163
164 x11GraphicsWindow::close_window();
165 }
166
167 /**
168 * Opens the window right now. Called from the window thread. Returns true
169 * if the window is successfully opened, or false if there was a problem.
170 */
171 bool glxGraphicsWindow::
172 open_window() {
173 glxGraphicsPipe *glx_pipe;
174 DCAST_INTO_R(glx_pipe, _pipe, false);
175
176 // GSG CreationInitialization
177 glxGraphicsStateGuardian *glxgsg;
178 if (_gsg == nullptr) {
179 // There is no old gsg. Create a new one.
180 glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, nullptr);
181 glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
182 _gsg = glxgsg;
183 } else {
184 // If the old gsg has the wrong pixel format, create a new one that shares
185 // with the old gsg.
186 DCAST_INTO_R(glxgsg, _gsg, false);
187 if (!glxgsg->get_fb_properties().subsumes(_fb_properties)) {
188 glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
189 glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), false, false);
190 _gsg = glxgsg;
191 }
192 }
193
194 if (glxgsg->_context == nullptr) {
195 // We're supposed to have a context at this point.
196 glxdisplay_cat.error()
197 << "No GLX context: cannot open window.\n";
198 return false;
199 }
200
201 _visual_info = glxgsg->_visual;
202 if (_visual_info == nullptr) {
203 // No X visual for this fbconfig; how can we open the window?
204 glxdisplay_cat.error()
205 << "No X visual: cannot open window.\n";
206 return false;
207 }
208
209 LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
210
211 if (glxgsg->_fbconfig != None) {
212 setup_colormap(glxgsg->_fbconfig);
213 } else {
214 setup_colormap(_visual_info);
215 }
216
217 if (!x11GraphicsWindow::open_window()) {
218 return false;
219 }
220
221 glXMakeCurrent(_display, _xwindow, glxgsg->_context);
222 glxgsg->reset_if_new();
223 if (!glxgsg->is_valid()) {
224 close_window();
225 return false;
226 }
227 if (!glxgsg->get_fb_properties().verify_hardware_software
228 (_fb_properties, glxgsg->get_gl_renderer())) {
229 close_window();
230 return false;
231 }
232 _fb_properties = glxgsg->get_fb_properties();
233
234 return true;
235 }
236
237 /**
238 * Allocates a colormap appropriate to the fbconfig and stores in in the
239 * _colormap method.
240 */
241 void glxGraphicsWindow::
242 setup_colormap(GLXFBConfig fbconfig) {
243 glxGraphicsStateGuardian *glxgsg;
244 DCAST_INTO_V(glxgsg, _gsg);
245 nassertv(glxgsg->_supports_fbconfig);
246
247 XVisualInfo *visual_info = glxgsg->_glXGetVisualFromFBConfig(_display, fbconfig);
248 if (visual_info == nullptr) {
249 // No X visual; no need to set up a colormap.
250 return;
251 }
252 int visual_class = visual_info->c_class;
253 Visual *visual = visual_info->visual;
254 XFree(visual_info);
255
256 glxGraphicsPipe *glx_pipe;
257 DCAST_INTO_V(glx_pipe, _pipe);
258 X11_Window root_window = glx_pipe->get_root();
259
260 int rc, is_rgb;
261
262 switch (visual_class) {
263 case PseudoColor:
264 rc = glxgsg->_glXGetFBConfigAttrib(_display, fbconfig, GLX_RGBA, &is_rgb);
265 if (rc == 0 && is_rgb) {
266 glxdisplay_cat.warning()
267 << "mesa pseudocolor not supported.\n";
268 // this is a terrible terrible hack, but it seems to work
269 _colormap = (Colormap)0;
270
271 } else {
272 _colormap = XCreateColormap(_display, root_window,
273 visual, AllocAll);
274 }
275 break;
276 case TrueColor:
277 case DirectColor:
278 _colormap = XCreateColormap(_display, root_window,
279 visual, AllocNone);
280 break;
281 case StaticColor:
282 case StaticGray:
283 case GrayScale:
284 _colormap = XCreateColormap(_display, root_window,
285 visual, AllocNone);
286 break;
287 default:
288 glxdisplay_cat.error()
289 << "Could not allocate a colormap for visual class "
290 << visual_class << ".\n";
291 break;
292 }
293 }
294
295 /**
296 * Allocates a colormap appropriate to the visual and stores in in the
297 * _colormap method.
298 */
299 void glxGraphicsWindow::
300 setup_colormap(XVisualInfo *visual) {
301 glxGraphicsPipe *glx_pipe;
302 DCAST_INTO_V(glx_pipe, _pipe);
303 X11_Window root_window = glx_pipe->get_root();
304
305 int visual_class = visual->c_class;
306 int rc, is_rgb;
307
308 switch (visual_class) {
309 case PseudoColor:
310 rc = glXGetConfig(_display, visual, GLX_RGBA, &is_rgb);
311 if (rc == 0 && is_rgb) {
312 glxdisplay_cat.warning()
313 << "mesa pseudocolor not supported.\n";
314 // this is a terrible terrible hack, but it seems to work
315 _colormap = (Colormap)0;
316
317 } else {
318 _colormap = XCreateColormap(_display, root_window,
319 visual->visual, AllocAll);
320 }
321 break;
322 case TrueColor:
323 case DirectColor:
324 _colormap = XCreateColormap(_display, root_window,
325 visual->visual, AllocNone);
326 break;
327 case StaticColor:
328 case StaticGray:
329 case GrayScale:
330 _colormap = XCreateColormap(_display, root_window,
331 visual->visual, AllocNone);
332 break;
333 default:
334 glxdisplay_cat.error()
335 << "Could not allocate a colormap for visual class "
336 << visual_class << ".\n";
337 break;
338 }
339 }
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
FrameBufferProperties::verify_hardware_software
bool verify_hardware_software(const FrameBufferProperties &props, const std::string &renderer) const
Validates that the properties represent the desired kind of renderer (hardware or software).
Definition: frameBufferProperties.cxx:604
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
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
GraphicsOutput::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: graphicsOutput.cxx:1299
GraphicsOutput::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
Definition: graphicsOutput.I:413
GraphicsOutput::get_name
get_name
Returns the name that was passed to the GraphicsOutput constructor.
Definition: graphicsOutput.h:120
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
PStatTimer
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:30
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
TypeHandle
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
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
glxGraphicsPipe
This graphics pipe represents the interface for creating OpenGL graphics windows on an X-based (e....
Definition: glxGraphicsPipe.h:76
glxGraphicsStateGuardian
A tiny specialization on GLGraphicsStateGuardian to add some glx-specific information.
Definition: glxGraphicsStateGuardian.h:74
glxGraphicsStateGuardian::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
Definition: glxGraphicsStateGuardian.I:19
glxGraphicsStateGuardian::choose_pixel_format
void choose_pixel_format(const FrameBufferProperties &properties, X11_Display *_display, int _screen, bool need_pbuffer, bool need_pixmap)
Selects a visual or fbconfig for all the windows and buffers that use this gsg.
Definition: glxGraphicsStateGuardian.cxx:226
glxGraphicsWindow::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: glxGraphicsWindow.cxx:137
glxGraphicsWindow::begin_frame
virtual bool begin_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread before beginning rendering for a given frame.
Definition: glxGraphicsWindow.cxx:56
glxGraphicsWindow::end_frame
virtual void end_frame(FrameMode mode, Thread *current_thread)
This function will be called within the draw thread after rendering is completed for a given frame.
Definition: glxGraphicsWindow.cxx:108
x11GraphicsPipe::get_root
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
Definition: x11GraphicsPipe.I:35
x11GraphicsPipe::get_display
X11_Display * get_display() const
Returns a pointer to the X display associated with the pipe: the display on which to create the windo...
Definition: x11GraphicsPipe.I:19
x11GraphicsPipe::get_screen
int get_screen() const
Returns the X screen number associated with the pipe.
Definition: x11GraphicsPipe.I:27
x11GraphicsWindow
Interfaces to the X11 window system.
Definition: x11GraphicsWindow.h:26
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
config_glxdisplay.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
glgsg.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
glxGraphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
glxGraphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
glxGraphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
graphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
keyboardButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightReMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
textEncoder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.