aboutsummaryrefslogtreecommitdiff
path: root/src/wld/pixman.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/wld/pixman.c')
-rw-r--r--src/wld/pixman.c620
1 files changed, 289 insertions, 331 deletions
diff --git a/src/wld/pixman.c b/src/wld/pixman.c
index 50a10ec..4f46119 100644
--- a/src/wld/pixman.c
+++ b/src/wld/pixman.c
@@ -24,427 +24,385 @@
#include "wld/pixman.h"
#include "wld/wld-private.h"
-#define PIXMAN_COLOR(c) { \
- .alpha = ((c >> 24) & 0xff) * 0x101, \
- .red = ((c >> 16) & 0xff) * 0x101, \
- .green = ((c >> 8) & 0xff) * 0x101, \
- .blue = ((c >> 0) & 0xff) * 0x101, \
-}
-
-struct pixman_renderer
-{
- struct wld_renderer base;
- pixman_image_t * target;
- pixman_glyph_cache_t * glyph_cache;
+#define PIXMAN_COLOR(c) \
+ { \
+ .alpha = ((c >> 24) & 0xff) * 0x101, .red = ((c >> 16) & 0xff) * 0x101, \
+ .green = ((c >> 8) & 0xff) * 0x101, .blue = ((c >> 0) & 0xff) * 0x101, \
+ }
+
+struct pixman_renderer {
+ struct wld_renderer base;
+ pixman_image_t *target;
+ pixman_glyph_cache_t *glyph_cache;
};
-struct pixman_buffer
-{
- struct buffer base;
- pixman_image_t * image;
+struct pixman_buffer {
+ struct buffer base;
+ pixman_image_t *image;
};
-struct pixman_map
-{
- struct wld_exporter exporter;
- struct wld_destructor destructor;
- pixman_image_t * image;
+struct pixman_map {
+ struct wld_exporter exporter;
+ struct wld_destructor destructor;
+ pixman_image_t *image;
};
#include "interface/context.h"
#define RENDERER_IMPLEMENTS_REGION
-#include "interface/renderer.h"
#include "interface/buffer.h"
+#include "interface/renderer.h"
IMPL(pixman_renderer, wld_renderer)
IMPL(pixman_buffer, wld_buffer)
-static struct wld_context context = { .impl = &wld_context_impl };
+static struct wld_context context = {.impl = &wld_context_impl};
EXPORT
-struct wld_context * wld_pixman_context = &context;
+struct wld_context *wld_pixman_context = &context;
-struct wld_renderer * context_create_renderer(struct wld_context * context)
-{
- struct pixman_renderer * renderer;
+struct wld_renderer *context_create_renderer(struct wld_context *context) {
+ struct pixman_renderer *renderer;
- if (!(renderer = malloc(sizeof *renderer)))
- goto error0;
+ if (!(renderer = malloc(sizeof *renderer)))
+ goto error0;
- if (!(renderer->glyph_cache = pixman_glyph_cache_create()))
- goto error1;
+ if (!(renderer->glyph_cache = pixman_glyph_cache_create()))
+ goto error1;
- renderer_initialize(&renderer->base, &wld_renderer_impl);
- renderer->target = NULL;
+ renderer_initialize(&renderer->base, &wld_renderer_impl);
+ renderer->target = NULL;
- return &renderer->base;
+ return &renderer->base;
- error1:
- free(renderer);
- error0:
- return NULL;
+error1:
+ free(renderer);
+error0:
+ return NULL;
}
-static struct buffer * new_buffer(pixman_image_t * image)
-{
- struct pixman_buffer * buffer;
+static struct buffer *new_buffer(pixman_image_t *image) {
+ struct pixman_buffer *buffer;
- if (!(buffer = malloc(sizeof *buffer)))
- return NULL;
+ if (!(buffer = malloc(sizeof *buffer)))
+ return NULL;
- buffer_initialize(&buffer->base, &wld_buffer_impl,
- pixman_image_get_width(image),
- pixman_image_get_height(image),
- format_pixman_to_wld(pixman_image_get_format(image)),
- pixman_image_get_stride(image));
- buffer->base.base.map = pixman_image_get_data(image);
- buffer->image = image;
+ buffer_initialize(&buffer->base, &wld_buffer_impl,
+ pixman_image_get_width(image),
+ pixman_image_get_height(image),
+ format_pixman_to_wld(pixman_image_get_format(image)),
+ pixman_image_get_stride(image));
+ buffer->base.base.map = pixman_image_get_data(image);
+ buffer->image = image;
- return &buffer->base;
+ return &buffer->base;
}
-struct buffer * context_create_buffer(struct wld_context * context,
- uint32_t width, uint32_t height,
- uint32_t format, uint32_t flags)
-{
- struct buffer * buffer;
- pixman_image_t * image;
+struct buffer *context_create_buffer(struct wld_context *context,
+ uint32_t width, uint32_t height,
+ uint32_t format, uint32_t flags) {
+ struct buffer *buffer;
+ pixman_image_t *image;
- image = pixman_image_create_bits(format_wld_to_pixman(format),
- width, height, NULL, 0);
+ image = pixman_image_create_bits(format_wld_to_pixman(format), width, height,
+ NULL, 0);
- if (!image)
- goto error0;
+ if (!image)
+ goto error0;
- if (!(buffer = new_buffer(image)))
- goto error1;
+ if (!(buffer = new_buffer(image)))
+ goto error1;
- return buffer;
+ return buffer;
- error1:
- pixman_image_unref(image);
- error0:
- return NULL;
+error1:
+ pixman_image_unref(image);
+error0:
+ return NULL;
}
-struct buffer * context_import_buffer(struct wld_context * context,
- uint32_t type, union wld_object object,
- uint32_t width, uint32_t height,
- uint32_t format, uint32_t pitch)
-{
- struct buffer * buffer;
- pixman_image_t * image;
-
- switch (type)
- {
- case WLD_OBJECT_DATA:
- image = pixman_image_create_bits(format_wld_to_pixman(format),
- width, height, object.ptr, pitch);
- break;
- default: image = NULL;
- }
-
- if (!image)
- goto error0;
-
- if (!(buffer = new_buffer(image)))
- goto error1;
-
- return buffer;
-
- error1:
- pixman_image_unref(image);
- error0:
- return NULL;
-
+struct buffer *context_import_buffer(struct wld_context *context, uint32_t type,
+ union wld_object object, uint32_t width,
+ uint32_t height, uint32_t format,
+ uint32_t pitch) {
+ struct buffer *buffer;
+ pixman_image_t *image;
+
+ switch (type) {
+ case WLD_OBJECT_DATA:
+ image = pixman_image_create_bits(format_wld_to_pixman(format), width,
+ height, object.ptr, pitch);
+ break;
+ default:
+ image = NULL;
+ }
+
+ if (!image)
+ goto error0;
+
+ if (!(buffer = new_buffer(image)))
+ goto error1;
+
+ return buffer;
+
+error1:
+ pixman_image_unref(image);
+error0:
+ return NULL;
}
-void context_destroy(struct wld_context * context)
-{
-}
+void context_destroy(struct wld_context *context) {}
-uint32_t renderer_capabilities(struct wld_renderer * renderer,
- struct buffer * buffer)
-{
- /* The pixman renderer can read and write to any buffer using it's map
- * implementation. */
- return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
+uint32_t renderer_capabilities(struct wld_renderer *renderer,
+ struct buffer *buffer) {
+ /* The pixman renderer can read and write to any buffer using it's map
+ * implementation. */
+ return WLD_CAPABILITY_READ | WLD_CAPABILITY_WRITE;
}
-static void destroy_image(pixman_image_t * image, void * data)
-{
- struct buffer * buffer = data;
+static void destroy_image(pixman_image_t *image, void *data) {
+ struct buffer *buffer = data;
- wld_unmap(&buffer->base);
+ wld_unmap(&buffer->base);
}
-bool map_export(struct wld_exporter * exporter, struct wld_buffer * buffer,
- uint32_t type, union wld_object * object)
-{
- struct pixman_map * map
- = CONTAINER_OF(exporter, struct pixman_map, exporter);
-
- switch (type)
- {
- case WLD_PIXMAN_OBJECT_IMAGE:
- object->ptr = pixman_image_ref(map->image);
- return true;
- default:
- return false;
- }
+bool map_export(struct wld_exporter *exporter, struct wld_buffer *buffer,
+ uint32_t type, union wld_object *object) {
+ struct pixman_map *map = CONTAINER_OF(exporter, struct pixman_map, exporter);
+
+ switch (type) {
+ case WLD_PIXMAN_OBJECT_IMAGE:
+ object->ptr = pixman_image_ref(map->image);
+ return true;
+ default:
+ return false;
+ }
}
-void map_destroy(struct wld_destructor * destructor)
-{
- struct pixman_map * map
- = CONTAINER_OF(destructor, struct pixman_map, destructor);
+void map_destroy(struct wld_destructor *destructor) {
+ struct pixman_map *map =
+ CONTAINER_OF(destructor, struct pixman_map, destructor);
- pixman_image_unref(map->image);
- free(map);
+ pixman_image_unref(map->image);
+ free(map);
}
-static pixman_image_t * pixman_image(struct buffer * buffer)
-{
- if (buffer->base.impl == &wld_buffer_impl)
- return pixman_image_ref(pixman_buffer(&buffer->base)->image);
+static pixman_image_t *pixman_image(struct buffer *buffer) {
+ if (buffer->base.impl == &wld_buffer_impl)
+ return pixman_image_ref(pixman_buffer(&buffer->base)->image);
- union wld_object object;
+ union wld_object object;
- if (wld_export(&buffer->base, WLD_PIXMAN_OBJECT_IMAGE, &object))
- return object.ptr;
+ if (wld_export(&buffer->base, WLD_PIXMAN_OBJECT_IMAGE, &object))
+ return object.ptr;
- struct pixman_map * map;
- pixman_image_t * image;
+ struct pixman_map *map;
+ pixman_image_t *image;
- if (!wld_map(&buffer->base))
- goto error0;
+ if (!wld_map(&buffer->base))
+ goto error0;
- image = pixman_image_create_bits(format_wld_to_pixman(buffer->base.format),
- buffer->base.width, buffer->base.height,
- buffer->base.map, buffer->base.pitch);
+ image = pixman_image_create_bits(format_wld_to_pixman(buffer->base.format),
+ buffer->base.width, buffer->base.height,
+ buffer->base.map, buffer->base.pitch);
- if (!image)
- goto error1;
+ if (!image)
+ goto error1;
- if (!(map = malloc(sizeof *map)))
- goto error2;
+ if (!(map = malloc(sizeof *map)))
+ goto error2;
- map->image = image;
- map->exporter.export = &map_export;
- wld_buffer_add_exporter(&buffer->base, &map->exporter);
- map->destructor.destroy = &map_destroy;
- wld_buffer_add_destructor(&buffer->base, &map->destructor);
- pixman_image_set_destroy_function(image, &destroy_image, buffer);
+ map->image = image;
+ map->exporter.export = &map_export;
+ wld_buffer_add_exporter(&buffer->base, &map->exporter);
+ map->destructor.destroy = &map_destroy;
+ wld_buffer_add_destructor(&buffer->base, &map->destructor);
+ pixman_image_set_destroy_function(image, &destroy_image, buffer);
- return pixman_image_ref(image);
+ return pixman_image_ref(image);
- error2:
- pixman_image_unref(image);
- error1:
- wld_unmap(&buffer->base);
- error0:
- return NULL;
+error2:
+ pixman_image_unref(image);
+error1:
+ wld_unmap(&buffer->base);
+error0:
+ return NULL;
}
-bool renderer_set_target(struct wld_renderer * base, struct buffer * buffer)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
+bool renderer_set_target(struct wld_renderer *base, struct buffer *buffer) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
- if (renderer->target)
- pixman_image_unref(renderer->target);
+ if (renderer->target)
+ pixman_image_unref(renderer->target);
- if (buffer)
- return (renderer->target = pixman_image(buffer));
+ if (buffer)
+ return (renderer->target = pixman_image(buffer));
- renderer->target = NULL;
- return true;
+ renderer->target = NULL;
+ return true;
}
-void renderer_fill_rectangle(struct wld_renderer * base, uint32_t color,
- int32_t x, int32_t y,
- uint32_t width, uint32_t height)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
- pixman_color_t pixman_color = PIXMAN_COLOR(color);
- pixman_box32_t box = { x, y, x + width, y + height };
+void renderer_fill_rectangle(struct wld_renderer *base, uint32_t color,
+ int32_t x, int32_t y, uint32_t width,
+ uint32_t height) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_box32_t box = {x, y, x + width, y + height};
- pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
- &pixman_color, 1, &box);
+ pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target, &pixman_color, 1,
+ &box);
}
-void renderer_fill_region(struct wld_renderer * base, uint32_t color,
- pixman_region32_t * region)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
- pixman_color_t pixman_color = PIXMAN_COLOR(color);
- pixman_box32_t * boxes;
- int num_boxes;
-
- boxes = pixman_region32_rectangles(region, &num_boxes);
- pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target,
- &pixman_color, num_boxes, boxes);
+void renderer_fill_region(struct wld_renderer *base, uint32_t color,
+ pixman_region32_t *region) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_box32_t *boxes;
+ int num_boxes;
+
+ boxes = pixman_region32_rectangles(region, &num_boxes);
+ pixman_image_fill_boxes(PIXMAN_OP_SRC, renderer->target, &pixman_color,
+ num_boxes, boxes);
}
-void renderer_copy_rectangle(struct wld_renderer * base, struct buffer * buffer,
- int32_t dst_x, int32_t dst_y,
- int32_t src_x, int32_t src_y,
- uint32_t width, uint32_t height)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
- pixman_image_t * src = pixman_image(buffer), * dst = renderer->target;
+void renderer_copy_rectangle(struct wld_renderer *base, struct buffer *buffer,
+ int32_t dst_x, int32_t dst_y, int32_t src_x,
+ int32_t src_y, uint32_t width, uint32_t height) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
+ pixman_image_t *src = pixman_image(buffer), *dst = renderer->target;
- if (!src) return;
+ if (!src)
+ return;
- pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
- src_x, src_y, 0, 0, dst_x, dst_y, width, height);
+ pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst, src_x, src_y, 0, 0,
+ dst_x, dst_y, width, height);
}
-void renderer_copy_region(struct wld_renderer * base, struct buffer * buffer,
+void renderer_copy_region(struct wld_renderer *base, struct buffer *buffer,
int32_t dst_x, int32_t dst_y,
- pixman_region32_t * region)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
- pixman_image_t * src = pixman_image(buffer), * dst = renderer->target;
-
- if (!src) return;
-
- pixman_image_set_clip_region32(src, region);
- pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst,
- region->extents.x1, region->extents.y1, 0, 0,
- region->extents.x1 + dst_x,
- region->extents.y1 + dst_y,
- region->extents.x2 - region->extents.x1,
- region->extents.y2 - region->extents.y1);
- pixman_image_set_clip_region32(src, NULL);
+ pixman_region32_t *region) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
+ pixman_image_t *src = pixman_image(buffer), *dst = renderer->target;
+
+ if (!src)
+ return;
+
+ pixman_image_set_clip_region32(src, region);
+ pixman_image_composite32(PIXMAN_OP_SRC, src, NULL, dst, region->extents.x1,
+ region->extents.y1, 0, 0, region->extents.x1 + dst_x,
+ region->extents.y1 + dst_y,
+ region->extents.x2 - region->extents.x1,
+ region->extents.y2 - region->extents.y1);
+ pixman_image_set_clip_region32(src, NULL);
}
-static inline uint8_t reverse(uint8_t byte)
-{
- byte = ((byte << 1) & 0xaa) | ((byte >> 1) & 0x55);
- byte = ((byte << 2) & 0xcc) | ((byte >> 2) & 0x33);
- byte = ((byte << 4) & 0xf0) | ((byte >> 4) & 0x0f);
+static inline uint8_t reverse(uint8_t byte) {
+ byte = ((byte << 1) & 0xaa) | ((byte >> 1) & 0x55);
+ byte = ((byte << 2) & 0xcc) | ((byte >> 2) & 0x33);
+ byte = ((byte << 4) & 0xf0) | ((byte >> 4) & 0x0f);
- return byte;
+ return byte;
}
-void renderer_draw_text(struct wld_renderer * base,
- struct font * font, uint32_t color,
- int32_t x, int32_t y, const char * text,
- uint32_t length, struct wld_extents * extents)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
- int ret;
- uint32_t c;
- struct glyph * glyph;
- FT_UInt glyph_index;
- pixman_glyph_t glyphs[length == -1 ? (length = strlen(text)) : length];
- uint32_t index = 0, origin_x = 0;
- pixman_color_t pixman_color = PIXMAN_COLOR(color);
- pixman_image_t * solid;
-
- solid = pixman_image_create_solid_fill(&pixman_color);
-
- while ((ret = FcUtf8ToUcs4((FcChar8 *) text, &c, length)) > 0 && c != '\0')
- {
- text += ret;
- length -= ret;
- glyph_index = FT_Get_Char_Index(font->face, c);
-
- if (!font_ensure_glyph(font, glyph_index))
- continue;
-
- glyph = font->glyphs[glyph_index];
-
- glyphs[index].x = origin_x;
- glyphs[index].y = 0;
- glyphs[index].glyph = pixman_glyph_cache_lookup(renderer->glyph_cache,
- font, glyph);
-
- /* If we don't have the glyph in our cache, do some conversions to make
- * pixman happy, and then insert it. */
- if (!glyphs[index].glyph)
- {
- uint8_t * src, * dst;
- uint32_t row, byte_index, bytes_per_row, pitch;
- pixman_image_t * image;
- FT_Bitmap * bitmap;
-
- bitmap = &glyph->bitmap;
- image = pixman_image_create_bits
- (PIXMAN_a1, bitmap->width, bitmap->rows, NULL, bitmap->pitch);
-
- if (!image)
- goto advance;
-
- pitch = pixman_image_get_stride(image);
- bytes_per_row = (bitmap->width + 7) / 8;
- src = bitmap->buffer;
- dst = (uint8_t *) pixman_image_get_data(image);
-
- for (row = 0; row < bitmap->rows; ++row)
- {
- /* Pixman's A1 format expects the bits in the opposite order
- * that Freetype gives us. Sigh... */
- for (byte_index = 0; byte_index < bytes_per_row; ++byte_index)
- dst[byte_index] = reverse(src[byte_index]);
-
- dst += pitch;
- src += bitmap->pitch;
- }
-
- /* Insert the glyph into the cache. */
- pixman_glyph_cache_freeze(renderer->glyph_cache);
- glyphs[index].glyph = pixman_glyph_cache_insert
- (renderer->glyph_cache, font, glyph,
- -glyph->x, -glyph->y, image);
- pixman_glyph_cache_thaw(renderer->glyph_cache);
-
- /* The glyph cache copies the contents of the glyph bitmap. */
- pixman_image_unref(image);
- }
-
- ++index;
-
- advance:
- origin_x += glyph->advance;
+void renderer_draw_text(struct wld_renderer *base, struct font *font,
+ uint32_t color, int32_t x, int32_t y, const char *text,
+ uint32_t length, struct wld_extents *extents) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
+ int ret;
+ uint32_t c;
+ struct glyph *glyph;
+ FT_UInt glyph_index;
+ pixman_glyph_t glyphs[length == -1 ? (length = strlen(text)) : length];
+ uint32_t index = 0, origin_x = 0;
+ pixman_color_t pixman_color = PIXMAN_COLOR(color);
+ pixman_image_t *solid;
+
+ solid = pixman_image_create_solid_fill(&pixman_color);
+
+ while ((ret = FcUtf8ToUcs4((FcChar8 *)text, &c, length)) > 0 && c != '\0') {
+ text += ret;
+ length -= ret;
+ glyph_index = FT_Get_Char_Index(font->face, c);
+
+ if (!font_ensure_glyph(font, glyph_index))
+ continue;
+
+ glyph = font->glyphs[glyph_index];
+
+ glyphs[index].x = origin_x;
+ glyphs[index].y = 0;
+ glyphs[index].glyph =
+ pixman_glyph_cache_lookup(renderer->glyph_cache, font, glyph);
+
+ /* If we don't have the glyph in our cache, do some conversions to make
+ * pixman happy, and then insert it. */
+ if (!glyphs[index].glyph) {
+ uint8_t *src, *dst;
+ uint32_t row, byte_index, bytes_per_row, pitch;
+ pixman_image_t *image;
+ FT_Bitmap *bitmap;
+
+ bitmap = &glyph->bitmap;
+ image = pixman_image_create_bits(PIXMAN_a1, bitmap->width, bitmap->rows,
+ NULL, bitmap->pitch);
+
+ if (!image)
+ goto advance;
+
+ pitch = pixman_image_get_stride(image);
+ bytes_per_row = (bitmap->width + 7) / 8;
+ src = bitmap->buffer;
+ dst = (uint8_t *)pixman_image_get_data(image);
+
+ for (row = 0; row < bitmap->rows; ++row) {
+ /* Pixman's A1 format expects the bits in the opposite order
+ * that Freetype gives us. Sigh... */
+ for (byte_index = 0; byte_index < bytes_per_row; ++byte_index)
+ dst[byte_index] = reverse(src[byte_index]);
+
+ dst += pitch;
+ src += bitmap->pitch;
+ }
+
+ /* Insert the glyph into the cache. */
+ pixman_glyph_cache_freeze(renderer->glyph_cache);
+ glyphs[index].glyph = pixman_glyph_cache_insert(
+ renderer->glyph_cache, font, glyph, -glyph->x, -glyph->y, image);
+ pixman_glyph_cache_thaw(renderer->glyph_cache);
+
+ /* The glyph cache copies the contents of the glyph bitmap. */
+ pixman_image_unref(image);
}
- pixman_composite_glyphs_no_mask(PIXMAN_OP_OVER, solid, renderer->target,
- 0, 0, x, y, renderer->glyph_cache,
- index, glyphs);
+ ++index;
- pixman_image_unref(solid);
+ advance:
+ origin_x += glyph->advance;
+ }
- if (extents)
- extents->advance = origin_x;
-}
+ pixman_composite_glyphs_no_mask(PIXMAN_OP_OVER, solid, renderer->target, 0, 0,
+ x, y, renderer->glyph_cache, index, glyphs);
-void renderer_flush(struct wld_renderer * renderer)
-{
+ pixman_image_unref(solid);
+
+ if (extents)
+ extents->advance = origin_x;
}
-void renderer_destroy(struct wld_renderer * base)
-{
- struct pixman_renderer * renderer = pixman_renderer(base);
+void renderer_flush(struct wld_renderer *renderer) {}
- pixman_glyph_cache_destroy(renderer->glyph_cache);
- free(renderer);
-}
+void renderer_destroy(struct wld_renderer *base) {
+ struct pixman_renderer *renderer = pixman_renderer(base);
-bool buffer_map(struct buffer * buffer)
-{
- return true;
+ pixman_glyph_cache_destroy(renderer->glyph_cache);
+ free(renderer);
}
-bool buffer_unmap(struct buffer * buffer)
-{
- return true;
-}
+bool buffer_map(struct buffer *buffer) { return true; }
-void buffer_destroy(struct buffer * base)
-{
- struct pixman_buffer * buffer = pixman_buffer(&base->base);
+bool buffer_unmap(struct buffer *buffer) { return true; }
- pixman_image_unref(buffer->image);
- free(buffer);
-}
+void buffer_destroy(struct buffer *base) {
+ struct pixman_buffer *buffer = pixman_buffer(&base->base);
+ pixman_image_unref(buffer->image);
+ free(buffer);
+}