static ClutterFeatureFlags clutter_backend_egl_get_features (ClutterBackend *backend) { ClutterBackendEGL *backend_egl = CLUTTER_BACKEND_EGL (backend); ClutterFeatureFlags flags; flags = clutter_backend_x11_get_features (backend); flags |= CLUTTER_FEATURE_STAGE_MULTIPLE; CLUTTER_NOTE (BACKEND, "Checking features\n" "GL_VENDOR: %s\n" "GL_RENDERER: %s\n" "GL_VERSION: %s\n" "EGL_VENDOR: %s\n" "EGL_VERSION: %s\n" "EGL_EXTENSIONS: %s\n", glGetString (GL_VENDOR), glGetString (GL_RENDERER), glGetString (GL_VERSION), eglQueryString (backend_egl->edpy, EGL_VENDOR), eglQueryString (backend_egl->edpy, EGL_VERSION), eglQueryString (backend_egl->edpy, EGL_EXTENSIONS)); return flags; }
static ClutterFeatureFlags clutter_backend_glx_get_features (ClutterBackend *backend) { ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); const gchar *glx_extensions = NULL; const gchar *gl_extensions = NULL; ClutterFeatureFlags flags; gboolean use_dri = FALSE; flags = clutter_backend_x11_get_features (backend); flags |= CLUTTER_FEATURE_STAGE_MULTIPLE; /* this will make sure that the GL context exists */ g_assert (backend_glx->gl_context != None); g_assert (glXGetCurrentDrawable () != None); CLUTTER_NOTE (BACKEND, "Checking features\n" " GL_VENDOR: %s\n" " GL_RENDERER: %s\n" " GL_VERSION: %s\n" " GL_EXTENSIONS: %s", glGetString (GL_VENDOR), glGetString (GL_RENDERER), glGetString (GL_VERSION), glGetString (GL_EXTENSIONS)); glx_extensions = glXQueryExtensionsString (clutter_x11_get_default_display (), clutter_x11_get_default_screen ()); CLUTTER_NOTE (BACKEND, " GLX Extensions: %s", glx_extensions); gl_extensions = (const gchar *)glGetString (GL_EXTENSIONS); /* When using glBlitFramebuffer or glXCopySubBufferMESA for sub stage * redraws, we cannot rely on glXSwapIntervalSGI to throttle the blits * so we need to resort to manually synchronizing with the vblank so we * always check for the video_sync extension... */ if (_cogl_check_extension ("GLX_SGI_video_sync", glx_extensions) && /* Note: the GLX_SGI_video_sync spec explicitly states this extension * only works for direct contexts. */ glXIsDirect (clutter_x11_get_default_display (), backend_glx->gl_context)) { backend_glx->get_video_sync = (GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI"); backend_glx->wait_video_sync = (WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI"); } use_dri = check_vblank_env ("dri"); /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */ if (check_vblank_env ("none")) { CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request"); goto vblank_setup_done; } if (g_getenv ("__GL_SYNC_TO_VBLANK") != NULL) { backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; CLUTTER_NOTE (BACKEND, "Using __GL_SYNC_TO_VBLANK hint"); goto vblank_setup_done; } /* We try two GL vblank syncing mechanisms. * glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI. * * glXSwapIntervalSGI is known to work with Mesa and in particular * the Intel drivers. glXGetVideoSyncSGI has serious problems with * Intel drivers causing terrible frame rate so it only tried as a * fallback. * * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have * no effect. */ if (!use_dri && _cogl_check_extension ("GLX_SGI_swap_control", glx_extensions)) { backend_glx->swap_interval = (SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI"); CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup"); if (backend_glx->swap_interval != NULL && backend_glx->swap_interval (1) == 0) { backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success"); #ifdef GLX_INTEL_swap_event /* GLX_INTEL_swap_event allows us to avoid blocking the CPU * while we wait for glXSwapBuffers to complete, and instead * we get an X event notifying us of completion... */ if (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_SWAP_EVENTS) && _cogl_check_extension ("GLX_INTEL_swap_event", glx_extensions)) { flags |= CLUTTER_FEATURE_SWAP_EVENTS; } #endif /* GLX_INTEL_swap_event */ goto vblank_setup_done; } CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed"); } if (!use_dri && !(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) && _cogl_check_extension ("GLX_SGI_video_sync", glx_extensions)) { CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup"); if ((backend_glx->get_video_sync != NULL) && (backend_glx->wait_video_sync != NULL)) { CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success"); backend_glx->vblank_type = CLUTTER_VBLANK_GLX; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; goto vblank_setup_done; } CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed"); } #ifdef __linux__ /* * DRI is really an extreme fallback -rumoured to work with Via chipsets */ if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) { CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup"); backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR); if (backend_glx->dri_fd >= 0) { CLUTTER_NOTE (BACKEND, "DRI vblank setup success"); backend_glx->vblank_type = CLUTTER_VBLANK_DRI; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; goto vblank_setup_done; } CLUTTER_NOTE (BACKEND, "DRI vblank setup failed"); } #endif /* __linux__ */ CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found"); vblank_setup_done: if (_cogl_check_extension ("GLX_MESA_copy_sub_buffer", glx_extensions)) { backend_glx->copy_sub_buffer = (CopySubBufferProc) cogl_get_proc_address ("glXCopySubBufferMESA"); backend_glx->can_blit_sub_buffer = TRUE; backend_glx->blit_sub_buffer_is_synchronized = TRUE; } else if (_cogl_check_extension ("GL_EXT_framebuffer_blit", gl_extensions)) { CLUTTER_NOTE (BACKEND, "Using glBlitFramebuffer fallback for sub_buffer copies"); backend_glx->blit_framebuffer = (BlitFramebufferProc) cogl_get_proc_address ("glBlitFramebuffer"); backend_glx->can_blit_sub_buffer = TRUE; backend_glx->blit_sub_buffer_is_synchronized = FALSE; } CLUTTER_NOTE (BACKEND, "backend features checked"); return flags; }
static ClutterFeatureFlags clutter_backend_glx_get_features (ClutterBackend *backend) { ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend); const gchar *glx_extensions = NULL; ClutterFeatureFlags flags; flags = clutter_backend_x11_get_features (backend); flags |= CLUTTER_FEATURE_STAGE_MULTIPLE; /* this will make sure that the GL context exists and * it's bound to a drawable */ g_assert (backend_glx->gl_context != None); g_assert (glXGetCurrentDrawable () != None); CLUTTER_NOTE (BACKEND, "Checking features\n" "GL_VENDOR: %s\n" "GL_RENDERER: %s\n" "GL_VERSION: %s\n" "GL_EXTENSIONS: %s\n", glGetString (GL_VENDOR), glGetString (GL_RENDERER), glGetString (GL_VERSION), glGetString (GL_EXTENSIONS)); glx_extensions = glXQueryExtensionsString (clutter_x11_get_default_display (), clutter_x11_get_default_screen ()); CLUTTER_NOTE (BACKEND, "GLX Extensions: %s", glx_extensions); /* First check for explicit disabling or it set elsewhere (eg NVIDIA) */ if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env ("none")) { CLUTTER_NOTE (BACKEND, "vblank sync: disabled at user request"); } else { /* We try two GL vblank syncing mechanisms. * glXSwapIntervalSGI is tried first, then glXGetVideoSyncSGI. * * glXSwapIntervalSGI is known to work with Mesa and in particular * the Intel drivers. glXGetVideoSyncSGI has serious problems with * Intel drivers causing terrible frame rate so it only tried as a * fallback. * * How well glXGetVideoSyncSGI works with other driver (ATI etc) needs * to be investigated. glXGetVideoSyncSGI on ATI at least seems to have * no effect. */ if (!check_vblank_env ("dri") && cogl_check_extension ("GLX_SGI_swap_control", glx_extensions)) { backend_glx->swap_interval = (SwapIntervalProc) cogl_get_proc_address ("glXSwapIntervalSGI"); CLUTTER_NOTE (BACKEND, "attempting glXSwapIntervalSGI vblank setup"); if (backend_glx->swap_interval != NULL) { if (backend_glx->swap_interval (1) == 0) { backend_glx->vblank_type = CLUTTER_VBLANK_GLX_SWAP; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI setup success"); } } if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) CLUTTER_NOTE (BACKEND, "glXSwapIntervalSGI vblank setup failed"); } if (!check_vblank_env ("dri") && !(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK) && cogl_check_extension ("GLX_SGI_video_sync", glx_extensions)) { CLUTTER_NOTE (BACKEND, "attempting glXGetVideoSyncSGI vblank setup"); backend_glx->get_video_sync = (GetVideoSyncProc) cogl_get_proc_address ("glXGetVideoSyncSGI"); backend_glx->wait_video_sync = (WaitVideoSyncProc) cogl_get_proc_address ("glXWaitVideoSyncSGI"); if ((backend_glx->get_video_sync != NULL) && (backend_glx->wait_video_sync != NULL)) { CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup success"); backend_glx->vblank_type = CLUTTER_VBLANK_GLX; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; } if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) CLUTTER_NOTE (BACKEND, "glXGetVideoSyncSGI vblank setup failed"); } #ifdef __linux__ /* * DRI is really an extreme fallback -rumoured to work with Via chipsets */ if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) { CLUTTER_NOTE (BACKEND, "attempting DRI vblank setup"); backend_glx->dri_fd = open("/dev/dri/card0", O_RDWR); if (backend_glx->dri_fd >= 0) { CLUTTER_NOTE (BACKEND, "DRI vblank setup success"); backend_glx->vblank_type = CLUTTER_VBLANK_DRI; flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; } if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) CLUTTER_NOTE (BACKEND, "DRI vblank setup failed"); } #endif if (!(flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) { CLUTTER_NOTE (BACKEND, "no use-able vblank mechanism found"); } } CLUTTER_NOTE (MISC, "backend features checked"); return flags; }