Panda3D
eglGraphicsBuffer.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 eglGraphicsBuffer.cxx
10  * @author rdb
11  * @date 2009-06-13
12  */
13 
14 #include "eglGraphicsBuffer.h"
16 #include "config_egldisplay.h"
17 #include "eglGraphicsPipe.h"
18 
19 #include "graphicsPipe.h"
20 #include "pStatTimer.h"
21 
22 TypeHandle eglGraphicsBuffer::_type_handle;
23 
24 /**
25  *
26  */
27 eglGraphicsBuffer::
28 eglGraphicsBuffer(GraphicsEngine *engine, GraphicsPipe *pipe,
29  const std::string &name,
30  const FrameBufferProperties &fb_prop,
31  const WindowProperties &win_prop,
32  int flags,
34  GraphicsOutput *host) :
35  GraphicsBuffer(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
36 {
37  eglGraphicsPipe *egl_pipe;
38  DCAST_INTO_V(egl_pipe, _pipe);
39  _pbuffer = EGL_NO_SURFACE;
40 
41  // Since the pbuffer never gets flipped, we get screenshots from the same
42  // buffer we draw into.
43  _screenshot_buffer_type = _draw_buffer_type;
44 }
45 
46 /**
47  *
48  */
49 eglGraphicsBuffer::
50 ~eglGraphicsBuffer() {
51  nassertv(_pbuffer == EGL_NO_SURFACE);
52 }
53 
54 /**
55  * This function will be called within the draw thread before beginning
56  * rendering for a given frame. It should do whatever setup is required, and
57  * return true if the frame should be rendered, or false if it should be
58  * skipped.
59  */
61 begin_frame(FrameMode mode, Thread *current_thread) {
62  PStatTimer timer(_make_current_pcollector, current_thread);
63 
64  begin_frame_spam(mode);
65  if (_gsg == nullptr) {
66  return false;
67  }
68 
70  DCAST_INTO_R(eglgsg, _gsg, false);
71  if (!eglMakeCurrent(eglgsg->_egl_display, _pbuffer, _pbuffer, eglgsg->_context)) {
72  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
73  << get_egl_error_string(eglGetError()) << "\n";
74  }
75 
76  // Now that we have made the context current to a window, we can reset the
77  // GSG state if this is the first time it has been used. (We can't just
78  // call reset() when we construct the GSG, because reset() requires having a
79  // current context.)
80  eglgsg->reset_if_new();
81 
82  if (mode == FM_render) {
83  CDLockedReader cdata(_cycler);
84  for (size_t i = 0; i != cdata->_textures.size(); ++i) {
85  const RenderTexture &rt = cdata->_textures[i];
86  RenderTextureMode rtm_mode = rt._rtm_mode;
87  if (rtm_mode == RTM_bind_or_copy) {
88  CDWriter cdataw(_cycler, cdata, false);
89  nassertr(cdata->_textures.size() == cdataw->_textures.size(), false);
90  cdataw->_textures[i]._rtm_mode = RTM_copy_texture;
91  }
92  }
93  clear_cube_map_selection();
94  }
95 
96  _gsg->set_current_properties(&get_fb_properties());
97  return _gsg->begin_frame(current_thread);
98 }
99 
100 /**
101  * This function will be called within the draw thread after rendering is
102  * completed for a given frame. It should do whatever finalization is
103  * required.
104  */
106 end_frame(FrameMode mode, Thread *current_thread) {
107  end_frame_spam(mode);
108  nassertv(_gsg != nullptr);
109 
110  if (mode == FM_render) {
111  copy_to_textures();
112  }
113 
114  _gsg->end_frame(current_thread);
115 
116  if (mode == FM_render) {
117  trigger_flip();
118  clear_cube_map_selection();
119  }
120 }
121 
122 /**
123  * Closes the buffer right now. Called from the window thread.
124  */
125 void eglGraphicsBuffer::
126 close_buffer() {
127  if (_gsg != nullptr) {
128  eglGraphicsStateGuardian *eglgsg;
129  DCAST_INTO_V(eglgsg, _gsg);
130  if (!eglMakeCurrent(eglgsg->_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
131  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
132  << get_egl_error_string(eglGetError()) << "\n";
133  }
134  _gsg.clear();
135 
136  if (_pbuffer != EGL_NO_SURFACE) {
137  if (!eglDestroySurface(_egl_display, _pbuffer)) {
138  egldisplay_cat.error() << "Failed to destroy surface: "
139  << get_egl_error_string(eglGetError()) << "\n";
140  }
141  _pbuffer = EGL_NO_SURFACE;
142  }
143  }
144 
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 eglGraphicsBuffer::
153 open_buffer() {
154  eglGraphicsPipe *egl_pipe;
155  DCAST_INTO_R(egl_pipe, _pipe, false);
156 
157  // GSG CreationInitialization
158  eglGraphicsStateGuardian *eglgsg;
159  if (_gsg == 0) {
160  // There is no old gsg. Create a new one.
161  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
162  eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
163  _gsg = eglgsg;
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(eglgsg, _gsg, false);
168  if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
169  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
170  eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), true, false);
171  _gsg = eglgsg;
172  }
173  }
174 
175  if (eglgsg->_fbconfig == nullptr) {
176  // If we didn't use an fbconfig to create the GSG, we can't create a
177  // PBuffer.
178  return false;
179  }
180 
181  int attrib_list[] = {
182  EGL_WIDTH, _size.get_x(),
183  EGL_HEIGHT, _size.get_y(),
184  EGL_NONE
185  };
186 
187  _pbuffer = eglCreatePbufferSurface(eglgsg->_egl_display, eglgsg->_fbconfig, attrib_list);
188 
189  if (_pbuffer == EGL_NO_SURFACE) {
190  egldisplay_cat.error()
191  << "Failed to create EGL pbuffer surface: "
192  << get_egl_error_string(eglGetError()) << "\n";
193  return false;
194  }
195 
196  if (!eglMakeCurrent(eglgsg->_egl_display, _pbuffer, _pbuffer, eglgsg->_context)) {
197  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
198  << get_egl_error_string(eglGetError()) << "\n";
199  }
200  eglgsg->reset_if_new();
201  if (!eglgsg->is_valid()) {
202  close_buffer();
203  return false;
204  }
206  (_fb_properties, eglgsg->get_gl_renderer())) {
207  close_buffer();
208  return false;
209  }
210  _fb_properties = eglgsg->get_fb_properties();
211 
212  _is_valid = true;
213  return true;
214 }
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.
pStatTimer.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsBuffer.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
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
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
eglGraphicsBuffer::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: eglGraphicsBuffer.cxx:106
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
x11GraphicsPipe::get_screen
int get_screen() const
Returns the X screen number associated with the pipe.
Definition: x11GraphicsPipe.I:27
eglGraphicsBuffer::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: eglGraphicsBuffer.cxx:61
config_egldisplay.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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