diff --git a/0001-kms-winsys-try-to-hobble-along-if-driver-doesn-t-sup.patch b/0001-kms-winsys-try-to-hobble-along-if-driver-doesn-t-sup.patch index 7ae580c..7495798 100644 --- a/0001-kms-winsys-try-to-hobble-along-if-driver-doesn-t-sup.patch +++ b/0001-kms-winsys-try-to-hobble-along-if-driver-doesn-t-sup.patch @@ -1,4 +1,4 @@ -From 5c22141866e5335dd111b64349f6ff2ee484a6b4 Mon Sep 17 00:00:00 2001 +From 68d9ba3b653a2fe0f0992ea2b6df753b3bfc9d61 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Wed, 11 Mar 2015 12:09:51 -0400 Subject: [PATCH] kms-winsys: try to hobble along if driver doesn't support @@ -6,21 +6,20 @@ Subject: [PATCH] kms-winsys: try to hobble along if driver doesn't support Some drivers ( like mgag200 ) don't yet support drmModePageFlip. -This commit tries to emulate the functionality using drmWaitVBlank -and drmModeSetCrtc in those cases. - -Failing all else, it just falls back to flipping right away. +This commit forgoes waiting for vblank and flips right away +in those cases. That prevents the hardware from freezing up the screen, +but does mean there will be some visible tearing. https://bugzilla.gnome.org/show_bug.cgi?id=746042 --- - cogl/winsys/cogl-winsys-egl-kms.c | 130 +++++++++++++++++++++++++++++++++----- - 1 file changed, 115 insertions(+), 15 deletions(-) + cogl/winsys/cogl-winsys-egl-kms.c | 52 +++++++++++++++++++++++++++++---------- + 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c -index b06c1da..c66eb45 100644 +index b06c1da..c5d014a 100644 --- a/cogl/winsys/cogl-winsys-egl-kms.c +++ b/cogl/winsys/cogl-winsys-egl-kms.c -@@ -45,104 +45,107 @@ +@@ -45,60 +45,61 @@ #include #include #include @@ -52,7 +51,6 @@ index b06c1da..c66eb45 100644 struct gbm_device *gbm; CoglClosure *swap_notify_idle; + CoglBool page_flips_not_supported; -+ CoglBool vblank_not_supported; } CoglRendererKMS; typedef struct _CoglOutputKMS @@ -83,52 +81,7 @@ index b06c1da..c66eb45 100644 int pending; } CoglFlipKMS; - typedef struct _CoglOnscreenKMS - { - struct gbm_surface *surface; - uint32_t current_fb_id; - uint32_t next_fb_id; - struct gbm_bo *current_bo; - struct gbm_bo *next_bo; - CoglBool pending_swap_notify; - - EGLSurface *pending_egl_surface; - struct gbm_surface *pending_surface; - } CoglOnscreenKMS; - - static const char device_name[] = "/dev/dri/card0"; -+static void setup_crtc_modes (CoglDisplay *display, int fb_id); - - static void - _cogl_winsys_renderer_disconnect (CoglRenderer *renderer) - { - CoglRendererEGL *egl_renderer = renderer->winsys; - CoglRendererKMS *kms_renderer = egl_renderer->platform; - - eglTerminate (egl_renderer->edpy); - - if (kms_renderer->opened_fd >= 0) - close (kms_renderer->opened_fd); - - g_slice_free (CoglRendererKMS, kms_renderer); - g_slice_free (CoglRendererEGL, egl_renderer); - } - - static void - flush_pending_swap_notify_cb (void *data, - void *user_data) - { - CoglFramebuffer *framebuffer = data; - - if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_ONSCREEN) - { - CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); - CoglOnscreenEGL *egl_onscreen = onscreen->winsys; - CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform; - - if (kms_onscreen->pending_swap_notify) - { -@@ -197,101 +200,168 @@ free_current_bo (CoglOnscreen *onscreen) +@@ -197,98 +198,107 @@ free_current_bo (CoglOnscreen *onscreen) kms_onscreen->current_bo = NULL; } } @@ -205,76 +158,17 @@ index b06c1da..c66eb45 100644 + process_flip (flip); +} + -+static void -+process_vblank (CoglFlipKMS *flip) -+{ -+ /* Normally the driver would set the next fb up for -+ * scan out after vblank for us and then call the -+ * page flip handler to clean things up. -+ * -+ * Not all drivers support the newer page flipping interface -+ * that provides this functionality, though, so try to emulate -+ * it -+ */ -+ if (flip->pending == 1) -+ { -+ CoglOnscreen *onscreen = flip->onscreen; -+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys; -+ CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform; -+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); -+ CoglContext *context = framebuffer->context; -+ CoglDisplay *display = context->display; -+ -+ setup_crtc_modes (display, kms_onscreen->next_fb_id); -+ -+ process_flip (flip); -+ } -+} -+ -+static void -+vblank_handler (int fd, -+ unsigned int frame, -+ unsigned int sec, -+ unsigned int usec, -+ void *data) -+{ -+ CoglFlipKMS *flip = data; -+ -+ process_vblank (flip); -+} -+ -+static gboolean -+fake_vblank_timeout_handler (gpointer data) -+{ -+ CoglFlipKMS *flip = data; -+ -+ /* Normally the next fb would get setup for -+ * scan out after a vblank interval. -+ * -+ * Not all drivers support vblank notification, though, -+ * so this handler just processes things right away. -+ */ -+ process_vblank (flip); -+ -+ return G_SOURCE_REMOVE; -+} -+ +static void handle_drm_event (CoglRendererKMS *kms_renderer) { drmEventContext evctx; -+ if (kms_renderer->page_flips_not_supported && -+ kms_renderer->vblank_not_supported) ++ if (kms_renderer->page_flips_not_supported) + return; + memset (&evctx, 0, sizeof evctx); evctx.version = DRM_EVENT_CONTEXT_VERSION; -- evctx.page_flip_handler = page_flip_handler; -+ if (kms_renderer->page_flips_not_supported) -+ evctx.vblank_handler = vblank_handler; -+ else -+ evctx.page_flip_handler = page_flip_handler; + evctx.page_flip_handler = page_flip_handler; drmHandleEvent (kms_renderer->fd, &evctx); } @@ -302,10 +196,11 @@ index b06c1da..c66eb45 100644 egl_renderer = renderer->winsys; egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable; - egl_renderer->platform = g_slice_new0 (CoglRendererKMS); - kms_renderer = egl_renderer->platform; - -@@ -552,75 +622,105 @@ setup_crtc_modes (CoglDisplay *display, int fb_id) +@@ -548,81 +558,90 @@ static void + setup_crtc_modes (CoglDisplay *display, int fb_id) + { + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayKMS *kms_display = egl_display->platform; CoglRendererEGL *egl_renderer = display->renderer->winsys; CoglRendererKMS *kms_renderer = egl_renderer->platform; GList *l; @@ -332,12 +227,12 @@ index b06c1da..c66eb45 100644 CoglRendererEGL *egl_renderer = display->renderer->winsys; CoglRendererKMS *kms_renderer = egl_renderer->platform; GList *l; ++ gboolean needs_flip = FALSE; for (l = kms_display->crtcs; l; l = l->next) { CoglKmsCrtc *crtc = l->data; -- int ret; -+ int ret = -1; + int ret; if (crtc->count == 0 || crtc->ignore) continue; @@ -345,8 +240,13 @@ index b06c1da..c66eb45 100644 - ret = drmModePageFlip (kms_renderer->fd, - crtc->id, fb_id, - DRM_MODE_PAGE_FLIP_EVENT, flip); ++ needs_flip = TRUE; + +- if (ret) + if (!kms_renderer->page_flips_not_supported) -+ { + { +- g_warning ("Failed to flip: %m"); +- continue; + ret = drmModePageFlip (kms_renderer->fd, + crtc->id, fb_id, + DRM_MODE_PAGE_FLIP_EVENT, flip); @@ -354,42 +254,15 @@ index b06c1da..c66eb45 100644 + { + g_warning ("Failed to flip: %m"); + kms_renderer->page_flips_not_supported = TRUE; -+ } -+ } - -- if (ret) -+ if (kms_renderer->page_flips_not_supported) - { -- g_warning ("Failed to flip: %m"); -- continue; -+ drmVBlank watch_for_next_vblank_operation = { 0 }; -+ -+ if (!kms_renderer->vblank_not_supported) -+ { -+ /* fall back to older way of waiting for vblanks directly -+ */ -+ watch_for_next_vblank_operation.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT; -+ watch_for_next_vblank_operation.request.sequence = 1; -+ watch_for_next_vblank_operation.request.signal = (gulong) flip; -+ -+ ret = drmWaitVBlank (kms_renderer->fd, &watch_for_next_vblank_operation); -+ -+ if (ret) -+ { -+ kms_renderer->vblank_not_supported = TRUE; -+ g_warning ("Failed to fall back to waiting for vblanks directly: %m"); -+ } ++ break; + } } -+ if (kms_renderer->page_flips_not_supported && -+ kms_renderer->vblank_not_supported) -+ { -+ g_idle_add (fake_vblank_timeout_handler, flip); -+ } -+ flip->pending++; } ++ ++ if (kms_renderer->page_flips_not_supported && needs_flip) ++ flip->pending = 1; } static void @@ -418,6 +291,76 @@ index b06c1da..c66eb45 100644 { CoglDisplayEGL *egl_display = display->winsys; CoglDisplayKMS *kms_display; + CoglRendererEGL *egl_renderer = display->renderer->winsys; + CoglRendererKMS *kms_renderer = egl_renderer->platform; +@@ -918,60 +937,67 @@ _cogl_winsys_onscreen_swap_buffers_with_damage (CoglOnscreen *onscreen, + + /* If this is the first framebuffer to be presented then we now setup the + * crtc modes, else we flip from the previous buffer */ + if (kms_display->pending_set_crtc) + { + setup_crtc_modes (context->display, kms_onscreen->next_fb_id); + kms_display->pending_set_crtc = FALSE; + } + + flip = g_slice_new0 (CoglFlipKMS); + flip->onscreen = onscreen; + + flip_all_crtcs (context->display, flip, kms_onscreen->next_fb_id); + + if (flip->pending == 0) + { + drmModeRmFB (kms_renderer->fd, kms_onscreen->next_fb_id); + gbm_surface_release_buffer (kms_onscreen->surface, + kms_onscreen->next_bo); + kms_onscreen->next_bo = NULL; + kms_onscreen->next_fb_id = 0; + g_slice_free (CoglFlipKMS, flip); + flip = NULL; + + queue_swap_notify_for_onscreen (onscreen); + } + else + { + /* Ensure the onscreen remains valid while it has any pending flips... */ + cogl_object_ref (flip->onscreen); ++ ++ /* Process flip right away if we can't wait for vblank */ ++ if (kms_renderer->page_flips_not_supported) ++ { ++ setup_crtc_modes (context->display, kms_onscreen->next_fb_id); ++ process_flip (flip); ++ } + } + } + + static CoglBool + _cogl_winsys_egl_context_init (CoglContext *context, + CoglError **error) + { + COGL_FLAGS_SET (context->features, + COGL_FEATURE_ID_SWAP_BUFFERS_EVENT, TRUE); + /* TODO: remove this deprecated feature */ + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SWAP_BUFFERS_EVENT, + TRUE); + COGL_FLAGS_SET (context->winsys_features, + COGL_WINSYS_FEATURE_SYNC_AND_COMPLETE_EVENT, + TRUE); + + return TRUE; + } + + static CoglBool + _cogl_winsys_onscreen_init (CoglOnscreen *onscreen, + CoglError **error) + { + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *context = framebuffer->context; + CoglDisplay *display = context->display; + CoglDisplayEGL *egl_display = display->winsys; + CoglDisplayKMS *kms_display = egl_display->platform; + CoglRenderer *renderer = display->renderer; -- -2.3.1 +2.3.3 diff --git a/cogl.spec b/cogl.spec index ac95ef7..59d6a5b 100644 --- a/cogl.spec +++ b/cogl.spec @@ -6,7 +6,7 @@ Name: cogl Version: 1.20.0 -Release: 2%{?dist} +Release: 3%{?dist} Summary: A library for using 3D graphics hardware to draw pretty pictures Group: Development/Libraries @@ -154,6 +154,9 @@ chrpath --delete $RPM_BUILD_ROOT%{_libdir}/libcogl-pango.so %endif %changelog +* Mon Mar 23 2015 Ray Strode 1.20.0-3 +- Update to upstreamed version of mgag200 fix + * Wed Mar 11 2015 Ray Strode 1.20.0-2 - Try to fix wayland on mgag200