commit ea86c0d

Michael Forney  ·  2014-01-13 22:20:00 +0000 UTC
parent 22f8d81
wayland-{shm,drm}: Use wld_context
7 files changed,  +244, -167
+81, -57
  1@@ -37,8 +37,9 @@
  2 
  3 #include <stdio.h>
  4 
  5-struct wld_wayland_drm_context
  6+struct drm_context
  7 {
  8+    struct wld_context base;
  9     struct wld_context * driver_context;
 10     struct wl_drm * wl;
 11     struct wl_registry * registry;
 12@@ -48,6 +49,9 @@ struct wld_wayland_drm_context
 13     bool authenticated;
 14 };
 15 
 16+#include "interface/context.h"
 17+IMPL(drm, context);
 18+
 19 static void registry_global(void * data, struct wl_registry * registry,
 20                             uint32_t name, const char * interface,
 21                             uint32_t version);
 22@@ -61,12 +65,7 @@ static void drm_capabilities(void * data, struct wl_drm * wl,
 23                              uint32_t capabilities);
 24 
 25 const struct wld_wayland_interface wayland_drm_interface = {
 26-    .create_context
 27-        = (wayland_create_context_func_t) &wld_wayland_drm_create_context,
 28-    .destroy_context
 29-        = (wayland_destroy_context_func_t) &wld_wayland_drm_destroy_context,
 30-    .create_drawable
 31-        = (wayland_create_drawable_func_t) &wld_wayland_drm_create_drawable
 32+    .create_context = &wld_wayland_drm_create_context,
 33 };
 34 
 35 const static struct wl_registry_listener registry_listener = {
 36@@ -82,16 +81,17 @@ const static struct wl_drm_listener drm_listener = {
 37 };
 38 
 39 EXPORT
 40-struct wld_wayland_drm_context * wld_wayland_drm_create_context
 41-    (struct wl_display * display, struct wl_event_queue * queue)
 42+struct wld_context * wld_wayland_drm_create_context(struct wl_display * display,
 43+                                                    struct wl_event_queue * queue)
 44 {
 45-    struct wld_wayland_drm_context * drm;
 46+    struct drm_context * drm;
 47 
 48     drm = malloc(sizeof *drm);
 49 
 50     if (!drm)
 51         goto error0;
 52 
 53+    context_initialize(&drm->base, &context_impl);
 54     drm->wl = NULL;
 55     drm->fd = -1;
 56     drm->capabilities = 0;
 57@@ -146,7 +146,7 @@ struct wld_wayland_drm_context * wld_wayland_drm_create_context
 58         goto error4;
 59     }
 60 
 61-    return drm;
 62+    return &drm->base;
 63 
 64   error4:
 65     close(drm->fd);
 66@@ -162,24 +162,12 @@ struct wld_wayland_drm_context * wld_wayland_drm_create_context
 67 }
 68 
 69 EXPORT
 70-void wld_wayland_drm_destroy_context(struct wld_wayland_drm_context * drm)
 71-{
 72-    wld_destroy_context(&drm->driver_context);
 73-    close(drm->fd);
 74-    wl_drm_destroy(drm->wl);
 75-    wl_registry_destroy(drm->registry);
 76-    wl_array_release(&drm->formats);
 77-
 78-    free(drm);
 79-}
 80-
 81-EXPORT
 82-bool wld_wayland_drm_has_format(struct wld_wayland_drm_context * drm,
 83-                                uint32_t format)
 84+bool wld_wayland_drm_has_format(struct wld_context * base, uint32_t format)
 85 {
 86+    struct drm_context * context = drm_context(base);
 87     uint32_t * supported_format;
 88 
 89-    wl_array_for_each(supported_format, &drm->formats)
 90+    wl_array_for_each(supported_format, &context->formats)
 91     {
 92         if (*supported_format == format)
 93             return true;
 94@@ -189,47 +177,83 @@ bool wld_wayland_drm_has_format(struct wld_wayland_drm_context * drm,
 95 }
 96 
 97 EXPORT
 98-int wld_wayland_drm_get_fd(struct wld_wayland_drm_context * drm)
 99+int wld_wayland_drm_get_fd(struct wld_context * base)
100 {
101-    return drm->authenticated ? drm->fd : -1;
102+    struct drm_context * context = drm_context(base);
103+
104+    return context->authenticated ? context->fd : -1;
105 }
106 
107-EXPORT
108-struct wld_drawable * wld_wayland_drm_create_drawable
109-    (struct wld_wayland_drm_context * drm, uint32_t width, uint32_t height,
110-     uint32_t format, struct wl_buffer ** buffer)
111+struct wld_drawable * context_create_drawable(struct wld_context * base,
112+                                              uint32_t width, uint32_t height,
113+                                              uint32_t format)
114 {
115+    struct drm_context * context = drm_context(base);
116     struct wld_drawable * drawable;
117+    struct wld_exporter * exporter;
118+    union wld_object object;
119+    struct wl_buffer * wl;
120 
121-    if (buffer && !wld_wayland_drm_has_format(drm, format))
122-        return NULL;
123+    if (!wld_wayland_drm_has_format(&context->base, format))
124+        goto error0;
125 
126-    drawable = wld_create_drawable(drm->driver_context, width, height, format);
127+    drawable = wld_create_drawable(context->driver_context, width, height, format);
128 
129     if (!drawable)
130-        return NULL;
131+        goto error0;
132 
133-    if (buffer)
134-    {
135-        union wld_object object;
136+    if (!wld_export(drawable, WLD_DRM_OBJECT_PRIME_FD, &object))
137+        goto error1;
138 
139-        wld_export(drawable, WLD_DRM_OBJECT_PRIME_FD, &object);
140-        *buffer = wl_drm_create_prime_buffer(drm->wl, object.i,
141-                                             width, height, format,
142-                                             0, drawable->pitch, 0, 0, 0, 0);
143-        close(prime_fd);
144-    }
145+    wl = wl_drm_create_prime_buffer(context->wl, object.i, width, height,
146+                                    format, 0, drawable->pitch, 0, 0, 0, 0);
147+    close(object.i);
148+
149+    if (!wl)
150+        goto error1;
151+
152+    if (!(exporter = wayland_create_exporter(wl)))
153+        goto error2;
154+
155+    drawable_add_exporter(drawable, exporter);
156 
157     return drawable;
158+
159+  error2:
160+    wl_buffer_destroy(wl);
161+  error1:
162+    wld_destroy_drawable(drawable);
163+  error0:
164+    return NULL;
165+}
166+
167+struct wld_drawable * context_import(struct wld_context * context,
168+                                     uint32_t type, union wld_object object,
169+                                     uint32_t width, uint32_t height,
170+                                     uint32_t format, uint32_t pitch)
171+{
172+    return NULL;
173+}
174+
175+void context_destroy(struct wld_context * base)
176+{
177+    struct drm_context * context = drm_context(base);
178+
179+    wld_destroy_context(context->driver_context);
180+    close(context->fd);
181+    wl_drm_destroy(context->wl);
182+    wl_registry_destroy(context->registry);
183+    wl_array_release(&context->formats);
184+    free(context);
185 }
186 
187 void registry_global(void * data, struct wl_registry * registry, uint32_t name,
188                      const char * interface, uint32_t version)
189 {
190-    struct wld_wayland_drm_context * drm = data;
191+    struct drm_context * context = data;
192 
193     if (strcmp(interface, "wl_drm") == 0 && version >= 2)
194-        drm->wl = wl_registry_bind(registry, name, &wl_drm_interface, 2);
195+        context->wl = wl_registry_bind(registry, name, &wl_drm_interface, 2);
196 }
197 
198 void registry_global_remove(void * data, struct wl_registry * registry,
199@@ -239,39 +263,39 @@ void registry_global_remove(void * data, struct wl_registry * registry,
200 
201 void drm_device(void * data, struct wl_drm * wl, const char * name)
202 {
203-    struct wld_wayland_drm_context * drm = data;
204+    struct drm_context * context = data;
205     drm_magic_t magic;
206 
207-    drm->fd = open(name, O_RDWR);
208+    context->fd = open(name, O_RDWR);
209 
210-    if (drm->fd == -1)
211+    if (context->fd == -1)
212     {
213         DEBUG("Couldn't open DRM device '%s'\n", name);
214         return;
215     }
216 
217-    drmGetMagic(drm->fd, &magic);
218+    drmGetMagic(context->fd, &magic);
219     wl_drm_authenticate(wl, magic);
220 }
221 
222 void drm_format(void * data, struct wl_drm * wl, uint32_t format)
223 {
224-    struct wld_wayland_drm_context * drm = data;
225+    struct drm_context * context = data;
226 
227-    *((uint32_t *) wl_array_add(&drm->formats, sizeof format)) = format;
228+    *((uint32_t *) wl_array_add(&context->formats, sizeof format)) = format;
229 }
230 
231 void drm_authenticated(void * data, struct wl_drm * wl)
232 {
233-    struct wld_wayland_drm_context * drm = data;
234+    struct drm_context * context = data;
235 
236-    drm->authenticated = true;
237+    context->authenticated = true;
238 }
239 
240 void drm_capabilities(void * data, struct wl_drm * wl, uint32_t capabilities)
241 {
242-    struct wld_wayland_drm_context * drm = data;
243+    struct drm_context * context = data;
244 
245-    drm->capabilities = capabilities;
246+    context->capabilities = capabilities;
247 }
248 
+3, -20
 1@@ -27,44 +27,27 @@
 2 #include <stdbool.h>
 3 #include <stdint.h>
 4 
 5-struct wld_wayland_drm_context;
 6-struct wld_drawable;
 7-
 8 struct wl_display;
 9 struct wl_event_queue;
10-struct wl_buffer;
11 
12 /**
13  * Create a new drawable context which creates Wayland buffers through the
14  * wl_drm interface, backed by hardware specific drawable implementations.
15  */
16-struct wld_wayland_drm_context * wld_wayland_drm_create_context
17+struct wld_context * wld_wayland_drm_create_context
18     (struct wl_display * display, struct wl_event_queue * queue);
19 
20-/**
21- * Destroy a Wayland DRM context.
22- */
23-void wld_wayland_drm_destroy_context(struct wld_wayland_drm_context * context);
24-
25 /**
26  * Check if the wl_drm global has the specified pixel format.
27  *
28  * @see enum wld_format
29  */
30-bool wld_wayland_drm_has_format(struct wld_wayland_drm_context * context,
31-                                uint32_t format);
32+bool wld_wayland_drm_has_format(struct wld_context * context, uint32_t format);
33 
34 /**
35  * Get the opened file descriptor for the DRM device.
36  */
37-int wld_wayland_drm_get_fd(struct wld_wayland_drm_context * context);
38-
39-/**
40- * Create a new DRM drawable with the specified dimensions.
41- */
42-struct wld_drawable * wld_wayland_drm_create_drawable
43-    (struct wld_wayland_drm_context * context, uint32_t width, uint32_t height,
44-     uint32_t format, struct wl_buffer ** buffer);
45+int wld_wayland_drm_get_fd(struct wld_context * context);
46 
47 #endif
48 
+4, -12
 1@@ -26,24 +26,14 @@
 2 
 3 #include <stdint.h>
 4 
 5-struct wld_drawable;
 6-
 7 struct wl_display;
 8 struct wl_event_queue;
 9 struct wl_buffer;
10 
11-typedef void * (* wayland_create_context_func_t)(struct wl_display * display,
12-                                                 struct wl_event_queue * queue);
13-typedef void (* wayland_destroy_context_func_t)(void * context);
14-typedef struct wld_drawable * (* wayland_create_drawable_func_t)
15-    (void * context, uint32_t width, uint32_t height, uint32_t format,
16-     struct wl_buffer ** buffer);
17-
18 struct wld_wayland_interface
19 {
20-    wayland_create_context_func_t create_context;
21-    wayland_destroy_context_func_t destroy_context;
22-    wayland_create_drawable_func_t create_drawable;
23+    struct wld_context * (* create_context)(struct wl_display * display,
24+                                            struct wl_event_queue * queue);
25 };
26 
27 #if WITH_WAYLAND_DRM
28@@ -60,5 +50,7 @@ extern const struct wld_wayland_interface wayland_shm_interface;
29 int wayland_roundtrip(struct wl_display * display,
30                       struct wl_event_queue * queue);
31 
32+struct wld_exporter * wayland_create_exporter(struct wl_buffer * buffer);
33+
34 #endif
35 
+79, -52
  1@@ -36,8 +36,10 @@
  2 #include <sys/mman.h>
  3 #include <wayland-client.h>
  4 
  5-struct wld_shm_context
  6+struct shm_context
  7 {
  8+    struct wld_context base;
  9+
 10     struct wl_registry * registry;
 11     struct wl_shm * wl;
 12     struct wl_array formats;
 13@@ -45,6 +47,9 @@ struct wld_shm_context
 14     struct wld_context * pixman_context;
 15 };
 16 
 17+#include "interface/context.h"
 18+IMPL(shm, context)
 19+
 20 static void registry_global(void * data, struct wl_registry * registry,
 21                             uint32_t name, const char * interface,
 22                             uint32_t version);
 23@@ -54,10 +59,7 @@ static void registry_global_remove(void * data, struct wl_registry * registry,
 24 static void shm_format(void * data, struct wl_shm * wl, uint32_t format);
 25 
 26 const struct wld_wayland_interface wayland_shm_interface = {
 27-    .create_context = (wayland_create_context_func_t) &wld_shm_create_context,
 28-    .destroy_context
 29-        = (wayland_destroy_context_func_t) &wld_shm_destroy_context,
 30-    .create_drawable = (wayland_create_drawable_func_t) &wld_shm_create_drawable
 31+    .create_context = &wld_shm_create_context,
 32 };
 33 
 34 const static struct wl_registry_listener registry_listener = {
 35@@ -83,74 +85,61 @@ static inline uint32_t wayland_format(uint32_t format)
 36 }
 37 
 38 EXPORT
 39-struct wld_shm_context * wld_shm_create_context(struct wl_display * display,
 40-                                                struct wl_event_queue * queue)
 41+struct wld_context * wld_shm_create_context(struct wl_display * display,
 42+                                            struct wl_event_queue * queue)
 43 {
 44-    struct wld_shm_context * shm;
 45+    struct shm_context * context;
 46 
 47-    shm = malloc(sizeof *shm);
 48-
 49-    if (!shm)
 50+    if (!(context = malloc(sizeof *context)))
 51         goto error0;
 52 
 53-    shm->wl = NULL;
 54-    wl_array_init(&shm->formats);
 55-
 56-    shm->registry = wl_display_get_registry(display);
 57+    context_initialize(&context->base, &context_impl);
 58+    context->wl = NULL;
 59+    wl_array_init(&context->formats);
 60 
 61-    if (!shm->registry)
 62+    if (!(context->registry = wl_display_get_registry(display)))
 63     {
 64         DEBUG("Couldn't get registry\n");
 65         goto error1;
 66     }
 67 
 68-    wl_registry_add_listener(shm->registry, &registry_listener, shm);
 69-    wl_proxy_set_queue((struct wl_proxy *) shm->registry, queue);
 70+    wl_registry_add_listener(context->registry, &registry_listener, context);
 71+    wl_proxy_set_queue((struct wl_proxy *) context->registry, queue);
 72 
 73-    shm->pixman_context = wld_pixman_create_context();
 74+    context->pixman_context = wld_pixman_create_context();
 75 
 76     /* Wait for wl_shm global. */
 77     wayland_roundtrip(display, queue);
 78 
 79-    if (!shm->wl)
 80+    if (!context->wl)
 81     {
 82         DEBUG("No wl_shm global\n");
 83         goto error2;
 84     }
 85 
 86-    wl_shm_add_listener(shm->wl, &shm_listener, shm);
 87+    wl_shm_add_listener(context->wl, &shm_listener, context);
 88 
 89     /* Wait for SHM formats. */
 90     wayland_roundtrip(display, queue);
 91 
 92-    return shm;
 93+    return &context->base;
 94 
 95   error2:
 96-    wl_registry_destroy(shm->registry);
 97+    wl_registry_destroy(context->registry);
 98   error1:
 99-    wl_array_release(&shm->formats);
100-    free(shm);
101+    wl_array_release(&context->formats);
102+    free(context);
103   error0:
104     return NULL;
105 }
106 
107 EXPORT
108-void wld_shm_destroy_context(struct wld_shm_context * shm)
109-{
110-    wld_destroy_context(shm->pixman_context);
111-    wl_shm_destroy(shm->wl);
112-    wl_registry_destroy(shm->registry);
113-    wl_array_release(&shm->formats);
114-
115-    free(shm);
116-}
117-
118-EXPORT
119-bool wld_shm_has_format(struct wld_shm_context * shm, uint32_t format)
120+bool wld_shm_has_format(struct wld_context * base, uint32_t format)
121 {
122+    struct shm_context * context = shm_context(base);
123     uint32_t * supported_format;
124 
125-    wl_array_for_each(supported_format, &shm->formats)
126+    wl_array_for_each(supported_format, &context->formats)
127     {
128         if (*supported_format == format)
129             return true;
130@@ -159,21 +148,22 @@ bool wld_shm_has_format(struct wld_shm_context * shm, uint32_t format)
131     return false;
132 }
133 
134-EXPORT
135-struct wld_drawable * wld_shm_create_drawable(struct wld_shm_context * shm,
136+struct wld_drawable * context_create_drawable(struct wld_context * base,
137                                               uint32_t width, uint32_t height,
138-                                              uint32_t format,
139-                                              struct wl_buffer ** buffer)
140+                                              uint32_t format)
141 {
142+    struct shm_context * context = shm_context(base);
143+    struct wld_drawable * drawable;
144+    struct wld_exporter * exporter;
145     char name[] = "/tmp/wld-XXXXXX";
146     uint32_t pitch = width * format_bytes_per_pixel(format);
147     uint32_t size = height * pitch;
148     int fd;
149     void * data;
150-    struct wl_shm_pool * pool;
151-    struct wld_drawable * drawable;
152     uint32_t shm_format = wayland_format(format);
153     union wld_object object;
154+    struct wl_shm_pool * pool;
155+    struct wl_buffer * wl;
156 
157     fd = mkostemp(name, O_CLOEXEC);
158 
159@@ -191,30 +181,67 @@ struct wld_drawable * wld_shm_create_drawable(struct wld_shm_context * shm,
160         goto error1;
161 
162     object.ptr = data;
163-    drawable = wld_import(shm->pixman_context, WLD_OBJECT_DATA, object,
164+    drawable = wld_import(context->pixman_context, WLD_OBJECT_DATA, object,
165                           width, height, format, pitch);
166 
167-    pool = wl_shm_create_pool(shm->wl, fd, size);
168-    *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, pitch,
169-                                        shm_format);
170+    if (!drawable)
171+        goto error2;
172+
173+    if (!(pool = wl_shm_create_pool(context->wl, fd, size)))
174+        goto error3;
175+
176+    wl = wl_shm_pool_create_buffer(pool, 0, width, height, pitch, shm_format);
177     wl_shm_pool_destroy(pool);
178+
179+    if (!wl)
180+        goto error3;
181+
182+    if (!(exporter = wayland_create_exporter(wl)))
183+        goto error4;
184+
185+    drawable_add_exporter(drawable, exporter);
186     close(fd);
187 
188     return drawable;
189 
190+  error4:
191+    wl_buffer_destroy(wl);
192+  error3:
193+    wld_destroy_drawable(drawable);
194+  error2:
195+    munmap(object.ptr, size);
196   error1:
197     close(fd);
198   error0:
199     return NULL;
200 }
201 
202+struct wld_drawable * context_import(struct wld_context * context,
203+                                     uint32_t type, union wld_object object,
204+                                     uint32_t width, uint32_t height,
205+                                     uint32_t format, uint32_t pitch)
206+{
207+    return NULL;
208+}
209+
210+void context_destroy(struct wld_context * base)
211+{
212+    struct shm_context * context = shm_context(base);
213+
214+    wld_destroy_context(context->pixman_context);
215+    wl_shm_destroy(context->wl);
216+    wl_registry_destroy(context->registry);
217+    wl_array_release(&context->formats);
218+    free(context);
219+}
220+
221 void registry_global(void * data, struct wl_registry * registry, uint32_t name,
222                      const char * interface, uint32_t version)
223 {
224-    struct wld_shm_context * shm = data;
225+    struct shm_context * context = data;
226 
227     if (strcmp(interface, "wl_shm") == 0)
228-        shm->wl = wl_registry_bind(registry, name, &wl_shm_interface, 1);
229+        context->wl = wl_registry_bind(registry, name, &wl_shm_interface, 1);
230 }
231 
232 void registry_global_remove(void * data, struct wl_registry * registry,
233@@ -224,8 +251,8 @@ void registry_global_remove(void * data, struct wl_registry * registry,
234 
235 void shm_format(void * data, struct wl_shm * wl, uint32_t format)
236 {
237-    struct wld_shm_context * shm = data;
238+    struct shm_context * context = data;
239 
240-    *((uint32_t *) wl_array_add(&shm->formats, sizeof format)) = format;
241+    *((uint32_t *) wl_array_add(&context->formats, sizeof format)) = format;
242 }
243 
+3, -20
 1@@ -27,39 +27,22 @@
 2 #include <stdbool.h>
 3 #include <stdint.h>
 4 
 5-struct wld_shm_context;
 6-struct wld_drawable;
 7-
 8 struct wl_display;
 9 struct wl_event_queue;
10-struct wl_buffer;
11 
12 /**
13  * Create a new drawable context which creates Wayland buffers through the
14  * wl_shm interface, back by Pixman drawables.
15  */
16-struct wld_shm_context * wld_shm_create_context(struct wl_display * display,
17-                                                struct wl_event_queue * queue);
18-
19-/**
20- * Destroy an SHM context.
21- */
22-void wld_shm_destroy_context(struct wld_shm_context * context);
23+struct wld_context * wld_shm_create_context(struct wl_display * display,
24+                                            struct wl_event_queue * queue);
25 
26 /**
27  * Check if the wl_shm global has the specified pixel format.
28  *
29  * @see enum wld_format
30  */
31-bool wld_shm_has_format(struct wld_shm_context * context, uint32_t format);
32-
33-/**
34- * Create a new SHM drawable with the specified dimensions.
35- */
36-struct wld_drawable * wld_shm_create_drawable(struct wld_shm_context * context,
37-                                              uint32_t width, uint32_t height,
38-                                              uint32_t format,
39-                                              struct wl_buffer ** buffer);
40+bool wld_shm_has_format(struct wld_context * context, uint32_t format);
41 
42 #endif
43 
+69, -6
  1@@ -33,10 +33,11 @@
  2 
  3 struct wld_wayland_context
  4 {
  5+    struct wld_context base;
  6     struct wl_display * display;
  7     struct wl_event_queue * queue;
  8     const struct wld_wayland_interface * interface;
  9-    void * context;
 10+    struct wld_context * context;
 11 };
 12 
 13 struct wayland_drawable
 14@@ -56,6 +57,12 @@ struct wayland_drawable
 15     uint32_t damage_tracking;
 16 };
 17 
 18+struct wayland_exporter
 19+{
 20+    struct wld_exporter base;
 21+    struct wl_buffer * buffer;
 22+};
 23+
 24 static void sync_done(void * data, struct wl_callback * callback,
 25                       uint32_t msecs);
 26 
 27@@ -63,6 +70,8 @@ static void buffer_release(void * data, struct wl_buffer * buffer);
 28 
 29 #define DRAWABLE_IMPLEMENTS_REGION
 30 #include "interface/drawable.h"
 31+#include "interface/exporter.h"
 32+IMPL(wayland, exporter)
 33 
 34 const struct wl_callback_listener sync_listener = {
 35     .done = &sync_done
 36@@ -162,7 +171,7 @@ struct wld_wayland_context * wld_wayland_create_context
 37 EXPORT
 38 void wld_wayland_destroy_context(struct wld_wayland_context * wayland)
 39 {
 40-    wayland->interface->destroy_context(wayland->context);
 41+    wld_destroy_context(wayland->context);
 42     free(wayland);
 43 }
 44 
 45@@ -172,6 +181,7 @@ struct wld_drawable * wld_wayland_create_drawable
 46      uint32_t width, uint32_t height, uint32_t format, uint32_t damage_flags)
 47 {
 48     struct wayland_drawable * wayland;
 49+    union wld_object object;
 50 
 51     wayland = malloc(sizeof *wayland);
 52 
 53@@ -179,18 +189,34 @@ struct wld_drawable * wld_wayland_create_drawable
 54         goto error0;
 55 
 56     wayland->context = context;
 57-    wayland->buffers[0].drawable = context->interface->create_drawable
 58-        (context->context, width, height, format, &wayland->buffers[0].wl);
 59+    wayland->buffers[0].drawable = wld_create_drawable(context->context,
 60+                                                       width, height, format);
 61 
 62     if (!wayland->buffers[0].drawable)
 63         goto error1;
 64 
 65-    wayland->buffers[1].drawable = context->interface->create_drawable
 66-        (context->context, width, height, format, &wayland->buffers[1].wl);
 67+    wayland->buffers[1].drawable = wld_create_drawable(context->context,
 68+                                                       width, height, format);
 69 
 70     if (!wayland->buffers[1].drawable)
 71         goto error2;
 72 
 73+    if (!wld_export(wayland->buffers[0].drawable,
 74+                    WLD_WAYLAND_OBJECT_BUFFER, &object))
 75+    {
 76+        goto error3;
 77+    }
 78+
 79+    wayland->buffers[0].wl = object.ptr;
 80+
 81+    if (!wld_export(wayland->buffers[1].drawable,
 82+                    WLD_WAYLAND_OBJECT_BUFFER, &object))
 83+    {
 84+        goto error3;
 85+    }
 86+
 87+    wayland->buffers[1].wl = object.ptr;
 88+
 89     wayland->buffers[0].busy = false;
 90     wayland->buffers[1].busy = false;
 91     pixman_region32_init(&wayland->buffers[0].damage);
 92@@ -210,6 +236,8 @@ struct wld_drawable * wld_wayland_create_drawable
 93 
 94     return &wayland->base;
 95 
 96+  error3:
 97+    wld_destroy_drawable(wayland->buffers[1].drawable);
 98   error2:
 99     wld_destroy_drawable(wayland->buffers[0].drawable);
100   error1:
101@@ -253,6 +281,41 @@ int wayland_roundtrip(struct wl_display * display,
102     return ret;
103 }
104 
105+struct wld_exporter * wayland_create_exporter(struct wl_buffer * buffer)
106+{
107+    struct wayland_exporter * exporter;
108+
109+    if (!(exporter = malloc(sizeof *exporter)))
110+        return NULL;
111+
112+    exporter_initialize(&exporter->base, &exporter_impl);
113+    exporter->buffer = buffer;
114+
115+    return &exporter->base;
116+}
117+
118+bool exporter_export(struct wld_exporter * base, struct wld_drawable * drawable,
119+                     uint32_t type, union wld_object * object)
120+{
121+    struct wayland_exporter * exporter = wayland_exporter(base);
122+
123+    switch (type)
124+    {
125+        case WLD_WAYLAND_OBJECT_BUFFER:
126+            object->ptr = exporter->buffer;
127+            return true;
128+        default: return false;
129+    }
130+}
131+
132+void exporter_destroy(struct wld_exporter * base)
133+{
134+    struct wayland_exporter * exporter = wayland_exporter(base);
135+
136+    wl_buffer_destroy(exporter->buffer);
137+    free(exporter);
138+}
139+
140 void sync_done(void * data, struct wl_callback * callback, uint32_t msecs)
141 {
142     bool * done = data;
+5, -0
 1@@ -48,6 +48,11 @@ enum wld_wayland_interface_id
 2     WLD_SHM
 3 };
 4 
 5+enum wld_wayland_object_type
 6+{
 7+    WLD_WAYLAND_OBJECT_BUFFER   = 0x00020000
 8+};
 9+
10 enum wld_wayland_damage_flags
11 {
12     /**