Panda3D
 All Classes Functions Variables Enumerations
glxGraphicsBuffer.cxx
1 // Filename: glxGraphicsBuffer.cxx
2 // Created by: drose (09Feb04)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "glxGraphicsBuffer.h"
16 #include "glxGraphicsStateGuardian.h"
17 #include "config_glxdisplay.h"
18 #include "glxGraphicsPipe.h"
19 
20 #include "graphicsPipe.h"
21 #include "glgsg.h"
22 #include "pStatTimer.h"
23 
24 TypeHandle glxGraphicsBuffer::_type_handle;
25 
26 ////////////////////////////////////////////////////////////////////
27 // Function: glxGraphicsBuffer::Constructor
28 // Access: Public
29 // Description:
30 ////////////////////////////////////////////////////////////////////
31 glxGraphicsBuffer::
32 glxGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
33  const string &name,
34  const FrameBufferProperties &fb_prop,
35  const WindowProperties &win_prop,
36  int flags,
38  GraphicsOutput *host) :
39  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
40 {
41  glxGraphicsPipe *glx_pipe;
42  DCAST_INTO_V(glx_pipe, _pipe);
43  _display = glx_pipe->get_display();
44  _pbuffer = None;
45 
46  // Since the pbuffer never gets flipped, we get screenshots from the
47  // same buffer we draw into.
48  _screenshot_buffer_type = _draw_buffer_type;
49 }
50 
51 ////////////////////////////////////////////////////////////////////
52 // Function: glxGraphicsBuffer::Destructor
53 // Access: Public, Virtual
54 // Description:
55 ////////////////////////////////////////////////////////////////////
56 glxGraphicsBuffer::
57 ~glxGraphicsBuffer() {
58  nassertv(_pbuffer == None);
59 }
60 
61 ////////////////////////////////////////////////////////////////////
62 // Function: glxGraphicsBuffer::begin_frame
63 // Access: Public, Virtual
64 // Description: This function will be called within the draw thread
65 // before beginning rendering for a given frame. It
66 // should do whatever setup is required, and return true
67 // if the frame should be rendered, or false if it
68 // should be skipped.
69 ////////////////////////////////////////////////////////////////////
71 begin_frame(FrameMode mode, Thread *current_thread) {
72  PStatTimer timer(_make_current_pcollector, current_thread);
73 
74  begin_frame_spam(mode);
75  if (_gsg == (GraphicsStateGuardian *)NULL ||
76  _pbuffer == None) {
77  return false;
78  }
79 
81  DCAST_INTO_R(glxgsg, _gsg, false);
82  glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
83 
84  // Now that we have made the context current to a window, we can
85  // reset the GSG state if this is the first time it has been used.
86  // (We can't just call reset() when we construct the GSG, because
87  // reset() requires having a current context.)
88  glxgsg->reset_if_new();
89 
90  if (mode == FM_render) {
91  CDLockedReader cdata(_cycler);
92  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
93  const RenderTexture &rt = cdata->_textures[i];
94  RenderTextureMode rtm_mode = rt._rtm_mode;
95  if (rtm_mode == RTM_bind_or_copy) {
96  CDWriter cdataw(_cycler, cdata, false);
97  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
98  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
99  }
100  }
101  clear_cube_map_selection();
102  }
103 
104  _gsg->set_current_properties(&get_fb_properties());
105  return _gsg->begin_frame(current_thread);
106 }
107 
108 ////////////////////////////////////////////////////////////////////
109 // Function: glxGraphicsBuffer::end_frame
110 // Access: Public, Virtual
111 // Description: This function will be called within the draw thread
112 // after rendering is completed for a given frame. It
113 // should do whatever finalization is required.
114 ////////////////////////////////////////////////////////////////////
116 end_frame(FrameMode mode, Thread *current_thread) {
117  end_frame_spam(mode);
118  nassertv(_gsg != (GraphicsStateGuardian *)NULL);
119 
120  if (mode == FM_render) {
121  copy_to_textures();
122  }
123 
124  _gsg->end_frame(current_thread);
125 
126  if (mode == FM_render) {
127  trigger_flip();
128  clear_cube_map_selection();
129  }
130 }
131 
132 ////////////////////////////////////////////////////////////////////
133 // Function: glxGraphicsBuffer::close_buffer
134 // Access: Protected, Virtual
135 // Description: Closes the buffer right now. Called from the window
136 // thread.
137 ////////////////////////////////////////////////////////////////////
138 void glxGraphicsBuffer::
139 close_buffer() {
140  if (_gsg != (GraphicsStateGuardian *)NULL) {
141  glXMakeCurrent(_display, None, NULL);
142 
143  if (_pbuffer != None) {
144  glxGraphicsStateGuardian *glxgsg;
145  DCAST_INTO_V(glxgsg, _gsg);
146  glxgsg->_glXDestroyPbuffer(_display, _pbuffer);
147  _pbuffer = None;
148  }
149 
150  _gsg.clear();
151  }
152 
153  _pbuffer = None;
154  _is_valid = false;
155 }
156 
157 ////////////////////////////////////////////////////////////////////
158 // Function: glxGraphicsBuffer::open_buffer
159 // Access: Protected, Virtual
160 // Description: Opens the buffer right now. Called from the window
161 // thread. Returns true if the buffer is successfully
162 // opened, or false if there was a problem.
163 ////////////////////////////////////////////////////////////////////
164 bool glxGraphicsBuffer::
165 open_buffer() {
166  glxGraphicsPipe *glx_pipe;
167  DCAST_INTO_R(glx_pipe, _pipe, false);
168 
169  // GSG Creation/Initialization
170  glxGraphicsStateGuardian *glxgsg;
171  if (_gsg == 0) {
172  // There is no old gsg. Create a new one.
173  glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, NULL);
174  glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
175  _gsg = glxgsg;
176  } else {
177  // If the old gsg has the wrong pixel format, create a
178  // new one that shares with the old gsg.
179  DCAST_INTO_R(glxgsg, _gsg, false);
180 
181  if (!glxgsg->_context_has_pbuffer ||
182  !glxgsg->get_fb_properties().subsumes(_fb_properties)) {
183  // We need a new pixel format, and hence a new GSG.
184  glxgsg = new glxGraphicsStateGuardian(_engine, _pipe, glxgsg);
185  glxgsg->choose_pixel_format(_fb_properties, glx_pipe->get_display(), glx_pipe->get_screen(), true, false);
186  _gsg = glxgsg;
187  }
188  }
189 
190  if (glxgsg->_fbconfig == None || !glxgsg->_context_has_pbuffer) {
191  // If we didn't use an fbconfig to create the GSG, or it doesn't
192  // support buffers, we can't create a PBuffer.
193  return false;
194  }
195 
196  nassertr(glxgsg->_supports_pbuffer, false);
197 
198  static const int max_attrib_list = 32;
199  int attrib_list[max_attrib_list];
200  int n = 0;
201 
202  if (glxgsg->_uses_sgix_pbuffer) {
203  // The SGI version passed in the size in the parameter list.
204  nassertr(n < max_attrib_list, false);
205  attrib_list[n] = (int)None;
206  _pbuffer = glxgsg->_glXCreateGLXPbufferSGIX(glxgsg->_display, glxgsg->_fbconfig,
207  get_x_size(), get_y_size(), attrib_list);
208  } else {
209  // The official GLX 1.3 version passes in the size in the attrib
210  // list.
211  attrib_list[n++] = GLX_PBUFFER_WIDTH;
212  attrib_list[n++] = get_x_size();
213  attrib_list[n++] = GLX_PBUFFER_HEIGHT;
214  attrib_list[n++] = get_y_size();
215 
216  nassertr(n < max_attrib_list, false);
217  attrib_list[n] = (int)None;
218  _pbuffer = glxgsg->_glXCreatePbuffer(glxgsg->_display, glxgsg->_fbconfig,
219  attrib_list);
220  }
221 
222  if (_pbuffer == None) {
223  glxdisplay_cat.error()
224  << "failed to create GLX pbuffer.\n";
225  return false;
226  }
227 
228  glXMakeCurrent(_display, _pbuffer, glxgsg->_context);
229  glxgsg->reset_if_new();
230  if (!glxgsg->is_valid()) {
231  close_buffer();
232  return false;
233  }
235  (_fb_properties, glxgsg->get_gl_renderer())) {
236  close_buffer();
237  return false;
238  }
239  _fb_properties = glxgsg->get_fb_properties();
240 
241  _is_valid = true;
242  return true;
243 }
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.
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
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.
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
Definition: pStatTimer.h:34
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
int get_screen() const
Returns the X screen number associated with the pipe.
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
bool verify_hardware_software(const FrameBufferProperties &props, const string &renderer) const
Validates that the properties represent the desired kind of renderer (hardware or software)...
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.
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:58
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
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 is a base class for the various different classes that represent the result of a frame of render...
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
A thread; that is, a lightweight process.
Definition: thread.h:51
Encapsulates all the communication with a particular instance of a given rendering backend...
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...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...