00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "eglGraphicsBuffer.h"
00016 #include "eglGraphicsPipe.h"
00017 #include "eglGraphicsPixmap.h"
00018 #include "eglGraphicsWindow.h"
00019 #include "eglGraphicsStateGuardian.h"
00020 #include "config_egldisplay.h"
00021 #include "frameBufferProperties.h"
00022
00023 TypeHandle eglGraphicsPipe::_type_handle;
00024
00025 bool eglGraphicsPipe::_error_handlers_installed = false;
00026 eglGraphicsPipe::ErrorHandlerFunc *eglGraphicsPipe::_prev_error_handler;
00027 eglGraphicsPipe::IOErrorHandlerFunc *eglGraphicsPipe::_prev_io_error_handler;
00028
00029 LightReMutex eglGraphicsPipe::_x_mutex;
00030
00031
00032
00033
00034
00035
00036 eglGraphicsPipe::
00037 eglGraphicsPipe(const string &display) {
00038 string display_spec = display;
00039 if (display_spec.empty()) {
00040 display_spec = display_cfg;
00041 }
00042 if (display_spec.empty()) {
00043 display_spec = ExecutionEnvironment::get_environment_variable("DISPLAY");
00044 }
00045 if (display_spec.empty()) {
00046 display_spec = ":0.0";
00047 }
00048
00049
00050
00051 setlocale(LC_ALL, "");
00052
00053
00054
00055
00056 setlocale(LC_NUMERIC, "C");
00057
00058 _is_valid = false;
00059 _supported_types = OT_window | OT_buffer | OT_texture_buffer;
00060 _display = NULL;
00061 _screen = 0;
00062 _root = (X11_Window)NULL;
00063 _im = (XIM)NULL;
00064 _hidden_cursor = None;
00065 _egl_display = NULL;
00066
00067 install_error_handlers();
00068
00069 _display = XOpenDisplay(display_spec.c_str());
00070 if (!_display) {
00071 egldisplay_cat.error()
00072 << "Could not open display \"" << display_spec << "\".\n";
00073 return;
00074 }
00075
00076 if (!XSupportsLocale()) {
00077 egldisplay_cat.warning()
00078 << "X does not support locale " << setlocale(LC_ALL, NULL) << "\n";
00079 }
00080 XSetLocaleModifiers("");
00081
00082 _screen = DefaultScreen(_display);
00083 _root = RootWindow(_display, _screen);
00084 _display_width = DisplayWidth(_display, _screen);
00085 _display_height = DisplayHeight(_display, _screen);
00086 _is_valid = true;
00087
00088 _egl_display = eglGetDisplay((NativeDisplayType) _display);
00089 if (!eglInitialize(_egl_display, NULL, NULL)) {
00090 egldisplay_cat.error()
00091 << "Couldn't initialize the EGL display: "
00092 << get_egl_error_string(eglGetError()) << "\n";
00093 }
00094
00095 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
00096 egldisplay_cat.error()
00097 << "Couldn't bind EGL to the OpenGL ES API: "
00098 << get_egl_error_string(eglGetError()) << "\n";
00099 }
00100
00101
00102
00103 _im = XOpenIM(_display, NULL, NULL, NULL);
00104 if (_im == (XIM)NULL) {
00105 egldisplay_cat.warning()
00106 << "Couldn't open input method.\n";
00107 }
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", false);
00124 _net_wm_window_type = XInternAtom(_display, "_NET_WM_WINDOW_TYPE", false);
00125 _net_wm_window_type_splash = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_SPLASH", false);
00126 _net_wm_window_type_fullscreen = XInternAtom(_display, "_NET_WM_WINDOW_TYPE_FULLSCREEN", false);
00127 _net_wm_state = XInternAtom(_display, "_NET_WM_STATE", false);
00128 _net_wm_state_fullscreen = XInternAtom(_display, "_NET_WM_STATE_FULLSCREEN", false);
00129 _net_wm_state_above = XInternAtom(_display, "_NET_WM_STATE_ABOVE", false);
00130 _net_wm_state_below = XInternAtom(_display, "_NET_WM_STATE_BELOW", false);
00131 _net_wm_state_add = XInternAtom(_display, "_NET_WM_STATE_ADD", false);
00132 _net_wm_state_remove = XInternAtom(_display, "_NET_WM_STATE_REMOVE", false);
00133 }
00134
00135
00136
00137
00138
00139
00140 eglGraphicsPipe::
00141 ~eglGraphicsPipe() {
00142 release_hidden_cursor();
00143 if (_im) {
00144 XCloseIM(_im);
00145 }
00146 if (_display) {
00147 XCloseDisplay(_display);
00148 }
00149 if (_egl_display) {
00150 if (!eglTerminate(_egl_display)) {
00151 egldisplay_cat.error() << "Failed to terminate EGL display: "
00152 << get_egl_error_string(eglGetError()) << "\n";
00153 }
00154 }
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 string eglGraphicsPipe::
00168 get_interface_name() const {
00169 return "OpenGL ES";
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179 PT(GraphicsPipe) eglGraphicsPipe::
00180 pipe_constructor() {
00181 return new eglGraphicsPipe;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 GraphicsPipe::PreferredWindowThread
00193 eglGraphicsPipe::get_preferred_window_thread() const {
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 return PWT_draw;
00206 }
00207
00208
00209
00210
00211
00212
00213 PT(GraphicsOutput) eglGraphicsPipe::
00214 make_output(const string &name,
00215 const FrameBufferProperties &fb_prop,
00216 const WindowProperties &win_prop,
00217 int flags,
00218 GraphicsEngine *engine,
00219 GraphicsStateGuardian *gsg,
00220 GraphicsOutput *host,
00221 int retry,
00222 bool &precertify) {
00223
00224 if (!_is_valid) {
00225 return NULL;
00226 }
00227
00228 eglGraphicsStateGuardian *eglgsg = 0;
00229 if (gsg != 0) {
00230 DCAST_INTO_R(eglgsg, gsg, NULL);
00231 }
00232
00233 bool support_rtt;
00234 support_rtt = false;
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 if (retry == 0) {
00247 if (((flags&BF_require_parasite)!=0)||
00248 ((flags&BF_refuse_window)!=0)||
00249 ((flags&BF_resizeable)!=0)||
00250 ((flags&BF_size_track_host)!=0)||
00251 ((flags&BF_rtt_cumulative)!=0)||
00252 ((flags&BF_can_bind_color)!=0)||
00253 ((flags&BF_can_bind_every)!=0)) {
00254 return NULL;
00255 }
00256 return new eglGraphicsWindow(engine, this, name, fb_prop, win_prop,
00257 flags, gsg, host);
00258 }
00259
00260
00261 if (retry == 1) {
00262 if ((host==0)||
00263
00264 ((flags&BF_require_parasite)!=0)||
00265 ((flags&BF_require_window)!=0)) {
00266 return NULL;
00267 }
00268
00269
00270 if ((flags & BF_fb_props_optional)==0) {
00271 if ((fb_prop.get_indexed_color() > 0)||
00272 (fb_prop.get_back_buffers() > 0)||
00273 (fb_prop.get_accum_bits() > 0)||
00274 (fb_prop.get_multisamples() > 0)) {
00275 return NULL;
00276 }
00277 }
00278
00279
00280 if ((eglgsg != 0) &&
00281 (eglgsg->is_valid()) &&
00282 (!eglgsg->needs_reset()) &&
00283 (eglgsg->_supports_framebuffer_object) &&
00284 (eglgsg->_glDrawBuffers != 0)&&
00285 (fb_prop.is_basic())) {
00286 precertify = true;
00287 }
00288 #ifdef OPENGLES_2
00289 return new GLES2GraphicsBuffer(engine, this, name, fb_prop, win_prop,
00290 flags, gsg, host);
00291 #else
00292 return new GLESGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00293 flags, gsg, host);
00294 #endif
00295 }
00296
00297
00298 if (retry == 2) {
00299 if (((flags&BF_require_parasite)!=0)||
00300 ((flags&BF_require_window)!=0)||
00301 ((flags&BF_resizeable)!=0)||
00302 ((flags&BF_size_track_host)!=0)) {
00303 return NULL;
00304 }
00305
00306 if (!support_rtt) {
00307 if (((flags&BF_rtt_cumulative)!=0)||
00308 ((flags&BF_can_bind_every)!=0)) {
00309
00310
00311 return NULL;
00312 }
00313 }
00314
00315 return new eglGraphicsBuffer(engine, this, name, fb_prop, win_prop,
00316 flags, gsg, host);
00317 }
00318
00319
00320 if (retry == 3) {
00321 if (((flags&BF_require_parasite)!=0)||
00322 ((flags&BF_require_window)!=0)||
00323 ((flags&BF_resizeable)!=0)||
00324 ((flags&BF_size_track_host)!=0)) {
00325 return NULL;
00326 }
00327
00328 if (((flags&BF_rtt_cumulative)!=0)||
00329 ((flags&BF_can_bind_every)!=0)) {
00330 return NULL;
00331 }
00332
00333 return new eglGraphicsPixmap(engine, this, name, fb_prop, win_prop,
00334 flags, gsg, host);
00335 }
00336
00337
00338 return NULL;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 void eglGraphicsPipe::
00348 make_hidden_cursor() {
00349 nassertv(_hidden_cursor == None);
00350
00351 unsigned int x_size, y_size;
00352 XQueryBestCursor(_display, _root, 1, 1, &x_size, &y_size);
00353
00354 Pixmap empty = XCreatePixmap(_display, _root, x_size, y_size, 1);
00355
00356 XColor black;
00357 memset(&black, 0, sizeof(black));
00358
00359 _hidden_cursor = XCreatePixmapCursor(_display, empty, empty,
00360 &black, &black, x_size, y_size);
00361 XFreePixmap(_display, empty);
00362 }
00363
00364
00365
00366
00367
00368
00369
00370 void eglGraphicsPipe::
00371 release_hidden_cursor() {
00372 if (_hidden_cursor != None) {
00373 XFreeCursor(_display, _hidden_cursor);
00374 _hidden_cursor = None;
00375 }
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389 void eglGraphicsPipe::
00390 install_error_handlers() {
00391 if (_error_handlers_installed) {
00392 return;
00393 }
00394
00395 _prev_error_handler = (ErrorHandlerFunc *)XSetErrorHandler(error_handler);
00396 _prev_io_error_handler = (IOErrorHandlerFunc *)XSetIOErrorHandler(io_error_handler);
00397 _error_handlers_installed = true;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406 int eglGraphicsPipe::
00407 error_handler(X11_Display *display, XErrorEvent *error) {
00408 static const int msg_len = 80;
00409 char msg[msg_len];
00410 XGetErrorText(display, error->error_code, msg, msg_len);
00411 egldisplay_cat.error()
00412 << msg << "\n";
00413
00414 if (x_error_abort) {
00415 abort();
00416 }
00417
00418
00419
00420 return 0;
00421 }
00422
00423
00424
00425
00426
00427
00428
00429 int eglGraphicsPipe::
00430 io_error_handler(X11_Display *display) {
00431 egldisplay_cat.fatal()
00432 << "X fatal error on display " << (void *)display << "\n";
00433
00434
00435
00436
00437
00438 return 0;
00439 }