xserver: Branch 'master' - 5 commits

Keith Packard keithp at kemper.freedesktop.org
Mon Jun 20 18:56:04 UTC 2016


 dix/dixutils.c          |   23 ++++++----
 glamor/glamor.c         |    6 +-
 hw/kdrive/ephyr/ephyr.c |  104 ++++++++++++++++++++++++++++++++++++------------
 hw/kdrive/ephyr/ephyr.h |    2 
 hw/kdrive/ephyr/hostx.c |   54 +++++++++++++++++++++++-
 hw/kdrive/ephyr/hostx.h |    9 ++++
 miext/shadow/shadow.c   |   20 +++------
 miext/shadow/shadow.h   |    1 
 8 files changed, 166 insertions(+), 53 deletions(-)

New commits:
commit 828887b6f4a997b6468da565a88b6fe9afcda191
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jun 14 13:45:27 2016 -0700

    ephyr: Process only the last expose or configure available from the server
    
    Delay expose or configure processing until the event queue is empty so
    that we don't end up processing a long series of events one at a
    time. Expose events already have a check waiting for the last in a
    series, this further improves that by discarding multiple
    series of events.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 015aef5..d7948e8 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -1141,6 +1141,7 @@ static void
 ephyrXcbProcessEvents(Bool queued_only)
 {
     xcb_connection_t *conn = hostx_get_xcbconn();
+    xcb_generic_event_t *expose = NULL, *configure = NULL;
 
     while (TRUE) {
         xcb_generic_event_t *xev = hostx_get_event(queued_only);
@@ -1164,7 +1165,9 @@ ephyrXcbProcessEvents(Bool queued_only)
             break;
 
         case XCB_EXPOSE:
-            ephyrProcessExpose(xev);
+            free(expose);
+            expose = xev;
+            xev = NULL;
             break;
 
         case XCB_MOTION_NOTIFY:
@@ -1188,14 +1191,28 @@ ephyrXcbProcessEvents(Bool queued_only)
             break;
 
         case XCB_CONFIGURE_NOTIFY:
-            ephyrProcessConfigureNotify(xev);
+            free(configure);
+            configure = xev;
+            xev = NULL;
             break;
         }
 
-        if (ephyr_glamor)
-            ephyr_glamor_process_event(xev);
+        if (xev) {
+            if (ephyr_glamor)
+                ephyr_glamor_process_event(xev);
+
+            free(xev);
+        }
+    }
+
+    if (configure) {
+        ephyrProcessConfigureNotify(configure);
+        free(configure);
+    }
 
-        free(xev);
+    if (expose) {
+        ephyrProcessExpose(expose);
+        free(expose);
     }
 }
 
commit c17a41794507d6d04c850e9e1bc04fc60c31de18
Author: Keith Packard <keithp at keithp.com>
Date:   Sat Jun 4 19:55:07 2016 -0700

    ephyr: Process queued X events before blocking [v2]
    
    If we end up reading all pending X events in the course of other server
    execution, then our notify FD callback won't get invoked and we won't
    process them. Fix this by noting that there are queued events in the
    block handler, setting the poll timeout to zero and queuing a work
    proc to clear the event queue.
    
    v2: use a work proc to clear the event queue rather than doing it in
        the block handler directly.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index e5f1883..015aef5 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -337,6 +337,16 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
 }
 
 static void
+ephyrXcbProcessEvents(Bool queued_only);
+
+static Bool
+ephyrEventWorkProc(ClientPtr client, void *closure)
+{
+    ephyrXcbProcessEvents(TRUE);
+    return TRUE;
+}
+
+static void
 ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead)
 {
     KdScreenPriv(pScreen);
@@ -345,20 +355,16 @@ ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead)
 
     pScreen->BlockHandler = scrpriv->BlockHandler;
     (*pScreen->BlockHandler)(pScreen, timeout, pRead);
+    scrpriv->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = ephyrScreenBlockHandler;
 
-    if (scrpriv->pDamage) {
-
-        /* Re-wrap if we're still tracking damage
-         */
-        scrpriv->BlockHandler = pScreen->BlockHandler;
-        pScreen->BlockHandler = ephyrScreenBlockHandler;
+    if (scrpriv->pDamage)
         ephyrInternalDamageRedisplay(pScreen);
-    } else {
 
-        /* Done tracking damage, note that we've left
-         * the block handler unwrapped
-         */
-        scrpriv->BlockHandler = NULL;
+    if (hostx_has_queued_event()) {
+        if (!QueueWorkProc(ephyrEventWorkProc, NULL, NULL))
+            FatalError("cannot queue event processing in ephyr block handler");
+        AdjustWaitForDelay(timeout, 0);
     }
 }
 
@@ -374,12 +380,6 @@ ephyrSetInternalDamage(ScreenPtr pScreen)
                                     (DamageDestroyFunc) 0,
                                     DamageReportNone, TRUE, pScreen, pScreen);
 
-    /* Wrap only once */
-    if (scrpriv->BlockHandler == NULL) {
-        scrpriv->BlockHandler = pScreen->BlockHandler;
-        pScreen->BlockHandler = ephyrScreenBlockHandler;
-    }
-
     pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
 
     DamageRegister(&pPixmap->drawable, scrpriv->pDamage);
@@ -682,6 +682,10 @@ ephyrInitScreen(ScreenPtr pScreen)
 Bool
 ephyrFinishInitScreen(ScreenPtr pScreen)
 {
+    KdScreenPriv(pScreen);
+    KdScreenInfo *screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = screen->driver;
+
     /* FIXME: Calling this even if not using shadow.
      * Seems harmless enough. But may be safer elsewhere.
      */
@@ -693,6 +697,9 @@ ephyrFinishInitScreen(ScreenPtr pScreen)
         return FALSE;
 #endif
 
+    scrpriv->BlockHandler = pScreen->BlockHandler;
+    pScreen->BlockHandler = ephyrScreenBlockHandler;
+
     return TRUE;
 }
 
@@ -1131,12 +1138,13 @@ ephyrProcessConfigureNotify(xcb_generic_event_t *xev)
 }
 
 static void
-ephyrXcbNotify(int fd, int ready, void *data)
+ephyrXcbProcessEvents(Bool queued_only)
 {
     xcb_connection_t *conn = hostx_get_xcbconn();
 
     while (TRUE) {
-        xcb_generic_event_t *xev = xcb_poll_for_event(conn);
+        xcb_generic_event_t *xev = hostx_get_event(queued_only);
+
         if (!xev) {
             /* If our XCB connection has died (for example, our window was
              * closed), exit now.
@@ -1191,6 +1199,12 @@ ephyrXcbNotify(int fd, int ready, void *data)
     }
 }
 
+static void
+ephyrXcbNotify(int fd, int ready, void *data)
+{
+    ephyrXcbProcessEvents(FALSE);
+}
+
 void
 ephyrCardFini(KdCardInfo * card)
 {
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index abe6eda..887f654 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -70,6 +70,7 @@ struct EphyrHostXVars {
     xcb_gcontext_t  gc;
     xcb_render_pictformat_t argb_format;
     xcb_cursor_t empty_cursor;
+    xcb_generic_event_t *saved_event;
     int depth;
     Bool use_sw_cursor;
     Bool use_fullscreen;
@@ -1227,6 +1228,31 @@ hostx_get_xcbconn(void)
     return HostX.conn;
 }
 
+xcb_generic_event_t *
+hostx_get_event(Bool queued_only)
+{
+    xcb_generic_event_t *xev;
+
+    if (HostX.saved_event) {
+        xev = HostX.saved_event;
+        HostX.saved_event = NULL;
+    } else {
+        if (queued_only)
+            xev = xcb_poll_for_queued_event(HostX.conn);
+        else
+            xev = xcb_poll_for_event(HostX.conn);
+    }
+    return xev;
+}
+
+Bool
+hostx_has_queued_event(void)
+{
+    if (!HostX.saved_event)
+        HostX.saved_event = xcb_poll_for_queued_event(HostX.conn);
+    return HostX.saved_event != NULL;
+}
+
 int
 hostx_get_screen(void)
 {
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index 6e0b07b..d0f3011 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -157,6 +157,12 @@ hostx_size_set_from_configure(Bool);
 xcb_connection_t *
 hostx_get_xcbconn(void);
 
+xcb_generic_event_t *
+hostx_get_event(Bool queued_only);
+
+Bool
+hostx_has_queued_event(void);
+
 int
 hostx_get_screen(void);
 
commit f3248eba6e2d0c099025f8e9a4874b431246eac7
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jun 14 13:19:49 2016 -0700

    ephyr: Handle window resize when using glamor
    
    Under glamor, we need to re-create the screen pixmap at the new size
    so that we can ask glamor for the associated texture. Fortunately, we
    can simply use ephyr_glamor_create_screen_resources to create the new
    pixmap.
    
    Because this is being done after the server has started, we need to
    walk the window heirarchy and reset any windows pointing at the old
    pixmap. I could easily be convinced that this TraverseTree should be
    moved to miSetScreenPixmap.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 2bc5ccc..e5f1883 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -510,6 +510,14 @@ ephyrRandRSetConfig(ScreenPtr pScreen,
     screen->width = newwidth;
     screen->height = newheight;
 
+    scrpriv->win_width = screen->width;
+    scrpriv->win_height = screen->height;
+#ifdef GLAMOR
+    ephyr_glamor_set_window_size(scrpriv->glamor,
+                                 scrpriv->win_width,
+                                 scrpriv->win_height);
+#endif
+
     if (!ephyrMapFramebuffer(screen))
         goto bail4;
 
@@ -520,12 +528,18 @@ ephyrRandRSetConfig(ScreenPtr pScreen,
     else
         ephyrUnsetInternalDamage(screen->pScreen);
 
+    ephyrSetScreenSizes(screen->pScreen);
+
     if (scrpriv->shadow) {
         if (!KdShadowSet(screen->pScreen,
                          scrpriv->randr, ephyrShadowUpdate, ephyrWindowLinear))
             goto bail4;
     }
     else {
+#ifdef GLAMOR
+        if (ephyr_glamor)
+            ephyr_glamor_create_screen_resources(pScreen);
+#endif
         /* Without shadow fb ( non rotated ) we need
          * to use damage to efficiently update display
          * via signal regions what to copy from 'fb'.
@@ -534,8 +548,6 @@ ephyrRandRSetConfig(ScreenPtr pScreen,
             goto bail4;
     }
 
-    ephyrSetScreenSizes(screen->pScreen);
-
     /*
      * Set frame buffer mapping
      */
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index d84c33b..abe6eda 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -1486,13 +1486,25 @@ ephyr_glamor_init(ScreenPtr screen)
     return TRUE;
 }
 
+static int
+ephyrSetPixmapVisitWindow(WindowPtr window, void *data)
+{
+    ScreenPtr screen = window->drawable.pScreen;
+
+    if (screen->GetWindowPixmap(window) == data) {
+        screen->SetWindowPixmap(window, screen->GetScreenPixmap(screen));
+        return WT_WALKCHILDREN;
+    }
+    return WT_DONTWALKCHILDREN;
+}
+
 Bool
 ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
 {
     KdScreenPriv(pScreen);
     KdScreenInfo *kd_screen = pScreenPriv->screen;
     EphyrScrPriv *scrpriv = kd_screen->driver;
-    PixmapPtr screen_pixmap;
+    PixmapPtr old_screen_pixmap, screen_pixmap;
     uint32_t tex;
 
     if (!ephyr_glamor)
@@ -1509,8 +1521,8 @@ ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
      *
      * Thus, delete the current screen pixmap, and put a fresh one in.
      */
-    screen_pixmap = pScreen->GetScreenPixmap(pScreen);
-    pScreen->DestroyPixmap(screen_pixmap);
+    old_screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+    pScreen->DestroyPixmap(old_screen_pixmap);
 
     screen_pixmap = pScreen->CreatePixmap(pScreen,
                                           pScreen->width,
@@ -1519,6 +1531,8 @@ ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
                                           GLAMOR_CREATE_NO_LARGE);
 
     pScreen->SetScreenPixmap(screen_pixmap);
+    if (pScreen->root && pScreen->SetWindowPixmap)
+        TraverseTree(pScreen->root, ephyrSetPixmapVisitWindow, old_screen_pixmap);
 
     /* Tell the GLX code what to GL texture to read from. */
     tex = glamor_get_pixmap_texture(screen_pixmap);
commit 235d21670dcff224807ff719c7fa86212058ec46
Author: Keith Packard <keithp at keithp.com>
Date:   Tue Jun 14 13:16:03 2016 -0700

    ephyr: Don't configure window while responding to configure events
    
    This leads to and endless sequence of window resizes.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 2114c1c..2bc5ccc 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -613,7 +613,9 @@ ephyrResizeScreen (ScreenPtr           pScreen,
     size.width = newwidth;
     size.height = newheight;
 
+    hostx_size_set_from_configure(TRUE);
     ret = ephyrRandRSetConfig (pScreen, screen->randr, 0, &size);
+    hostx_size_set_from_configure(FALSE);
     if (ret) {
         RROutputPtr output;
 
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index cdb12b0..d84c33b 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -79,6 +79,7 @@ struct EphyrHostXVars {
     KdScreenInfo **screens;
 
     long damage_debug_msec;
+    Bool size_set_from_configure;
 };
 
 /* memset ( missing> ) instead of below  */
@@ -878,6 +879,7 @@ hostx_screen_init(KdScreenInfo *screen,
             xallocarray(scrpriv->ximg->stride, buffer_height);
     }
 
+    if (!HostX.size_set_from_configure)
     {
         uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
         uint32_t values[2] = {width, height};
@@ -1213,6 +1215,12 @@ hostx_load_keymap(KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr controls)
     return TRUE;
 }
 
+void
+hostx_size_set_from_configure(Bool ss)
+{
+    HostX.size_set_from_configure = ss;
+}
+
 xcb_connection_t *
 hostx_get_xcbconn(void)
 {
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index 96d7394..6e0b07b 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -151,6 +151,9 @@ hostx_paint_rect(KdScreenInfo *screen,
 Bool
 hostx_load_keymap(KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr controls);
 
+void
+hostx_size_set_from_configure(Bool);
+
 xcb_connection_t *
 hostx_get_xcbconn(void);
 
commit fb1edccf3c90c626f120b3c399657f24d3f7901e
Author: Keith Packard <keithp at keithp.com>
Date:   Thu May 26 12:11:46 2016 -0700

    dix: Call screen block/wakeup handlers closest to blocking [v3]
    
    The screen block and wakeup handlers are the only ones which provide a
    well known ordering between the wrapping layers; placing these as
    close as possible to the server blocking provides a way for the driver
    to control the flow of execution correctly.
    
    Switch the shadow code to run in the screen block handler so that it
    now occurrs just before the server goes to sleep.
    
    Switch glamor to call down to the driver after it has executed its own
    block handler piece, in case the driver needs to perform additional
    flushing work after glamor has called glFlush.
    
    These changes ensure that the following modules update the screen in
    the correct order:
    
    animated cursors        (uses RegisterBlockAndWakeupHandlers dynamically)
    composite               (dynamic wrapping)
    misprite                (dynamic wrapping)
    shadow                  (static wrapping)
    glamor                  (static wrapping)
    driver                  (static wrapping)
    
    It looks like there's still a bit of confusion between composite and
    misprite; if composite updates after misprite, then it's possible
    you'd exit the block handler chain with the cursor left hidden. To fix
    that, misprite should be wrapping during ScreenInit time and not
    unwrapping. And composite might as well join in that fun, just to make
    things consistent.
    
    [v2] Unwrap BlockHandler in shadowCloseScreen (ajax)
    [v3] ephyr: Use screen block handler for flushing changes
    
    ephyr needs to make sure it calls glXSwapBuffers after glamor finishes
    its rendering. As the screen block handler is now called last, we have
    to use that instead of a registered block/wakeup handler to make sure
    the GL rendering is done before we copy it to the front buffer.
    
    Signed-off-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/dix/dixutils.c b/dix/dixutils.c
index b6b0023..3d2e7a3 100644
--- a/dix/dixutils.c
+++ b/dix/dixutils.c
@@ -383,16 +383,19 @@ BlockHandler(void *pTimeout, void *pReadmask)
     int i, j;
 
     ++inHandler;
-    for (i = 0; i < screenInfo.numScreens; i++)
-        (*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i],
-                                                pTimeout, pReadmask);
-    for (i = 0; i < screenInfo.numGPUScreens; i++)
-        (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i],
-                                                   pTimeout, pReadmask);
     for (i = 0; i < numHandlers; i++)
         if (!handlers[i].deleted)
             (*handlers[i].BlockHandler) (handlers[i].blockData,
                                          pTimeout, pReadmask);
+
+    for (i = 0; i < screenInfo.numGPUScreens; i++)
+        (*screenInfo.gpuscreens[i]->BlockHandler) (screenInfo.gpuscreens[i],
+                                                   pTimeout, pReadmask);
+
+    for (i = 0; i < screenInfo.numScreens; i++)
+        (*screenInfo.screens[i]->BlockHandler) (screenInfo.screens[i],
+                                                pTimeout, pReadmask);
+
     if (handlerDeleted) {
         for (i = 0; i < numHandlers;)
             if (handlers[i].deleted) {
@@ -418,16 +421,16 @@ WakeupHandler(int result, void *pReadmask)
     int i, j;
 
     ++inHandler;
-    for (i = numHandlers - 1; i >= 0; i--)
-        if (!handlers[i].deleted)
-            (*handlers[i].WakeupHandler) (handlers[i].blockData,
-                                          result, pReadmask);
     for (i = 0; i < screenInfo.numScreens; i++)
         (*screenInfo.screens[i]->WakeupHandler) (screenInfo.screens[i],
                                                  result, pReadmask);
     for (i = 0; i < screenInfo.numGPUScreens; i++)
         (*screenInfo.gpuscreens[i]->WakeupHandler) (screenInfo.gpuscreens[i],
                                                     result, pReadmask);
+    for (i = numHandlers - 1; i >= 0; i--)
+        if (!handlers[i].deleted)
+            (*handlers[i].WakeupHandler) (handlers[i].blockData,
+                                          result, pReadmask);
     if (handlerDeleted) {
         for (i = 0; i < numHandlers;)
             if (handlers[i].deleted) {
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 62b5c3a..7d82ce8 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -264,13 +264,13 @@ _glamor_block_handler(ScreenPtr screen, void *timeout, void *readmask)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
+    glamor_make_current(glamor_priv);
+    glFlush();
+
     screen->BlockHandler = glamor_priv->saved_procs.block_handler;
     screen->BlockHandler(screen, timeout, readmask);
     glamor_priv->saved_procs.block_handler = screen->BlockHandler;
     screen->BlockHandler = _glamor_block_handler;
-
-    glamor_make_current(glamor_priv);
-    glFlush();
 }
 
 static void
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 2e7c86c..2114c1c 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -337,17 +337,29 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
 }
 
 static void
-ephyrInternalDamageBlockHandler(void *data, OSTimePtr pTimeout, void *pRead)
+ephyrScreenBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead)
 {
-    ScreenPtr pScreen = (ScreenPtr) data;
+    KdScreenPriv(pScreen);
+    KdScreenInfo *screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = screen->driver;
 
-    ephyrInternalDamageRedisplay(pScreen);
-}
+    pScreen->BlockHandler = scrpriv->BlockHandler;
+    (*pScreen->BlockHandler)(pScreen, timeout, pRead);
 
-static void
-ephyrInternalDamageWakeupHandler(void *data, int i, void *LastSelectMask)
-{
-    /* FIXME: Not needed ? */
+    if (scrpriv->pDamage) {
+
+        /* Re-wrap if we're still tracking damage
+         */
+        scrpriv->BlockHandler = pScreen->BlockHandler;
+        pScreen->BlockHandler = ephyrScreenBlockHandler;
+        ephyrInternalDamageRedisplay(pScreen);
+    } else {
+
+        /* Done tracking damage, note that we've left
+         * the block handler unwrapped
+         */
+        scrpriv->BlockHandler = NULL;
+    }
 }
 
 Bool
@@ -362,10 +374,11 @@ ephyrSetInternalDamage(ScreenPtr pScreen)
                                     (DamageDestroyFunc) 0,
                                     DamageReportNone, TRUE, pScreen, pScreen);
 
-    if (!RegisterBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler,
-                                        ephyrInternalDamageWakeupHandler,
-                                        (void *) pScreen))
-        return FALSE;
+    /* Wrap only once */
+    if (scrpriv->BlockHandler == NULL) {
+        scrpriv->BlockHandler = pScreen->BlockHandler;
+        pScreen->BlockHandler = ephyrScreenBlockHandler;
+    }
 
     pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
 
@@ -382,10 +395,7 @@ ephyrUnsetInternalDamage(ScreenPtr pScreen)
     EphyrScrPriv *scrpriv = screen->driver;
 
     DamageDestroy(scrpriv->pDamage);
-
-    RemoveBlockAndWakeupHandlers(ephyrInternalDamageBlockHandler,
-                                 ephyrInternalDamageWakeupHandler,
-                                 (void *) pScreen);
+    scrpriv->pDamage = NULL;
 }
 
 #ifdef RANDR
@@ -736,6 +746,7 @@ ephyrScreenFini(KdScreenInfo * screen)
     if (scrpriv->shadow) {
         KdShadowFbFree(screen);
     }
+    scrpriv->BlockHandler = NULL;
 }
 
 void
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 7723bf1..b48a21c 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -84,6 +84,8 @@ typedef struct _ephyrScrPriv {
     int mynum;                  /* Screen number */
     unsigned long cmap[256];
 
+    ScreenBlockHandlerProcPtr   BlockHandler;
+
     /**
      * Per-screen Xlib-using state for glamor (private to
      * ephyr_glamor_glx.c)
diff --git a/miext/shadow/shadow.c b/miext/shadow/shadow.c
index 0dd3604a..405c4dd 100644
--- a/miext/shadow/shadow.c
+++ b/miext/shadow/shadow.c
@@ -65,16 +65,15 @@ shadowRedisplay(ScreenPtr pScreen)
 }
 
 static void
-shadowBlockHandler(void *data, OSTimePtr pTimeout, void *pRead)
+shadowBlockHandler(ScreenPtr pScreen, void *timeout, void *pRead)
 {
-    ScreenPtr pScreen = (ScreenPtr) data;
+    shadowBuf(pScreen);
 
     shadowRedisplay(pScreen);
-}
 
-static void
-shadowWakeupHandler(void *data, int i, void *LastSelectMask)
-{
+    unwrap(pBuf, pScreen, BlockHandler);
+    pScreen->BlockHandler(pScreen, timeout, pRead);
+    wrap(pBuf, pScreen, BlockHandler);
 }
 
 static void
@@ -100,6 +99,7 @@ shadowCloseScreen(ScreenPtr pScreen)
 
     unwrap(pBuf, pScreen, GetImage);
     unwrap(pBuf, pScreen, CloseScreen);
+    unwrap(pBuf, pScreen, BlockHandler);
     shadowRemove(pScreen, pBuf->pPixmap);
     DamageDestroy(pBuf->pDamage);
     if (pBuf->pPixmap)
@@ -132,6 +132,7 @@ shadowSetup(ScreenPtr pScreen)
 
     wrap(pBuf, pScreen, CloseScreen);
     wrap(pBuf, pScreen, GetImage);
+    wrap(pBuf, pScreen, BlockHandler);
     pBuf->update = 0;
     pBuf->window = 0;
     pBuf->pPixmap = 0;
@@ -148,10 +149,6 @@ shadowAdd(ScreenPtr pScreen, PixmapPtr pPixmap, ShadowUpdateProc update,
 {
     shadowBuf(pScreen);
 
-    if (!RegisterBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
-                                        (void *) pScreen))
-        return FALSE;
-
     /*
      * Map simple rotation values to bitmasks; fortunately,
      * these are all unique
@@ -192,7 +189,4 @@ shadowRemove(ScreenPtr pScreen, PixmapPtr pPixmap)
         pBuf->closure = 0;
         pBuf->pPixmap = 0;
     }
-
-    RemoveBlockAndWakeupHandlers(shadowBlockHandler, shadowWakeupHandler,
-                                 (void *) pScreen);
 }
diff --git a/miext/shadow/shadow.h b/miext/shadow/shadow.h
index 86fa944..7f22169 100644
--- a/miext/shadow/shadow.h
+++ b/miext/shadow/shadow.h
@@ -54,6 +54,7 @@ typedef struct _shadowBuf {
     /* screen wrappers */
     GetImageProcPtr GetImage;
     CloseScreenProcPtr CloseScreen;
+    ScreenBlockHandlerProcPtr BlockHandler;
 } shadowBufRec;
 
 /* Match defines from randr extension */


More information about the xorg-commit mailing list