Panda3D
eglGraphicsPixmap.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 eglGraphicsPixmap.cxx
10  * @author rdb
11  * @date 2009-06-13
12  */
13 
14 #include "eglGraphicsPixmap.h"
15 #include "eglGraphicsWindow.h"
17 #include "config_egldisplay.h"
18 #include "eglGraphicsPipe.h"
19 
20 #include "graphicsPipe.h"
21 #include "pStatTimer.h"
22 
23 TypeHandle eglGraphicsPixmap::_type_handle;
24 
25 /**
26  *
27  */
28 eglGraphicsPixmap::
29 eglGraphicsPixmap(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  eglGraphicsPipe *egl_pipe;
39  DCAST_INTO_V(egl_pipe, _pipe);
40  _display = egl_pipe->get_display();
41  _egl_display = egl_pipe->_egl_display;
42  _drawable = None;
43  _x_pixmap = None;
44  _egl_surface = EGL_NO_SURFACE;
45 
46  // Since the pixmap never gets flipped, we get screenshots from the same
47  // pixmap we draw into.
48  _screenshot_buffer_type = _draw_buffer_type;
49 }
50 
51 /**
52  *
53  */
54 eglGraphicsPixmap::
55 ~eglGraphicsPixmap() {
56  nassertv(_x_pixmap == None && _egl_surface == EGL_NO_SURFACE);
57 }
58 
59 /**
60  * This function will be called within the draw thread before beginning
61  * rendering for a given frame. It should do whatever setup is required, and
62  * return true if the frame should be rendered, or false if it should be
63  * skipped.
64  */
66 begin_frame(FrameMode mode, Thread *current_thread) {
67  PStatTimer timer(_make_current_pcollector, current_thread);
68 
69  begin_frame_spam(mode);
70  if (_gsg == nullptr) {
71  return false;
72  }
73 
75  DCAST_INTO_R(eglgsg, _gsg, false);
76  if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
77  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
78  << get_egl_error_string(eglGetError()) << "\n";
79  }
80 
81  // Now that we have made the context current to a window, we can reset the
82  // GSG state if this is the first time it has been used. (We can't just
83  // call reset() when we construct the GSG, because reset() requires having a
84  // current context.)
85  eglgsg->reset_if_new();
86 
87  if (mode == FM_render) {
88  CDLockedReader cdata(_cycler);
89  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
90  const RenderTexture &rt = cdata->_textures[i];
91  RenderTextureMode rtm_mode = rt._rtm_mode;
92  if (rtm_mode == RTM_bind_or_copy) {
93  CDWriter cdataw(_cycler, cdata, false);
94  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
95  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
96  }
97  }
98  clear_cube_map_selection();
99  }
100 
101  _gsg->set_current_properties(&get_fb_properties());
102  return _gsg->begin_frame(current_thread);
103 }
104 
105 /**
106  * This function will be called within the draw thread after rendering is
107  * completed for a given frame. It should do whatever finalization is
108  * required.
109  */
111 end_frame(FrameMode mode, Thread *current_thread) {
112  end_frame_spam(mode);
113  nassertv(_gsg != nullptr);
114 
115  if (mode == FM_render) {
116  copy_to_textures();
117  }
118 
119  _gsg->end_frame(current_thread);
120 
121  if (mode == FM_render) {
122  trigger_flip();
123  clear_cube_map_selection();
124  }
125 }
126 
127 /**
128  * Closes the pixmap right now. Called from the window thread.
129  */
130 void eglGraphicsPixmap::
131 close_buffer() {
132  if (_gsg != nullptr) {
133  if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
134  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
135  << get_egl_error_string(eglGetError()) << "\n";
136  }
137  _gsg.clear();
138  }
139 
140  if (_egl_surface != EGL_NO_SURFACE) {
141  if (!eglDestroySurface(_egl_display, _egl_surface)) {
142  egldisplay_cat.error() << "Failed to destroy surface: "
143  << get_egl_error_string(eglGetError()) << "\n";
144  }
145  _egl_surface = EGL_NO_SURFACE;
146  }
147 
148  if (_x_pixmap != None) {
149  XFreePixmap(_display, _x_pixmap);
150  _x_pixmap = None;
151  }
152 
153  _is_valid = false;
154 }
155 
156 /**
157  * Opens the pixmap right now. Called from the window thread. Returns true
158  * if the pixmap is successfully opened, or false if there was a problem.
159  */
160 bool eglGraphicsPixmap::
161 open_buffer() {
162  eglGraphicsPipe *egl_pipe;
163  DCAST_INTO_R(egl_pipe, _pipe, false);
164 
165  // GSG CreationInitialization
166  eglGraphicsStateGuardian *eglgsg;
167  if (_gsg == 0) {
168  // There is no old gsg. Create a new one.
169  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
170  eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
171  _gsg = eglgsg;
172  } else {
173  // If the old gsg has the wrong pixel format, create a new one that shares
174  // with the old gsg.
175  DCAST_INTO_R(eglgsg, _gsg, false);
176  if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
177  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
178  eglgsg->choose_pixel_format(_fb_properties, _display, egl_pipe->get_screen(), false, true);
179  _gsg = eglgsg;
180  }
181  }
182 
183  if (eglgsg->_fbconfig == None) {
184  // If we didn't use an fbconfig to create the GSG, we can't create a
185  // PBuffer.
186  return false;
187  }
188 
189  XVisualInfo *visual_info = eglgsg->_visual;
190  if (visual_info == nullptr) {
191  // No X visual for this fbconfig; how can we create the pixmap?
192  egldisplay_cat.error()
193  << "No X visual: cannot create pixmap.\n";
194  return false;
195  }
196 
197  _drawable = egl_pipe->get_root();
198  if (_host != nullptr) {
199  if (_host->is_of_type(eglGraphicsWindow::get_class_type())) {
200  eglGraphicsWindow *win = DCAST(eglGraphicsWindow, _host);
201  _drawable = win->get_xwindow();
202  } else if (_host->is_of_type(eglGraphicsPixmap::get_class_type())) {
203  eglGraphicsPixmap *pix = DCAST(eglGraphicsPixmap, _host);
204  _drawable = pix->_drawable;
205  }
206  }
207 
208  _x_pixmap = XCreatePixmap(_display, _drawable,
209  _size.get_x(), _size.get_y(), visual_info->depth);
210  if (_x_pixmap == None) {
211  egldisplay_cat.error()
212  << "Failed to create X pixmap.\n";
213  close_buffer();
214  return false;
215  }
216 
217  nassertr(eglgsg->_fbconfig, false);
218  _egl_surface = eglCreatePixmapSurface(_egl_display, eglgsg->_fbconfig, (NativePixmapType) _x_pixmap, nullptr);
219 
220  if (_egl_surface == EGL_NO_SURFACE) {
221  egldisplay_cat.error()
222  << "Failed to create EGL pixmap surface:"
223  << get_egl_error_string(eglGetError()) << "\n";
224  close_buffer();
225  return false;
226  }
227 
228  eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context);
229  eglgsg->reset_if_new();
230  if (!eglgsg->is_valid()) {
231  close_buffer();
232  return false;
233  }
235  (_fb_properties, eglgsg->get_gl_renderer())) {
236  close_buffer();
237  return false;
238  }
239  _fb_properties = eglgsg->get_fb_properties();
240 
241  _is_valid = true;
242  return true;
243 }
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
eglGraphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsWindow
An interface to the egl system for managing GLES windows under X.
Definition: eglGraphicsWindow.h:25
x11GraphicsPipe::get_root
X11_Window get_root() const
Returns the handle to the root window on the pipe's display.
Definition: x11GraphicsPipe.I:35
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
eglGraphicsPixmap::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: eglGraphicsPixmap.cxx:111
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
x11GraphicsWindow::get_xwindow
X11_Window get_xwindow() const
Returns the X11 Window handle.
Definition: x11GraphicsWindow.I:18
CycleDataWriter
This template class calls PipelineCycler::write() in the constructor and PipelineCycler::release_writ...
Definition: cycleDataWriter.h:34
eglGraphicsPipe
This graphics pipe represents the interface for creating OpenGL ES graphics windows on an X-based (e....
Definition: eglGraphicsPipe.h:45
eglGraphicsStateGuardian::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: eglGraphicsStateGuardian.cxx:133
eglGraphicsPixmap.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
GraphicsPipe
An object to create GraphicsOutputs that share a particular 3-D API.
Definition: graphicsPipe.h:52
eglGraphicsStateGuardian.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsStateGuardian::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Gets the FrameBufferProperties for all windows and buffers that use this GSG.
Definition: eglGraphicsStateGuardian.I:19
GraphicsOutput::get_fb_properties
const FrameBufferProperties & get_fb_properties() const
Returns the framebuffer properties of the window.
Definition: graphicsOutput.I:413
get_egl_error_string
const std::string get_egl_error_string(int error)
Returns the given EGL error as string.
Definition: config_androiddisplay.cxx:67
CycleDataLockedReader
This template class calls PipelineCycler::read() in the constructor and PipelineCycler::release_read(...
Definition: cycleDataLockedReader.h:40
eglGraphicsPixmap
Another offscreen buffer in the EGL environment.
Definition: eglGraphicsPixmap.h:27
x11GraphicsPipe::get_screen
int get_screen() const
Returns the X screen number associated with the pipe.
Definition: x11GraphicsPipe.I:27
config_egldisplay.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsPixmap::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: eglGraphicsPixmap.cxx:66
GraphicsStateGuardian
Encapsulates all the communication with a particular instance of a given rendering backend.
Definition: graphicsStateGuardian.h:65
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
Thread
A thread; that is, a lightweight process.
Definition: thread.h:46
eglGraphicsStateGuardian
A tiny specialization on GLESGraphicsStateGuardian to add some egl-specific information.
Definition: eglGraphicsStateGuardian.h:28
eglGraphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.