commit e2b75f7

Michael Forney  ·  2014-01-14 08:40:02 +0000 UTC
parent bbb03ae
pixman: Allow read/write to arbitrary buffers using drawable_map

The first time pixman sees an unknown drawable, it maps it and then
adds a pixman image exporter to the drawable.
2 files changed,  +93, -13
+88, -13
  1@@ -39,12 +39,20 @@ struct pixman_renderer
  2     pixman_glyph_cache_t * glyph_cache;
  3 };
  4 
  5+struct pixman_exporter
  6+{
  7+    struct wld_exporter base;
  8+    pixman_image_t * image;
  9+};
 10+
 11 #include "interface/context.h"
 12 #define RENDERER_IMPLEMENTS_REGION
 13 #include "interface/renderer.h"
 14 #include "interface/drawable.h"
 15+#include "interface/exporter.h"
 16 IMPL(pixman, renderer)
 17 IMPL(pixman, drawable)
 18+IMPL(pixman, exporter)
 19 
 20 static struct wld_context context = { .impl = &context_impl };
 21 const struct wld_drawable_impl * const pixman_drawable_impl = &drawable_impl;
 22@@ -168,11 +176,56 @@ void context_destroy(struct wld_context * context)
 23 
 24 uint32_t renderer_capabilities(struct wld_renderer * renderer,
 25                                struct wld_drawable * drawable)
 26+{
 27+    /* The pixman renderer can read and write to any drawable using it's map
 28+     * implementation. */
 29+    return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
 30+}
 31+
 32+static void destroy_image(pixman_image_t * image, void * data)
 33+{
 34+    struct wld_drawable * drawable = data;
 35+
 36+    wld_unmap(drawable);
 37+}
 38+
 39+static pixman_image_t * pixman_image(struct wld_drawable * drawable)
 40 {
 41     if (drawable->impl == &drawable_impl)
 42-        return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
 43+        return pixman_image_ref(pixman_drawable(drawable)->image);
 44+
 45+    union wld_object object;
 46+
 47+    if (wld_export(drawable, WLD_PIXMAN_OBJECT_IMAGE, &object))
 48+        return object.ptr;
 49+
 50+    struct pixman_exporter * exporter;
 51+    pixman_image_t * image;
 52+
 53+    if (!wld_map(drawable))
 54+        goto error0;
 55+
 56+    image = pixman_image_create_bits(format_wld_to_pixman(drawable->format),
 57+                                     drawable->width, drawable->height,
 58+                                     drawable->map.data, drawable->pitch);
 59+    pixman_image_set_destroy_function(image, &destroy_image, drawable);
 60+
 61+    if (!image)
 62+        goto error1;
 63+
 64+    if (!(exporter = malloc(sizeof *exporter)))
 65+        return NULL;
 66+
 67+    exporter_initialize(&exporter->base, &exporter_impl);
 68+    exporter->image = image;
 69+    drawable_add_exporter(drawable, &exporter->base);
 70+
 71+    return pixman_image_ref(image);
 72 
 73-    return 0;
 74+  error1:
 75+    wld_unmap(drawable);
 76+  error0:
 77+    return NULL;
 78 }
 79 
 80 bool renderer_set_target(struct wld_renderer * base,
 81@@ -180,11 +233,13 @@ bool renderer_set_target(struct wld_renderer * base,
 82 {
 83     struct pixman_renderer * renderer = pixman_renderer(base);
 84 
 85-    if (drawable && drawable->impl != &drawable_impl)
 86-        return false;
 87+    if (renderer->target)
 88+        pixman_image_unref(renderer->target);
 89 
 90-    renderer->target = drawable ? pixman_drawable(drawable)->image : NULL;
 91+    if (drawable)
 92+        return (renderer->target = pixman_image(drawable));
 93 
 94+    renderer->target = NULL;
 95     return true;
 96 }
 97 
 98@@ -220,12 +275,10 @@ void renderer_copy_rectangle(struct wld_renderer * base,
 99                              uint32_t width, uint32_t height)
100 {
101     struct pixman_renderer * renderer = pixman_renderer(base);
102-    pixman_image_t * dst = renderer->target, * src;
103+    pixman_image_t * src = pixman_image(drawable), * dst = renderer->target;
104 
105-    if (drawable->impl != &drawable_impl)
106-        return;
107+    if (!src) return;
108 
109-    src = pixman_drawable(drawable)->image;
110     pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
111                              src_x, src_y, 0, 0, dst_x, dst_y, width, height);
112 }
113@@ -236,12 +289,10 @@ void renderer_copy_region(struct wld_renderer * base,
114                           pixman_region32_t * region)
115 {
116     struct pixman_renderer * renderer = pixman_renderer(base);
117-    pixman_image_t * dst = renderer->target, * src;
118+    pixman_image_t * src = pixman_image(drawable), * dst = renderer->target;
119 
120-    if (drawable->impl != &drawable_impl)
121-        return;
122+    if (!src) return;
123 
124-    src = pixman_drawable(drawable)->image;
125     pixman_image_set_clip_region32(src, region);
126     pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
127                              region->extents.x1, region->extents.y1, 0, 0,
128@@ -383,3 +434,27 @@ void drawable_destroy(struct wld_drawable * drawable)
129     free(pixman);
130 }
131 
132+/**** Exporter ****/
133+bool exporter_export(struct wld_exporter * base, struct wld_drawable * drawable,
134+                     uint32_t type, union wld_object * object)
135+{
136+    struct pixman_exporter * exporter = pixman_exporter(base);
137+
138+    switch (type)
139+    {
140+        case WLD_PIXMAN_OBJECT_IMAGE:
141+            object->ptr = pixman_image_ref(exporter->image);
142+            return true;
143+        default:
144+            return false;
145+    }
146+}
147+
148+void exporter_destroy(struct wld_exporter * base)
149+{
150+    struct pixman_exporter * exporter = pixman_exporter(base);
151+
152+    pixman_image_unref(exporter->image);
153+    free(exporter);
154+}
155+
+5, -0
 1@@ -26,6 +26,11 @@
 2 
 3 #include <stdint.h>
 4 
 5+enum wld_pixman_object_type
 6+{
 7+    WLD_PIXMAN_OBJECT_IMAGE = 0x00030000
 8+};
 9+
10 extern struct wld_context * wld_pixman_context;
11 
12 static inline struct wld_context * wld_pixman_create_context()