[PATCH 6/6] glamor: Use Present to delay Xv painting to vblank interval

Keith Packard keithp at keithp.com
Wed Aug 6 22:21:07 PDT 2014


For un-redirected windows, this uses present_vblank_window_queue to
start painting the screen during vblank and reduce tearing on the
screen

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 glamor/glamor_priv.h |  2 ++
 glamor/glamor_xv.c   | 63 ++++++++++++++++++++++++++++++++++++++++++++++++----
 2 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 05d3eac..a0b790c 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -1016,6 +1016,8 @@ typedef struct {
     RegionRec clip;
     PixmapPtr src_pix[3];       /* y, u, v for planar */
     int src_pix_w, src_pix_h;
+    uint64_t present_id;
+    unsigned long serialNumber;
 } glamor_port_private;
 
 extern XvAttributeRec glamor_xv_attributes[];
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index 367b89f..a71ac10 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -37,6 +37,7 @@
 #endif
 
 #include "glamor_priv.h"
+#include "present_vblank.h"
 
 #include <X11/extensions/Xv.h>
 #include "../hw/xfree86/common/fourcc.h"
@@ -138,6 +139,11 @@ glamor_xv_stop_video(glamor_port_private *port_priv)
 {
     int i;
 
+    if (port_priv->present_id) {
+        present_vblank_cancel(port_priv->pDraw->pScreen, port_priv->present_id);
+        port_priv->present_id = 0;
+    }
+
     for (i = 0; i < 3; i++) {
         if (port_priv->src_pix[i]) {
             glamor_destroy_pixmap(port_priv->src_pix[i]);
@@ -260,9 +266,6 @@ glamor_xv_render(glamor_port_private *port_priv)
     int ref = port_priv->transform_index;
     GLint uloc, sampler_loc;
 
-    if (!glamor_priv->xv_prog)
-        glamor_init_xv_shader(screen);
-
     cont = RTFContrast(port_priv->contrast);
     bright = RTFBrightness(port_priv->brightness);
     gamma = (float) port_priv->gamma / 1000.0;
@@ -389,6 +392,29 @@ glamor_xv_render(glamor_port_private *port_priv)
     DamageDamageRegion(port_priv->pDraw, &port_priv->clip);
 }
 
+static void
+glamor_xv_present(WindowPtr     window,
+                  void          *closure,
+                  uint64_t      ust,
+                  uint64_t      msc)
+{
+    glamor_port_private *port_priv = closure;
+
+    port_priv->present_id = 0;
+    if (port_priv->serialNumber == window->drawable.serialNumber) {
+        glamor_xv_render(port_priv);
+        glFlush();
+    }
+}
+
+static Bool
+glamor_window_is_redirected(WindowPtr window)
+{
+    ScreenPtr   screen = window->drawable.pScreen;
+
+    return screen->GetWindowPixmap (window) != screen->GetScreenPixmap(screen);
+}
+
 int
 glamor_xv_put_image(glamor_port_private *port_priv,
                     DrawablePtr pDrawable,
@@ -404,6 +430,7 @@ glamor_xv_put_image(glamor_port_private *port_priv,
                     RegionPtr clipBoxes)
 {
     ScreenPtr pScreen = pDrawable->pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
     int srcPitch, srcPitch2;
     int top, nlines;
     int s2offset, s3offset, tmp;
@@ -413,6 +440,11 @@ glamor_xv_put_image(glamor_port_private *port_priv,
     srcPitch = width;
     srcPitch2 = width >> 1;
 
+    glamor_make_current(glamor_priv);
+
+    if (!glamor_priv->xv_prog)
+        glamor_init_xv_shader(pScreen);
+
     if (!port_priv->src_pix[0] ||
         (width != port_priv->src_pix_w || height != port_priv->src_pix_h)) {
         int i;
@@ -489,7 +521,30 @@ glamor_xv_put_image(glamor_port_private *port_priv,
     port_priv->w = width;
     port_priv->h = height;
     port_priv->pDraw = pDrawable;
-    glamor_xv_render(port_priv);
+
+    if (port_priv->present_id) {
+        present_vblank_cancel(pScreen, port_priv->present_id);
+        port_priv->present_id = 0;
+    }
+
+    if (pDrawable->type == DRAWABLE_WINDOW &&
+        !glamor_window_is_redirected((WindowPtr) pDrawable))
+    {
+        port_priv->serialNumber = pDrawable->serialNumber;
+        port_priv->present_id = present_vblank_window_queue((WindowPtr) pDrawable,
+                                                            present_whence_relative,
+                                                            1,
+                                                            0,
+                                                            glamor_xv_present,
+                                                            port_priv);
+    }
+
+    if (!port_priv->present_id)
+        glamor_xv_render(port_priv);
+
+    if (port_priv->present_id == PRESENT_VBLANK_QUEUE_EXECUTED)
+        port_priv->present_id = 0;
+
     return Success;
 }
 
-- 
2.0.1



More information about the xorg-devel mailing list