summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-06-12 22:38:01 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-06-12 22:30:31 +0100
commit86888723901030c5cb9da16cbb03508d4b13332f (patch)
treed7916dbf5a6275a68ecd4c25d012a7641641e24f
parentb881d1b16a8beec024ac18eca8308418e34cb05d (diff)
sna: Just do a pointer exchange when flipping with no scanout
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/sna.h2
-rw-r--r--src/sna/sna_display.c14
-rw-r--r--src/sna/sna_dri.c47
3 files changed, 50 insertions, 13 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 7456f05a..ae8e5548 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -274,6 +274,8 @@ extern int sna_do_pageflip(struct sna *sna,
PixmapPtr *old_front,
uint32_t *old_fb);
+extern PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap);
+
void sna_mode_delete_fb(struct sna *sna, PixmapPtr pixmap, uint32_t fb);
static inline struct sna *
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index e893a370..c2347ef3 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -1523,6 +1523,20 @@ static int do_page_flip(struct sna *sna, void *data, int ref_crtc_hw_id)
return count;
}
+PixmapPtr sna_set_screen_pixmap(struct sna *sna, PixmapPtr pixmap)
+{
+ PixmapPtr old = sna->front;
+ ScrnInfoPtr scrn = sna->scrn;
+
+ sna->front = pixmap;
+ pixmap->refcnt++;
+
+ sna_redirect_screen_pixmap(scrn, old, sna->front);
+ scrn->displayWidth = sna_pixmap_get_bo(pixmap)->pitch / sna->mode.cpp;
+
+ return old;
+}
+
int
sna_do_pageflip(struct sna *sna,
PixmapPtr pixmap,
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 14a2f3d1..75e2c444 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -670,7 +670,8 @@ can_flip(struct sna * sna,
ScreenPtr screen = draw->pScreen;
- assert(draw->type == DRAWABLE_WINDOW);
+ if (draw->type == DRAWABLE_PIXMAP)
+ return FALSE;
if (front->format != back->format) {
DBG(("%s: no, format mismatch, front = %d, back = %d\n",
@@ -969,10 +970,30 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
(long long)divisor,
(long long)remainder));
+ flip = 0;
+ if (can_flip(sna, draw, front, back)) {
+ DBG(("%s: can flip\n", __FUNCTION__));
+ swap_type = DRI2_FLIP;
+ flip = 1;
+ }
+
/* Drawable not displayed... just complete the swap */
pipe = sna_dri_get_pipe(draw);
- if (pipe == -1)
- goto blit_fallback;
+ if (pipe == -1) {
+ struct sna_dri_private *back_priv = back->driverPrivate;
+ PixmapPtr pixmap;
+
+ if (!flip)
+ goto blit_fallback;
+
+ pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
+ pixmap->refcnt--;
+ assert(pixmap->refcnt > 0);
+ sna_dri_exchange_buffers(draw, front, back);
+ DRI2SwapComplete(client, draw, 0, 0, 0,
+ DRI2_EXCHANGE_COMPLETE, func, data);
+ return TRUE;
+ }
/* Truncate to match kernel interfaces; means occasional overflow
* misses, but that's generally not a big deal */
@@ -1002,13 +1023,6 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
sna_dri_reference_buffer(front);
sna_dri_reference_buffer(back);
- flip = 0;
- if (can_flip(sna, draw, front, back)) {
- DBG(("%s: can flip\n", __FUNCTION__));
- swap_type = DRI2_FLIP;
- flip = 1;
- }
-
info->type = swap_type;
if (divisor == 0)
goto immediate;
@@ -1155,9 +1169,7 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
DBG(("%s()\n", __FUNCTION__));
- /* Drawable not displayed... just complete the swap */
- pipe = sna_dri_get_pipe(draw);
- if (pipe == -1 || !can_flip(sna, draw, front, back)) {
+ if (!can_flip(sna, draw, front, back)) {
BoxRec box, *boxes;
int n;
@@ -1194,6 +1206,15 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
return;
}
+ pipe = sna_dri_get_pipe(draw);
+ if (pipe == -1) {
+ /* Drawable not displayed... just complete the swap */
+ pixmap = sna_set_screen_pixmap(sna, back_priv->pixmap);
+ pixmap->refcnt--;
+ assert(pixmap->refcnt > 0);
+ goto exchange;
+ }
+
if (!sna->dri.flip_pending[pipe]) {
struct sna_dri_frame_event *info;
DRI2BufferPtr t;