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