commit 3b8db51

Michael Forney  ·  2014-02-06 08:56:18 +0000 UTC
parent 3a416f3
Split exporters into destructors
12 files changed,  +179, -225
M dumb.c
M wld.h
+16, -13
 1@@ -37,17 +37,10 @@ void buffer_initialize(struct buffer * buffer,
 2     buffer->references = 1;
 3     buffer->map_references = 0;
 4     buffer->exporters = NULL;
 5+    buffer->destructors = NULL;
 6     pixman_region32_init_rect(&buffer->base.damage, 0, 0, width, height);
 7 }
 8 
 9-EXPORT
10-void wld_exporter_initialize(struct wld_exporter * exporter,
11-                             const struct wld_exporter_impl * impl)
12-{
13-    *((const struct wld_exporter_impl **) &exporter->impl) = impl;
14-    exporter->next = NULL;
15-}
16-
17 EXPORT
18 bool wld_map(struct wld_buffer * base)
19 {
20@@ -84,7 +77,7 @@ bool wld_export(struct wld_buffer * base,
21 
22     for (exporter = buffer->exporters; exporter; exporter = exporter->next)
23     {
24-        if (exporter->impl->export(exporter, &buffer->base, type, object))
25+        if (exporter->export(exporter, &buffer->base, type, object))
26             return true;
27     }
28 
29@@ -101,6 +94,16 @@ void wld_buffer_add_exporter(struct wld_buffer * base,
30     buffer->exporters = exporter;
31 }
32 
33+EXPORT
34+void wld_buffer_add_destructor(struct wld_buffer * base,
35+                               struct wld_destructor * destructor)
36+{
37+    struct buffer * buffer = (void *) base;
38+
39+    destructor->next = buffer->destructors;
40+    buffer->destructors = destructor;
41+}
42+
43 EXPORT
44 void wld_buffer_reference(struct wld_buffer * base)
45 {
46@@ -113,7 +116,7 @@ EXPORT
47 void wld_buffer_unreference(struct wld_buffer * base)
48 {
49     struct buffer * buffer = (void *) base;
50-    struct wld_exporter * exporter, * next;
51+    struct wld_destructor * destructor, * next;
52 
53     if (--buffer->references > 0)
54         return;
55@@ -123,10 +126,10 @@ void wld_buffer_unreference(struct wld_buffer * base)
56 
57     pixman_region32_fini(&buffer->base.damage);
58 
59-    for (exporter = buffer->exporters, next = exporter ? exporter->next : NULL;
60-         exporter; exporter = next, next = exporter ? exporter->next : NULL)
61+    for (destructor = buffer->destructors; destructor; destructor = next)
62     {
63-        exporter->impl->destroy(exporter);
64+        next = destructor->next;
65+        destructor->destroy(destructor);
66     }
67 
68     buffer->base.impl->destroy(buffer);
M dumb.c
+34, -41
  1@@ -48,7 +48,6 @@ struct dumb_buffer
  2 
  3 #include "interface/context.h"
  4 #include "interface/buffer.h"
  5-#include "interface/exporter.h"
  6 #define DRM_DRIVER_NAME dumb
  7 #include "interface/drm.h"
  8 IMPL(dumb_context, wld_context)
  9@@ -79,6 +78,39 @@ struct wld_renderer * context_create_renderer(struct wld_context * context)
 10     return wld_create_renderer(wld_pixman_context);
 11 }
 12 
 13+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
 14+                   uint32_t type, union wld_object * object)
 15+{
 16+    struct dumb_buffer * buffer = dumb_buffer(base);
 17+
 18+    switch (type)
 19+    {
 20+        case WLD_DRM_OBJECT_HANDLE:
 21+            object->u32 = buffer->handle;
 22+            return true;
 23+        case WLD_DRM_OBJECT_PRIME_FD:
 24+            if (drmPrimeHandleToFD(buffer->context->fd, buffer->handle,
 25+                                   DRM_CLOEXEC, &object->i) != 0)
 26+            {
 27+                return false;
 28+            }
 29+
 30+            return true;
 31+        case WLD_DRM_OBJECT_GEM_NAME:
 32+        {
 33+            struct drm_gem_flink flink = { .handle = buffer->handle };
 34+
 35+            if (drmIoctl(buffer->context->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
 36+                return false;
 37+
 38+            object->u32 = flink.name;
 39+            return true;
 40+        }
 41+        default:
 42+            return false;
 43+    }
 44+}
 45+
 46 static struct buffer * new_buffer(struct dumb_context * context,
 47                                   uint32_t width, uint32_t height,
 48                                   uint32_t format, uint32_t handle,
 49@@ -93,7 +125,7 @@ static struct buffer * new_buffer(struct dumb_context * context,
 50                       width, height, format, pitch);
 51     buffer->context = context;
 52     buffer->handle = handle;
 53-    wld_exporter_initialize(&buffer->exporter, &wld_exporter_impl);
 54+    buffer->exporter.export = &export;
 55     wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
 56 
 57     return &buffer->base;
 58@@ -221,42 +253,3 @@ void buffer_destroy(struct buffer * base)
 59     free(buffer);
 60 }
 61 
 62-/**** Exporter ****/
 63-
 64-bool exporter_export(struct wld_exporter * exporter, struct wld_buffer * base,
 65-                     uint32_t type, union wld_object * object)
 66-{
 67-    struct dumb_buffer * buffer = dumb_buffer(base);
 68-
 69-    switch (type)
 70-    {
 71-        case WLD_DRM_OBJECT_HANDLE:
 72-            object->u32 = buffer->handle;
 73-            return true;
 74-        case WLD_DRM_OBJECT_PRIME_FD:
 75-            if (drmPrimeHandleToFD(buffer->context->fd, buffer->handle,
 76-                                   DRM_CLOEXEC, &object->i) != 0)
 77-            {
 78-                return false;
 79-            }
 80-
 81-            return true;
 82-        case WLD_DRM_OBJECT_GEM_NAME:
 83-        {
 84-            struct drm_gem_flink flink = { .handle = buffer->handle };
 85-
 86-            if (drmIoctl(buffer->context->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
 87-                return false;
 88-
 89-            object->u32 = flink.name;
 90-            return true;
 91-        }
 92-        default:
 93-            return false;
 94-    }
 95-}
 96-
 97-void exporter_destroy(struct wld_exporter * exporter)
 98-{
 99-}
100-
+24, -30
 1@@ -54,7 +54,6 @@ struct intel_buffer
 2 #include "interface/context.h"
 3 #include "interface/renderer.h"
 4 #include "interface/buffer.h"
 5-#include "interface/exporter.h"
 6 #define DRM_DRIVER_NAME intel
 7 #include "interface/drm.h"
 8 IMPL(intel_context, wld_context)
 9@@ -112,6 +111,29 @@ struct wld_renderer * context_create_renderer(struct wld_context * base)
10     return NULL;
11 }
12 
13+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
14+                   uint32_t type, union wld_object * object)
15+{
16+    struct intel_buffer * buffer = intel_buffer(base);
17+
18+    switch (type)
19+    {
20+        case WLD_DRM_OBJECT_HANDLE:
21+            object->u32 = buffer->bo->handle;
22+            return true;
23+        case WLD_DRM_OBJECT_PRIME_FD:
24+            if (drm_intel_bo_gem_export_to_prime(buffer->bo, &object->i) != 0)
25+                return false;
26+            return true;
27+        case WLD_DRM_OBJECT_GEM_NAME:
28+            if (drm_intel_bo_flink(buffer->bo, &object->u32) != 0)
29+                return false;
30+            return true;
31+        default:
32+            return false;
33+    }
34+}
35+
36 static struct buffer * new_buffer(uint32_t width, uint32_t height,
37                                   uint32_t format, uint32_t pitch,
38                                   drm_intel_bo * bo)
39@@ -124,7 +146,7 @@ static struct buffer * new_buffer(uint32_t width, uint32_t height,
40     buffer_initialize(&buffer->base, &wld_buffer_impl,
41                       width, height, format, pitch);
42     buffer->bo = bo;
43-    wld_exporter_initialize(&buffer->exporter, &wld_exporter_impl);
44+    buffer->exporter.export = &export;
45     wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
46 
47     return &buffer->base;
48@@ -371,31 +393,3 @@ void buffer_destroy(struct buffer * base)
49     free(buffer);
50 }
51 
52-/**** Exporter ****/
53-bool exporter_export(struct wld_exporter * exporter, struct wld_buffer * base,
54-                     uint32_t type, union wld_object * object)
55-{
56-    struct intel_buffer * buffer = intel_buffer(base);
57-
58-    switch (type)
59-    {
60-        case WLD_DRM_OBJECT_HANDLE:
61-            object->u32 = buffer->bo->handle;
62-            return true;
63-        case WLD_DRM_OBJECT_PRIME_FD:
64-            if (drm_intel_bo_gem_export_to_prime(buffer->bo, &object->i) != 0)
65-                return false;
66-            return true;
67-        case WLD_DRM_OBJECT_GEM_NAME:
68-            if (drm_intel_bo_flink(buffer->bo, &object->u32) != 0)
69-                return false;
70-            return true;
71-        default:
72-            return false;
73-    }
74-}
75-
76-void exporter_destroy(struct wld_exporter * exporter)
77-{
78-}
79-
+0, -33
 1@@ -1,33 +0,0 @@
 2-/* wld: interface/exporter.h
 3- *
 4- * Copyright (c) 2013, 2014 Michael Forney
 5- *
 6- * Permission is hereby granted, free of charge, to any person obtaining a copy
 7- * of this software and associated documentation files (the "Software"), to deal
 8- * in the Software without restriction, including without limitation the rights
 9- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10- * copies of the Software, and to permit persons to whom the Software is
11- * furnished to do so, subject to the following conditions:
12- *
13- * The above copyright notice and this permission notice shall be included in
14- * all copies or substantial portions of the Software.
15- *
16- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22- * SOFTWARE.
23- */
24-
25-static void exporter_destroy(struct wld_exporter * exporter);
26-static bool exporter_export(struct wld_exporter * exporter,
27-                            struct wld_buffer * buffer,
28-                            uint32_t type, union wld_object * object);
29-
30-static const struct wld_exporter_impl wld_exporter_impl = {
31-    .destroy = &exporter_destroy,
32-    .export = &exporter_export
33-};
34-
+24, -30
 1@@ -75,7 +75,6 @@ struct nouveau_buffer
 2 #include "interface/buffer.h"
 3 #define DRM_DRIVER_NAME nouveau
 4 #include "interface/drm.h"
 5-#include "interface/exporter.h"
 6 IMPL(nouveau_context, wld_context)
 7 IMPL(nouveau_renderer, wld_renderer)
 8 IMPL(nouveau_buffer, wld_buffer)
 9@@ -298,6 +297,29 @@ struct wld_renderer * context_create_renderer(struct wld_context * base)
10     return NULL;
11 }
12 
13+static bool export(struct wld_exporter * exporter, struct wld_buffer * base,
14+                   uint32_t type, union wld_object * object)
15+{
16+    struct nouveau_buffer * buffer = nouveau_buffer(base);
17+
18+    switch (type)
19+    {
20+        case WLD_DRM_OBJECT_HANDLE:
21+            object->u32 = buffer->bo->handle;
22+            return true;
23+        case WLD_DRM_OBJECT_PRIME_FD:
24+            if (nouveau_bo_set_prime(buffer->bo, &object->i) != 0)
25+                return false;
26+            return true;
27+        case WLD_DRM_OBJECT_GEM_NAME:
28+            if (nouveau_bo_name_get(buffer->bo, &object->u32) != 0)
29+                return false;
30+            return true;
31+        default:
32+            return false;
33+    }
34+}
35+
36 static struct nouveau_buffer * new_buffer(struct nouveau_context * context,
37                                           uint32_t width, uint32_t height,
38                                           uint32_t format, uint32_t pitch)
39@@ -310,7 +332,7 @@ static struct nouveau_buffer * new_buffer(struct nouveau_context * context,
40     buffer_initialize(&buffer->base, &wld_buffer_impl,
41                         width, height, format, pitch);
42     buffer->context = context;
43-    wld_exporter_initialize(&buffer->exporter, &wld_exporter_impl);
44+    buffer->exporter.export = &export;
45     wld_buffer_add_exporter(&buffer->base.base, &buffer->exporter);
46 
47     return buffer;
48@@ -658,31 +680,3 @@ void buffer_destroy(struct buffer * base)
49     free(buffer);
50 }
51 
52-/**** Exporter ****/
53-bool exporter_export(struct wld_exporter * exporter, struct wld_buffer * base,
54-                     uint32_t type, union wld_object * object)
55-{
56-    struct nouveau_buffer * buffer = nouveau_buffer(base);
57-
58-    switch (type)
59-    {
60-        case WLD_DRM_OBJECT_HANDLE:
61-            object->u32 = buffer->bo->handle;
62-            return true;
63-        case WLD_DRM_OBJECT_PRIME_FD:
64-            if (nouveau_bo_set_prime(buffer->bo, &object->i) != 0)
65-                return false;
66-            return true;
67-        case WLD_DRM_OBJECT_GEM_NAME:
68-            if (nouveau_bo_name_get(buffer->bo, &object->u32) != 0)
69-                return false;
70-            return true;
71-        default:
72-            return false;
73-    }
74-}
75-
76-void exporter_destroy(struct wld_exporter * exporter)
77-{
78-}
79-
+35, -33
  1@@ -44,9 +44,10 @@ struct pixman_buffer
  2     pixman_image_t * image;
  3 };
  4 
  5-struct pixman_exporter
  6+struct pixman_map
  7 {
  8-    struct wld_exporter base;
  9+    struct wld_exporter exporter;
 10+    struct wld_destructor destructor;
 11     pixman_image_t * image;
 12 };
 13 
 14@@ -54,10 +55,8 @@ struct pixman_exporter
 15 #define RENDERER_IMPLEMENTS_REGION
 16 #include "interface/renderer.h"
 17 #include "interface/buffer.h"
 18-#include "interface/exporter.h"
 19 IMPL(pixman_renderer, wld_renderer)
 20 IMPL(pixman_buffer, wld_buffer)
 21-IMPL(pixman_exporter, wld_exporter)
 22 
 23 static struct wld_context context = { .impl = &wld_context_impl };
 24 
 25@@ -178,6 +177,31 @@ static void destroy_image(pixman_image_t * image, void * data)
 26     wld_unmap(&buffer->base);
 27 }
 28 
 29+bool map_export(struct wld_exporter * exporter, struct wld_buffer * buffer,
 30+                uint32_t type, union wld_object * object)
 31+{
 32+    struct pixman_map * map
 33+        = CONTAINER_OF(exporter, struct pixman_map, exporter);
 34+
 35+    switch (type)
 36+    {
 37+        case WLD_PIXMAN_OBJECT_IMAGE:
 38+            object->ptr = pixman_image_ref(map->image);
 39+            return true;
 40+        default:
 41+            return false;
 42+    }
 43+}
 44+
 45+void map_destroy(struct wld_destructor * destructor)
 46+{
 47+    struct pixman_map * map
 48+        = CONTAINER_OF(destructor, struct pixman_map, destructor);
 49+
 50+    pixman_image_unref(map->image);
 51+    free(map);
 52+}
 53+
 54 static pixman_image_t * pixman_image(struct buffer * buffer)
 55 {
 56     if (buffer->base.impl == &wld_buffer_impl)
 57@@ -188,7 +212,7 @@ static pixman_image_t * pixman_image(struct buffer * buffer)
 58     if (wld_export(&buffer->base, WLD_PIXMAN_OBJECT_IMAGE, &object))
 59         return object.ptr;
 60 
 61-    struct pixman_exporter * exporter;
 62+    struct pixman_map * map;
 63     pixman_image_t * image;
 64 
 65     if (!wld_map(&buffer->base))
 66@@ -201,12 +225,14 @@ static pixman_image_t * pixman_image(struct buffer * buffer)
 67     if (!image)
 68         goto error1;
 69 
 70-    if (!(exporter = malloc(sizeof *exporter)))
 71+    if (!(map = malloc(sizeof *map)))
 72         goto error2;
 73 
 74-    wld_exporter_initialize(&exporter->base, &wld_exporter_impl);
 75-    exporter->image = image;
 76-    wld_buffer_add_exporter(&buffer->base, &exporter->base);
 77+    map->image = image;
 78+    map->exporter.export = &map_export;
 79+    wld_buffer_add_exporter(&buffer->base, &map->exporter);
 80+    map->destructor.destroy = &map_destroy;
 81+    wld_buffer_add_destructor(&buffer->base, &map->destructor);
 82     pixman_image_set_destroy_function(image, &destroy_image, buffer);
 83 
 84     return pixman_image_ref(image);
 85@@ -422,27 +448,3 @@ void buffer_destroy(struct buffer * base)
 86     free(buffer);
 87 }
 88 
 89-/**** Exporter ****/
 90-bool exporter_export(struct wld_exporter * base, struct wld_buffer * buffer,
 91-                     uint32_t type, union wld_object * object)
 92-{
 93-    struct pixman_exporter * exporter = pixman_exporter(base);
 94-
 95-    switch (type)
 96-    {
 97-        case WLD_PIXMAN_OBJECT_IMAGE:
 98-            object->ptr = pixman_image_ref(exporter->image);
 99-            return true;
100-        default:
101-            return false;
102-    }
103-}
104-
105-void exporter_destroy(struct wld_exporter * base)
106-{
107-    struct pixman_exporter * exporter = pixman_exporter(base);
108-
109-    pixman_image_unref(exporter->image);
110-    free(exporter);
111-}
112-
+1, -4
 1@@ -195,7 +195,6 @@ struct buffer * context_create_buffer(struct wld_context * base,
 2 {
 3     struct drm_context * context = drm_context(base);
 4     struct buffer * buffer;
 5-    struct wld_exporter * exporter;
 6     union wld_object object;
 7     struct wl_buffer * wl;
 8 
 9@@ -218,11 +217,9 @@ struct buffer * context_create_buffer(struct wld_context * base,
10     if (!wl)
11         goto error1;
12 
13-    if (!(exporter = wayland_create_exporter(wl)))
14+    if (!wayland_buffer_add_exporter(buffer, wl))
15         goto error2;
16 
17-    wld_buffer_add_exporter(&buffer->base, exporter);
18-
19     return buffer;
20 
21   error2:
+2, -1
 1@@ -26,6 +26,7 @@
 2 
 3 #include "wld.h"
 4 
 5+struct buffer;
 6 struct wl_display;
 7 struct wl_event_queue;
 8 struct wl_buffer;
 9@@ -57,7 +58,7 @@ extern const struct wld_wayland_interface wayland_shm_interface;
10 int wayland_roundtrip(struct wl_display * display,
11                       struct wl_event_queue * queue);
12 
13-struct wld_exporter * wayland_create_exporter(struct wl_buffer * buffer);
14+bool wayland_buffer_add_exporter(struct buffer * buffer, struct wl_buffer * wl);
15 
16 #endif
17 
+3, -5
 1@@ -164,7 +164,6 @@ struct buffer * context_create_buffer(struct wld_context * base,
 2 {
 3     struct shm_context * context = shm_context(base);
 4     struct shm_buffer * buffer;
 5-    struct wld_exporter * exporter;
 6     char name[] = "/tmp/wld-XXXXXX";
 7     uint32_t pitch = width * format_bytes_per_pixel(format);
 8     size_t size = pitch * height;
 9@@ -195,13 +194,12 @@ struct buffer * context_create_buffer(struct wld_context * base,
10     if (!wl)
11         goto error2;
12 
13-    if (!(exporter = wayland_create_exporter(wl)))
14-        goto error3;
15-
16     buffer_initialize(&buffer->base, &wld_buffer_impl,
17                       width, height, format, pitch);
18     buffer->fd = fd;
19-    wld_buffer_add_exporter(&buffer->base.base, exporter);
20+
21+    if (!(wayland_buffer_add_exporter(&buffer->base, wl)))
22+        goto error3;
23 
24     return &buffer->base;
25 
+31, -27
 1@@ -28,10 +28,11 @@
 2 #include <stdlib.h>
 3 #include <wayland-client.h>
 4 
 5-struct wayland_exporter
 6+struct wayland_buffer
 7 {
 8-    struct wld_exporter base;
 9-    struct wl_buffer * buffer;
10+    struct wld_exporter exporter;
11+    struct wld_destructor destructor;
12+    struct wl_buffer * wl;
13 };
14 
15 struct wayland_buffer_socket
16@@ -44,9 +45,6 @@ struct wayland_buffer_socket
17     struct wl_event_queue * queue;
18 };
19 
20-#include "interface/exporter.h"
21-IMPL(wayland_exporter, wld_exporter)
22-
23 static bool buffer_socket_attach(struct buffer_socket * socket,
24                                  struct buffer * buffer);
25 static void buffer_socket_process(struct buffer_socket * socket);
26@@ -205,39 +203,45 @@ int wayland_roundtrip(struct wl_display * display,
27     return ret;
28 }
29 
30-struct wld_exporter * wayland_create_exporter(struct wl_buffer * buffer)
31-{
32-    struct wayland_exporter * exporter;
33-
34-    if (!(exporter = malloc(sizeof *exporter)))
35-        return NULL;
36-
37-    wld_exporter_initialize(&exporter->base, &wld_exporter_impl);
38-    exporter->buffer = buffer;
39-
40-    return &exporter->base;
41-}
42-
43-bool exporter_export(struct wld_exporter * base, struct wld_buffer * buffer,
44-                     uint32_t type, union wld_object * object)
45+static bool buffer_export(struct wld_exporter * exporter,
46+                          struct wld_buffer * buffer,
47+                          uint32_t type, union wld_object * object)
48 {
49-    struct wayland_exporter * exporter = wayland_exporter(base);
50+    struct wayland_buffer * wayland_buffer
51+        = CONTAINER_OF(exporter, struct wayland_buffer, exporter);
52 
53     switch (type)
54     {
55         case WLD_WAYLAND_OBJECT_BUFFER:
56-            object->ptr = exporter->buffer;
57+            object->ptr = wayland_buffer->wl;
58             return true;
59         default: return false;
60     }
61 }
62 
63-void exporter_destroy(struct wld_exporter * base)
64+static void buffer_destroy(struct wld_destructor * destructor)
65 {
66-    struct wayland_exporter * exporter = wayland_exporter(base);
67+    struct wayland_buffer * wayland_buffer
68+        = CONTAINER_OF(destructor, struct wayland_buffer, destructor);
69 
70-    wl_buffer_destroy(exporter->buffer);
71-    free(exporter);
72+    wl_buffer_destroy(wayland_buffer->wl);
73+    free(wayland_buffer);
74+}
75+
76+bool wayland_buffer_add_exporter(struct buffer * buffer, struct wl_buffer * wl)
77+{
78+    struct wayland_buffer * wayland_buffer;
79+
80+    if (!(wayland_buffer = malloc(sizeof *wayland_buffer)))
81+        return false;
82+
83+    wayland_buffer->wl = wl;
84+    wayland_buffer->exporter.export = &buffer_export;
85+    wld_buffer_add_exporter(&buffer->base, &wayland_buffer->exporter);
86+    wayland_buffer->destructor.destroy = &buffer_destroy;
87+    wld_buffer_add_destructor(&buffer->base, &wayland_buffer->destructor);
88+
89+    return true;
90 }
91 
92 bool buffer_socket_attach(struct buffer_socket * base, struct buffer * buffer)
+1, -0
1@@ -127,6 +127,7 @@ struct buffer
2 
3     unsigned references, map_references;
4     struct wld_exporter * exporters;
5+    struct wld_destructor * destructors;
6 };
7 
8 struct wld_buffer_impl
M wld.h
+8, -8
 1@@ -157,20 +157,17 @@ static inline void wld_font_text_extents(struct wld_font * font,
 2 
 3 struct wld_exporter
 4 {
 5-    const struct wld_exporter_impl * const impl;
 6+    bool (* export)(struct wld_exporter * exporter, struct wld_buffer * buffer,
 7+                    uint32_t type, union wld_object * object);
 8     struct wld_exporter * next;
 9 };
10 
11-struct wld_exporter_impl
12+struct wld_destructor
13 {
14-    bool (* export)(struct wld_exporter * exporter, struct wld_buffer * buffer,
15-                    uint32_t type, union wld_object * object);
16-    void (* destroy)(struct wld_exporter * exporter);
17+    void (* destroy)(struct wld_destructor * destructor);
18+    struct wld_destructor * next;
19 };
20 
21-void wld_exporter_initialize(struct wld_exporter * exporter,
22-                             const struct wld_exporter_impl * impl);
23-
24 struct wld_buffer
25 {
26     const struct wld_buffer_impl * const impl;
27@@ -190,6 +187,9 @@ bool wld_export(struct wld_buffer * buffer,
28 void wld_buffer_add_exporter(struct wld_buffer * buffer,
29                              struct wld_exporter * exporter);
30 
31+void wld_buffer_add_destructor(struct wld_buffer * buffer,
32+                               struct wld_destructor * destructor);
33+
34 /**
35  * Increase the reference count of a buffer.
36  */