228
213
static ClutterFeatureFlags
229
214
clutter_backend_glx_get_features (ClutterBackend *backend)
231
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
232
const gchar *glx_extensions = NULL;
216
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
217
const gchar *glx_extensions = NULL;
233
218
ClutterFeatureFlags flags;
219
gboolean use_dri = FALSE;
235
221
flags = clutter_backend_x11_get_features (backend);
236
222
flags |= CLUTTER_FEATURE_STAGE_MULTIPLE;
238
/* this will make sure that the GL context exists and
239
* it's bound to a drawable
224
/* this will make sure that the GL context exists */
241
225
g_assert (backend_glx->gl_context != None);
242
226
g_assert (glXGetCurrentDrawable () != None);
244
CLUTTER_NOTE (BACKEND, "Checking features\n"
248
"GL_EXTENSIONS: %s\n",
228
CLUTTER_NOTE (BACKEND,
229
"Checking features\n"
233
" GL_EXTENSIONS: %s",
249
234
glGetString (GL_VENDOR),
250
235
glGetString (GL_RENDERER),
251
236
glGetString (GL_VERSION),
252
237
glGetString (GL_EXTENSIONS));
255
240
glXQueryExtensionsString (clutter_x11_get_default_display (),
256
clutter_x11_get_default_screen ());
258
CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions);
241
clutter_x11_get_default_screen ());
243
CLUTTER_NOTE (BACKEND, " GLX Extensions: %s", glx_extensions);
245
use_dri = check_vblank_env ("dri");
260
247
/* First check for explicit disabling or it set elsewhere (eg NVIDIA) */
261
if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none"))
248
if (check_vblank_env ("none"))
263
250
CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request");
267
/* We try two GL vblank syncing mechanisms.
268
* glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI.
270
* glXSwapIntervalSGI is known to work with Mesa and in particular
271
* the Intel drivers. glXGetVideoSyncSGI has serious problems with
272
* Intel drivers causing terrible frame rate so it only tried as a
275
* How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
276
* to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
279
if (!check_vblank_env ("dri") &&
280
cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
282
backend_glx->swap_interval =
283
(SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI");
285
CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup");
287
if (backend_glx->swap_interval != NULL)
289
if (backend_glx->swap_interval (1) == 0)
251
goto vblank_setup_done;
254
if (g_getenv ("__GL_SYNC_TO_VBLANK") != NULL)
256
backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
257
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
259
CLUTTER_NOTE (BACKEND, "Using __GL_SYNC_TO_VBLANK hint");
260
goto vblank_setup_done;
263
/* We try two GL vblank syncing mechanisms.
264
* glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI.
266
* glXSwapIntervalSGI is known to work with Mesa and in particular
267
* the Intel drivers. glXGetVideoSyncSGI has serious problems with
268
* Intel drivers causing terrible frame rate so it only tried as a
271
* How well glXGetVideoSyncSGI works with other driver (ATI etc) needs
272
* to be investigated. glXGetVideoSyncSGI on ATI at least seems to have
276
_cogl_check_extension ("GLX_SGI_swap_control", glx_extensions))
278
backend_glx->swap_interval =
279
(SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI");
281
CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup");
283
if (backend_glx->swap_interval != NULL &&
284
backend_glx->swap_interval (1) == 0)
286
backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
287
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
289
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success");
291
#ifdef GLX_INTEL_swap_event
292
/* GLX_INTEL_swap_event allows us to avoid blocking the CPU
293
* while we wait for glXSwapBuffers to complete, and instead
294
* we get an X event notifying us of completion...
296
if (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_SWAP_EVENTS) &&
297
_cogl_check_extension ("GLX_INTEL_swap_event", glx_extensions))
299
flags |= CLUTTER_FEATURE_SWAP_EVENTS;
301
#endif /* GLX_INTEL_swap_event */
303
goto vblank_setup_done;
306
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed");
310
!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) &&
311
_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
313
CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup");
315
backend_glx->get_video_sync =
316
(GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI");
318
backend_glx->wait_video_sync =
319
(WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI");
321
if ((backend_glx->get_video_sync != NULL) &&
322
(backend_glx->wait_video_sync != NULL))
324
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success");
326
backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
327
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
329
goto vblank_setup_done;
332
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
337
* DRI is really an extreme fallback -rumoured to work with Via chipsets
339
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
341
CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");
343
backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
344
if (backend_glx->dri_fd >= 0)
346
CLUTTER_NOTE (BACKEND, "DRI vblank setup success");
348
backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
349
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
351
goto vblank_setup_done;
354
CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
356
#endif /* __linux__ */
358
CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found");
362
if (_cogl_check_extension ("GLX_MESA_copy_sub_buffer", glx_extensions))
364
backend_glx->copy_sub_buffer =
365
(CopySubBufferProc) cogl_get_proc_address ("glXCopySubBufferMESA");
368
CLUTTER_NOTE (BACKEND, "backend features checked");
373
/* It seems the GLX spec never defined an invalid GLXFBConfig that
374
* we could overload as an indication of error, so we have to return
375
* an explicit boolean status. */
377
_clutter_backend_glx_get_fbconfig (ClutterBackendGLX *backend_glx,
380
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend_glx);
381
GLXFBConfig *configs = NULL;
382
gboolean use_argb = clutter_x11_get_use_argb_visual ();
384
static const int attributes[] = {
385
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
386
GLX_RENDER_TYPE, GLX_RGBA_BIT,
387
GLX_DOUBLEBUFFER, GL_TRUE,
397
if (backend_x11->xdpy == None || backend_x11->xscreen == None)
400
/* If we don't already have a cached config then try to get one */
401
if (!backend_glx->found_fbconfig)
403
CLUTTER_NOTE (BACKEND,
404
"Retrieving GL fbconfig, dpy: %p, xscreen; %p (%d)",
406
backend_x11->xscreen,
407
backend_x11->xscreen_num);
409
configs = glXChooseFBConfig (backend_x11->xdpy,
410
backend_x11->xscreen_num,
417
for (i = 0; i < n_configs; i++)
291
backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP;
292
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
293
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success");
421
vinfo = glXGetVisualFromFBConfig (backend_x11->xdpy,
426
if (vinfo->depth == 32 &&
427
(vinfo->red_mask == 0xff0000 &&
428
vinfo->green_mask == 0x00ff00 &&
429
vinfo->blue_mask == 0x0000ff))
431
CLUTTER_NOTE (BACKEND,
432
"Found GLX visual ARGB [index:%d]", i);
434
backend_glx->found_fbconfig = TRUE;
435
backend_glx->fbconfig = configs[i];
297
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
298
CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed");
301
if (!check_vblank_env ("dri") &&
302
!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) &&
303
cogl_check_extension ("GLX_SGI_video_sync", glx_extensions))
305
CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup");
307
backend_glx->get_video_sync =
308
(GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI");
310
backend_glx->wait_video_sync =
311
(WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI");
313
if ((backend_glx->get_video_sync != NULL) &&
314
(backend_glx->wait_video_sync != NULL))
316
CLUTTER_NOTE (BACKEND,
317
"glXGetVideoSyncSGI vblank setup success");
319
backend_glx->vblank_type = CLUTTER_VBLANK_GLX;
320
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
323
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
324
CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed");
328
* DRI is really an extreme fallback -rumoured to work with Via chipsets
330
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
332
CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup");
333
backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR);
334
if (backend_glx->dri_fd >= 0)
336
CLUTTER_NOTE (BACKEND, "DRI vblank setup success");
337
backend_glx->vblank_type = CLUTTER_VBLANK_DRI;
338
flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK;
341
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
342
CLUTTER_NOTE (BACKEND, "DRI vblank setup failed");
345
if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK))
347
CLUTTER_NOTE (BACKEND,
348
"no use-able vblank mechanism found");
352
CLUTTER_NOTE (MISC, "backend features checked");
441
/* If we make it here then we didn't find an RGBA config so
442
we'll fall back to using an RGB config */
443
CLUTTER_NOTE (BACKEND, "ARGB visual requested, but none found");
448
backend_glx->found_fbconfig = TRUE;
449
backend_glx->fbconfig = configs[0];
457
if (backend_glx->found_fbconfig)
459
*config = backend_glx->fbconfig;
468
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11)
470
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend_x11);
473
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
476
return glXGetVisualFromFBConfig (backend_x11->xdpy, config);
358
480
clutter_backend_glx_create_context (ClutterBackend *backend,
359
gboolean is_offscreen,
362
483
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
363
484
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
488
XSetWindowAttributes attrs;
489
XVisualInfo *xvisinfo;
493
GLXDrawable dummy_drawable;
495
if (backend_glx->gl_context != None)
498
xdisplay = clutter_x11_get_default_display ();
499
root_xwin = clutter_x11_get_root_window ();
501
if (!_clutter_backend_glx_get_fbconfig (backend_glx, &config))
503
g_set_error (error, CLUTTER_INIT_ERROR,
504
CLUTTER_INIT_ERROR_BACKEND,
505
"Unable to find suitable fbconfig for the GLX context");
509
CLUTTER_NOTE (BACKEND, "Creating GLX Context (display: %p)", xdisplay);
511
backend_glx->gl_context = glXCreateNewContext (xdisplay,
365
516
if (backend_glx->gl_context == None)
367
XVisualInfo *xvisinfo;
370
clutter_backend_x11_get_visual_info (backend_x11, is_offscreen);
372
CLUTTER_NOTE (GL, "Creating GL Context (display: %p, %s)",
374
is_offscreen ? "offscreen" : "onscreen");
376
backend_glx->gl_context = glXCreateContext (backend_x11->xdpy,
379
is_offscreen ? False : True);
383
if (backend_glx->gl_context == None)
385
g_set_error (error, CLUTTER_INIT_ERROR,
386
CLUTTER_INIT_ERROR_BACKEND,
387
"Unable to create suitable %s GL context",
388
is_offscreen ? "offscreen" : "onscreen");
396
is_direct = glXIsDirect (backend_x11->xdpy,
397
backend_glx->gl_context);
399
CLUTTER_NOTE (GL, "Setting %s context",
400
is_direct ? "direct" : "indirect");
401
_cogl_set_indirect_context (!is_direct);
518
g_set_error (error, CLUTTER_INIT_ERROR,
519
CLUTTER_INIT_ERROR_BACKEND,
520
"Unable to create suitable GL context");
524
is_direct = glXIsDirect (xdisplay, backend_glx->gl_context);
526
CLUTTER_NOTE (GL, "Setting %s context",
529
_cogl_set_indirect_context (!is_direct);
531
/* COGL assumes that there is always a GL context selected; in order
532
* to make sure that a GLX context exists and is made current, we use
533
* a dummy, offscreen override-redirect window to which we can always
534
* fall back if no stage is available
536
* XXX - we need to do this dance because GLX does not allow creating
537
* a context and querying it for basic information (even the function
538
* pointers) unless it's made current to a real Drawable. it should be
539
* possible to avoid this in future releases of Mesa and X11, but right
540
* now this is the best solution available.
542
xvisinfo = glXGetVisualFromFBConfig (xdisplay, config);
543
if (xvisinfo == None)
545
g_set_error (error, CLUTTER_INIT_ERROR,
546
CLUTTER_INIT_ERROR_BACKEND,
547
"Unable to retrieve the X11 visual");
551
clutter_x11_trap_x_errors ();
553
attrs.override_redirect = True;
554
attrs.colormap = XCreateColormap (xdisplay,
558
attrs.border_pixel = 0;
560
backend_glx->dummy_xwin = XCreateWindow (xdisplay, root_xwin,
566
CWOverrideRedirect | CWColormap | CWBorderPixel,
569
/* Try and create a GLXWindow to use with extensions dependent on
570
* GLX versions >= 1.3 that don't accept regular X Windows as GLX
572
if (glXQueryVersion (backend_x11->xdpy, &major, &minor) &&
573
major == 1 && minor >= 3)
575
backend_glx->dummy_glxwin = glXCreateWindow (backend_x11->xdpy,
577
backend_glx->dummy_xwin,
581
if (backend_glx->dummy_glxwin)
582
dummy_drawable = backend_glx->dummy_glxwin;
584
dummy_drawable = backend_glx->dummy_xwin;
586
CLUTTER_NOTE (BACKEND, "Selecting dummy 0x%x for the GLX context",
587
(unsigned int) dummy_drawable);
589
glXMakeContextCurrent (xdisplay,
592
backend_glx->gl_context);
596
if (clutter_x11_untrap_x_errors ())
598
g_set_error (error, CLUTTER_INIT_ERROR,
599
CLUTTER_INIT_ERROR_BACKEND,
600
"Unable to select the newly created GLX context");
607
/* TODO: remove this interface in favour of
608
* _clutter_stage_window_make_current () */
409
clutter_backend_glx_ensure_context (ClutterBackend *backend,
610
clutter_backend_glx_ensure_context (ClutterBackend *backend,
410
611
ClutterStage *stage)
412
613
ClutterStageWindow *impl;
450
657
/* we might get here inside the final dispose cycle, so we
451
658
* need to handle this gracefully
453
if (stage_x11->xwin == None)
660
if (drawable == None)
455
ClutterBackendX11 *backend_x11;
662
GLXDrawable dummy_drawable;
457
backend_x11 = CLUTTER_BACKEND_X11 (backend);
458
CLUTTER_NOTE (MULTISTAGE,
664
CLUTTER_NOTE (BACKEND,
459
665
"Received a stale stage, clearing all context");
461
glXMakeCurrent (backend_x11->xdpy, None, NULL);
667
if (backend_glx->dummy_glxwin)
668
dummy_drawable = backend_glx->dummy_glxwin;
670
dummy_drawable = backend_glx->dummy_xwin;
672
if (dummy_drawable == None)
673
glXMakeContextCurrent (backend_x11->xdpy, None, None, NULL);
676
glXMakeContextCurrent (backend_x11->xdpy,
679
backend_glx->gl_context);
465
684
CLUTTER_NOTE (BACKEND,
466
"MakeCurrent dpy: %p, window: 0x%x (%s), context: %p",
468
(int) stage_x11->xwin,
685
"MakeContextCurrent dpy: %p, window: 0x%x (%s), context: %p",
687
(unsigned int) drawable,
469
688
stage_x11->is_foreign_xwin ? "foreign" : "native",
470
689
backend_glx->gl_context);
472
glXMakeCurrent (stage_x11->xdpy,
474
backend_glx->gl_context);
691
glXMakeContextCurrent (backend_x11->xdpy,
694
backend_glx->gl_context);
477
697
if (clutter_x11_untrap_x_errors ())
478
698
g_critical ("Unable to make the stage window 0x%x the current "
480
(int) stage_x11->xwin);
485
glx_wait_for_vblank (ClutterBackendGLX *backend_glx)
487
/* If we are going to wait for VBLANK manually, we not only need
488
* to flush out pending drawing to the GPU before we sleep, we
489
* need to wait for it to finish. Otherwise, we may end up with
492
* - We finish drawing - GPU drawing continues
493
* - We go to sleep - GPU drawing continues
494
* VBLANK - We call glXSwapBuffers - GPU drawing continues
495
* - GPU drawing continues
496
* - Swap buffers happens
498
* Producing a tear. Calling glFinish() first will cause us to properly
499
* wait for the next VBLANK before we swap. This obviously does not
500
* happen when we use GLX_SWAP and let the driver do the right thing
503
switch (backend_glx->vblank_type)
505
case CLUTTER_VBLANK_GLX_SWAP:
509
case CLUTTER_VBLANK_GLX:
511
unsigned int retraceCount;
515
backend_glx->get_video_sync (&retraceCount);
516
backend_glx->wait_video_sync (2,
517
(retraceCount + 1) % 2,
522
case CLUTTER_VBLANK_DRI:
525
drm_wait_vblank_t blank;
529
blank.request.type = DRM_VBLANK_RELATIVE;
530
blank.request.sequence = 1;
531
blank.request.signal = 0;
532
drm_wait_vblank (backend_glx->dri_fd, &blank);
537
case CLUTTER_VBLANK_NONE:
700
(unsigned int) drawable);
705
* FIXME: we should remove backend_class->redraw() and just
706
* have stage_window_iface->redraw()
544
709
clutter_backend_glx_redraw (ClutterBackend *backend,
545
710
ClutterStage *stage)
547
ClutterStageGLX *stage_glx;
548
ClutterStageX11 *stage_x11;
549
ClutterStageWindow *impl;
712
ClutterStageWindow *impl = _clutter_stage_get_window (stage);
551
impl = _clutter_stage_get_window (stage);
552
714
if (G_UNLIKELY (impl == NULL))
554
716
CLUTTER_NOTE (BACKEND, "Stage [%p] has no implementation", stage);
558
720
g_assert (CLUTTER_IS_STAGE_GLX (impl));
560
stage_x11 = CLUTTER_STAGE_X11 (impl);
561
stage_glx = CLUTTER_STAGE_GLX (impl);
563
/* this will cause the stage implementation to be painted */
564
clutter_actor_paint (CLUTTER_ACTOR (stage));
567
if (stage_x11->xwin != None)
569
/* wait for the next vblank */
570
CLUTTER_NOTE (BACKEND, "Waiting for vblank");
571
glx_wait_for_vblank (CLUTTER_BACKEND_GLX (backend));
573
/* push on the screen */
574
CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
576
(unsigned long) stage_x11->xwin);
577
glXSwapBuffers (stage_x11->xdpy, stage_x11->xwin);
722
clutter_stage_glx_redraw (CLUTTER_STAGE_GLX (impl),
588
static ClutterActor *
726
static ClutterStageWindow *
589
727
clutter_backend_glx_create_stage (ClutterBackend *backend,
590
728
ClutterStage *wrapper,
593
731
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
594
ClutterStageX11 *stage_x11;
732
ClutterStageWindow *stage_window;
733
ClutterStageX11 *stage_x11;
597
735
CLUTTER_NOTE (BACKEND, "Creating stage of type '%s'",
598
736
g_type_name (CLUTTER_STAGE_TYPE));
600
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
738
stage_window = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
602
740
/* copy backend data into the stage */
603
stage_x11 = CLUTTER_STAGE_X11 (stage);
604
stage_x11->xdpy = backend_x11->xdpy;
605
stage_x11->xwin_root = backend_x11->xwin_root;
606
stage_x11->xscreen = backend_x11->xscreen_num;
607
stage_x11->backend = backend_x11;
741
stage_x11 = CLUTTER_STAGE_X11 (stage_window);
608
742
stage_x11->wrapper = wrapper;
610
744
CLUTTER_NOTE (BACKEND,
611
745
"GLX stage created[%p] (dpy:%p, screen:%d, root:%u, wrap:%p)",
615
(unsigned int) stage_x11->xwin_root,
748
backend_x11->xscreen_num,
749
(unsigned int) backend_x11->xwin_root,
622
clutter_backend_glx_get_visual_info (ClutterBackendX11 *backend_x11,
623
gboolean for_offscreen)
625
XVisualInfo *xvisinfo;
626
int onscreen_gl_attributes[] = {
637
int offscreen_gl_attributes[] = {
649
if (backend_x11->xdpy == None || backend_x11->xscreen == None)
652
CLUTTER_NOTE (BACKEND,
653
"Retrieving GL visual (for %s use), dpy: %p, xscreen; %p (%d)",
654
for_offscreen ? "offscreen" : "onscreen",
656
backend_x11->xscreen,
657
backend_x11->xscreen_num);
659
xvisinfo = glXChooseVisual (backend_x11->xdpy,
660
backend_x11->xscreen_num,
661
for_offscreen ? offscreen_gl_attributes
662
: onscreen_gl_attributes);