summaryrefslogtreecommitdiff
path: root/src/sna/sna_dri2.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-06-04 08:29:51 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-06-05 12:28:22 +0100
commit8369166349c92a20d9a2e7d0256e63f66fe2682b (patch)
treed8474a46e9b4fad974f36b1ddb0826d26555734b /src/sna/sna_dri2.c
parent08148896196443a8582c30b47ff546acca78d69c (diff)
sna/dri2: Enable immediate buffer exchanges
The primary benefit of this is avoid the extra blit when using a compositor and instead propagate the compositor flip on the frontbuffer to the scanout, or equivalently allows a fullscreen game to flip onto the scanout without intervention by TearFree. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna/sna_dri2.c')
-rw-r--r--src/sna/sna_dri2.c648
1 files changed, 339 insertions, 309 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 317f5985..9e591be1 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -72,6 +72,7 @@ struct sna_dri2_private {
PixmapPtr pixmap;
struct kgem_bo *bo;
bool scanout;
+ bool stale;
uint32_t size;
int refcnt;
};
@@ -83,7 +84,7 @@ get_private(void *buffer)
}
#if DRI2INFOREC_VERSION >= 4
-enum frame_event_type {
+enum event_type {
WAITMSC = 0,
SWAP,
SWAP_WAIT,
@@ -100,13 +101,12 @@ struct dri_bo {
uint32_t name;
};
-struct sna_dri2_frame_event {
+struct sna_dri2_event {
DrawablePtr draw;
ClientPtr client;
- enum frame_event_type type;
+ enum event_type type;
xf86CrtcPtr crtc;
int pipe;
- int count;
bool queued;
/* for swaps & flips only */
@@ -116,53 +116,54 @@ struct sna_dri2_frame_event {
DRI2BufferPtr back;
struct kgem_bo *bo;
- struct sna_dri2_frame_event *chain;
+ struct sna_dri2_event *chain;
struct list cache;
int mode;
};
+static void sna_dri2_flip_event(struct sna *sna,
+ struct sna_dri2_event *flip);
+
static void
-sna_dri2_get_back(struct sna *sna, struct sna_dri2_frame_event *info)
+sna_dri2_get_back(struct sna *sna,
+ DRI2BufferPtr back,
+ struct sna_dri2_event *info)
{
struct kgem_bo *bo;
uint32_t name;
- DBG(("%s: scanout=(%d, %d), back=%d, cache?=%d\n",
- __FUNCTION__,
- sna->dri2.scanout[0].bo ? sna->dri2.scanout[0].bo->handle : 0,
- sna->dri2.scanout[1].bo ? sna->dri2.scanout[1].bo->handle : 0,
- get_private(info->back)->bo->handle,
- !list_is_empty(&info->cache)));
+ get_private(back)->stale = false;
- bo = get_private(info->back)->bo;
+ bo = get_private(back)->bo;
assert(bo->refcnt);
- assert(bo->flush);
- if (!(bo == sna->dri2.scanout[0].bo || bo == sna->dri2.scanout[1].bo)) {
+ DBG(("%s: back buffer handle=%d, scanout?=%d\n",
+ __FUNCTION__, bo->handle, bo->active_scanout));
+ if (bo->active_scanout == 0) {
DBG(("%s: reuse unattached back\n", __FUNCTION__));
return;
}
bo = NULL;
- if (!list_is_empty(&info->cache)) {
- struct dri_bo *c = list_first_entry(&info->cache, struct dri_bo, link);
- if (c->bo) {
- bo = c->bo;
- name = c->name;
- DBG(("%s: reuse cache handle=%d,name=%d\n", __FUNCTION__,
- bo->handle, name));
- list_move_tail(&c->link, &info->cache);
- c->bo = NULL;
+ if (info) {
+ struct dri_bo *c;
+ list_for_each_entry(c, &info->cache, link) {
+ if (c->bo && c->bo->scanout == 0) {
+ bo = c->bo;
+ name = c->name;
+ DBG(("%s: reuse cache handle=%d\n", __FUNCTION__, bo->handle));
+ list_move_tail(&c->link, &info->cache);
+ c->bo = NULL;
+ }
}
}
if (bo == NULL) {
+ DrawablePtr draw = &sna->front->drawable;
DBG(("%s: allocating new backbuffer\n", __FUNCTION__));
bo = kgem_create_2d(&sna->kgem,
- info->draw->width,
- info->draw->height,
- info->draw->bitsPerPixel,
- get_private(info->front)->bo->tiling,
+ draw->width, draw->height, draw->bitsPerPixel,
+ get_private(back)->bo->tiling,
CREATE_SCANOUT);
if (bo == NULL)
return;
@@ -173,29 +174,35 @@ sna_dri2_get_back(struct sna *sna, struct sna_dri2_frame_event *info)
return;
}
}
+ assert(bo->active_scanout == 0);
- assert(!(bo == sna->dri2.scanout[0].bo || bo == sna->dri2.scanout[1].bo));
- assert(name);
-
- unref(get_private(info->back)->bo);
- get_private(info->back)->bo = bo;
- info->back->name = name;
-
- assert(get_private(info->back)->bo != sna->dri2.scanout[0].bo);
- assert(get_private(info->back)->bo != sna->dri2.scanout[1].bo);
+ if (info) {
+ bool found = false;
+ struct dri_bo *c;
- assert(bo->refcnt == 1);
- assert(bo->flush);
-}
+ list_for_each_entry_reverse(c, &info->cache, link) {
+ if (c->bo == NULL) {
+ found = true;
+ _list_del(&c->link);
+ break;
+ }
+ }
+ if (!found)
+ c = malloc(sizeof(*c));
+ if (c != NULL) {
+ c->bo = kgem_bo_reference(get_private(back)->bo);
+ c->name = back->name;
+ list_add(&c->link, &info->cache);
+ }
+ }
-static inline struct sna_dri2_frame_event *
-to_frame_event(uintptr_t data)
-{
- return (struct sna_dri2_frame_event *)(data & ~3);
+ kgem_bo_destroy(&sna->kgem, get_private(back)->bo);
+ get_private(back)->bo = bo;
+ back->name = name;
}
struct dri2_window {
- struct sna_dri2_frame_event *chain;
+ struct sna_dri2_event *chain;
xf86CrtcPtr crtc;
int64_t msc_delta;
};
@@ -205,7 +212,7 @@ static struct dri2_window *dri2_window(WindowPtr win)
return ((void **)__get_private(win, sna_window_key))[1];
}
-static struct sna_dri2_frame_event *
+static struct sna_dri2_event *
sna_dri2_window_get_chain(WindowPtr win)
{
struct dri2_window *priv = dri2_window(win);
@@ -238,19 +245,12 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer)
if (buffer->attachment == DRI2BufferBackLeft &&
draw->type != DRAWABLE_PIXMAP) {
- struct sna_dri2_frame_event *info;
-
- info = sna_dri2_window_get_chain((WindowPtr)draw);
- DBG(("%s: draw->id=%lu, active? %d, current back? %d\n",
- __FUNCTION__, (long)draw->id, info!=NULL, info && info->back == buffer));
- if (info && info->back == buffer) {
- DBG(("%s: replacing back buffer\n", __FUNCTION__));
- sna_dri2_get_back(to_sna_from_drawable(draw), info);
- }
+ DBG(("%s: replacing back buffer\n", __FUNCTION__));
+ sna_dri2_get_back(to_sna_from_drawable(draw), buffer,
+ sna_dri2_window_get_chain((WindowPtr)draw));
assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name);
- assert(get_private(buffer)->bo != to_sna_from_drawable(draw)->dri2.scanout[0].bo);
- assert(get_private(buffer)->bo != to_sna_from_drawable(draw)->dri2.scanout[1].bo);
+ assert(get_private(buffer)->bo->active_scanout == 0);
}
}
@@ -315,19 +315,25 @@ static struct kgem_bo *sna_pixmap_set_dri(struct sna *sna,
}
priv = sna_pixmap_move_to_gpu(pixmap,
- MOVE_READ | MOVE_WRITE | __MOVE_FORCE | __MOVE_DRI);
+ MOVE_READ | __MOVE_FORCE | __MOVE_DRI);
if (priv == NULL) {
DBG(("%s: failed to move to GPU, BadAlloc\n", __FUNCTION__));
return NULL;
}
assert(priv->flush == false);
- assert(priv->cow == NULL);
assert(priv->cpu_damage == NULL);
assert(priv->gpu_bo);
assert(priv->gpu_bo->proxy == NULL);
assert(priv->gpu_bo->flush == false);
+ /* Henceforth, we need to broadcast all updates to clients and
+ * flush our rendering before doing so.
+ */
+ priv->gpu_bo->flush = true;
+ if (priv->gpu_bo->exec)
+ sna->kgem.flush = 1;
+
tiling = color_tiling(sna, &pixmap->drawable);
if (tiling < 0)
tiling = -tiling;
@@ -350,11 +356,10 @@ static inline void sna_pixmap_set_buffer(PixmapPtr pixmap, void *ptr)
}
void
-sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap)
+sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap, struct kgem_bo *bo)
{
DRI2BufferPtr buffer;
struct sna_dri2_private *private;
- struct kgem_bo *bo;
buffer = sna_pixmap_get_buffer(pixmap);
if (buffer == NULL)
@@ -368,7 +373,7 @@ sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap)
private = get_private(buffer);
assert(private->pixmap == pixmap);
- bo = sna_pixmap(pixmap)->gpu_bo;
+ assert(bo != private->bo);
if (private->bo == bo)
return;
@@ -378,7 +383,8 @@ sna_dri2_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap)
buffer->name = kgem_bo_flink(&sna->kgem, bo);
private->bo = ref(bo);
- assert(bo->flush);
+ bo->flush = true;
+ assert(sna_pixmap(pixmap)->flush);
/* XXX DRI2InvalidateDrawable(&pixmap->drawable); */
}
@@ -562,8 +568,6 @@ sna_dri2_create_buffer(DrawablePtr draw,
sna_accel_watch_flush(sna, 1);
}
- assert(bo->flush == true);
-
return buffer;
err:
@@ -667,14 +671,10 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
assert(pixmap->drawable.width * pixmap->drawable.bitsPerPixel <= 8*bo->pitch);
assert(pixmap->drawable.height * bo->pitch <= kgem_bo_size(bo));
assert(bo->proxy == NULL);
- assert(bo->flush);
assert(priv->pinned & PIN_DRI2);
assert((priv->pinned & (PIN_PRIME | PIN_DRI3)) == 0);
assert(priv->flush);
- if (priv->cow && priv->gpu_bo != bo)
- sna_pixmap_undo_cow(sna, priv, 0);
-
/* Post damage on the new front buffer so that listeners, such
* as DisplayLink know take a copy and shove it over the USB,
* also for software cursors and the like.
@@ -688,11 +688,19 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
damage(pixmap, priv, NULL);
assert(bo->refcnt);
+ if (priv->move_to_gpu)
+ priv->move_to_gpu(sna, priv, 0);
if (priv->gpu_bo != bo) {
+ priv->gpu_bo->flush = false;
+ if (priv->cow)
+ sna_pixmap_undo_cow(sna, priv, 0);
if (priv->gpu_bo) {
sna_pixmap_unmap(pixmap, priv);
kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
}
+ bo->flush = true;
+ if (bo->exec)
+ sna->kgem.flush = 1;
priv->gpu_bo = ref(bo);
}
if (bo->domain != DOMAIN_GPU)
@@ -1005,10 +1013,7 @@ sna_dri2_copy_region(DrawablePtr draw,
assert(get_private(dst)->refcnt);
assert(get_private(src)->bo->refcnt);
- assert(get_private(src)->bo->flush);
-
assert(get_private(dst)->bo->refcnt);
- assert(get_private(dst)->bo->flush);
DBG(("%s: region (%d, %d), (%d, %d) x %ld\n",
__FUNCTION__,
@@ -1119,11 +1124,10 @@ sna_dri2_get_crtc(DrawablePtr draw)
}
static void
-sna_dri2_remove_frame_event(WindowPtr win,
- struct sna_dri2_frame_event *info)
+sna_dri2_remove_event(WindowPtr win, struct sna_dri2_event *info)
{
struct dri2_window *priv;
- struct sna_dri2_frame_event *chain;
+ struct sna_dri2_event *chain;
assert(win->drawable.type == DRAWABLE_WINDOW);
DBG(("%s: remove[%p] from window %ld)\n",
@@ -1146,11 +1150,11 @@ sna_dri2_remove_frame_event(WindowPtr win,
chain->chain = info->chain;
}
-static struct sna_dri2_frame_event *
-sna_dri2_add_frame_event(DrawablePtr draw, ClientPtr client)
+static struct sna_dri2_event *
+sna_dri2_add_event(DrawablePtr draw, ClientPtr client)
{
struct dri2_window *priv;
- struct sna_dri2_frame_event *info, *chain;
+ struct sna_dri2_event *info, *chain;
assert(draw->type == DRAWABLE_WINDOW);
DBG(("%s: adding event to window %ld)\n",
@@ -1160,7 +1164,7 @@ sna_dri2_add_frame_event(DrawablePtr draw, ClientPtr client)
if (priv == NULL)
return NULL;
- info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ info = calloc(1, sizeof(struct sna_dri2_event));
if (info == NULL)
return NULL;
@@ -1187,12 +1191,12 @@ sna_dri2_add_frame_event(DrawablePtr draw, ClientPtr client)
}
static void
-sna_dri2_frame_event_info_free(struct sna *sna,
- DrawablePtr draw,
- struct sna_dri2_frame_event *info)
+sna_dri2_event_free(struct sna *sna,
+ DrawablePtr draw,
+ struct sna_dri2_event *info)
{
if (draw && draw->type == DRAWABLE_WINDOW)
- sna_dri2_remove_frame_event((WindowPtr)draw, info);
+ sna_dri2_remove_event((WindowPtr)draw, info);
_sna_dri2_destroy_buffer(sna, info->front);
_sna_dri2_destroy_buffer(sna, info->back);
@@ -1202,10 +1206,8 @@ sna_dri2_frame_event_info_free(struct sna *sna,
c = list_first_entry(&info->cache, struct dri_bo, link);
list_del(&c->link);
- if (c->bo) {
- assert(c->bo->refcnt == 1);
+ if (c->bo)
kgem_bo_destroy(&sna->kgem, c->bo);
- }
free(c);
}
@@ -1228,7 +1230,7 @@ void sna_dri2_destroy_window(WindowPtr win)
if (priv->chain) {
struct sna *sna = to_sna_from_drawable(&win->drawable);
- struct sna_dri2_frame_event *info, *chain;
+ struct sna_dri2_event *info, *chain;
DBG(("%s: freeing chain\n", __FUNCTION__));
@@ -1238,13 +1240,13 @@ void sna_dri2_destroy_window(WindowPtr win)
chain = info->chain;
info->chain = NULL;
+ assert(info->queued);
while ((info = chain)) {
chain = info->chain;
- if (info->queued) {
- info->draw = NULL;
- info->chain = NULL;
- } else
- sna_dri2_frame_event_info_free(sna, NULL, info);
+ info->chain = NULL;
+ info->draw = NULL;
+ if (!info->queued)
+ sna_dri2_event_free(sna, NULL, info);
}
}
@@ -1252,95 +1254,33 @@ void sna_dri2_destroy_window(WindowPtr win)
}
static void
-update_scanout(struct sna *sna, struct kgem_bo *bo, int name)
-{
- assert(sna->dri2.scanout[1].bo == NULL);
- assert(sna->dri2.scanout[0].bo->scanout);
- assert(sna->dri2.scanout[0].bo->refcnt);
- sna->dri2.scanout[1] = sna->dri2.scanout[0];
- sna->dri2.scanout[0].bo = ref(bo);
- sna->dri2.scanout[0].name = name;
- assert(sna->dri2.scanout[0].bo->scanout);
-
- DBG(("%s: pending scanout handle=%d, active scanout handle=%d\n",
- __FUNCTION__, sna->dri2.scanout[0].bo->handle, sna->dri2.scanout[1].bo->handle));
- assert(sna->dri2.scanout[0].bo->handle != sna->dri2.scanout[1].bo->handle);
-}
-
-static void
-retire_scanout(struct sna *sna,
- struct sna_dri2_frame_event *flip)
+sna_dri2_flip_handler(struct sna *sna,
+ struct drm_event_vblank *event,
+ void *data)
{
- struct dri_bo *c = NULL;
-
- if (sna->dri2.scanout[1].bo == NULL)
- return;
-
- DBG(("%s: retiring previous scanout handle=%d, name=%d, refcnt=%d (current scanout handle=%d)\n",
- __FUNCTION__,
- sna->dri2.scanout[1].bo->handle,
- sna->dri2.scanout[1].name,
- sna->dri2.scanout[1].bo->refcnt,
- sna->dri2.scanout[0].bo->handle));
-
- if (flip &&
- sna->dri2.scanout[1].bo != sna->dri2.scanout[0].bo &&
- sna->dri2.scanout[1].bo->refcnt == 1) {
- DBG(("%s: adding old scanout to flip cache\n", __FUNCTION__));
- if (!list_is_empty(&flip->cache))
- c = list_last_entry(&flip->cache, struct dri_bo, link);
- if (c) {
- if (c->bo == NULL)
- _list_del(&c->link);
- else
- c = NULL;
- }
- if (c == NULL)
- c = malloc(sizeof(*c));
- if (c != NULL) {
- c->bo = sna->dri2.scanout[1].bo;
- c->name = sna->dri2.scanout[1].name;
- list_add(&c->link, &flip->cache);
- }
- }
-
- if (c == NULL) {
- DBG(("%s: not caching old scanout handle=%d, still busy\n",
- __FUNCTION__, sna->dri2.scanout[1].bo->handle));
- kgem_bo_destroy(&sna->kgem, sna->dri2.scanout[1].bo);
- }
-
- sna->dri2.scanout[1].bo = NULL;
+ DBG(("%s: sequence=%d\n", __FUNCTION__, event->sequence));
+ sna_dri2_flip_event(sna, data);
}
static bool
-sna_dri2_page_flip(struct sna *sna, struct sna_dri2_frame_event *info)
+sna_dri2_flip(struct sna *sna, struct sna_dri2_event *info)
{
struct kgem_bo *bo = get_private(info->back)->bo;
- struct dri_bo tmp;
+ struct kgem_bo *tmp_bo;
+ uint32_t tmp_name;
DBG(("%s(type=%d)\n", __FUNCTION__, info->type));
assert(sna_pixmap_get_buffer(sna->front) == info->front);
assert(get_drawable_pixmap(info->draw)->drawable.height * bo->pitch <= kgem_bo_size(bo));
- assert(sna->dri2.scanout[0].bo);
- assert(sna->dri2.scanout[0].bo->scanout);
- assert(sna->dri2.scanout[1].bo == NULL);
assert(bo->refcnt);
- if (info->type == FLIP_ASYNC)
- info->count = sna_page_flip(sna, bo, NULL, -1);
- else
- info->count = sna_page_flip(sna, bo, info, info->pipe);
- if (!info->count)
+ if (!sna_page_flip(sna, bo, sna_dri2_flip_handler,
+ info->type == FLIP_ASYNC ? NULL : info))
return false;
- update_scanout(sna, bo, info->back->name);
-
assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
- if (info->type == FLIP_ASYNC)
- retire_scanout(sna, NULL);
- else
+ if (info->type != FLIP_ASYNC)
sna->dri2.flip_pending = info;
DBG(("%s: marked handle=%d as scanout, swap front (handle=%d, name=%d) and back (handle=%d, name=%d)\n",
@@ -1348,16 +1288,17 @@ sna_dri2_page_flip(struct sna *sna, struct sna_dri2_frame_event *info)
get_private(info->front)->bo->handle, info->front->name,
get_private(info->back)->bo->handle, info->back->name));
- tmp.bo = get_private(info->front)->bo;
- tmp.name = info->front->name;
+ tmp_bo = get_private(info->front)->bo;
+ tmp_name = info->front->name;
set_bo(sna->front, bo);
info->front->name = info->back->name;
get_private(info->front)->bo = bo;
- info->back->name = tmp.name;
- get_private(info->back)->bo = tmp.bo;
+ info->back->name = tmp_name;
+ get_private(info->back)->bo = tmp_bo;
+ get_private(info->back)->stale = true;
info->queued = true;
return true;
@@ -1495,6 +1436,74 @@ can_flip(struct sna * sna,
return true;
}
+static bool
+can_xchg(struct sna * sna,
+ DrawablePtr draw,
+ DRI2BufferPtr front,
+ DRI2BufferPtr back)
+{
+ WindowPtr win = (WindowPtr)draw;
+ PixmapPtr pixmap;
+
+ if (draw->type == DRAWABLE_PIXMAP)
+ return false;
+
+ if (front->format != back->format) {
+ DBG(("%s: no, format mismatch, front = %d, back = %d\n",
+ __FUNCTION__, front->format, back->format));
+ return false;
+ }
+
+ if (front->attachment != DRI2BufferFrontLeft) {
+ DBG(("%s: no, front attachment [%d] is not FrontLeft [%d]\n",
+ __FUNCTION__,
+ front->attachment,
+ DRI2BufferFrontLeft));
+ return false;
+ }
+
+ DBG(("%s: window size: %dx%d, clip=(%d, %d), (%d, %d) x %d\n",
+ __FUNCTION__,
+ win->drawable.width, win->drawable.height,
+ win->clipList.extents.x1, win->clipList.extents.y1,
+ win->clipList.extents.x2, win->clipList.extents.y2,
+ RegionNumRects(&win->clipList)));
+ if (is_clipped(&win->clipList, draw)) {
+ DBG(("%s: no, %dx%d window is clipped: clip region=(%d, %d), (%d, %d)\n",
+ __FUNCTION__,
+ draw->width, draw->height,
+ win->clipList.extents.x1,
+ win->clipList.extents.y1,
+ win->clipList.extents.x2,
+ win->clipList.extents.y2));
+ return false;
+ }
+
+ if (get_private(back)->size != get_private(front)->size) {
+ DBG(("%s: no, back buffer %dx%d does not match front buffer %dx%d\n",
+ __FUNCTION__,
+ get_private(back)->size & 0x7fff, (get_private(back)->size >> 16) & 0x7fff,
+ get_private(front)->size & 0x7fff, (get_private(front)->size >> 16) & 0x7fff));
+ return false;
+ }
+
+ pixmap = get_window_pixmap(win);
+ if (pixmap == sna->front && !(sna->flags & SNA_TEAR_FREE)) {
+ DBG(("%s: no, front buffer, requires flipping\n",
+ __FUNCTION__));
+ return false;
+ }
+
+ if (sna_pixmap(pixmap)->pinned & ~(PIN_DRI2 | PIN_SCANOUT)) {
+ DBG(("%s: no, pinned: %x\n",
+ __FUNCTION__, sna_pixmap(pixmap)->pinned));
+ return false;
+ }
+
+ DBG(("%s: yes\n", __FUNCTION__));
+ return true;
+}
+
static void
sna_dri2_exchange_buffers(DrawablePtr draw,
DRI2BufferPtr front,
@@ -1517,14 +1526,15 @@ sna_dri2_exchange_buffers(DrawablePtr draw,
pixmap->drawable.width,
pixmap->drawable.height));
- DBG(("%s: back_bo pitch=%d, size=%d, ref=%d\n",
- __FUNCTION__, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt));
- DBG(("%s: front_bo pitch=%d, size=%d, ref=%d\n",
- __FUNCTION__, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt));
+ DBG(("%s: back_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
+ __FUNCTION__, back_bo->pitch, kgem_bo_size(back_bo), back_bo->refcnt, back_bo->active_scanout));
+ DBG(("%s: front_bo pitch=%d, size=%d, ref=%d, active_scanout?=%d\n",
+ __FUNCTION__, front_bo->pitch, kgem_bo_size(front_bo), front_bo->refcnt, front_bo->active_scanout));
assert(front_bo->refcnt);
assert(back_bo->refcnt);
assert(sna_pixmap_get_buffer(pixmap) == front);
+
assert(pixmap->drawable.height * back_bo->pitch <= kgem_bo_size(back_bo));
assert(pixmap->drawable.height * front_bo->pitch <= kgem_bo_size(front_bo));
@@ -1532,14 +1542,20 @@ sna_dri2_exchange_buffers(DrawablePtr draw,
get_private(front)->bo = back_bo;
get_private(back)->bo = front_bo;
+ get_private(back)->stale = true;
tmp = front->name;
front->name = back->name;
back->name = tmp;
+
+ assert(front_bo->refcnt);
+ assert(back_bo->refcnt);
+
+ assert(get_private(front)->bo == sna_pixmap(pixmap)->gpu_bo);
}
static void frame_swap_complete(struct sna *sna,
- struct sna_dri2_frame_event *frame,
+ struct sna_dri2_event *frame,
int type)
{
const struct ust_msc *swap;
@@ -1579,17 +1595,22 @@ static void fake_swap_complete(struct sna *sna, ClientPtr client,
type, func, data);
}
-static void chain_swap(struct sna *sna, DrawablePtr draw, struct sna_dri2_frame_event *chain)
+static void chain_swap(struct sna *sna, struct sna_dri2_event *chain)
{
union drm_wait_vblank vbl;
- assert(chain == sna_dri2_window_get_chain((WindowPtr)draw));
+ if (chain->draw == NULL) {
+ sna_dri2_event_free(sna, NULL, chain);
+ return;
+ }
+
+ assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
DBG(("%s: chaining draw=%ld, type=%d\n",
- __FUNCTION__, (long)draw->id, chain->type));
+ __FUNCTION__, (long)chain->draw->id, chain->type));
switch (chain->type) {
case SWAP_THROTTLE:
DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
- if (sna->mode.shadow_flip && !sna->mode.shadow_damage) {
+ if (sna->mode.shadow && !sna->mode.shadow_damage) {
/* recursed from wait_for_shadow(), simply requeue */
DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
VG_CLEAR(vbl);
@@ -1597,7 +1618,7 @@ static void chain_swap(struct sna *sna, DrawablePtr draw, struct sna_dri2_frame_
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)chain;
+ vbl.request.signal = (uintptr_t)chain;
if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
chain->queued = true;
@@ -1607,9 +1628,13 @@ static void chain_swap(struct sna *sna, DrawablePtr draw, struct sna_dri2_frame_
DBG(("%s -- requeue failed, errno=%d\n", __FUNCTION__, errno));
}
- chain->bo = __sna_dri2_copy_region(sna, draw, NULL,
- chain->back, chain->front,
- true);
+ if (can_xchg(sna, chain->draw, chain->front, chain->back)) {
+ sna_dri2_exchange_buffers(chain->draw, chain->front, chain->back);
+ } else {
+ chain->bo = __sna_dri2_copy_region(sna, chain->draw, NULL,
+ chain->back, chain->front,
+ true);
+ }
case SWAP:
break;
default:
@@ -1621,14 +1646,14 @@ static void chain_swap(struct sna *sna, DrawablePtr draw, struct sna_dri2_frame_
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)chain;
+ vbl.request.signal = (uintptr_t)chain;
chain->queued = true;
if (sna_wait_vblank(sna, &vbl, chain->pipe)) {
DBG(("%s: vblank wait failed, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, chain, DRI2_BLIT_COMPLETE);
- sna_dri2_frame_event_info_free(sna, draw, chain);
+ sna_dri2_event_free(sna, chain->draw, chain);
} else {
- if (chain->type == SWAP_THROTTLE && !swap_limit(draw, 2)) {
+ if (chain->type == SWAP_THROTTLE && !swap_limit(chain->draw, 2)) {
DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, chain, DRI2_BLIT_COMPLETE);
}
@@ -1654,7 +1679,7 @@ static inline bool rq_is_busy(struct kgem *kgem, struct kgem_bo *bo)
}
static bool sna_dri2_blit_complete(struct sna *sna,
- struct sna_dri2_frame_event *info)
+ struct sna_dri2_event *info)
{
if (rq_is_busy(&sna->kgem, info->bo)) {
union drm_wait_vblank vbl;
@@ -1667,7 +1692,7 @@ static bool sna_dri2_blit_complete(struct sna *sna,
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
assert(info->queued);
if (!sna_wait_vblank(sna, &vbl, info->pipe))
return false;
@@ -1679,7 +1704,7 @@ static bool sna_dri2_blit_complete(struct sna *sna,
void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
{
- struct sna_dri2_frame_event *info = (void *)(uintptr_t)event->user_data;
+ struct sna_dri2_event *info = (void *)(uintptr_t)event->user_data;
DrawablePtr draw;
union drm_wait_vblank vbl;
uint64_t msc;
@@ -1698,18 +1723,21 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
case FLIP:
/* If we can still flip... */
if (can_flip(sna, draw, info->front, info->back, info->crtc) &&
- sna_dri2_page_flip(sna, info))
+ sna_dri2_flip(sna, info))
return;
/* else fall through to blit */
case SWAP:
- if (sna->mode.shadow_flip && !sna->mode.shadow_damage) {
+ if (sna->mode.shadow && !sna->mode.shadow_damage) {
/* recursed from wait_for_shadow(), simply requeue */
DBG(("%s -- recursed from wait_for_shadow(), requeuing\n", __FUNCTION__));
- } else {
+ } else if (can_xchg(sna, draw, info->front, info->back)) {
+ sna_dri2_exchange_buffers(draw, info->front, info->back);
+ info->type = SWAP_WAIT;
+ } else {
info->bo = __sna_dri2_copy_region(sna, draw, NULL,
- info->back, info->front, true);
+ info->back, info->front, true);
info->type = SWAP_WAIT;
}
@@ -1718,7 +1746,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
assert(info->queued);
if (!sna_wait_vblank(sna, &vbl, info->pipe))
@@ -1763,18 +1791,19 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event)
if (info->chain) {
assert(info->chain != info);
- sna_dri2_remove_frame_event((WindowPtr)draw, info);
- chain_swap(sna, draw, info->chain);
+ assert(info->draw == draw);
+ sna_dri2_remove_event((WindowPtr)draw, info);
+ chain_swap(sna, info->chain);
draw = NULL;
}
done:
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
}
static bool
sna_dri2_immediate_blit(struct sna *sna,
- struct sna_dri2_frame_event *info,
+ struct sna_dri2_event *info,
bool sync, bool event)
{
DrawablePtr draw = info->draw;
@@ -1805,7 +1834,7 @@ sna_dri2_immediate_blit(struct sna *sna,
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
ret = !sna_wait_vblank(sna, &vbl, info->pipe);
if (ret) {
info->queued = true;
@@ -1827,7 +1856,7 @@ sna_dri2_immediate_blit(struct sna *sna,
}
static bool
-sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
+sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_event *info)
{
DBG(("%s(mode=%d)\n", __FUNCTION__, info->mode));
@@ -1839,27 +1868,11 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
if (bo != sna_pixmap(sna->front)->gpu_bo)
return false;
- if (bo == sna->dri2.scanout[0].bo) {
- DBG(("%s: flip chain already complete\n", __FUNCTION__));
-
- if (info->draw) {
- sna_dri2_remove_frame_event((WindowPtr)info->draw, info);
- if (info->chain)
- chain_swap(sna, info->draw, info->chain);
- }
-
- info->draw = NULL;
+ if (!sna_page_flip(sna, bo, sna_dri2_flip_handler, info))
return false;
- } else {
- info->count = sna_page_flip(sna, bo, info, info->pipe);
- if (!info->count)
- return false;
-
- update_scanout(sna, bo, info->front->name);
- assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
- sna->dri2.flip_pending = info;
- }
+ assert(sna->dri2.flip_pending == NULL || sna->dri2.flip_pending == info);
+ sna->dri2.flip_pending = info;
} else {
info->type = -info->mode;
@@ -1870,11 +1883,11 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
return false;
assert(sna_pixmap_get_buffer(get_drawable_pixmap(info->draw)) == info->front);
- if (!sna_dri2_page_flip(sna, info))
+ if (!sna_dri2_flip(sna, info))
return false;
if (!XORG_CAN_TRIPLE_BUFFER) {
- sna_dri2_get_back(sna, info);
+ sna_dri2_get_back(sna, info->back, info);
DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, info, DRI2_FLIP_COMPLETE);
}
@@ -1886,7 +1899,7 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_frame_event *info)
static void chain_flip(struct sna *sna)
{
- struct sna_dri2_frame_event *chain = sna->dri2.flip_pending;
+ struct sna_dri2_event *chain = sna->dri2.flip_pending;
assert(chain->type == FLIP);
DBG(("%s: chaining type=%d, cancelled?=%d\n",
@@ -1894,14 +1907,14 @@ static void chain_flip(struct sna *sna)
sna->dri2.flip_pending = NULL;
if (chain->draw == NULL) {
- sna_dri2_frame_event_info_free(sna, NULL, chain);
+ sna_dri2_event_free(sna, NULL, chain);
return;
}
assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw));
if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) &&
- sna_dri2_page_flip(sna, chain)) {
+ sna_dri2_flip(sna, chain)) {
DBG(("%s: performing chained flip\n", __FUNCTION__));
} else {
DBG(("%s: emitting chained vsync'ed blit\n", __FUNCTION__));
@@ -1919,7 +1932,7 @@ static void chain_flip(struct sna *sna)
DRM_VBLANK_RELATIVE |
DRM_VBLANK_EVENT;
vbl.request.sequence = 1;
- vbl.request.signal = (unsigned long)chain;
+ vbl.request.signal = (uintptr_t)chain;
if (!sna_wait_vblank(sna, &vbl, chain->pipe)) {
chain->queued = true;
@@ -1929,18 +1942,15 @@ static void chain_flip(struct sna *sna)
DBG(("%s: fake triple buffering (or vblank wait failed), unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, chain, DRI2_BLIT_COMPLETE);
- sna_dri2_frame_event_info_free(sna, chain->draw, chain);
+ sna_dri2_event_free(sna, chain->draw, chain);
}
}
static void sna_dri2_flip_event(struct sna *sna,
- struct sna_dri2_frame_event *flip)
+ struct sna_dri2_event *flip)
{
DBG(("%s(pipe=%d, event=%d)\n", __FUNCTION__, flip->pipe, flip->type));
- assert(!sna->mode.shadow_flip);
-
- retire_scanout(sna, flip);
if (sna->dri2.flip_pending == flip)
sna->dri2.flip_pending = NULL;
@@ -1949,7 +1959,7 @@ static void sna_dri2_flip_event(struct sna *sna,
case FLIP:
DBG(("%s: swap complete, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, flip, DRI2_FLIP_COMPLETE);
- sna_dri2_frame_event_info_free(sna, flip->draw, flip);
+ sna_dri2_event_free(sna, flip->draw, flip);
if (sna->dri2.flip_pending)
chain_flip(sna);
@@ -1960,56 +1970,36 @@ static void sna_dri2_flip_event(struct sna *sna,
frame_swap_complete(sna, flip, DRI2_FLIP_COMPLETE);
case FLIP_COMPLETE:
if (sna->dri2.flip_pending) {
- sna_dri2_frame_event_info_free(sna, flip->draw, flip);
+ sna_dri2_event_free(sna, flip->draw, flip);
chain_flip(sna);
} else if (!flip->mode) {
DBG(("%s: flip chain complete\n", __FUNCTION__));
if (flip->chain) {
- sna_dri2_remove_frame_event((WindowPtr)flip->draw,
- flip);
- chain_swap(sna, flip->draw, flip->chain);
+ sna_dri2_remove_event((WindowPtr)flip->draw,
+ flip);
+ chain_swap(sna, flip->chain);
flip->draw = NULL;
}
- sna_dri2_frame_event_info_free(sna, flip->draw, flip);
+ sna_dri2_event_free(sna, flip->draw, flip);
} else if (!sna_dri2_flip_continue(sna, flip)) {
DBG(("%s: no longer able to flip\n", __FUNCTION__));
if (flip->draw == NULL || !sna_dri2_immediate_blit(sna, flip, false, flip->mode < 0))
- sna_dri2_frame_event_info_free(sna, flip->draw, flip);
+ sna_dri2_event_free(sna, flip->draw, flip);
}
break;
default: /* Unknown type */
xf86DrvMsg(sna->scrn->scrnIndex, X_WARNING,
"%s: unknown vblank event received\n", __func__);
- sna_dri2_frame_event_info_free(sna, flip->draw, flip);
+ sna_dri2_event_free(sna, flip->draw, flip);
if (sna->dri2.flip_pending)
chain_flip(sna);
break;
}
}
-void
-sna_dri2_page_flip_handler(struct sna *sna,
- struct drm_event_vblank *event)
-{
- struct sna_dri2_frame_event *info = to_frame_event(event->user_data);
-
- DBG(("%s: pending flip_count=%d\n", __FUNCTION__, info->count));
- assert(info->count > 0);
-
- /* Is this the event whose info shall be delivered to higher level? */
- if (event->user_data & 1)
- sna_crtc_record_event(info->crtc, event);
-
- if (--info->count)
- return;
-
- DBG(("%s: sequence=%d\n", __FUNCTION__, event->sequence));
- sna_dri2_flip_event(sna, info);
-}
-
static uint64_t
get_current_msc(struct sna *sna, DrawablePtr draw, xf86CrtcPtr crtc)
{
@@ -2105,7 +2095,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
DRI2SwapEventPtr func, void *data)
{
struct sna *sna = to_sna_from_drawable(draw);
- struct sna_dri2_frame_event *info;
+ struct sna_dri2_event *info;
uint64_t current_msc;
if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
@@ -2142,7 +2132,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
}
}
- info = sna_dri2_add_frame_event(draw, client);
+ info = sna_dri2_add_event(draw, client);
if (info == NULL)
return false;
@@ -2153,13 +2143,6 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
info->front = sna_dri2_reference_buffer(front);
info->back = sna_dri2_reference_buffer(back);
- if (sna->dri2.scanout[0].bo == NULL) {
- sna->dri2.scanout[0].bo = ref(get_private(front)->bo);
- sna->dri2.scanout[0].name = info->front->name;
- }
- assert(sna->dri2.scanout[0].bo == get_private(front)->bo);
- assert(sna->dri2.scanout[0].bo->scanout);
-
if (sna->dri2.flip_pending) {
/* We need to first wait (one vblank) for the
* async flips to complete before this client
@@ -2172,9 +2155,9 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
current_msc++;
} else {
info->type = type = use_triple_buffer(sna, client, *target_msc == 0);
- if (!sna_dri2_page_flip(sna, info)) {
+ if (!sna_dri2_flip(sna, info)) {
DBG(("%s: flip failed, falling back\n", __FUNCTION__));
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
return false;
}
}
@@ -2183,11 +2166,11 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
if (type >= FLIP_COMPLETE) {
new_back:
if (!XORG_CAN_TRIPLE_BUFFER)
- sna_dri2_get_back(sna, info);
+ sna_dri2_get_back(sna, back, info);
DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__));
frame_swap_complete(sna, info, DRI2_EXCHANGE_COMPLETE);
if (info->type == FLIP_ASYNC)
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
}
out:
DBG(("%s: target_msc=%llu\n", __FUNCTION__, current_msc + 1));
@@ -2195,7 +2178,7 @@ out:
return true;
}
- info = sna_dri2_add_frame_event(draw, client);
+ info = sna_dri2_add_event(draw, client);
if (info == NULL)
return false;
@@ -2207,13 +2190,6 @@ out:
info->front = sna_dri2_reference_buffer(front);
info->back = sna_dri2_reference_buffer(back);
- if (sna->dri2.scanout[0].bo == NULL) {
- sna->dri2.scanout[0].bo = ref(get_private(front)->bo);
- sna->dri2.scanout[0].name = info->front->name;
- }
- assert(sna->dri2.scanout[0].bo == get_private(front)->bo);
- assert(sna->dri2.scanout[0].bo->scanout);
-
/*
* If divisor is zero, or current_msc is smaller than target_msc
* we just need to make sure target_msc passes before initiating
@@ -2233,8 +2209,8 @@ out:
}
if (*target_msc <= current_msc + 1) {
- if (!sna_dri2_page_flip(sna, info)) {
- sna_dri2_frame_event_info_free(sna, draw, info);
+ if (!sna_dri2_flip(sna, info)) {
+ sna_dri2_event_free(sna, draw, info);
return false;
}
*target_msc = current_msc + 1;
@@ -2249,10 +2225,10 @@ out:
/* Account for 1 frame extra pageflip delay */
vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
if (sna_wait_vblank(sna, &vbl, info->pipe)) {
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
return false;
}
}
@@ -2263,6 +2239,67 @@ out:
return true;
}
+static bool
+sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
+ DRI2BufferPtr front, DRI2BufferPtr back,
+ CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
+ DRI2SwapEventPtr func, void *data)
+{
+ struct sna *sna = to_sna_from_drawable(draw);
+ uint64_t current_msc;
+ bool sync, event;
+
+ if (!immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc))
+ return false;
+
+ sync = current_msc < *target_msc;
+ event = sna_dri2_window_get_chain((WindowPtr)draw) == NULL;
+ if (!sync || event) {
+ DBG(("%s: performing immediate xchg on pipe %d\n",
+ __FUNCTION__, sna_crtc_to_pipe(crtc)));
+ sna_dri2_exchange_buffers(draw, front, back);
+ }
+ if (sync) {
+ struct sna_dri2_event *info;
+
+ info = sna_dri2_add_event(draw, client);
+ if (!info)
+ goto complete;
+
+ info->event_complete = func;
+ info->event_data = data;
+
+ info->front = sna_dri2_reference_buffer(front);
+ info->back = sna_dri2_reference_buffer(back);
+ info->type = SWAP_THROTTLE;
+
+ if (event) {
+ union drm_wait_vblank vbl;
+
+ VG_CLEAR(vbl);
+ vbl.request.type =
+ DRM_VBLANK_RELATIVE |
+ DRM_VBLANK_EVENT;
+ vbl.request.sequence = 1;
+ vbl.request.signal = (uintptr_t)info;
+
+ if (sna_wait_vblank(sna, &vbl, info->pipe)) {
+ sna_dri2_event_free(sna, draw, info);
+ goto complete;
+ }
+
+ info->queued = true;
+ swap_limit(draw, 2);
+ }
+ } else {
+complete:
+ fake_swap_complete(sna, client, draw, crtc, DRI2_EXCHANGE_COMPLETE, func, data);
+ }
+
+ *target_msc = current_msc + 1;
+ return true;
+}
+
/*
* ScheduleSwap is responsible for requesting a DRM vblank event for the
* appropriate frame.
@@ -2291,7 +2328,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
struct sna *sna = to_sna_from_drawable(draw);
union drm_wait_vblank vbl;
xf86CrtcPtr crtc = NULL;
- struct sna_dri2_frame_event *info = NULL;
+ struct sna_dri2_event *info = NULL;
CARD64 current_msc;
DBG(("%s: draw=%ld, pixmap=%ld, back=%u (refs=%d/%d, flush=%d) , fron=%u (refs=%d/%d, flush=%d)\n",
@@ -2319,11 +2356,13 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
assert(get_private(front)->bo->flush);
assert(get_private(back)->bo->refcnt);
- assert(get_private(back)->bo->flush);
if (get_private(front)->pixmap != get_drawable_pixmap(draw))
goto skip;
+ if (get_private(back)->stale)
+ goto skip;
+
assert(sna_pixmap_from_drawable(draw)->flush);
/* Drawable not displayed... just complete the swap */
@@ -2334,6 +2373,12 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
goto blit;
}
+ if (can_xchg(sna, draw, front, back) &&
+ sna_dri2_schedule_xchg(client, draw, crtc, front, back,
+ target_msc, divisor, remainder,
+ func, data))
+ return TRUE;
+
if (can_flip(sna, draw, front, back, crtc) &&
sna_dri2_schedule_flip(client, draw, crtc, front, back,
target_msc, divisor, remainder,
@@ -2342,7 +2387,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
VG_CLEAR(vbl);
- info = sna_dri2_add_frame_event(draw, client);
+ info = sna_dri2_add_event(draw, client);
if (!info)
goto blit;
@@ -2353,21 +2398,18 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
info->front = sna_dri2_reference_buffer(front);
info->back = sna_dri2_reference_buffer(back);
- info->type = SWAP;
-
if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
bool sync = current_msc < *target_msc;
if (!sna_dri2_immediate_blit(sna, info, sync, true))
- sna_dri2_frame_event_info_free(sna, draw, info);
- if (*target_msc)
- *target_msc = current_msc + sync;
+ sna_dri2_event_free(sna, draw, info);
+ *target_msc = current_msc + sync;
return TRUE;
}
vbl.request.type =
DRM_VBLANK_ABSOLUTE |
DRM_VBLANK_EVENT;
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
/*
* If divisor is zero, or current_msc is smaller than target_msc
@@ -2391,7 +2433,7 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
if (*target_msc <= current_msc + 1) {
DBG(("%s: performing blit before queueing\n", __FUNCTION__));
info->bo = __sna_dri2_copy_region(sna, draw, NULL,
- info->back, info->front,
+ back, front,
true);
info->type = SWAP_WAIT;
@@ -2414,7 +2456,7 @@ blit:
DBG(("%s -- blit\n", __FUNCTION__));
__sna_dri2_copy_region(sna, draw, NULL, back, front, false);
if (info)
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
skip:
DBG(("%s: unable to show frame, unblocking client\n", __FUNCTION__));
if (crtc == NULL)
@@ -2469,7 +2511,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
CARD64 divisor, CARD64 remainder)
{
struct sna *sna = to_sna_from_drawable(draw);
- struct sna_dri2_frame_event *info = NULL;
+ struct sna_dri2_event *info = NULL;
xf86CrtcPtr crtc;
CARD64 current_msc;
union drm_wait_vblank vbl;
@@ -2508,14 +2550,14 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
if (divisor == 0 && current_msc >= target_msc)
goto out_complete;
- info = sna_dri2_add_frame_event(draw, client);
+ info = sna_dri2_add_event(draw, client);
if (!info)
goto out_complete;
assert(info->crtc == crtc);
info->type = WAITMSC;
- vbl.request.signal = (unsigned long)info;
+ vbl.request.signal = (uintptr_t)info;
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
/*
* If divisor is zero, or current_msc is smaller than target_msc,
@@ -2543,7 +2585,7 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
return TRUE;
out_free_info:
- sna_dri2_frame_event_info_free(sna, draw, info);
+ sna_dri2_event_free(sna, draw, info);
out_complete:
if (crtc == NULL)
crtc = sna_mode_first_crtc(sna);
@@ -2719,18 +2761,6 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen)
return DRI2ScreenInit(screen, &info);
}
-void sna_dri2_reset_scanout(struct sna *sna)
-{
- if (sna->dri2.scanout[1].bo != NULL) {
- kgem_bo_destroy(&sna->kgem, sna->dri2.scanout[1].bo);
- sna->dri2.scanout[1].bo = NULL;
- }
- if (sna->dri2.scanout[0].bo != NULL) {
- kgem_bo_destroy(&sna->kgem, sna->dri2.scanout[0].bo);
- sna->dri2.scanout[0].bo = NULL;
- }
-}
-
void sna_dri2_close(struct sna *sna, ScreenPtr screen)
{
DBG(("%s()\n", __FUNCTION__));