Panda3D
eglGraphicsWindow.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 eglGraphicsWindow.cxx
10  * @author rdb
11  * @date 2009-05-21
12  */
13 
14 #include "eglGraphicsWindow.h"
16 #include "config_egldisplay.h"
17 #include "eglGraphicsPipe.h"
18 
19 #include "graphicsPipe.h"
20 #include "keyboardButton.h"
21 #include "mouseButton.h"
22 #include "clockObject.h"
23 #include "pStatTimer.h"
24 #include "textEncoder.h"
25 #include "throw_event.h"
26 #include "lightReMutexHolder.h"
27 #include "nativeWindowHandle.h"
28 #include "get_x11.h"
29 
30 TypeHandle eglGraphicsWindow::_type_handle;
31 
32 /**
33  *
34  */
35 eglGraphicsWindow::
36 eglGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
37  const std::string &name,
38  const FrameBufferProperties &fb_prop,
39  const WindowProperties &win_prop,
40  int flags,
42  GraphicsOutput *host) :
43  x11GraphicsWindow(engine, pipe, name, fb_prop, win_prop, flags, gsg, host)
44 {
45  eglGraphicsPipe *egl_pipe;
46  DCAST_INTO_V(egl_pipe, _pipe);
47  _egl_display = egl_pipe->_egl_display;
48  _egl_surface = 0;
49 }
50 
51 /**
52  *
53  */
54 eglGraphicsWindow::
55 ~eglGraphicsWindow() {
56 }
57 
58 /**
59  * This function will be called within the draw thread before beginning
60  * rendering for a given frame. It should do whatever setup is required, and
61  * return true if the frame should be rendered, or false if it should be
62  * skipped.
63  */
65 begin_frame(FrameMode mode, Thread *current_thread) {
66  PStatTimer timer(_make_current_pcollector, current_thread);
67 
68  begin_frame_spam(mode);
69  if (_gsg == nullptr) {
70  return false;
71  }
72  if (_awaiting_configure) {
73  // Don't attempt to draw while we have just reconfigured the window and we
74  // haven't got the notification back yet.
75  return false;
76  }
77 
79  DCAST_INTO_R(eglgsg, _gsg, false);
80  {
81  LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
82 
83  if (eglGetCurrentDisplay() == _egl_display &&
84  eglGetCurrentSurface(EGL_READ) == _egl_surface &&
85  eglGetCurrentSurface(EGL_DRAW) == _egl_surface &&
86  eglGetCurrentContext() == eglgsg->_context) {
87  // No need to make the context current again. Short-circuit this
88  // possibly-expensive call.
89  } else {
90  // Need to set the context.
91  if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
92  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
93  << get_egl_error_string(eglGetError()) << "\n";
94  }
95  }
96  }
97 
98  // Now that we have made the context current to a window, we can reset the
99  // GSG state if this is the first time it has been used. (We can't just
100  // call reset() when we construct the GSG, because reset() requires having a
101  // current context.)
102  eglgsg->reset_if_new();
103 
104  if (mode == FM_render) {
105  // begin_render_texture();
106  clear_cube_map_selection();
107  }
108 
109  _gsg->set_current_properties(&get_fb_properties());
110  return _gsg->begin_frame(current_thread);
111 }
112 
113 /**
114  * This function will be called within the draw thread after rendering is
115  * completed for a given frame. It should do whatever finalization is
116  * required.
117  */
119 end_frame(FrameMode mode, Thread *current_thread) {
120  end_frame_spam(mode);
121  nassertv(_gsg != nullptr);
122 
123  if (mode == FM_render) {
124  // end_render_texture();
125  copy_to_textures();
126  }
127 
128  _gsg->end_frame(current_thread);
129 
130  if (mode == FM_render) {
131  trigger_flip();
132  clear_cube_map_selection();
133  }
134 }
135 
136 /**
137  * This function will be called within the draw thread after begin_flip() has
138  * been called on all windows, to finish the exchange of the front and back
139  * buffers.
140  *
141  * This should cause the window to wait for the flip, if necessary.
142  */
145  if (_gsg != nullptr && _flip_ready) {
146 
147  // It doesn't appear to be necessary to ensure the graphics context is
148  // current before flipping the windows, and insisting on doing so can be a
149  // significant performance hit.
150 
151  // make_current();
152 
153  LightReMutexHolder holder(eglGraphicsPipe::_x_mutex);
154  eglSwapBuffers(_egl_display, _egl_surface);
155  }
157 }
158 
159 /**
160  * Closes the window right now. Called from the window thread.
161  */
162 void eglGraphicsWindow::
163 close_window() {
164  if (_gsg != nullptr) {
165  if (!eglMakeCurrent(_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
166  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
167  << get_egl_error_string(eglGetError()) << "\n";
168  }
169  _gsg.clear();
170  }
171 
172  if (_ic != (XIC)nullptr) {
173  XDestroyIC(_ic);
174  _ic = (XIC)nullptr;
175  }
176 
177  if (_egl_surface != 0) {
178  if (!eglDestroySurface(_egl_display, _egl_surface)) {
179  egldisplay_cat.error() << "Failed to destroy surface: "
180  << get_egl_error_string(eglGetError()) << "\n";
181  }
182  }
183 
184  if (_xwindow != (X11_Window)nullptr) {
185  XDestroyWindow(_display, _xwindow);
186  _xwindow = (X11_Window)nullptr;
187 
188  // This may be necessary if we just closed the last X window in an
189  // application, so the server hears the close request.
190  XFlush(_display);
191  }
192  GraphicsWindow::close_window();
193 }
194 
195 /**
196  * Opens the window right now. Called from the window thread. Returns true
197  * if the window is successfully opened, or false if there was a problem.
198  */
199 bool eglGraphicsWindow::
200 open_window() {
201  eglGraphicsPipe *egl_pipe;
202  DCAST_INTO_R(egl_pipe, _pipe, false);
203 
204  // GSG CreationInitialization
205  eglGraphicsStateGuardian *eglgsg;
206  if (_gsg == 0) {
207  // There is no old gsg. Create a new one.
208  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, nullptr);
209  eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
210  _gsg = eglgsg;
211  } else {
212  // If the old gsg has the wrong pixel format, create a new one that shares
213  // with the old gsg.
214  DCAST_INTO_R(eglgsg, _gsg, false);
215  if (!eglgsg->get_fb_properties().subsumes(_fb_properties)) {
216  eglgsg = new eglGraphicsStateGuardian(_engine, _pipe, eglgsg);
217  eglgsg->choose_pixel_format(_fb_properties, egl_pipe->get_display(), egl_pipe->get_screen(), false, false);
218  _gsg = eglgsg;
219  }
220  }
221 
222  _visual_info = eglgsg->_visual;
223  if (_visual_info == nullptr) {
224  // No X visual for this fbconfig; how can we open the window?
225  egldisplay_cat.error()
226  << "No X visual: cannot open window.\n";
227  return false;
228  }
229 
230  setup_colormap(_visual_info);
231 
232  if (!x11GraphicsWindow::open_window()) {
233  return false;
234  }
235 
236  _egl_surface = eglCreateWindowSurface(_egl_display, eglgsg->_fbconfig, (NativeWindowType) _xwindow, nullptr);
237  if (eglGetError() != EGL_SUCCESS) {
238  egldisplay_cat.error()
239  << "Failed to create window surface.\n";
240  return false;
241  }
242 
243  if (!eglMakeCurrent(_egl_display, _egl_surface, _egl_surface, eglgsg->_context)) {
244  egldisplay_cat.error() << "Failed to call eglMakeCurrent: "
245  << get_egl_error_string(eglGetError()) << "\n";
246  }
247  eglgsg->reset_if_new();
248  if (!eglgsg->is_valid()) {
249  close_window();
250  return false;
251  }
253  (_fb_properties, eglgsg->get_gl_renderer())) {
254  close_window();
255  return false;
256  }
257  _fb_properties = eglgsg->get_fb_properties();
258 
259  return true;
260 }
eglGraphicsWindow::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: eglGraphicsWindow.cxx:144
FrameBufferProperties
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
Definition: frameBufferProperties.h:26
eglGraphicsWindow::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: eglGraphicsWindow.cxx:65
throw_event.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsPipe.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LightReMutexHolder
Similar to MutexHolder, but for a light reentrant mutex.
Definition: lightReMutexHolder.h:25
eglGraphicsWindow::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: eglGraphicsWindow.cxx:119
mouseButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
clockObject.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
keyboardButton.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
get_x11.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
x11GraphicsWindow
Interfaces to the X11 window system.
Definition: x11GraphicsWindow.h:26
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
x11GraphicsPipe::get_screen
int get_screen() const
Returns the X screen number associated with the pipe.
Definition: x11GraphicsPipe.I:27
nativeWindowHandle.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
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
GraphicsOutput::end_flip
virtual void end_flip()
This function will be called within the draw thread after begin_flip() has been called on all windows...
Definition: graphicsOutput.cxx:1299
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
textEncoder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
lightReMutexHolder.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
eglGraphicsWindow.h
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.