summaryrefslogtreecommitdiff
path: root/src/sna
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-05-23 13:34:38 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-05-23 13:57:16 +0100
commit605fcd9050efc816ac8163e8d626f466d98261c2 (patch)
tree0e73e689b4fa87fc5907a4a272d28d68912280a5 /src/sna
parent36a4a654da87b22f7ce31d1ca99389cedb57eee8 (diff)
sna/dri2: Handle allocation failure adding frame events gracefully
Now that we do not preallocate the storage for the chain in the Window devPrivates, we need to check for an allocation failure. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna')
-rw-r--r--src/sna/sna_dri2.c103
1 files changed, 44 insertions, 59 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c
index 8589ffeb..4b1775d0 100644
--- a/src/sna/sna_dri2.c
+++ b/src/sna/sna_dri2.c
@@ -474,9 +474,10 @@ static void sna_dri2_destroy_buffer(DrawablePtr draw, DRI2Buffer2Ptr buffer)
_sna_dri2_destroy_buffer(to_sna_from_drawable(draw), buffer);
}
-static void sna_dri2_reference_buffer(DRI2BufferPtr buffer)
+static DRI2BufferPtr sna_dri2_reference_buffer(DRI2BufferPtr buffer)
{
get_private(buffer)->refcnt++;
+ return buffer;
}
static inline void damage(PixmapPtr pixmap, struct sna_pixmap *priv, RegionPtr region)
@@ -943,12 +944,12 @@ struct dri2_window {
static struct dri2_window *dri2_window(WindowPtr win)
{
- assert(win->drawable.type == DRAWABLE_WINDOW);
return ((void **)__get_private(win, sna_window_key))[1];
}
static void dri2_window_attach(WindowPtr win, struct dri2_window *priv)
{
+ assert(win->drawable.type == DRAWABLE_WINDOW);
assert(dri2_window(win) == NULL);
((void **)__get_private(win, sna_window_key))[1] = priv;
assert(dri2_window(win) == priv);
@@ -1053,25 +1054,35 @@ sna_dri2_remove_frame_event(WindowPtr win,
chain->chain = info->chain;
}
-static void
-sna_dri2_add_frame_event(DrawablePtr draw, struct sna_dri2_frame_event *info)
+static struct sna_dri2_frame_event *
+sna_dri2_add_frame_event(DrawablePtr draw, ClientPtr client)
{
struct dri2_window *priv;
- struct sna_dri2_frame_event *chain;
-
- if (draw->type != DRAWABLE_WINDOW)
- return;
+ struct sna_dri2_frame_event *info, *chain;
+ assert(draw->type == DRAWABLE_WINDOW);
DBG(("%s: add[%p] to window %ld)\n",
__FUNCTION__, info, (long)draw->id));
priv = dri2_window((WindowPtr)draw);
- assert(priv);
+ if (priv == NULL)
+ return NULL;
+
+ info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ if (info == NULL)
+ return NULL;
+
+ list_init(&info->cache);
+ info->draw = draw;
+ info->client = client;
+ info->crtc = priv->crtc;
+ info->pipe = sna_crtc_to_pipe(priv->crtc);
+
assert(priv->chain != info);
if (priv->chain == NULL) {
priv->chain = info;
- return;
+ return info;
}
chain = priv->chain;
@@ -1080,6 +1091,7 @@ sna_dri2_add_frame_event(DrawablePtr draw, struct sna_dri2_frame_event *info)
assert(chain != info);
chain->chain = info;
+ return info;
}
static void
@@ -1121,15 +1133,16 @@ sna_dri2_frame_event_info_free(struct sna *sna,
void sna_dri2_destroy_window(WindowPtr win)
{
- struct sna *sna = to_sna_from_drawable(&win->drawable);
- struct dri2_window *priv = dri2_window(win);
+ struct dri2_window *priv;
+ priv = dri2_window(win);
if (priv == NULL)
return;
DBG(("%s: window=%ld\n", __FUNCTION__, win->drawable.serialNumber));
if (priv->chain) {
+ struct sna *sna = to_sna_from_drawable(&win->drawable);
struct sna_dri2_frame_event *info, *chain;
DBG(("%s: freeing chain\n", __FUNCTION__));
@@ -2028,7 +2041,6 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
{
struct sna *sna = to_sna_from_drawable(draw);
struct sna_dri2_frame_event *info;
- int pipe = sna_crtc_to_pipe(crtc);
uint64_t current_msc;
if (immediate_swap(sna, *target_msc, divisor, draw, crtc, &current_msc)) {
@@ -2036,15 +2048,14 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
info = sna->dri2.flip_pending;
DBG(("%s: performing immediate swap on pipe %d, pending? %d, mode: %d\n",
- __FUNCTION__, pipe, info != NULL, info ? info->mode : 0));
+ __FUNCTION__, sna_crtc_to_pipe(crtc), info != NULL, info ? info->mode : 0));
if (info && info->draw == draw) {
assert(info->type != FLIP);
assert(info->front == front);
if (info->back != back) {
_sna_dri2_destroy_buffer(sna, info->back);
- info->back = back;
- sna_dri2_reference_buffer(back);
+ info->back = sna_dri2_reference_buffer(back);
}
if (current_msc >= *target_msc) {
DBG(("%s: executing xchg of pending flip\n",
@@ -2061,28 +2072,21 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc,
}
}
- info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ info = sna_dri2_add_frame_event(draw, client);
if (info == NULL)
return false;
- list_init(&info->cache);
- info->draw = draw;
- info->client = client;
+ assert(info->crtc == crtc);
info->event_complete = func;
info->event_data = data;
- info->front = front;
- info->back = back;
- info->crtc = crtc;
- info->pipe = pipe;
+
+ info->front = sna_dri2_reference_buffer(front);
+ info->back = sna_dri2_reference_buffer(back);
info->scanout[0].bo = ref(get_private(front)->bo);
info->scanout[0].name = info->front->name;
assert(info->scanout[0].bo->scanout);
- sna_dri2_add_frame_event(draw, info);
- sna_dri2_reference_buffer(front);
- sna_dri2_reference_buffer(back);
-
if (sna->dri2.flip_pending) {
/* We need to first wait (one vblank) for the
* async flips to complete before this client
@@ -2115,29 +2119,22 @@ out:
return true;
}
- info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ info = sna_dri2_add_frame_event(draw, client);
if (info == NULL)
return false;
- list_init(&info->cache);
- info->draw = draw;
- info->client = client;
+ assert(info->crtc == crtc);
info->event_complete = func;
info->event_data = data;
- info->front = front;
- info->back = back;
- info->crtc = crtc;
- info->pipe = pipe;
info->type = FLIP;
+ info->front = sna_dri2_reference_buffer(front);
+ info->back = sna_dri2_reference_buffer(back);
+
info->scanout[0].bo = ref(get_private(front)->bo);
info->scanout[0].name = info->front->name;
assert(info->scanout[0].bo->scanout);
- sna_dri2_add_frame_event(draw, info);
- sna_dri2_reference_buffer(front);
- sna_dri2_reference_buffer(back);
-
/*
* If divisor is zero, or current_msc is smaller than target_msc
* we just need to make sure target_msc passes before initiating
@@ -2175,7 +2172,7 @@ out:
vbl.reply.sequence = draw_target_seq(draw, *target_msc - 1);
vbl.request.signal = (unsigned long)info;
- if (sna_wait_vblank(sna, &vbl, pipe)) {
+ if (sna_wait_vblank(sna, &vbl, info->pipe)) {
sna_dri2_frame_event_info_free(sna, draw, info);
return false;
}
@@ -2266,23 +2263,16 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
VG_CLEAR(vbl);
- info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ info = sna_dri2_add_frame_event(draw, client);
if (!info)
goto blit;
- list_init(&info->cache);
- info->draw = draw;
- info->client = client;
+ assert(info->crtc == crtc);
info->event_complete = func;
info->event_data = data;
- info->front = front;
- info->back = back;
- info->crtc = crtc;
- info->pipe = sna_crtc_to_pipe(crtc);
- sna_dri2_add_frame_event(draw, info);
- sna_dri2_reference_buffer(front);
- sna_dri2_reference_buffer(back);
+ info->front = sna_dri2_reference_buffer(front);
+ info->back = sna_dri2_reference_buffer(back);
info->type = SWAP;
@@ -2446,17 +2436,12 @@ sna_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, CARD64 target_msc
if (divisor == 0 && current_msc >= target_msc)
goto out_complete;
- info = calloc(1, sizeof(struct sna_dri2_frame_event));
+ info = sna_dri2_add_frame_event(draw, client);
if (!info)
goto out_complete;
- list_init(&info->cache);
- info->draw = draw;
- info->client = client;
+ assert(info->crtc == crtc);
info->type = WAITMSC;
- info->crtc = crtc;
- info->pipe = pipe;
- sna_dri2_add_frame_event(draw, info);
vbl.request.signal = (unsigned long)info;
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;