commit 4ee9dac

Michael Forney  ·  2014-01-14 01:50:47 +0000 UTC
parent 1c0784b
Separate actual rendering to renderer
15 files changed,  +525, -278
M dumb.c
M wld.h
+6, -1
 1@@ -15,7 +15,12 @@ CLEAN_FILES     := $(TARGETS)
 2 
 3 WLD_REQUIRES = fontconfig pixman-1
 4 WLD_REQUIRES_PRIVATE = freetype2
 5-WLD_SOURCES = context.c drawable.c color.c font.c
 6+WLD_SOURCES =           \
 7+    color.c             \
 8+    context.c           \
 9+    drawable.c          \
10+    font.c              \
11+    renderer.c
12 WLD_HEADERS = wld.h
13 
14 ifeq ($(ENABLE_DEBUG),1)
+6, -0
 1@@ -29,6 +29,12 @@ void context_initialize(struct wld_context * context,
 2     *((const struct wld_context_impl **) &context->impl) = impl;
 3 }
 4 
 5+EXPORT
 6+struct wld_renderer * wld_create_renderer(struct wld_context * context)
 7+{
 8+    return context->impl->create_renderer(context);
 9+}
10+
11 EXPORT
12 struct wld_drawable * wld_create_drawable(struct wld_context * context,
13                                           uint32_t width, uint32_t height,
+2, -89
  1@@ -25,41 +25,6 @@
  2 
  3 #include <assert.h>
  4 
  5-void default_fill_region(struct wld_drawable * drawable, uint32_t color,
  6-                         pixman_region32_t * region)
  7-{
  8-    pixman_box32_t * box;
  9-    int num_boxes;
 10-
 11-    box = pixman_region32_rectangles(region, &num_boxes);
 12-
 13-    while (num_boxes--)
 14-    {
 15-        drawable->impl->fill_rectangle(drawable, color, box->x1, box->y1,
 16-                                       box->x2 - box->x1,
 17-                                       box->y2 - box->y1);
 18-        ++box;
 19-    }
 20-}
 21-
 22-void default_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
 23-                         pixman_region32_t * region,
 24-                         int32_t dst_x, int32_t dst_y)
 25-{
 26-    pixman_box32_t * box;
 27-    int num_boxes;
 28-
 29-    box = pixman_region32_rectangles(region, &num_boxes);
 30-
 31-    while (num_boxes--)
 32-    {
 33-        dst->impl->copy_rectangle(src, dst, box->x1, box->y1,
 34-                                  dst_x + box->x1, dst_y + box->y1,
 35-                                  box->x2 - box->x1, box->y2 - box->y1);
 36-        ++box;
 37-    }
 38-}
 39-
 40 void drawable_initialize(struct wld_drawable * drawable,
 41                          const struct wld_drawable_impl * impl,
 42                          uint32_t width, uint32_t height,
 43@@ -87,58 +52,6 @@ void exporter_initialize(struct wld_exporter * exporter,
 44     exporter->next = NULL;
 45 }
 46 
 47-EXPORT
 48-void wld_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
 49-                        int32_t x, int32_t y, uint32_t width, uint32_t height)
 50-{
 51-    drawable->impl->fill_rectangle(drawable, color, x, y, width, height);
 52-}
 53-
 54-EXPORT
 55-void wld_fill_region(struct wld_drawable * drawable, uint32_t color,
 56-                     pixman_region32_t * region)
 57-{
 58-    drawable->impl->fill_region(drawable, color, region);
 59-}
 60-
 61-EXPORT
 62-void wld_copy_rectangle(struct wld_drawable * src, struct wld_drawable * dst,
 63-                        int32_t src_x, int32_t src_y,
 64-                        int32_t dst_x, int32_t dst_y,
 65-                        uint32_t width, uint32_t height)
 66-{
 67-    assert(src->impl == dst->impl);
 68-    dst->impl->copy_rectangle(src, dst, src_x, src_y, dst_x, dst_y,
 69-                              width, height);
 70-}
 71-
 72-EXPORT
 73-void wld_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
 74-                     pixman_region32_t * region, int32_t dst_x, int32_t dst_y)
 75-{
 76-    assert(src->impl == dst->impl);
 77-    dst->impl->copy_region(src, dst, region, dst_x, dst_y);
 78-}
 79-
 80-EXPORT
 81-void wld_draw_text_n(struct wld_drawable * drawable,
 82-                          struct wld_font * font_base, uint32_t color,
 83-                          int32_t x, int32_t y,
 84-                          const char * text, int32_t length,
 85-                          struct wld_extents * extents)
 86-{
 87-    struct font * font = (void *) font_base;
 88-
 89-    drawable->impl->draw_text(drawable, font, color, x, y,
 90-                              text, length, extents);
 91-}
 92-
 93-EXPORT
 94-void wld_destroy_drawable(struct wld_drawable * drawable)
 95-{
 96-    drawable->impl->destroy(drawable);
 97-}
 98-
 99 EXPORT
100 void wld_write(struct wld_drawable * drawable, const void * data, size_t size)
101 {
102@@ -167,8 +80,8 @@ bool wld_export(struct wld_drawable * drawable,
103 }
104 
105 EXPORT
106-void wld_flush(struct wld_drawable * drawable)
107+void wld_destroy_drawable(struct wld_drawable * drawable)
108 {
109-    drawable->impl->flush(drawable);
110+    drawable->impl->destroy(drawable);
111 }
112 
M dumb.c
+8, -11
 1@@ -27,6 +27,7 @@
 2 #include "drm.h"
 3 
 4 #include <fcntl.h>
 5+#include <unistd.h>
 6 #include <sys/mman.h>
 7 #include <xf86drm.h>
 8 
 9@@ -35,7 +36,6 @@
10 struct dumb_context
11 {
12     struct wld_context base;
13-    struct wld_context * pixman;
14     int fd;
15 };
16 
17@@ -65,20 +65,17 @@ struct wld_context * driver_create_context(int drm_fd)
18     struct dumb_context * context;
19 
20     if (!(context = malloc(sizeof *context)))
21-        goto error0;
22-
23-    if (!(context->pixman = wld_pixman_create_context()))
24-        goto error1;
25+        return NULL;
26 
27     context_initialize(&context->base, &context_impl);
28     context->fd = drm_fd;
29 
30     return &context->base;
31+}
32 
33-  error1:
34-    free(context);
35-  error0:
36-    return NULL;
37+struct wld_renderer * context_create_renderer(struct wld_context * context)
38+{
39+    return wld_create_renderer(wld_pixman_context);
40 }
41 
42 static struct wld_drawable * new_drawable(struct dumb_context * context,
43@@ -106,7 +103,7 @@ static struct wld_drawable * new_drawable(struct dumb_context * context,
44     if (data == MAP_FAILED)
45         goto error1;
46 
47-    if (!pixman_initialize_drawable(context->pixman, &drawable->pixman,
48+    if (!pixman_initialize_drawable(wld_pixman_context, &drawable->pixman,
49                                     width, height, data, pitch, format))
50     {
51         goto error2;
52@@ -198,7 +195,7 @@ void context_destroy(struct wld_context * base)
53 {
54     struct dumb_context * context = dumb_context(base);
55 
56-    wld_destroy_context(context->pixman);
57+    close(context->fd);
58     free(context);
59 }
60 
+96, -41
  1@@ -34,25 +34,31 @@ struct intel_context
  2 {
  3     struct wld_context base;
  4     drm_intel_bufmgr * bufmgr;
  5+};
  6+
  7+struct intel_renderer
  8+{
  9+    struct wld_renderer base;
 10     struct intel_batch * batch;
 11+    struct intel_drawable * target;
 12 };
 13 
 14 struct intel_drawable
 15 {
 16     struct wld_drawable base;
 17     struct wld_exporter exporter;
 18-
 19-    struct intel_context * context;
 20     drm_intel_bo * bo;
 21     pixman_image_t * virtual;
 22 };
 23 
 24 #include "interface/context.h"
 25+#include "interface/renderer.h"
 26 #include "interface/drawable.h"
 27 #include "interface/exporter.h"
 28 #define DRM_DRIVER_NAME intel
 29 #include "interface/drm.h"
 30 IMPL(intel, context)
 31+IMPL(intel, renderer)
 32 IMPL(intel, drawable)
 33 
 34 bool driver_device_supported(uint32_t vendor_id, uint32_t device_id)
 35@@ -75,23 +81,37 @@ struct wld_context * driver_create_context(int drm_fd)
 36     if (!context->bufmgr)
 37         goto error1;
 38 
 39-    context->batch = intel_batch_new(context->bufmgr);
 40-
 41-    if (!context->batch)
 42-        goto error2;
 43-
 44     return &context->base;
 45 
 46-  error2:
 47-    drm_intel_bufmgr_destroy(context->bufmgr);
 48   error1:
 49     free(context);
 50   error0:
 51     return NULL;
 52 }
 53 
 54-static struct intel_drawable * new_drawable(struct intel_context * context,
 55-                                            uint32_t width, uint32_t height,
 56+/**** Context ****/
 57+struct wld_renderer * context_create_renderer(struct wld_context * base)
 58+{
 59+    struct intel_context * context = intel_context(base);
 60+    struct intel_renderer * renderer;
 61+
 62+    if (!(renderer = malloc(sizeof *renderer)))
 63+        goto error0;
 64+
 65+    if (!(renderer->batch = intel_batch_new(context->bufmgr)))
 66+        goto error1;
 67+
 68+    renderer_initialize(&renderer->base, &renderer_impl);
 69+
 70+    return &renderer->base;
 71+
 72+  error1:
 73+    free(renderer);
 74+  error0:
 75+    return NULL;
 76+}
 77+
 78+static struct intel_drawable * new_drawable(uint32_t width, uint32_t height,
 79                                             uint32_t format)
 80 {
 81     struct intel_drawable * intel;
 82@@ -101,7 +121,6 @@ static struct intel_drawable * new_drawable(struct intel_context * context,
 83 
 84     drawable_initialize(&intel->base, &drawable_impl,
 85                         width, height, format, 0);
 86-    intel->context = context;
 87     intel->virtual = NULL;
 88     exporter_initialize(&intel->exporter, &exporter_impl);
 89     drawable_add_exporter(&intel->base, &intel->exporter);
 90@@ -117,7 +136,7 @@ struct wld_drawable * context_create_drawable(struct wld_context * base,
 91     struct intel_drawable * intel;
 92     uint32_t tiling_mode = width >= 128 ? I915_TILING_X : I915_TILING_NONE;
 93 
 94-    if (!(intel = new_drawable(context, width, height, format)))
 95+    if (!(intel = new_drawable(width, height, format)))
 96         return NULL;
 97 
 98     intel->bo = drm_intel_bo_alloc_tiled(context->bufmgr, "drawable",
 99@@ -155,7 +174,7 @@ struct wld_drawable * context_import(struct wld_context * base,
100     if (!bo)
101         goto error0;
102 
103-    if (!(intel = new_drawable(context, width, height, format)))
104+    if (!(intel = new_drawable(width, height, format)))
105         goto error1;
106 
107     intel->bo = bo;
108@@ -173,41 +192,69 @@ void context_destroy(struct wld_context * base)
109 {
110     struct intel_context * context = intel_context(base);
111 
112-    intel_batch_destroy(context->batch);
113     drm_intel_bufmgr_destroy(context->bufmgr);
114     free(context);
115 }
116 
117-void drawable_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
118+/**** Renderer ****/
119+uint32_t renderer_capabilities(struct wld_renderer * renderer,
120+                               struct wld_drawable * drawable)
121+{
122+    if (drawable->impl == &drawable_impl)
123+        return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
124+
125+    return 0;
126+}
127+
128+bool renderer_set_target(struct wld_renderer * base,
129+                         struct wld_drawable * drawable)
130+{
131+    struct intel_renderer * renderer = intel_renderer(base);
132+
133+    if (drawable && drawable->impl != &drawable_impl)
134+        return false;
135+
136+    renderer->target = drawable ? intel_drawable(drawable) : NULL;
137+
138+    return true;
139+}
140+
141+void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
142                              int32_t x, int32_t y,
143                              uint32_t width, uint32_t height)
144 {
145-    struct intel_drawable * intel = (void *) drawable;
146+    struct intel_renderer * renderer = intel_renderer(base);
147 
148-    xy_color_blt(intel->context->batch, intel->bo, intel->base.pitch,
149+    xy_color_blt(renderer->batch, renderer->target->bo,
150+                 renderer->target->base.pitch,
151                  x, y, x + width, y + height, color);
152 }
153 
154-void drawable_copy_rectangle(struct wld_drawable * src_drawable,
155-                             struct wld_drawable * dst_drawable,
156-                             int32_t src_x, int32_t src_y,
157+void renderer_copy_rectangle(struct wld_renderer * base,
158+                             struct wld_drawable * drawable_base,
159                              int32_t dst_x, int32_t dst_y,
160+                             int32_t src_x, int32_t src_y,
161                              uint32_t width, uint32_t height)
162 {
163-    struct intel_drawable * src = (void *) src_drawable;
164-    struct intel_drawable * dst = (void *) dst_drawable;
165+    struct intel_renderer * renderer = intel_renderer(base);
166+
167+    if (drawable_base->impl != &drawable_impl)
168+        return;
169 
170-    xy_src_copy_blt(dst->context->batch,
171-                    src->bo, src->base.pitch, src_x, src_y,
172-                    dst->bo, dst->base.pitch, dst_x, dst_y, width, height);
173+    struct intel_drawable * drawable = intel_drawable(drawable_base);
174+
175+    xy_src_copy_blt(renderer->batch, drawable->bo, drawable->base.pitch,
176+                    src_x, src_y,
177+                    renderer->target->bo, renderer->target->base.pitch,
178+                    dst_x, dst_y, width, height);
179 }
180 
181-void drawable_draw_text(struct wld_drawable * drawable,
182+void renderer_draw_text(struct wld_renderer * base,
183                         struct font * font, uint32_t color,
184                         int32_t x, int32_t y, const char * text, int32_t length,
185                         struct wld_extents * extents)
186 {
187-    struct intel_drawable * intel = (void *) drawable;
188+    struct intel_renderer * renderer = intel_renderer(base);
189     int ret;
190     struct glyph * glyph;
191     uint32_t row;
192@@ -217,8 +264,8 @@ void drawable_draw_text(struct wld_drawable * drawable,
193     uint8_t * byte;
194     int32_t origin_x = x;
195 
196-    xy_setup_blt(intel->context->batch, true, INTEL_BLT_RASTER_OPERATION_SRC,
197-                 0, color, intel->bo, intel->base.pitch);
198+    xy_setup_blt(renderer->batch, true, INTEL_BLT_RASTER_OPERATION_SRC,
199+                 0, color, renderer->target->bo, renderer->target->base.pitch);
200 
201     while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
202     {
203@@ -245,7 +292,7 @@ void drawable_draw_text(struct wld_drawable * drawable,
204         }
205 
206       retry:
207-        ret = xy_text_immediate_blt(intel->context->batch, intel->bo,
208+        ret = xy_text_immediate_blt(renderer->batch, renderer->target->bo,
209                                     origin_x + glyph->x, y + glyph->y,
210                                     origin_x + glyph->x + glyph->bitmap.width,
211                                     y + glyph->y + glyph->bitmap.rows,
212@@ -254,10 +301,10 @@ void drawable_draw_text(struct wld_drawable * drawable,
213 
214         if (ret == INTEL_BATCH_NO_SPACE)
215         {
216-            intel_batch_flush(intel->context->batch);
217-            xy_setup_blt(intel->context->batch, true,
218+            intel_batch_flush(renderer->batch);
219+            xy_setup_blt(renderer->batch, true,
220                          INTEL_BLT_RASTER_OPERATION_SRC, 0, color,
221-                         intel->bo, intel->base.pitch);
222+                         renderer->target->bo, renderer->target->base.pitch);
223             goto retry;
224         }
225 
226@@ -269,6 +316,21 @@ void drawable_draw_text(struct wld_drawable * drawable,
227         extents->advance = origin_x - x;
228 }
229 
230+void renderer_flush(struct wld_renderer * base)
231+{
232+    struct intel_renderer * renderer = intel_renderer(base);
233+
234+    intel_batch_flush(renderer->batch);
235+}
236+
237+void renderer_destroy(struct wld_renderer * base)
238+{
239+    struct intel_renderer * renderer = intel_renderer(base);
240+
241+    intel_batch_destroy(renderer->batch);
242+    free(renderer);
243+}
244+
245 void drawable_write(struct wld_drawable * drawable, const void * data, size_t size)
246 {
247     struct intel_drawable * intel = (void *) drawable;
248@@ -304,13 +366,6 @@ pixman_image_t * drawable_map(struct wld_drawable * drawable)
249     return intel->virtual;
250 }
251 
252-void drawable_flush(struct wld_drawable * drawable)
253-{
254-    struct intel_drawable * intel = (void *) drawable;
255-
256-    intel_batch_flush(intel->context->batch);
257-}
258-
259 void drawable_destroy(struct wld_drawable * drawable)
260 {
261     struct intel_drawable * intel = (void *) drawable;
+3, -0
 1@@ -21,6 +21,8 @@
 2  * SOFTWARE.
 3  */
 4 
 5+static struct wld_renderer * context_create_renderer
 6+    (struct wld_context * context);
 7 static struct wld_drawable * context_create_drawable
 8     (struct wld_context * context,
 9      uint32_t width, uint32_t height, uint32_t format);
10@@ -30,6 +32,7 @@ static struct wld_drawable * context_import
11 static void context_destroy(struct wld_context * context);
12 
13 static const struct wld_context_impl context_impl = {
14+    .create_renderer = &context_create_renderer,
15     .create_drawable = &context_create_drawable,
16     .import = &context_import,
17     .destroy = &context_destroy
+0, -33
 1@@ -21,47 +21,14 @@
 2  * SOFTWARE.
 3  */
 4 
 5-static void drawable_fill_rectangle(struct wld_drawable * drawable,
 6-                                    uint32_t color, int32_t x, int32_t y,
 7-                                    uint32_t width, uint32_t height);
 8-static void drawable_copy_rectangle(struct wld_drawable * src,
 9-                                    struct wld_drawable * dst,
10-                                    int32_t src_x, int32_t src_y,
11-                                    int32_t dst_x, int32_t dst_y,
12-                                    uint32_t width, uint32_t height);
13-#ifdef DRAWABLE_IMPLEMENTS_REGION
14-static void drawable_fill_region(struct wld_drawable * drawable, uint32_t color,
15-                                 pixman_region32_t * region);
16-static void drawable_copy_region(struct wld_drawable * src,
17-                                 struct wld_drawable * drawable,
18-                                 pixman_region32_t * region,
19-                                 int32_t dst_x, int32_t dst_y);
20-#endif
21-static void drawable_draw_text(struct wld_drawable * drawable,
22-                               struct font * font, uint32_t color,
23-                               int32_t x, int32_t y,
24-                               const char * text, int32_t length,
25-                               struct wld_extents * extents);
26 static void drawable_write(struct wld_drawable * drawable,
27                            const void * data, size_t size);
28 static pixman_image_t * drawable_map(struct wld_drawable * drawable);
29-static void drawable_flush(struct wld_drawable * drawable);
30 static void drawable_destroy(struct wld_drawable * drawable);
31 
32 static const struct wld_drawable_impl drawable_impl = {
33-    .fill_rectangle = &drawable_fill_rectangle,
34-    .copy_rectangle = &drawable_copy_rectangle,
35-#ifdef DRAWABLE_IMPLEMENTS_REGION
36-    .fill_region = &drawable_fill_region,
37-    .copy_region = &drawable_copy_region,
38-#else
39-    .fill_region = &default_fill_region,
40-    .copy_region = &default_copy_region,
41-#endif
42-    .draw_text = &drawable_draw_text,
43     .write = &drawable_write,
44     .map = &drawable_map,
45-    .flush = &drawable_flush,
46     .destroy = &drawable_destroy
47 };
48 
+68, -0
 1@@ -0,0 +1,68 @@
 2+/* wld: interface/drawable.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 uint32_t renderer_capabilities(struct wld_renderer * renderer,
26+                                      struct wld_drawable * drawable);
27+static bool renderer_set_target(struct wld_renderer * renderer,
28+                                struct wld_drawable * drawable);
29+static void renderer_fill_rectangle(struct wld_renderer * renderer,
30+                                    uint32_t color, int32_t x, int32_t y,
31+                                    uint32_t width, uint32_t height);
32+static void renderer_copy_rectangle(struct wld_renderer * renderer,
33+                                    struct wld_drawable * drawable,
34+                                    int32_t dst_x, int32_t dst_y,
35+                                    int32_t src_x, int32_t src_y,
36+                                    uint32_t width, uint32_t height);
37+#ifdef RENDERER_IMPLEMENTS_REGION
38+static void renderer_fill_region(struct wld_renderer * base, uint32_t color,
39+                                 pixman_region32_t * region);
40+static void renderer_copy_region(struct wld_renderer * base,
41+                                 struct wld_drawable * drawable,
42+                                 int32_t dst_x, int32_t dst_y,
43+                                 pixman_region32_t * region);
44+#endif
45+static void renderer_draw_text(struct wld_renderer * renderer,
46+                               struct font * font, uint32_t color,
47+                               int32_t x, int32_t y,
48+                               const char * text, int32_t length,
49+                               struct wld_extents * extents);
50+static void renderer_flush(struct wld_renderer * renderer);
51+static void renderer_destroy(struct wld_renderer * renderer);
52+
53+static const struct wld_renderer_impl renderer_impl = {
54+    .capabilities = &renderer_capabilities,
55+    .set_target = &renderer_set_target,
56+    .fill_rectangle = &renderer_fill_rectangle,
57+    .copy_rectangle = &renderer_copy_rectangle,
58+#ifdef RENDERER_IMPLEMENTS_REGION
59+    .fill_region = &renderer_fill_region,
60+    .copy_region = &renderer_copy_region,
61+#else
62+    .fill_region = &default_fill_region,
63+    .copy_region = &default_copy_region,
64+#endif
65+    .draw_text = &renderer_draw_text,
66+    .flush = &renderer_flush,
67+    .destroy = &renderer_destroy
68+};
69+
+101, -60
  1@@ -32,33 +32,43 @@
  2     .blue   = ((c >>  0) & 0xff) * 0x101,   \
  3 }
  4 
  5-struct pixman_context
  6+struct pixman_renderer
  7 {
  8-    struct wld_context base;
  9+    struct wld_renderer base;
 10+    pixman_image_t * target;
 11     pixman_glyph_cache_t * glyph_cache;
 12 };
 13 
 14 #include "interface/context.h"
 15-#define DRAWABLE_IMPLEMENTS_REGION
 16+#define RENDERER_IMPLEMENTS_REGION
 17+#include "interface/renderer.h"
 18 #include "interface/drawable.h"
 19+IMPL(pixman, renderer)
 20+IMPL(pixman, drawable)
 21 
 22+static struct wld_context context = { .impl = &context_impl };
 23 const struct wld_drawable_impl * const pixman_drawable_impl = &drawable_impl;
 24 
 25 EXPORT
 26-struct wld_context * wld_pixman_create_context()
 27+struct wld_context * wld_pixman_context = &context;
 28+
 29+struct wld_renderer * context_create_renderer(struct wld_context * context)
 30 {
 31-    struct pixman_context * context;
 32+    struct pixman_renderer * renderer;
 33 
 34-    if (!(context = malloc(sizeof *context)))
 35+    if (!(renderer = malloc(sizeof *renderer)))
 36         goto error0;
 37 
 38-    if (!(context->glyph_cache = pixman_glyph_cache_create()))
 39+    if (!(renderer->glyph_cache = pixman_glyph_cache_create()))
 40         goto error1;
 41 
 42-    return &context->base;
 43+    renderer_initialize(&renderer->base, &renderer_impl);
 44+    renderer->target = NULL;
 45+
 46+    return &renderer->base;
 47 
 48   error1:
 49-    free(context);
 50+    free(renderer);
 51   error0:
 52     return NULL;
 53 }
 54@@ -78,8 +88,7 @@ bool pixman_initialize_drawable
 55     return drawable->image != NULL;
 56 }
 57 
 58-struct wld_drawable * new_drawable(struct pixman_context * context,
 59-                                   pixman_image_t * image)
 60+struct wld_drawable * new_drawable(pixman_image_t * image)
 61 {
 62     struct pixman_drawable * drawable;
 63 
 64@@ -91,17 +100,15 @@ struct wld_drawable * new_drawable(struct pixman_context * context,
 65                         pixman_image_get_height(image),
 66                         format_pixman_to_wld(pixman_image_get_format(image)),
 67                         pixman_image_get_stride(image));
 68-    drawable->context = context;
 69     drawable->image = image;
 70 
 71     return &drawable->base;
 72 }
 73 
 74-struct wld_drawable * context_create_drawable(struct wld_context * base,
 75+struct wld_drawable * context_create_drawable(struct wld_context * context,
 76                                               uint32_t width, uint32_t height,
 77                                               uint32_t format)
 78 {
 79-    struct pixman_context * context = (void *) base;
 80     struct wld_drawable * drawable;
 81     pixman_image_t * image;
 82 
 83@@ -111,7 +118,7 @@ struct wld_drawable * context_create_drawable(struct wld_context * base,
 84     if (!image)
 85         goto error0;
 86 
 87-    if (!(drawable = new_drawable(context, image)))
 88+    if (!(drawable = new_drawable(image)))
 89         goto error1;
 90 
 91     return drawable;
 92@@ -122,11 +129,11 @@ struct wld_drawable * context_create_drawable(struct wld_context * base,
 93     return NULL;
 94 }
 95 
 96-struct wld_drawable * context_import
 97-    (struct wld_context * base, uint32_t type, union wld_object object,
 98-     uint32_t width, uint32_t height, uint32_t format, uint32_t pitch)
 99+struct wld_drawable * context_import(struct wld_context * context,
100+                                     uint32_t type, union wld_object object,
101+                                     uint32_t width, uint32_t height,
102+                                     uint32_t format, uint32_t pitch)
103 {
104-    struct pixman_context * context = (void *) base;
105     struct wld_drawable * drawable;
106     pixman_image_t * image;
107 
108@@ -142,7 +149,7 @@ struct wld_drawable * context_import
109     if (!image)
110         goto error0;
111 
112-    if (!(drawable = new_drawable(context, image)))
113+    if (!(drawable = new_drawable(image)))
114         goto error1;
115 
116     return drawable;
117@@ -154,68 +161,94 @@ struct wld_drawable * context_import
118 
119 }
120 
121-void context_destroy(struct wld_context * base)
122+void context_destroy(struct wld_context * context)
123+{
124+}
125+
126+uint32_t renderer_capabilities(struct wld_renderer * renderer,
127+                               struct wld_drawable * drawable)
128 {
129-    struct pixman_context * context = (void *) base;
130+    if (drawable->impl == &drawable_impl)
131+        return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
132 
133-    pixman_glyph_cache_destroy(context->glyph_cache);
134-    free(context);
135+    return 0;
136 }
137 
138-void drawable_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
139+bool renderer_set_target(struct wld_renderer * base,
140+                         struct wld_drawable * drawable)
141+{
142+    struct pixman_renderer * renderer = pixman_renderer(base);
143+
144+    if (drawable && drawable->impl != &drawable_impl)
145+        return false;
146+
147+    renderer->target = drawable ? pixman_drawable(drawable)->image : NULL;
148+
149+    return true;
150+}
151+
152+void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
153                              int32_t x, int32_t y,
154                              uint32_t width, uint32_t height)
155 {
156-    struct pixman_drawable * pixman = (void *) drawable;
157+    struct pixman_renderer * renderer = pixman_renderer(base);
158     pixman_color_t pixman_color = PIXMAN_COLOR(color);
159     pixman_box32_t box = { x, y, x + width, y + height };
160 
161-    pixman_image_fill_boxes(PIXMAN_OP_SRC, pixman->image, &pixman_color,
162-                            1, &box);
163+    pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
164+                            &pixman_color, 1, &box);
165 }
166 
167-void drawable_fill_region(struct wld_drawable * drawable, uint32_t color,
168+void renderer_fill_region(struct wld_renderer * base, uint32_t color,
169                           pixman_region32_t * region)
170 {
171-    struct pixman_drawable * pixman = (void *) drawable;
172+    struct pixman_renderer * renderer = pixman_renderer(base);
173     pixman_color_t pixman_color = PIXMAN_COLOR(color);
174     pixman_box32_t * boxes;
175     int num_boxes;
176 
177     boxes = pixman_region32_rectangles(region, &num_boxes);
178-    pixman_image_fill_boxes(PIXMAN_OP_SRC, pixman->image, &pixman_color,
179-                            num_boxes, boxes);
180+    pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
181+                            &pixman_color, num_boxes, boxes);
182 }
183 
184-void drawable_copy_rectangle(struct wld_drawable * src_drawable,
185-                             struct wld_drawable * dst_drawable,
186-                             int32_t src_x, int32_t src_y,
187+void renderer_copy_rectangle(struct wld_renderer * base,
188+                             struct wld_drawable * drawable,
189                              int32_t dst_x, int32_t dst_y,
190+                             int32_t src_x, int32_t src_y,
191                              uint32_t width, uint32_t height)
192 {
193-    struct pixman_drawable * src = (void *) src_drawable;
194-    struct pixman_drawable * dst = (void *) dst_drawable;
195+    struct pixman_renderer * renderer = pixman_renderer(base);
196+    pixman_image_t * dst = renderer->target, * src;
197 
198-    pixman_image_composite32(PIXMAN_OP_SRC, src->image, NULL, dst->image,
199+    if (drawable->impl != &drawable_impl)
200+        return;
201+
202+    src = pixman_drawable(drawable)->image;
203+    pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
204                              src_x, src_y, 0, 0, dst_x, dst_y, width, height);
205 }
206 
207-void drawable_copy_region(struct wld_drawable * src_drawable,
208-                          struct wld_drawable * dst_drawable,
209-                          pixman_region32_t * region,
210-                          int32_t dst_x, int32_t dst_y)
211+void renderer_copy_region(struct wld_renderer * base,
212+                          struct wld_drawable * drawable,
213+                          int32_t dst_x, int32_t dst_y,
214+                          pixman_region32_t * region)
215 {
216-    struct pixman_drawable * src = (void *) src_drawable;
217-    struct pixman_drawable * dst = (void *) dst_drawable;
218+    struct pixman_renderer * renderer = pixman_renderer(base);
219+    pixman_image_t * dst = renderer->target, * src;
220 
221-    pixman_image_set_clip_region32(src->image, region);
222-    pixman_image_composite32(PIXMAN_OP_SRC, src->image, NULL, dst->image,
223+    if (drawable->impl != &drawable_impl)
224+        return;
225+
226+    src = pixman_drawable(drawable)->image;
227+    pixman_image_set_clip_region32(src, region);
228+    pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
229                              region->extents.x1, region->extents.y1, 0, 0,
230                              region->extents.x1 + dst_x,
231                              region->extents.y1 + dst_y,
232                              region->extents.x2 - region->extents.x1,
233                              region->extents.y2 - region->extents.y1);
234-    pixman_image_set_clip_region32(src->image, NULL);
235+    pixman_image_set_clip_region32(src, NULL);
236 }
237 
238 static inline uint8_t reverse(uint8_t byte)
239@@ -227,12 +260,12 @@ static inline uint8_t reverse(uint8_t byte)
240     return byte;
241 }
242 
243-void drawable_draw_text(struct wld_drawable * drawable,
244+void renderer_draw_text(struct wld_renderer * base,
245                         struct font * font, uint32_t color,
246                         int32_t x, int32_t y, const char * text, int32_t length,
247                         struct wld_extents * extents)
248 {
249-    struct pixman_drawable * pixman = (void *) drawable;
250+    struct pixman_renderer * renderer = pixman_renderer(base);
251     int ret;
252     uint32_t c;
253     struct glyph * glyph;
254@@ -257,8 +290,8 @@ void drawable_draw_text(struct wld_drawable * drawable,
255 
256         glyphs[index].x = origin_x;
257         glyphs[index].y = 0;
258-        glyphs[index].glyph = pixman_glyph_cache_lookup
259-            (pixman->context->glyph_cache, font, glyph);
260+        glyphs[index].glyph = pixman_glyph_cache_lookup(renderer->glyph_cache,
261+                                                        font, glyph);
262 
263         /* If we don't have the glyph in our cache, do some conversions to make
264          * pixman happy, and then insert it. */
265@@ -293,11 +326,11 @@ void drawable_draw_text(struct wld_drawable * drawable,
266             }
267 
268             /* Insert the glyph into the cache. */
269-            pixman_glyph_cache_freeze(pixman->context->glyph_cache);
270+            pixman_glyph_cache_freeze(renderer->glyph_cache);
271             glyphs[index].glyph = pixman_glyph_cache_insert
272-                (pixman->context->glyph_cache, font, glyph,
273+                (renderer->glyph_cache, font, glyph,
274                  -glyph->x, -glyph->y, image);
275-            pixman_glyph_cache_thaw(pixman->context->glyph_cache);
276+            pixman_glyph_cache_thaw(renderer->glyph_cache);
277 
278             /* The glyph cache copies the contents of the glyph bitmap. */
279             pixman_image_unref(image);
280@@ -309,8 +342,8 @@ void drawable_draw_text(struct wld_drawable * drawable,
281         origin_x += glyph->advance;
282     }
283 
284-    pixman_composite_glyphs_no_mask(PIXMAN_OP_OVER, solid, pixman->image, 0, 0,
285-                                    x, y, pixman->context->glyph_cache,
286+    pixman_composite_glyphs_no_mask(PIXMAN_OP_OVER, solid, renderer->target,
287+                                    0, 0, x, y, renderer->glyph_cache,
288                                     index, glyphs);
289 
290     pixman_image_unref(solid);
291@@ -319,6 +352,18 @@ void drawable_draw_text(struct wld_drawable * drawable,
292         extents->advance = origin_x;
293 }
294 
295+void renderer_flush(struct wld_renderer * renderer)
296+{
297+}
298+
299+void renderer_destroy(struct wld_renderer * base)
300+{
301+    struct pixman_renderer * renderer = pixman_renderer(base);
302+
303+    pixman_glyph_cache_destroy(renderer->glyph_cache);
304+    free(renderer);
305+}
306+
307 void drawable_write(struct wld_drawable * drawable,
308                     const void * data, size_t size)
309 {
310@@ -334,10 +379,6 @@ pixman_image_t * drawable_map(struct wld_drawable * drawable)
311     return pixman_image_ref(pixman->image);
312 }
313 
314-void drawable_flush(struct wld_drawable * drawable)
315-{
316-}
317-
318 void drawable_destroy(struct wld_drawable * drawable)
319 {
320     struct pixman_drawable * pixman = (void *) drawable;
+5, -6
 1@@ -26,13 +26,12 @@
 2 
 3 #include <stdint.h>
 4 
 5-struct wld_context;
 6+extern struct wld_context * wld_pixman_context;
 7 
 8-/**
 9- * Create a new drawing context which uses Pixman to do software rendering on
10- * buffers in memory.
11- */
12-struct wld_context * wld_pixman_create_context();
13+static inline struct wld_context * wld_pixman_create_context()
14+{
15+    return wld_pixman_context;
16+}
17 
18 #endif
19 
+145, -0
  1@@ -0,0 +1,145 @@
  2+/* wld: renderer.c
  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+#include "wld-private.h"
 26+
 27+void default_fill_region(struct wld_renderer * renderer, uint32_t color,
 28+                         pixman_region32_t * region)
 29+{
 30+    pixman_box32_t * box;
 31+    int num_boxes;
 32+
 33+    box = pixman_region32_rectangles(region, &num_boxes);
 34+
 35+    while (num_boxes--)
 36+    {
 37+        renderer->impl->fill_rectangle(renderer, color, box->x1, box->y1,
 38+                                       box->x2 - box->x1, box->y2 - box->y1);
 39+        ++box;
 40+    }
 41+}
 42+
 43+void default_copy_region(struct wld_renderer * renderer,
 44+                         struct wld_drawable * drawable,
 45+                         int32_t dst_x, int32_t dst_y,
 46+                         pixman_region32_t * region)
 47+{
 48+    pixman_box32_t * box;
 49+    int num_boxes;
 50+
 51+    box = pixman_region32_rectangles(region, &num_boxes);
 52+
 53+    while (num_boxes--)
 54+    {
 55+        renderer->impl->copy_rectangle(renderer, drawable,
 56+                                       dst_x + box->x1, dst_y + box->y1,
 57+                                       box->x1, box->y1,
 58+                                       box->x2 - box->x1, box->y2 - box->y1);
 59+        ++box;
 60+    }
 61+}
 62+
 63+void renderer_initialize(struct wld_renderer * renderer,
 64+                         const struct wld_renderer_impl * impl)
 65+{
 66+    *((const struct wld_renderer_impl **) &renderer->impl) = impl;
 67+    renderer->target = NULL;
 68+}
 69+
 70+EXPORT
 71+void wld_destroy_renderer(struct wld_renderer * renderer)
 72+{
 73+    renderer->impl->destroy(renderer);
 74+}
 75+
 76+EXPORT
 77+uint32_t wld_capabilities(struct wld_renderer * renderer,
 78+                          struct wld_drawable * drawable)
 79+{
 80+    return renderer->impl->capabilities(renderer, drawable);
 81+}
 82+
 83+EXPORT
 84+bool wld_set_target_drawable(struct wld_renderer * renderer,
 85+                             struct wld_drawable * drawable)
 86+{
 87+    if (!renderer->impl->set_target(renderer, drawable))
 88+        return false;
 89+
 90+    renderer->target = drawable;
 91+
 92+    return true;
 93+}
 94+
 95+EXPORT
 96+void wld_fill_rectangle(struct wld_renderer * renderer, uint32_t color,
 97+                        int32_t x, int32_t y, uint32_t width, uint32_t height)
 98+{
 99+    renderer->impl->fill_rectangle(renderer, color, x, y, width, height);
100+}
101+
102+EXPORT
103+void wld_fill_region(struct wld_renderer * renderer, uint32_t color,
104+                     pixman_region32_t * region)
105+{
106+    renderer->impl->fill_region(renderer, color, region);
107+}
108+
109+EXPORT
110+void wld_copy_rectangle(struct wld_renderer * renderer,
111+                        struct wld_drawable * drawable,
112+                        int32_t dst_x, int32_t dst_y,
113+                        int32_t src_x, int32_t src_y,
114+                        uint32_t width, uint32_t height)
115+{
116+    renderer->impl->copy_rectangle(renderer, drawable, dst_x, dst_y,
117+                                   src_x, src_y, width, height);
118+}
119+
120+EXPORT
121+void wld_copy_region(struct wld_renderer * renderer,
122+                     struct wld_drawable * drawable,
123+                     int32_t dst_x, int32_t dst_y, pixman_region32_t * region)
124+{
125+    renderer->impl->copy_region(renderer, drawable, dst_x, dst_y, region);
126+}
127+
128+EXPORT
129+void wld_draw_text_n(struct wld_renderer * renderer,
130+                     struct wld_font * font_base, uint32_t color,
131+                     int32_t x, int32_t y, const char * text, int32_t length,
132+                     struct wld_extents * extents)
133+{
134+    struct font * font = (void *) font_base;
135+
136+    renderer->impl->draw_text(renderer, font, color, x, y, text, length,
137+                              extents);
138+}
139+
140+EXPORT
141+void wld_flush(struct wld_renderer * renderer)
142+{
143+    renderer->impl->flush(renderer);
144+    renderer->impl->set_target(renderer, NULL);
145+}
146+
+7, -0
 1@@ -184,6 +184,13 @@ int wld_wayland_drm_get_fd(struct wld_context * base)
 2     return context->authenticated ? context->fd : -1;
 3 }
 4 
 5+struct wld_renderer * context_create_renderer(struct wld_context * base)
 6+{
 7+    struct drm_context * context = drm_context(base);
 8+
 9+    return wld_create_renderer(context->driver_context);
10+}
11+
12 struct wld_drawable * context_create_drawable(struct wld_context * base,
13                                               uint32_t width, uint32_t height,
14                                               uint32_t format)
+6, -6
 1@@ -43,8 +43,6 @@ struct shm_context
 2     struct wl_registry * registry;
 3     struct wl_shm * wl;
 4     struct wl_array formats;
 5-
 6-    struct wld_context * pixman_context;
 7 };
 8 
 9 #include "interface/context.h"
10@@ -106,8 +104,6 @@ struct wld_context * wld_shm_create_context(struct wl_display * display,
11     wl_registry_add_listener(context->registry, &registry_listener, context);
12     wl_proxy_set_queue((struct wl_proxy *) context->registry, queue);
13 
14-    context->pixman_context = wld_pixman_create_context();
15-
16     /* Wait for wl_shm global. */
17     wayland_roundtrip(display, queue);
18 
19@@ -148,6 +144,11 @@ bool wld_shm_has_format(struct wld_context * base, uint32_t format)
20     return false;
21 }
22 
23+struct wld_renderer * context_create_renderer(struct wld_context * context)
24+{
25+    return wld_create_renderer(wld_pixman_context);
26+}
27+
28 struct wld_drawable * context_create_drawable(struct wld_context * base,
29                                               uint32_t width, uint32_t height,
30                                               uint32_t format)
31@@ -181,7 +182,7 @@ struct wld_drawable * context_create_drawable(struct wld_context * base,
32         goto error1;
33 
34     object.ptr = data;
35-    drawable = wld_import(context->pixman_context, WLD_OBJECT_DATA, object,
36+    drawable = wld_import(wld_pixman_context, WLD_OBJECT_DATA, object,
37                           width, height, format, pitch);
38 
39     if (!drawable)
40@@ -228,7 +229,6 @@ void context_destroy(struct wld_context * base)
41 {
42     struct shm_context * context = shm_context(base);
43 
44-    wld_destroy_context(context->pixman_context);
45     wl_shm_destroy(context->wl);
46     wl_registry_destroy(context->registry);
47     wl_array_release(&context->formats);
+32, -17
 1@@ -85,6 +85,7 @@ struct font
 2 
 3 struct wld_context_impl
 4 {
 5+    struct wld_renderer * (* create_renderer)(struct wld_context * context);
 6     struct wld_drawable * (* create_drawable)(struct wld_context * context,
 7                                               uint32_t width, uint32_t height,
 8                                               uint32_t format);
 9@@ -95,29 +96,39 @@ struct wld_context_impl
10     void (* destroy)(struct wld_context * context);
11 };
12 
13-struct wld_drawable_impl
14+struct wld_renderer_impl
15 {
16-    void (* fill_rectangle)(struct wld_drawable * drawable, uint32_t color,
17-                            int32_t x, int32_t y,
18+    uint32_t (* capabilities)(struct wld_renderer * renderer,
19+                              struct wld_drawable * buffer);
20+    bool (* set_target)(struct wld_renderer * renderer,
21+                        struct wld_drawable * drawable);
22+    void (* fill_rectangle)(struct wld_renderer * renderer,
23+                            uint32_t color, int32_t x, int32_t y,
24                             uint32_t width, uint32_t height);
25-    void (* fill_region)(struct wld_drawable * drawable, uint32_t color,
26-                         pixman_region32_t * region);
27-    void (* copy_rectangle)(struct wld_drawable * src,
28-                            struct wld_drawable * dst,
29-                            int32_t src_x, int32_t src_y,
30+    void (* fill_region)(struct wld_renderer * renderer,
31+                         uint32_t color, pixman_region32_t * region);
32+    void (* copy_rectangle)(struct wld_renderer * renderer,
33+                            struct wld_drawable * src,
34                             int32_t dst_x, int32_t dst_y,
35+                            int32_t src_x, int32_t src_y,
36                             uint32_t width, uint32_t height);
37-    void (* copy_region)(struct wld_drawable * src, struct wld_drawable * dst,
38-                         pixman_region32_t * region,
39-                         int32_t dst_x, int32_t dst_y);
40-    void (* draw_text)(struct wld_drawable * drawable,
41+    void (* copy_region)(struct wld_renderer * renderer,
42+                         struct wld_drawable * src,
43+                         int32_t dst_x, int32_t dst_y,
44+                         pixman_region32_t * region);
45+    void (* draw_text)(struct wld_renderer * renderer,
46                        struct font * font, uint32_t color,
47                        int32_t x, int32_t y, const char * text, int32_t length,
48                        struct wld_extents * extents);
49+    void (* flush)(struct wld_renderer * renderer);
50+    void (* destroy)(struct wld_renderer * renderer);
51+};
52+
53+struct wld_drawable_impl
54+{
55     void (* write)(struct wld_drawable * drawable,
56                    const void * data, size_t size);
57     pixman_image_t * (* map)(struct wld_drawable * drawable);
58-    void (* flush)(struct wld_drawable * drawable);
59     void (* destroy)(struct wld_drawable * drawable);
60 };
61 
62@@ -181,19 +192,23 @@ static inline uint32_t format_pixman_to_wld(pixman_format_code_t format)
63 /**
64  * This default fill_region method is implemented in terms of fill_rectangle.
65  */
66-void default_fill_region(struct wld_drawable * drawable, uint32_t color,
67+void default_fill_region(struct wld_renderer * renderer, uint32_t color,
68                          pixman_region32_t * region);
69 
70 /**
71  * This default copy_region method is implemented in terms of copy_rectangle.
72  */
73-void default_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
74-                         pixman_region32_t * region,
75-                         int32_t dst_x, int32_t dst_y);
76+void default_copy_region(struct wld_renderer * renderer,
77+                         struct wld_drawable * drawable,
78+                         int32_t dst_x, int32_t dst_y,
79+                         pixman_region32_t * region);
80 
81 void context_initialize(struct wld_context * context,
82                         const struct wld_context_impl * impl);
83 
84+void renderer_initialize(struct wld_renderer * renderer,
85+                         const struct wld_renderer_impl * impl);
86+
87 void drawable_initialize(struct wld_drawable * drawable,
88                          const struct wld_drawable_impl * impl,
89                          uint32_t width, uint32_t height,
M wld.h
+40, -14
 1@@ -66,6 +66,8 @@ struct wld_context
 2     const struct wld_context_impl * const impl;
 3 };
 4 
 5+struct wld_renderer * wld_create_renderer(struct wld_context * context);
 6+
 7 struct wld_drawable * wld_create_drawable(struct wld_context * context,
 8                                           uint32_t width, uint32_t height,
 9                                           uint32_t format);
10@@ -158,24 +160,52 @@ struct wld_drawable
11 bool wld_export(struct wld_drawable * drawable,
12                 uint32_t type, union wld_object * object);
13 
14+void wld_write(struct wld_drawable * drawable, const void * data, size_t size);
15+
16+pixman_image_t * wld_map(struct wld_drawable * drawable);
17+
18 /**
19  * Destroy a drawable (created with any context).
20  */
21 void wld_destroy_drawable(struct wld_drawable * drawable);
22 
23-void wld_fill_rectangle(struct wld_drawable * drawable, uint32_t color,
24+/**** Renderers ****/
25+
26+struct wld_renderer
27+{
28+    const struct wld_renderer_impl * const impl;
29+    struct wld_drawable * target;
30+};
31+
32+enum wld_capability
33+{
34+    WLD_CAPABILITY_READ     = 1<<0,
35+    WLD_CAPABILITY_WRITE    = 1<<1,
36+};
37+
38+void wld_destroy_renderer(struct wld_renderer * renderer);
39+
40+uint32_t wld_capabilities(struct wld_renderer * renderer,
41+                          struct wld_drawable * drawable);
42+
43+bool wld_set_target_buffer(struct wld_renderer * renderer,
44+                           struct wld_drawable * drawable);
45+
46+void wld_fill_rectangle(struct wld_renderer * renderer, uint32_t color,
47                         int32_t x, int32_t y, uint32_t width, uint32_t height);
48 
49-void wld_fill_region(struct wld_drawable * drawable, uint32_t color,
50+void wld_fill_region(struct wld_renderer * renderer, uint32_t color,
51                      pixman_region32_t * region);
52 
53-void wld_copy_rectangle(struct wld_drawable * src, struct wld_drawable * dst,
54-                        int32_t src_x, int32_t src_y,
55+void wld_copy_rectangle(struct wld_renderer * renderer,
56+                        struct wld_drawable * drawable,
57                         int32_t dst_x, int32_t dst_y,
58+                        int32_t src_x, int32_t src_y,
59                         uint32_t width, uint32_t height);
60 
61-void wld_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
62-                     pixman_region32_t * region, int32_t dst_x, int32_t dst_y);
63+void wld_copy_region(struct wld_renderer * renderer,
64+                     struct wld_drawable * drawable,
65+                     int32_t dst_x, int32_t dst_y, pixman_region32_t * region);
66 
67 /**
68  * Draw a UTF-8 text string to the given drawable.
69@@ -184,24 +214,20 @@ void wld_copy_region(struct wld_drawable * src, struct wld_drawable * dst,
70  * @param extents   If not NULL, will be initialized to the extents of the
71  *                  drawn text
72  */
73-void wld_draw_text_n(struct wld_drawable * drawable,
74+void wld_draw_text_n(struct wld_renderer * renderer,
75                      struct wld_font * font, uint32_t color,
76                      int32_t x, int32_t y, const char * text, int32_t length,
77                      struct wld_extents * extents);
78 
79-static inline void wld_draw_text(struct wld_drawable * drawable,
80+static inline void wld_draw_text(struct wld_renderer * renderer,
81                                  struct wld_font * font, uint32_t color,
82                                  int32_t x, int32_t y, const char * text,
83                                  struct wld_extents * extents)
84 {
85-    wld_draw_text_n(drawable, font, color, x, y, text, INT32_MAX, extents);
86+    wld_draw_text_n(renderer, font, color, x, y, text, INT32_MAX, extents);
87 }
88 
89-void wld_write(struct wld_drawable * drawable, const void * data, size_t size);
90-
91-pixman_image_t * wld_map(struct wld_drawable * drawable);
92-
93-void wld_flush(struct wld_drawable * drawable);
94+void wld_flush(struct wld_renderer * renderer);
95 
96 #endif
97