Panda3D
glxGraphicsBuffer.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 glxGraphicsBuffer.cxx
10  * @author drose
11  * @date 2004-02-09
12  */
13 
14 #include "glxGraphicsBuffer.h"
16 #include "config_glxdisplay.h"
17 #include "glxGraphicsPipe.h"
18 
19 #include "graphicsPipe.h"
20 #include "glgsg.h"
21 #include "pStatTimer.h"
22 
23 TypeHandle glxGraphicsBuffer::_type_handle;
24 
25 /**
26  *
27  */
28 glxGraphicsBuffer::
29 glxGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
30  const std::string &name,
31  const FrameBufferProperties &fb_prop,
32  const WindowProperties &win_prop,
33  int flags,
35  GraphicsOutput *host) :
36  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
37 {
38  glxGraphicsPipe *glx_pipe;
39  DCAST_INTO_V(glx_pipe, _pipe);
40  _display = glx_pipe->get_display();
41  _pbuffer = None;
42 
43  // Since the pbuffer never gets flipped, we get screenshots from the same
44  // buffer we draw into.
45  _screenshot_buffer_type = _draw_buffer_type;
46 }
47 
48 /**
49  *
50  */
51 glxGraphicsBuffer::
52 ~glxGraphicsBuffer() {
53  nassertv(_pbuffer == None);
54 }
55 
56 /**
57  * This function will be called within the draw thread before beginning
58  * rendering for a given frame. It should do whatever setup is required, and
59  * return true if the frame should be rendered, or false if it should be
60  * skipped.
61  */
63 begin_frame(FrameMode mode, Thread *current_thread) {
64  PStatTimer timer(_make_current_pcollector, current_thread);
65 
66  begin_frame_spam(mode);
67  if (_gsg == nullptr ||
68  _pbuffer == None) {
69  return false;
70  }
71 
73  DCAST_INTO_R(glxgsg, _gsg, false);
74  {
75  LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
76  glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
77  }
78 
79  // Now that we have made the context current to a window, we can reset the
80  // GSG state if this is the first time it has been used. (We can't just
81  // call reset() when we construct the GSG, because reset() requires having a
82  // current context.)
83  glxgsg->reset_if_new();
84 
85  if (mode == FM_render) {
86  CDLockedReader cdata(_cycler);
87  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
88  const RenderTexture &rt = cdata->_textures[i];
89  RenderTextureMode rtm_mode = rt._rtm_mode;
90  if (rtm_mode == RTM_bind_or_copy) {
91  CDWriter cdataw(_cycler, cdata, false);
92  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
93  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
94  }
95  }
96  clear_cube_map_selection();
97  }
98 
99  _gsg->set_current_properties(&get_fb_properties());
100  return _gsg->begin_frame(current_thread);
101 }
102 
103 /**
104  * This function will be called within the draw thread after rendering is
105  * completed for a given frame. It should do whatever finalization is
106  * required.
107  */
109 end_frame(FrameMode mode, Thread *current_thread) {
110  end_frame_spam(mode);
111  nassertv(_gsg != nullptr);
112 
113  if (mode == FM_render) {
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 }
124 
125 /**
126  * Closes the buffer right now. Called from the window thread.
127  */
128 void glxGraphicsBuffer::
129 close_buffer() {
130  if (_gsg != nullptr) {
131  LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
132  glXMakeCurrent(_display, None, nullptr);
133 
134  if (_pbuffer != None) {
135  glxGraphicsStateGuardian *glxgsg;
136  DCAST_INTO_V(glxgsg, _gsg);
137  glxgsg->_glXDestroyPbuffer(_display, _pbuffer);
138  _pbuffer = None;
139  }
140 
141  _gsg.clear();
142  }
143 
144  _pbuffer = None;
145  _is_valid = false;
146 }
147 
148 /**
149  * Opens the buffer right now. Called from the window thread. Returns true
150  * if the buffer is successfully opened, or false if there was a problem.
151  */
152 bool glxGraphicsBuffer::
153 open_buffer() {
154  glxGraphicsPipe *glx_pipe;
155  DCAST_INTO_R(glx_pipe, _pipe, false);
156 
157  // GSG CreationInitialization
158  glxGraphicsStateGuardian *glxgsg;
159  if (_gsg == nullptr) {
160  // There is no old gsg. Create a new one.
161  glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, nullptr);
162  glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
163  _gsg = glxgsg;
164  } else {
165  // If the old gsg has the wrong pixel format, create a new one that shares
166  // with the old gsg.
167  DCAST_INTO_R(glxgsg, _gsg, false);
168 
169  if (!glxgsg->_context_has_pbuffer ||
170  !glxgsg->get_fb_properties().subsumes(_fb_properties)) {
171  // We need a new pixel format, and hence a new GSG.
172  glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
173  glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
174  _gsg = glxgsg;
175  }
176  }
177 
178  if (glxgsg->_fbconfig == None || !glxgsg->_context_has_pbuffer) {
179  // If we didn't use an fbconfig to create the GSG, or it doesn't support
180  // buffers, we can't create a PBuffer.
181  return false;
182  }
183 
184  nassertr(glxgsg->_supports_pbuffer, false);
185 
186  LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
187 
188  static const int max_attrib_list = 32;
189  int attrib_list[max_attrib_list];
190  int n = 0;
191 
192  if (glxgsg->_uses_sgix_pbuffer) {
193  // The SGI version passed in the size in the parameter list.
194  nassertr(n < max_attrib_list, false);
195  attrib_list[n] = (int)None;
196  _pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig,
197  get_x_size(), get_y_size(), attrib_list);
198  } else {
199  // The official GLX 1.3 version passes in the size in the attrib list.
200  attrib_list[n++] = GLX_PBUFFER_WIDTH;
201  attrib_list[n++] = get_x_size();
202  attrib_list[n++] = GLX_PBUFFER_HEIGHT;
203  attrib_list[n++] = get_y_size();
204 
205  nassertr(n < max_attrib_list, false);
206  attrib_list[n] = (int)None;
207  _pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig,
208  attrib_list);
209  }
210 
211  if (_pbuffer == None) {
212  glxdisplay_cat.error()
213  << "failed to create GLX pbuffer.\n";
214  return false;
215  }
216 
217  glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
218  glxgsg->reset_if_new();
219  if (!glxgsg->is_valid()) {
220  close_buffer();
221  return false;
222  }
224  (_fb_properties, glxgsg->get_gl_renderer())) {
225  close_buffer();
226  return false;
227  }
228  _fb_properties = glxgsg->get_fb_properties();
229 
230  _is_valid = true;
231  return true;
232 }
This graphics pipe represents the interface for creating OpenGL graphics windows on an X-based (e....
A tiny specialization on GLGraphicsStateGuardian to add some glx-specific information.
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.
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
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
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A container for the various kinds of properties we might ask to have on a graphics window before we o...
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.
An offscreen buffer for rendering into.
int get_screen() const
Returns the X screen number associated with the pipe.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
X11_Display * get_display() const
Returns a pointer to the X display associated with the pipe: the display on which to create the windo...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
This is a base class for the various different classes that represent the result of a frame of render...
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).
Similar to MutexHolder, but for a light reentrant mutex.
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A thread; that is, a lightweight process.
Definition: thread.h:46
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.
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.
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...
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.