commit f61ad4e

Michael Forney  ·  2014-01-01 06:53:22 +0000 UTC
parent 6fb42cc
Add context abstraction
16 files changed,  +346, -275
M drm.c
M drm.h
M dumb.c
M wld.h
+1, -1
1@@ -15,7 +15,7 @@ CLEAN_FILES     := $(TARGETS)
2 
3 WLD_REQUIRES = fontconfig pixman-1
4 WLD_REQUIRES_PRIVATE = freetype2
5-WLD_SOURCES = drawable.c color.c font.c
6+WLD_SOURCES = context.c drawable.c color.c font.c
7 WLD_HEADERS = wld.h
8 
9 ifeq ($(ENABLE_DEBUG),1)
+55, -0
 1@@ -0,0 +1,55 @@
 2+/* wld: context.c
 3+ *
 4+ * Copyright (c) 2013 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+#include "wld-private.h"
26+
27+void context_initialize(struct wld_context * context,
28+                        const struct wld_context_impl * impl)
29+{
30+    *((const struct wld_context_impl **) &context->impl) = impl;
31+}
32+
33+EXPORT
34+struct wld_drawable * wld_create_drawable(struct wld_context * context,
35+                                          uint32_t width, uint32_t height,
36+                                          uint32_t format)
37+{
38+    return context->impl->create_drawable(context, width, height, format);
39+}
40+
41+EXPORT
42+struct wld_drawable * wld_import(struct wld_context * context,
43+                                 uint32_t type, union wld_object object,
44+                                 uint32_t width, uint32_t height,
45+                                 uint32_t format, uint32_t pitch)
46+{
47+    return context->impl->import(context, type, object,
48+                                 width, height, format, pitch);
49+}
50+
51+EXPORT
52+void wld_destroy_context(struct wld_context * context)
53+{
54+    context->impl->destroy(context);
55+}
56+
+3, -28
 1@@ -26,30 +26,13 @@
 2 
 3 #include "wld-private.h"
 4 
 5-typedef bool (* drm_device_supported_func_t)(uint32_t vendor_id,
 6-                                             uint32_t device_id);
 7-typedef void * (* drm_create_context_func_t)(int drm_fd);
 8-typedef void (* drm_destroy_context_func_t)(void * context);
 9-typedef struct wld_drawable * (* drm_create_drawable_func_t)
10-    (void * context, uint32_t width, uint32_t height, uint32_t format);
11-typedef struct wld_drawable * (* drm_import_func_t)
12-    (void * context, uint32_t width, uint32_t height, uint32_t format,
13-     int prime_fd, unsigned long pitch);
14-typedef struct wld_drawable * (* drm_import_gem_func_t)
15-    (void * context, uint32_t width, uint32_t height, uint32_t format,
16-     uint32_t gem_name, unsigned long pitch);
17-
18 typedef int (* drm_export_func_t)(struct wld_drawable * drawable);
19 typedef uint32_t (* drm_get_handle_func_t)(struct wld_drawable * drawable);
20 
21 struct wld_drm_interface
22 {
23-    drm_device_supported_func_t device_supported;
24-    drm_create_context_func_t create_context;
25-    drm_destroy_context_func_t destroy_context;
26-    drm_create_drawable_func_t create_drawable;
27-    drm_import_func_t import;
28-    drm_import_gem_func_t import_gem;
29+    bool (* device_supported)(uint32_t vendor_id, uint32_t device_id);
30+    struct wld_context * (* create_context)(int drm_fd);
31 };
32 
33 struct drm_draw_interface
34@@ -59,19 +42,11 @@ struct drm_draw_interface
35     drm_get_handle_func_t get_handle;
36 };
37 
38-struct wld_drm_context
39-{
40-    const struct wld_drm_interface * interface;
41-    void * context;
42-};
43-
44 #if WITH_DRM_INTEL
45 extern const struct wld_drm_interface intel_drm;
46 #endif
47 extern const struct wld_drm_interface dumb_drm;
48-
49-bool drm_initialize_context(struct wld_drm_context * context, int fd);
50-void drm_finalize_context(struct wld_drm_context * context);
51+extern const struct wld_context_impl * dumb_context_impl;
52 
53 #endif
54 
M drm.c
+7, -66
 1@@ -68,80 +68,21 @@ static const struct wld_drm_interface * find_drm_interface(int fd)
 2     return NULL;
 3 }
 4 
 5-bool drm_initialize_context(struct wld_drm_context * drm, int fd)
 6-{
 7-    if (!(drm->interface = find_drm_interface(fd)))
 8-        return false;
 9-
10-    if (!(drm->context = drm->interface->create_context(fd)))
11-        return false;
12-
13-    return true;
14-}
15-
16-void drm_finalize_context(struct wld_drm_context * drm)
17-{
18-    drm->interface->destroy_context(drm->context);
19-}
20-
21-EXPORT
22-struct wld_drm_context * wld_drm_create_context(int fd)
23-{
24-    struct wld_drm_context * drm;
25-
26-    if (!(drm = malloc(sizeof *drm)))
27-        goto error0;
28-
29-    if (!drm_initialize_context(drm, fd))
30-        goto error1;
31-
32-    return drm;
33-
34-  error1:
35-    free(drm);
36-  error0:
37-    return NULL;
38-}
39-
40-EXPORT
41-void wld_drm_destroy_context(struct wld_drm_context * drm)
42-{
43-    drm_finalize_context(drm);
44-    free(drm);
45-}
46-
47 EXPORT
48-bool wld_drm_is_dumb(struct wld_drm_context * drm)
49+struct wld_context * wld_drm_create_context(int fd)
50 {
51-    return drm->interface == &dumb_drm;
52-}
53+    const struct wld_drm_interface * interface;
54 
55-EXPORT
56-struct wld_drawable * wld_drm_create_drawable(struct wld_drm_context * drm,
57-                                              uint32_t width, uint32_t height,
58-                                              uint32_t format)
59-{
60-    return drm->interface->create_drawable(drm->context, width, height, format);
61-}
62+    if (!(interface = find_drm_interface(fd)))
63+        return NULL;
64 
65-EXPORT
66-struct wld_drawable * wld_drm_import(struct wld_drm_context * drm,
67-                                     uint32_t width, uint32_t height,
68-                                     uint32_t format,
69-                                     int prime_fd, unsigned long pitch)
70-{
71-    return drm->interface->import(drm->context, width, height, format,
72-                                  prime_fd, pitch);
73+    return interface->create_context(fd);
74 }
75 
76 EXPORT
77-struct wld_drawable * wld_drm_import_gem(struct wld_drm_context * drm,
78-                                         uint32_t width, uint32_t height,
79-                                         uint32_t format,
80-                                         uint32_t gem_name, unsigned long pitch)
81+bool wld_drm_is_dumb(struct wld_context * context)
82 {
83-    return drm->interface->import_gem(drm->context, width, height, format,
84-                                      gem_name, pitch);
85+    return context->impl == dumb_context_impl;
86 }
87 
88 EXPORT
M drm.h
+8, -36
 1@@ -27,46 +27,18 @@
 2 #include <stdbool.h>
 3 #include <stdint.h>
 4 
 5-struct wld_drm_context;
 6-struct wld_drawable;
 7+enum wld_drm_object_type
 8+{
 9+    WLD_DRM_OBJECT_PRIME_FD = 0x00010000,
10+    WLD_DRM_OBJECT_GEM_NAME = 0x00010001
11+};
12 
13 /**
14- * Create a new DRM context from an opened DRM device file descriptor.
15+ * Create a new WLD context from an opened DRM device file descriptor.
16  */
17-struct wld_drm_context * wld_drm_create_context(int fd);
18+struct wld_context * wld_drm_create_context(int fd);
19 
20-/**
21- * Destroy a DRM context.
22- */
23-void wld_drm_destroy_context(struct wld_drm_context * drm);
24-
25-bool wld_drm_is_dumb(struct wld_drm_context * drm);
26-
27-/**
28- * Create a new DRM drawable.
29- */
30-struct wld_drawable * wld_drm_create_drawable(struct wld_drm_context * drm,
31-                                              uint32_t width, uint32_t height,
32-                                              uint32_t format);
33-
34-/**
35- * Create a new DRM drawable by importing a PRIME file descriptor.
36- */
37-struct wld_drawable * wld_drm_import(struct wld_drm_context * context,
38-                                     uint32_t width, uint32_t height,
39-                                     uint32_t format,
40-                                     int prime_fd, unsigned long pitch);
41-
42-/**
43- * Create a new DRM drawable by importing a GEM name.
44- *
45- * This is provided for compatibility with clients that don't support PRIME.
46- * You should use wld_drm_import_drawable and PRIME if possible.
47- */
48-struct wld_drawable * wld_drm_import_gem(struct wld_drm_context * context,
49-                                         uint32_t width, uint32_t height,
50-                                         uint32_t format, uint32_t gem_name,
51-                                         unsigned long pitch);
52+bool wld_drm_is_dumb(struct wld_context * context);
53 
54 /**
55  * Export a DRM drawable to a PRIME file descriptor.
M dumb.c
+31, -33
  1@@ -24,6 +24,7 @@
  2 #include "pixman.h"
  3 #include "pixman-private.h"
  4 #include "drm-private.h"
  5+#include "drm.h"
  6 
  7 #include <fcntl.h>
  8 #include <sys/mman.h>
  9@@ -33,7 +34,8 @@
 10 
 11 struct dumb_context
 12 {
 13-    struct wld_pixman_context * pixman;
 14+    struct wld_context base;
 15+    struct wld_context * pixman;
 16     int fd;
 17 };
 18 
 19@@ -45,7 +47,11 @@ struct dumb_drawable
 20 };
 21 
 22 #define DRM_DRIVER_NAME dumb
 23+#include "interface/context.h"
 24 #include "interface/drm.h"
 25+IMPL(dumb, context)
 26+
 27+const struct wld_context_impl * dumb_context_impl = &context_impl;
 28 
 29 /* DRM drawable */
 30 static int drawable_export(struct wld_drawable * drawable);
 31@@ -62,7 +68,7 @@ bool drm_device_supported(uint32_t vendor_id, uint32_t device_id)
 32     return true;
 33 }
 34 
 35-void * drm_create_context(int drm_fd)
 36+struct wld_context * drm_create_context(int drm_fd)
 37 {
 38     struct dumb_context * context;
 39 
 40@@ -72,6 +78,7 @@ void * drm_create_context(int drm_fd)
 41     if (!(context->pixman = wld_pixman_create_context()))
 42         goto error1;
 43 
 44+    context_initialize(&context->base, &context_impl);
 45     context->fd = drm_fd;
 46 
 47     if (!draw_initialized)
 48@@ -80,7 +87,7 @@ void * drm_create_context(int drm_fd)
 49         draw_initialized = true;
 50     }
 51 
 52-    return context;
 53+    return &context->base;
 54 
 55   error1:
 56     free(context);
 57@@ -88,14 +95,6 @@ void * drm_create_context(int drm_fd)
 58     return NULL;
 59 }
 60 
 61-void drm_destroy_context(void * base)
 62-{
 63-    struct dumb_context * context = base;
 64-
 65-    wld_pixman_destroy_context(context->pixman);
 66-    free(context);
 67-}
 68-
 69 static struct wld_drawable * new_drawable(struct dumb_context * context,
 70                                           uint32_t width, uint32_t height,
 71                                           uint32_t format, uint32_t handle,
 72@@ -141,11 +140,11 @@ static struct wld_drawable * new_drawable(struct dumb_context * context,
 73     return NULL;
 74 }
 75 
 76-struct wld_drawable * drm_create_drawable(void * base,
 77-                                          uint32_t width, uint32_t height,
 78-                                          uint32_t format)
 79+struct wld_drawable * context_create_drawable(struct  wld_context * base,
 80+                                              uint32_t width, uint32_t height,
 81+                                              uint32_t format)
 82 {
 83-    struct dumb_context * context = base;
 84+    struct dumb_context * context = dumb_context(base);
 85     struct wld_drawable * drawable;
 86     struct drm_mode_create_dumb create_dumb_arg = {
 87         .height = height, .width = width,
 88@@ -178,33 +177,32 @@ struct wld_drawable * drm_create_drawable(void * base,
 89     return NULL;
 90 }
 91 
 92-struct wld_drawable * drm_import(void * base, uint32_t width, uint32_t height,
 93-                                 uint32_t format, int prime_fd,
 94-                                 unsigned long pitch)
 95+struct wld_drawable * context_import(struct wld_context * base,
 96+                                     uint32_t type, union wld_object object,
 97+                                     uint32_t width, uint32_t height,
 98+                                     uint32_t format, uint32_t pitch)
 99 {
100-    struct dumb_context * context = base;
101-    int ret;
102+    struct dumb_context * context = dumb_context(base);
103     uint32_t handle;
104 
105-    ret = drmPrimeFDToHandle(context->fd, prime_fd, &handle);
106-
107-    if (ret != 0)
108-        goto error0;
109+    switch (type)
110+    {
111+        case WLD_DRM_OBJECT_PRIME_FD:
112+            if (drmPrimeFDToHandle(context->fd, object.i, &handle) != 0)
113+                return NULL;
114+            break;
115+        default: return NULL;
116+    }
117 
118     return new_drawable(context, width, height, format, handle, pitch);
119-
120-  error0:
121-    return NULL;
122 }
123 
124-struct wld_drawable * drm_import_gem(void * context,
125-                                     uint32_t width, uint32_t height,
126-                                     uint32_t format,
127-                                     uint32_t gem_name, unsigned long pitch)
128+void context_destroy(struct wld_context * base)
129 {
130-    DEBUG("dumb: import_gem is not supported\n");
131+    struct dumb_context * context = dumb_context(base);
132 
133-    return NULL;
134+    wld_destroy_context(context->pixman);
135+    free(context);
136 }
137 
138 static int drawable_export(struct wld_drawable * drawable)
+48, -38
  1@@ -22,6 +22,7 @@
  2  */
  3 
  4 #include "drm-private.h"
  5+#include "drm.h"
  6 #include "wld-private.h"
  7 
  8 #include <unistd.h>
  9@@ -31,6 +32,7 @@
 10 
 11 struct intel_context
 12 {
 13+    struct wld_context base;
 14     drm_intel_bufmgr * bufmgr;
 15     struct intel_batch * batch;
 16 };
 17@@ -44,16 +46,18 @@ struct intel_drawable
 18     pixman_image_t * virtual;
 19 };
 20 
 21+#include "interface/context.h"
 22 #define DRM_DRIVER_NAME intel
 23 #include "interface/drm.h"
 24 #include "interface/drm_drawable.h"
 25+IMPL(intel, context)
 26 
 27 bool drm_device_supported(uint32_t vendor_id, uint32_t device_id)
 28 {
 29     return vendor_id == 0x8086;
 30 }
 31 
 32-void * drm_create_context(int drm_fd)
 33+struct wld_context * drm_create_context(int drm_fd)
 34 {
 35     struct intel_context * context;
 36 
 37@@ -62,6 +66,7 @@ void * drm_create_context(int drm_fd)
 38     if (!context)
 39         goto error0;
 40 
 41+    context_initialize(&context->base, &context_impl);
 42     context->bufmgr = drm_intel_bufmgr_gem_init(drm_fd, INTEL_BATCH_SIZE);
 43 
 44     if (!context->bufmgr)
 45@@ -72,7 +77,7 @@ void * drm_create_context(int drm_fd)
 46     if (!context->batch)
 47         goto error2;
 48 
 49-    return context;
 50+    return &context->base;
 51 
 52   error2:
 53     drm_intel_bufmgr_destroy(context->bufmgr);
 54@@ -82,15 +87,6 @@ void * drm_create_context(int drm_fd)
 55     return NULL;
 56 }
 57 
 58-void drm_destroy_context(void * base)
 59-{
 60-    struct intel_context * context = base;
 61-
 62-    intel_batch_destroy(context->batch);
 63-    drm_intel_bufmgr_destroy(context->bufmgr);
 64-    free(context);
 65-}
 66-
 67 static struct intel_drawable * new_drawable(struct intel_context * context,
 68                                             uint32_t width, uint32_t height,
 69                                             uint32_t format)
 70@@ -110,11 +106,11 @@ static struct intel_drawable * new_drawable(struct intel_context * context,
 71     return intel;
 72 }
 73 
 74-struct wld_drawable * drm_create_drawable(void * base,
 75-                                          uint32_t width, uint32_t height,
 76-                                          uint32_t format)
 77+struct wld_drawable * context_create_drawable(struct wld_context * base,
 78+                                              uint32_t width, uint32_t height,
 79+                                              uint32_t format)
 80 {
 81-    struct intel_context * context = base;
 82+    struct intel_context * context = intel_context(base);
 83     struct intel_drawable * intel;
 84     uint32_t tiling_mode = width >= 128 ? I915_TILING_X : I915_TILING_NONE;
 85 
 86@@ -128,41 +124,55 @@ struct wld_drawable * drm_create_drawable(void * base,
 87     return &intel->base;
 88 }
 89 
 90-struct wld_drawable * drm_import(void * base,
 91-                                 uint32_t width, uint32_t height,
 92-                                 uint32_t format,
 93-                                 int prime_fd, unsigned long pitch)
 94+struct wld_drawable * context_import(struct wld_context * base,
 95+                                     uint32_t type, union wld_object object,
 96+                                     uint32_t width, uint32_t height,
 97+                                     uint32_t format, uint32_t pitch)
 98 {
 99-    struct intel_context * context = base;
100+    struct intel_context * context = intel_context(base);
101     struct intel_drawable * intel;
102-    uint32_t size = width * height * 4;
103+    drm_intel_bo * bo;
104+
105+    switch (type)
106+    {
107+        case WLD_DRM_OBJECT_PRIME_FD:
108+        {
109+            uint32_t size = width * height * format_bytes_per_pixel(format);
110+            bo = drm_intel_bo_gem_create_from_prime(context->bufmgr,
111+                                                    object.i, size);
112+            break;
113+        }
114+        case WLD_DRM_OBJECT_GEM_NAME:
115+            bo = drm_intel_bo_gem_create_from_name(context->bufmgr, "buffer",
116+                                                   object.u32);
117+            break;
118+        default: bo = NULL;
119+    };
120+
121+    if (!bo)
122+        goto error0;
123 
124     if (!(intel = new_drawable(context, width, height, format)))
125-        return NULL;
126+        goto error1;
127 
128-    intel->bo = drm_intel_bo_gem_create_from_prime(context->bufmgr,
129-                                                   prime_fd, size);
130+    intel->bo = bo;
131     intel->base.pitch = pitch;
132 
133     return &intel->base;
134+
135+  error1:
136+    drm_intel_bo_unreference(bo);
137+  error0:
138+    return NULL;
139 }
140 
141-struct wld_drawable * drm_import_gem(void * base,
142-                                     uint32_t width, uint32_t height,
143-                                     uint32_t format,
144-                                     uint32_t gem_name, unsigned long pitch)
145+void context_destroy(struct wld_context * base)
146 {
147-    struct intel_context * context = base;
148-    struct intel_drawable * intel;
149+    struct intel_context * context = intel_context(base);
150 
151-    if (!(intel = new_drawable(context, width, height, format)))
152-        return NULL;
153-
154-    intel->bo = drm_intel_bo_gem_create_from_name(context->bufmgr, "drawable",
155-                                                  gem_name);
156-    intel->base.pitch = pitch;
157-
158-    return &intel->base;
159+    intel_batch_destroy(context->batch);
160+    drm_intel_bufmgr_destroy(context->bufmgr);
161+    free(context);
162 }
163 
164 void drawable_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
+37, -0
 1@@ -0,0 +1,37 @@
 2+/* wld: interface/context.h
 3+ *
 4+ * Copyright (c) 2013 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 struct wld_drawable * context_create_drawable
26+    (struct wld_context * context,
27+     uint32_t width, uint32_t height, uint32_t format);
28+static struct wld_drawable * context_import
29+    (struct wld_context * context, uint32_t type, union wld_object object,
30+     uint32_t width, uint32_t height, uint32_t format, uint32_t pitch);
31+static void context_destroy(struct wld_context * context);
32+
33+static const struct wld_context_impl context_impl = {
34+    .create_drawable = &context_create_drawable,
35+    .import = &context_import,
36+    .destroy = &context_destroy
37+};
38+
+1, -16
 1@@ -27,28 +27,13 @@
 2 
 3 /* DRM implementation */
 4 static bool drm_device_supported(uint32_t vendor_id, uint32_t device_id);
 5-static void * drm_create_context(int drm_fd);
 6-static void drm_destroy_context(void * context);
 7-static struct wld_drawable * drm_create_drawable
 8-    (void * context, uint32_t width, uint32_t height, uint32_t format);
 9-static struct wld_drawable * drm_import(void * context,
10-                                        uint32_t width, uint32_t height,
11-                                        uint32_t format, int prime_fd,
12-                                        unsigned long pitch);
13-static struct wld_drawable * drm_import_gem(void * context,
14-                                            uint32_t width, uint32_t height,
15-                                            uint32_t format, uint32_t gem_name,
16-                                            unsigned long pitch);
17+static struct wld_context * drm_create_context(int drm_fd);
18 
19 #define EXPAND(f, x) f(x)
20 #define VAR(name) name ## _drm
21 const struct wld_drm_interface EXPAND(VAR, DRM_DRIVER_NAME) = {
22     .device_supported = &drm_device_supported,
23     .create_context = &drm_create_context,
24-    .destroy_context = &drm_destroy_context,
25-    .create_drawable = &drm_create_drawable,
26-    .import = &drm_import,
27-    .import_gem = &drm_import_gem,
28 };
29 #undef VAR
30 #undef EXPAND
+3, -3
 1@@ -26,19 +26,19 @@
 2 
 3 #include "wld.h"
 4 
 5-struct wld_pixman_context;
 6+struct wld_context;
 7 
 8 struct pixman_drawable
 9 {
10     struct wld_drawable base;
11     pixman_image_t * image;
12-    struct wld_pixman_context * context;
13+    struct pixman_context * context;
14 };
15 
16 extern const struct wld_draw_interface * const pixman_draw;
17 
18 bool pixman_initialize_drawable
19-    (struct wld_pixman_context * context, struct pixman_drawable * drawable,
20+    (struct wld_context * context, struct pixman_drawable * drawable,
21      uint32_t width, uint32_t height,
22      void * data, uint32_t pitch, uint32_t format);
23 
+79, -25
  1@@ -32,20 +32,22 @@
  2     .blue   = ((c >>  0) & 0xff) * 0x101,   \
  3 }
  4 
  5-struct wld_pixman_context
  6+struct pixman_context
  7 {
  8+    struct wld_context base;
  9     pixman_glyph_cache_t * glyph_cache;
 10 };
 11 
 12+#include "interface/context.h"
 13 #define DRAWABLE_IMPLEMENTS_REGION
 14 #include "interface/drawable.h"
 15 
 16 const struct wld_draw_interface * const pixman_draw = &draw_interface;
 17 
 18 EXPORT
 19-struct wld_pixman_context * wld_pixman_create_context()
 20+struct wld_context * wld_pixman_create_context()
 21 {
 22-    struct wld_pixman_context * context;
 23+    struct pixman_context * context;
 24 
 25     if (!(context = malloc(sizeof *context)))
 26         goto error0;
 27@@ -53,7 +55,7 @@ struct wld_pixman_context * wld_pixman_create_context()
 28     if (!(context->glyph_cache = pixman_glyph_cache_create()))
 29         goto error1;
 30 
 31-    return context;
 32+    return &context->base;
 33 
 34   error1:
 35     free(context);
 36@@ -61,15 +63,8 @@ struct wld_pixman_context * wld_pixman_create_context()
 37     return NULL;
 38 }
 39 
 40-EXPORT
 41-void wld_pixman_destroy_context(struct wld_pixman_context * context)
 42-{
 43-    pixman_glyph_cache_destroy(context->glyph_cache);
 44-    free(context);
 45-}
 46-
 47 bool pixman_initialize_drawable
 48-    (struct wld_pixman_context * context, struct pixman_drawable * drawable,
 49+    (struct wld_context * context, struct pixman_drawable * drawable,
 50      uint32_t width, uint32_t height,
 51      void * data, uint32_t pitch, uint32_t format)
 52 {
 53@@ -79,7 +74,7 @@ bool pixman_initialize_drawable
 54     drawable->base.format = format;
 55     drawable->base.pitch = pitch;
 56 
 57-    drawable->context = context;
 58+    drawable->context = (void *) context;
 59     drawable->image = pixman_image_create_bits(format_wld_to_pixman(format),
 60                                                width, height,
 61                                                (uint32_t *) data, pitch);
 62@@ -87,30 +82,89 @@ bool pixman_initialize_drawable
 63     return drawable->image != NULL;
 64 }
 65 
 66-EXPORT
 67-struct wld_drawable * wld_pixman_create_drawable
 68-    (struct wld_pixman_context * context, uint32_t width, uint32_t height,
 69-     void * data, uint32_t pitch, uint32_t format)
 70+struct wld_drawable * new_drawable(struct pixman_context * context,
 71+                                   pixman_image_t * image)
 72+{
 73+    struct pixman_drawable * drawable;
 74+
 75+    if (!(drawable = malloc(sizeof *drawable)))
 76+        return NULL;
 77+
 78+    drawable->base.interface = &draw_interface;
 79+    drawable->base.width = pixman_image_get_width(image);
 80+    drawable->base.height = pixman_image_get_height(image);
 81+    drawable->base.format = format_pixman_to_wld
 82+        (pixman_image_get_format(image));
 83+    drawable->base.pitch = pixman_image_get_stride(image);
 84+    drawable->context = context;
 85+    drawable->image = image;
 86+
 87+    return &drawable->base;
 88+}
 89+
 90+struct wld_drawable * context_create_drawable(struct wld_context * base,
 91+                                              uint32_t width, uint32_t height,
 92+                                              uint32_t format)
 93 {
 94-    struct pixman_drawable * pixman;
 95+    struct pixman_context * context = (void *) base;
 96+    struct wld_drawable * drawable;
 97+    pixman_image_t * image;
 98 
 99-    pixman = malloc(sizeof *pixman);
100+    image = pixman_image_create_bits(format_wld_to_pixman(format),
101+                                     width, height, NULL, 0);
102 
103-    if (!pixman)
104+    if (!image)
105         goto error0;
106 
107-    if (!pixman_initialize_drawable(context, pixman, width, height,
108-                                    data, pitch, format))
109-    {
110+    if (!(drawable = new_drawable(context, image)))
111         goto error1;
112+
113+    return drawable;
114+
115+  error1:
116+    pixman_image_unref(image);
117+  error0:
118+    return NULL;
119+}
120+
121+struct wld_drawable * context_import
122+    (struct wld_context * base, uint32_t type, union wld_object object,
123+     uint32_t width, uint32_t height, uint32_t format, uint32_t pitch)
124+{
125+    struct pixman_context * context = (void *) base;
126+    struct wld_drawable * drawable;
127+    pixman_image_t * image;
128+
129+    switch (type)
130+    {
131+        case WLD_OBJECT_DATA:
132+            image = pixman_image_create_bits(format_wld_to_pixman(format),
133+                                             width, height, object.ptr, pitch);
134+            break;
135+        default: image = NULL;
136     }
137 
138-    return &pixman->base;
139+    if (!image)
140+        goto error0;
141+
142+    if (!(drawable = new_drawable(context, image)))
143+        goto error1;
144+
145+    return drawable;
146 
147   error1:
148-    free(pixman);
149+    pixman_image_unref(image);
150   error0:
151     return NULL;
152+
153+}
154+
155+void context_destroy(struct wld_context * base)
156+{
157+    struct pixman_context * context = (void *) base;
158+
159+    pixman_glyph_cache_destroy(context->glyph_cache);
160+    free(context);
161 }
162 
163 void drawable_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
+2, -17
 1@@ -26,28 +26,13 @@
 2 
 3 #include <stdint.h>
 4 
 5-struct wld_pixman_context;
 6-struct wld_drawable;
 7+struct wld_context;
 8 
 9 /**
10  * Create a new drawing context which uses Pixman to do software rendering on
11  * buffers in memory.
12  */
13-struct wld_pixman_context * wld_pixman_create_context();
14-
15-/**
16- * Destroy a Pixman context.
17- */
18-void wld_pixman_destroy_context(struct wld_pixman_context * context);
19-
20-/**
21- * Create a new Pixman drawable with the specified dimensions.
22- *
23- * If data is NULL, new backing memory will be allocated.
24- */
25-struct wld_drawable * wld_pixman_create_drawable
26-    (struct wld_pixman_context * context, uint32_t width, uint32_t height,
27-     void * data, uint32_t pitch, uint32_t format);
28+struct wld_context * wld_pixman_create_context();
29 
30 #endif
31 
+7, -8
 1@@ -39,8 +39,7 @@
 2 
 3 struct wld_wayland_drm_context
 4 {
 5-    struct wld_drm_context context;
 6-
 7+    struct wld_context * driver_context;
 8     struct wl_drm * wl;
 9     struct wl_registry * registry;
10     struct wl_array formats;
11@@ -141,7 +140,7 @@ struct wld_wayland_drm_context * wld_wayland_drm_create_context
12         goto error4;
13     }
14 
15-    if (!drm_initialize_context(&drm->context, drm->fd))
16+    if (!(drm->driver_context = wld_drm_create_context(drm->fd)))
17     {
18         DEBUG("Couldn't initialize context for DRM device\n");
19         goto error4;
20@@ -165,7 +164,7 @@ struct wld_wayland_drm_context * wld_wayland_drm_create_context
21 EXPORT
22 void wld_wayland_drm_destroy_context(struct wld_wayland_drm_context * drm)
23 {
24-    drm_finalize_context(&drm->context);
25+    wld_destroy_context(&drm->driver_context);
26     close(drm->fd);
27     wl_drm_destroy(drm->wl);
28     wl_registry_destroy(drm->registry);
29@@ -205,17 +204,17 @@ struct wld_drawable * wld_wayland_drm_create_drawable
30     if (buffer && !wld_wayland_drm_has_format(drm, format))
31         return NULL;
32 
33-    drawable = wld_drm_create_drawable(&drm->context, width, height, format);
34+    drawable = wld_create_drawable(drm->driver_context, width, height, format);
35 
36     if (!drawable)
37         return NULL;
38 
39     if (buffer)
40     {
41-        int prime_fd;
42+        union wld_object object;
43 
44-        prime_fd = wld_drm_export(drawable);
45-        *buffer = wl_drm_create_prime_buffer(drm->wl, prime_fd,
46+        wld_export(drawable, WLD_DRM_OBJECT_PRIME_FD, &object);
47+        *buffer = wl_drm_create_prime_buffer(drm->wl, object.i,
48                                              width, height, format,
49                                              0, drawable->pitch, 0, 0, 0, 0);
50         close(prime_fd);
+6, -4
 1@@ -42,7 +42,7 @@ struct wld_shm_context
 2     struct wl_shm * wl;
 3     struct wl_array formats;
 4 
 5-    struct wld_pixman_context * pixman_context;
 6+    struct wld_context * pixman_context;
 7 };
 8 
 9 static void registry_global(void * data, struct wl_registry * registry,
10@@ -137,7 +137,7 @@ struct wld_shm_context * wld_shm_create_context(struct wl_display * display,
11 EXPORT
12 void wld_shm_destroy_context(struct wld_shm_context * shm)
13 {
14-    wld_pixman_destroy_context(shm->pixman_context);
15+    wld_destroy_context(shm->pixman_context);
16     wl_shm_destroy(shm->wl);
17     wl_registry_destroy(shm->registry);
18     wl_array_release(&shm->formats);
19@@ -173,6 +173,7 @@ struct wld_drawable * wld_shm_create_drawable(struct wld_shm_context * shm,
20     struct wl_shm_pool * pool;
21     struct wld_drawable * drawable;
22     uint32_t shm_format = wayland_format(format);
23+    union wld_object object;
24 
25     fd = mkostemp(name, O_CLOEXEC);
26 
27@@ -189,8 +190,9 @@ struct wld_drawable * wld_shm_create_drawable(struct wld_shm_context * shm,
28     if (data == MAP_FAILED)
29         goto error1;
30 
31-    drawable = wld_pixman_create_drawable(shm->pixman_context, width, height,
32-                                          data, pitch, format);
33+    object.ptr = data;
34+    drawable = wld_import(shm->pixman_context, WLD_OBJECT_DATA, object,
35+                          width, height, format, pitch);
36 
37     pool = wl_shm_create_pool(shm->wl, fd, size);
38     *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, pitch,
+28, -0
 1@@ -83,6 +83,18 @@ struct font
 2     struct glyph ** glyphs;
 3 };
 4 
 5+struct wld_context_impl
 6+{
 7+    struct wld_drawable * (* create_drawable)(struct wld_context * context,
 8+                                              uint32_t width, uint32_t height,
 9+                                              uint32_t format);
10+    struct wld_drawable * (* import)(struct wld_context * context,
11+                                     uint32_t type, union wld_object object,
12+                                     uint32_t width, uint32_t height,
13+                                     uint32_t format, uint32_t pitch);
14+    void (* destroy)(struct wld_context * context);
15+};
16+
17 struct wld_draw_interface
18 {
19     void (* fill_rectangle)(struct wld_drawable * drawable, uint32_t color,
20@@ -140,6 +152,19 @@ static inline pixman_format_code_t format_wld_to_pixman(uint32_t format)
21     }
22 }
23 
24+static inline uint32_t format_pixman_to_wld(pixman_format_code_t format)
25+{
26+    switch (format)
27+    {
28+        case PIXMAN_a8r8g8b8:
29+            return WLD_FORMAT_ARGB8888;
30+        case PIXMAN_x8r8g8b8:
31+            return WLD_FORMAT_XRGB8888;
32+        default:
33+            return 0;
34+    }
35+}
36+
37 /**
38  * This default fill_region method is implemented in terms of fill_rectangle.
39  */
40@@ -153,5 +178,8 @@ void default_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
41                          pixman_region32_t * region,
42                          int32_t dst_x, int32_t dst_y);
43 
44+void context_initialize(struct wld_context * context,
45+                        const struct wld_context_impl * impl);
46+
47 #endif
48 
M wld.h
+30, -0
 1@@ -47,6 +47,36 @@ enum wld_format
 2 
 3 bool wld_lookup_named_color(const char * name, uint32_t * color);
 4 
 5+/**** WLD Context ****/
 6+
 7+enum wld_object_type
 8+{
 9+    WLD_OBJECT_DATA = 0x0
10+};
11+
12+union wld_object
13+{
14+    void * ptr;
15+    uint32_t u32;
16+    int i;
17+};
18+
19+struct wld_context
20+{
21+    const struct wld_context_impl * const impl;
22+};
23+
24+struct wld_drawable * wld_create_drawable(struct wld_context * context,
25+                                          uint32_t width, uint32_t height,
26+                                          uint32_t format);
27+
28+struct wld_drawable * wld_import(struct wld_context * context, uint32_t type,
29+                                 union wld_object object,
30+                                 uint32_t width, uint32_t height,
31+                                 uint32_t format, uint32_t pitch);
32+
33+void wld_destroy_context(struct wld_context * context);
34+
35 /**** Font Handling ****/
36 
37 struct wld_extents