From: Egbert Eich <[email protected]>

copy_front() calls sna_pixmap_force_to_gpu() which may fail. If we pretend
to have been successful and continue the caller sna_mode_resize() may finish
successfully pretending a mode change has succeeded which might leave a mode
behind which is unusable.
This patch makes copy_front() fail if sna_pixmap_force_to_gpu() fails which
allows sna_mode_resize() to detect this situation, clean up gracefully,
ie. destroy the newly created front pixmap and fail itself. This way an
application requesting such a mode will receive a proper XError while the
previous mode will be restored leaving the user with a usable mode.

Signed-off-by: Egbert Eich <[email protected]>
---
 src/sna/sna_display.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 2a98fb9..25873c4 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4044,22 +4044,22 @@ void sna_mode_discover(struct sna *sna)
        }
 }
 
-static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
+static Bool copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
 {
        struct sna_pixmap *old_priv, *new_priv;
 
        DBG(("%s\n", __FUNCTION__));
 
        if (wedged(sna))
-               return;
+               return FALSE;
 
        old_priv = sna_pixmap_force_to_gpu(old, MOVE_READ);
        if (!old_priv)
-               return;
+               return FALSE;
 
        new_priv = sna_pixmap_force_to_gpu(new, MOVE_WRITE);
        if (!new_priv)
-               return;
+               return FALSE;
 
        if (old_priv->clear) {
                (void)sna->render.fill_one(sna, new, new_priv->gpu_bo,
@@ -4137,6 +4137,8 @@ static void copy_front(struct sna *sna, PixmapPtr old, 
PixmapPtr new)
        }
 
        sna_damage_all(&new_priv->gpu_damage, new);
+
+       return TRUE;
 }
 
 static Bool
@@ -4182,7 +4184,10 @@ sna_mode_resize(ScrnInfoPtr scrn, int width, int height)
        assert(sna->mode.shadow_damage == NULL);
        assert(sna->mode.shadow == NULL);
 
-       copy_front(sna, sna->front, new_front);
+       if (!copy_front(sna, sna->front, new_front)) {
+               screen->DestroyPixmap(new_front);
+               return FALSE;
+       }
 
        screen->SetScreenPixmap(new_front);
        assert(screen->GetScreenPixmap(screen) == new_front);
-- 
1.8.4.5

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to