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 }
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
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
GraphicsBuffer
An offscreen buffer for rendering into.
Definition: graphicsBuffer.h:27
config_glxdisplay.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
glgsg.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
GraphicsOutput::get_y_size
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
Definition: graphicsOutput.I:159
GraphicsOutput::get_x_size
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
Definition: graphicsOutput.I:145
glxGraphicsPipe
This graphics pipe represents the interface for creating OpenGL graphics windows on an X-based (e....
Definition: glxGraphicsPipe.h:76
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
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
graphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
GraphicsEngine
This class is the main interface to controlling the render process.
Definition: graphicsEngine.h:53
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
GraphicsOutput
This is a base class for the various different classes that represent the result of a frame of render...
Definition: graphicsOutput.h:63
glxGraphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
CycleDataWriter
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
Definition: cycleDataWriter.h:34
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
glxGraphicsBuffer::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: glxGraphicsBuffer.cxx:63
GraphicsOutput::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
Definition: graphicsOutput.I:413
CycleDataLockedReader
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
Definition: cycleDataLockedReader.h:40
x11GraphicsPipe::get_screen
int get_screen() const
Returns the X screen number associated with the pipe.
Definition: x11GraphicsPipe.I:27
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
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
glxGraphicsBuffer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
glxGraphicsBuffer::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: glxGraphicsBuffer.cxx:109
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
glxGraphicsStateGuardian
A tiny specialization on GLGraphicsStateGuardian to add some glx-specific information.
Definition: glxGraphicsStateGuardian.h:74
glxGraphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.