Panda3D
Loading...
Searching...
No Matches
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
23TypeHandle glxGraphicsBuffer::_type_handle;
24
25/**
26 *
27 */
28glxGraphicsBuffer::
29glxGraphicsBuffer(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 */
51glxGraphicsBuffer::
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 */
63begin_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 */
109end_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 */
128void glxGraphicsBuffer::
129close_buffer() {
130 if (_gsg != nullptr) {
131 LightReMutexHolder holder(glxGraphicsPipe::_x_mutex);
132 glXMakeCurrent(_display, None, nullptr);
133
134 if (_pbuffer != None) {
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 */
152bool glxGraphicsBuffer::
153open_buffer() {
154 glxGraphicsPipe *glx_pipe;
155 DCAST_INTO_R(glx_pipe, _pipe, false);
156
157 // GSG CreationInitialization
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 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...
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
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).
bool subsumes(const FrameBufferProperties &other) const
Returns true if this set of properties makes strictly greater or equal demands of the framebuffer tha...
An offscreen buffer for rendering into.
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...
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
int get_y_size() const
Returns the visible height of the window or buffer, if it is known.
int get_x_size() const
Returns the visible width of the window or buffer, if it is known.
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.
Similar to MutexHolder, but for a light reentrant mutex.
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
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...
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.
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.
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.
X11_Display * get_display() const
Returns a pointer to the X display associated with the pipe: the display on which to create the windo...
int get_screen() const
Returns the X screen number associated with the pipe.
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.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.