commit 8820ace

Michael Forney  ·  2013-07-25 07:04:26 +0000 UTC
parent 6fb96f3
wayland: Ensure buffer is released before drawing
1 files changed,  +50, -0
+50, -0
  1@@ -33,6 +33,7 @@
  2 
  3 struct wld_wayland_context
  4 {
  5+    struct wl_display * display;
  6     struct wl_event_queue * queue;
  7     const struct wld_wayland_interface * interface;
  8     void * context;
  9@@ -48,6 +49,7 @@ struct wayland_drawable
 10     {
 11         struct wl_buffer * wl;
 12         struct wld_drawable * drawable;
 13+        bool busy;
 14     } buffers[2];
 15     uint8_t front_buffer;
 16 };
 17@@ -58,6 +60,8 @@ _Static_assert(offsetof(struct wayland_drawable, base) == 0,
 18 static void sync_done(void * data, struct wl_callback * callback,
 19                       uint32_t msecs);
 20 
 21+static void buffer_release(void * data, struct wl_buffer * buffer);
 22+
 23 static void wayland_fill_rectangle(struct wld_drawable * drawable,
 24                                    uint32_t color, int32_t x, int32_t y,
 25                                    uint32_t width, uint32_t height);
 26@@ -83,6 +87,10 @@ const struct wl_callback_listener sync_listener = {
 27     .done = &sync_done
 28 };
 29 
 30+const struct wl_buffer_listener buffer_listener = {
 31+    .release = &buffer_release
 32+};
 33+
 34 const struct wld_draw_interface wayland_draw = {
 35     .fill_rectangle = &wayland_fill_rectangle,
 36     .fill_region = &wayland_fill_region,
 37@@ -115,6 +123,7 @@ struct wld_wayland_context * wld_wayland_create_context
 38     if (!wayland)
 39         goto error0;
 40 
 41+    wayland->display = display;
 42     wayland->queue = wl_display_create_queue(display);
 43     wayland->context = NULL;
 44     wayland->interface = NULL;
 45@@ -206,6 +215,8 @@ struct wld_drawable * wld_wayland_create_drawable
 46     if (!wayland->buffers[1].drawable)
 47         goto error2;
 48 
 49+    wayland->buffers[0].busy = false;
 50+    wayland->buffers[1].busy = false;
 51     wayland->front_buffer = 0;
 52     wayland->surface = surface;
 53 
 54@@ -213,6 +224,11 @@ struct wld_drawable * wld_wayland_create_drawable
 55     wayland->base.width = width;
 56     wayland->base.height = height;
 57 
 58+    wl_buffer_add_listener(wayland->buffers[0].wl, &buffer_listener,
 59+                           &wayland->buffers[0].busy);
 60+    wl_buffer_add_listener(wayland->buffers[1].wl, &buffer_listener,
 61+                           &wayland->buffers[1].busy);
 62+
 63     return &wayland->base;
 64 
 65   error2:
 66@@ -250,12 +266,39 @@ void sync_done(void * data, struct wl_callback * callback, uint32_t msecs)
 67     *done = true;
 68 }
 69 
 70+void buffer_release(void * data, struct wl_buffer * buffer)
 71+{
 72+    bool * busy = data;
 73+
 74+    *busy = false;
 75+}
 76+
 77+static void wait_for_backbuf(struct wayland_drawable * wayland)
 78+{
 79+    if (BACKBUF(wayland).busy)
 80+    {
 81+        int ret, count = 0;
 82+
 83+        do {
 84+            ret = wl_display_dispatch_queue(wayland->context->display,
 85+                                            wayland->context->queue);
 86+        } while (BACKBUF(wayland).busy && ret != -1);
 87+    }
 88+}
 89+
 90+static void begin(struct wayland_drawable * wayland)
 91+{
 92+    /* Wait for the back buffer to become available. */
 93+    wait_for_backbuf(wayland);
 94+}
 95+
 96 static void wayland_fill_rectangle(struct wld_drawable * drawable,
 97                                    uint32_t color, int32_t x, int32_t y,
 98                                    uint32_t width, uint32_t height)
 99 {
100     struct wayland_drawable * wayland = (void *) drawable;
101 
102+    begin(wayland);
103     wld_fill_rectangle(BACKBUF(wayland).drawable, color, x, y, width, height);
104 }
105 
106@@ -264,6 +307,7 @@ static void wayland_fill_region(struct wld_drawable * drawable, uint32_t color,
107 {
108     struct wayland_drawable * wayland = (void *) drawable;
109 
110+    begin(wayland);
111     wld_fill_region(BACKBUF(wayland).drawable, color, region);
112 }
113 
114@@ -291,6 +335,7 @@ static void wayland_draw_text_utf8(struct wld_drawable * drawable,
115 {
116     struct wayland_drawable * wayland = (void *) drawable;
117 
118+    begin(wayland);
119     wld_draw_text_utf8_n(BACKBUF(wayland).drawable, &font->base, color,
120                          x, y, text, length);
121 }
122@@ -299,9 +344,14 @@ static void wayland_flush(struct wld_drawable * drawable)
123 {
124     struct wayland_drawable * wayland = (void *) drawable;
125 
126+    wait_for_backbuf(wayland);
127+
128     wld_flush(BACKBUF(wayland).drawable);
129     wl_surface_attach(wayland->surface, BACKBUF(wayland).wl, 0, 0);
130     wl_surface_commit(wayland->surface);
131+
132+    BACKBUF(wayland).busy = true;
133+
134     wayland->front_buffer ^= 1;
135 }
136