summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension-python/dimension.pxd4
-rw-r--r--libdimension-python/dimension.pyx4
-rw-r--r--libdimension/canvas.c37
-rw-r--r--libdimension/dimension/canvas.h25
-rw-r--r--libdimension/dimension/gl.h3
-rw-r--r--libdimension/dimension/png.h3
-rw-r--r--libdimension/gl-stubs.c2
-rw-r--r--libdimension/gl.c11
-rw-r--r--libdimension/png-stubs.c2
-rw-r--r--libdimension/png.c11
-rw-r--r--libdimension/rgba.c44
-rw-r--r--libdimension/rgba.h28
-rw-r--r--libdimension/tests/gl.c2
-rw-r--r--libdimension/tests/png.c2
-rw-r--r--libdimension/tests/render.c4
15 files changed, 95 insertions, 87 deletions
diff --git a/libdimension-python/dimension.pxd b/libdimension-python/dimension.pxd
index f002125..df291a6 100644
--- a/libdimension-python/dimension.pxd
+++ b/libdimension-python/dimension.pxd
@@ -219,13 +219,13 @@ cdef extern from "../libdimension/dimension.h":
void dmnsn_canvas_clear(dmnsn_canvas *canvas, dmnsn_tcolor tcolor)
- int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
+ int dmnsn_png_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
int dmnsn_png_write_canvas(dmnsn_canvas *canvas, FILE *file)
dmnsn_future *dmnsn_png_write_canvas_async(dmnsn_canvas *canvas, FILE *file)
dmnsn_canvas *dmnsn_png_read_canvas(dmnsn_pool *pool, FILE *file)
dmnsn_future *dmnsn_png_read_canvas_async(dmnsn_canvas **canvas, dmnsn_pool *pool, FILE *file)
- int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
+ int dmnsn_gl_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
int dmnsn_gl_write_canvas(dmnsn_canvas *canvas)
############
diff --git a/libdimension-python/dimension.pyx b/libdimension-python/dimension.pyx
index 58b68e2..2bdcc64 100644
--- a/libdimension-python/dimension.pyx
+++ b/libdimension-python/dimension.pyx
@@ -666,12 +666,12 @@ cdef class Canvas:
def optimize_PNG(self):
"""Optimize a canvas for PNG output."""
- if dmnsn_png_optimize_canvas(self._canvas) != 0:
+ if dmnsn_png_optimize_canvas(_get_pool(), self._canvas) != 0:
_raise_OSError()
def optimize_GL(self):
"""Optimize a canvas for OpenGL output."""
- if dmnsn_gl_optimize_canvas(self._canvas) != 0:
+ if dmnsn_gl_optimize_canvas(_get_pool(), self._canvas) != 0:
_raise_OSError()
def clear(self, c):
diff --git a/libdimension/canvas.c b/libdimension/canvas.c
index b605108..2aade47 100644
--- a/libdimension/canvas.c
+++ b/libdimension/canvas.c
@@ -25,50 +25,37 @@
#include "dimension-internal.h"
-/// cleanup_fn for canvases.
-static void dmnsn_canvas_cleanup(void *ptr);
-
dmnsn_canvas *
dmnsn_new_canvas(dmnsn_pool *pool, size_t width, size_t height)
{
- dmnsn_canvas *canvas = DMNSN_PALLOC_TIDY(pool, dmnsn_canvas, dmnsn_canvas_cleanup);
+ dmnsn_canvas *canvas = DMNSN_PALLOC(pool, dmnsn_canvas);
canvas->width = width;
canvas->height = height;
- canvas->optimizers = DMNSN_NEW_ARRAY(dmnsn_canvas_optimizer);
+ canvas->optimizers = DMNSN_PALLOC_ARRAY(pool, dmnsn_canvas_optimizer *);
canvas->pixels = dmnsn_palloc(pool, sizeof(dmnsn_tcolor)*width*height);
return canvas;
}
void
-dmnsn_canvas_cleanup(void *ptr)
+dmnsn_init_canvas_optimizer(dmnsn_canvas_optimizer *optimizer)
{
- dmnsn_canvas *canvas = ptr;
-
- // Free the optimizers
- DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
- if (i->free_fn) {
- i->free_fn(i->ptr);
- }
- }
- dmnsn_delete_array(canvas->optimizers);
+ optimizer->optimizer_fn = NULL;
}
// Set a canvas optimizer
void
-dmnsn_canvas_optimize(dmnsn_canvas *canvas,
- const dmnsn_canvas_optimizer *optimizer)
+dmnsn_canvas_optimize(dmnsn_canvas *canvas, const dmnsn_canvas_optimizer *optimizer)
{
- dmnsn_array_push(canvas->optimizers, optimizer);
+ dmnsn_array_push(canvas->optimizers, &optimizer);
}
// Find an optimizer if it's already installed
dmnsn_canvas_optimizer *
-dmnsn_canvas_find_optimizer(const dmnsn_canvas *canvas,
- dmnsn_canvas_optimizer_fn *optimizer_fn)
+dmnsn_canvas_find_optimizer(const dmnsn_canvas *canvas, dmnsn_canvas_optimizer_fn *optimizer_fn)
{
- DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
- if (i->optimizer_fn == optimizer_fn) {
- return i;
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer **, i, canvas->optimizers) {
+ if ((*i)->optimizer_fn == optimizer_fn) {
+ return *i;
}
}
@@ -88,8 +75,8 @@ dmnsn_canvas_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y,
canvas->pixels[y*canvas->width + x] = tcolor;
// Call the optimizers
- DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) {
- i->optimizer_fn(canvas, i->ptr, x, y);
+ DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer **, i, canvas->optimizers) {
+ (*i)->optimizer_fn(*i, canvas, x, y);
}
}
diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h
index d03a37e..e325364 100644
--- a/libdimension/dimension/canvas.h
+++ b/libdimension/dimension/canvas.h
@@ -41,23 +41,22 @@ typedef struct dmnsn_canvas {
dmnsn_tcolor *pixels;
} dmnsn_canvas;
+/* Forward-declare dmnsn_canvas_optimizer. */
+typedef struct dmnsn_canvas_optimizer dmnsn_canvas_optimizer;
+
/**
* Canvas optimizer callback type.
+ * @param[in] optimizer The canvas optimizer.
* @param[in] canvas The canvas that was just updated.
- * @param[in] ptr The canvas optimizer's data pointer.
- * @param[in] x The x-coordinate that was just updated.
- * @param[in] y The y-coordinate that was just updated.
+ * @param[in] x The x-coordinate that was just updated.
+ * @param[in] y The y-coordinate that was just updated.
*/
-typedef void dmnsn_canvas_optimizer_fn(const dmnsn_canvas *canvas, void *ptr,
- size_t x, size_t y);
+typedef void dmnsn_canvas_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y);
/** Canvas optimizer. */
-typedef struct dmnsn_canvas_optimizer {
+struct dmnsn_canvas_optimizer {
dmnsn_canvas_optimizer_fn *optimizer_fn; /**< Optimizer callback. */
- dmnsn_free_fn *free_fn; /**< Destructor callback. */
-
- void *ptr; /**< Generic pointer. */
-} dmnsn_canvas_optimizer;
+};
/**
* Allocate a new canvas.
@@ -69,6 +68,12 @@ typedef struct dmnsn_canvas_optimizer {
dmnsn_canvas *dmnsn_new_canvas(dmnsn_pool *pool, size_t width, size_t height);
/**
+ * Initialize a dmnsn_canvas_optimizer field
+ * @param[in] optimizer The optimizer to initialize.
+ */
+void dmnsn_init_canvas_optimizer(dmnsn_canvas_optimizer *optimizer);
+
+/**
* Set a canvas optimizer
* @param[in,out] canvas The canvas to optimize.
* @param[in] optimizer The optimizer to use.
diff --git a/libdimension/dimension/gl.h b/libdimension/dimension/gl.h
index 8e64ba6..284a248 100644
--- a/libdimension/dimension/gl.h
+++ b/libdimension/dimension/gl.h
@@ -25,10 +25,11 @@
/**
* Optimize a canvas for GL drawing
+ * @param[in] pool The memory pool to allocate from.
* @param[in,out] canvas The canvas to optimize.
* @return Whether the canvas was successfully optimized.
*/
-int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas);
+int dmnsn_gl_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas);
/**
* Write canvas to GL framebuffer.
diff --git a/libdimension/dimension/png.h b/libdimension/dimension/png.h
index c45a9bf..f4d2c1e 100644
--- a/libdimension/dimension/png.h
+++ b/libdimension/dimension/png.h
@@ -27,10 +27,11 @@
/**
* Optimize a canvas for PNG exporting
+ * @param[in] pool The memory pool to allocate from.
* @param[in,out] canvas The canvas to optimize.
* @return Whether the canvas was successfully optimized.
*/
-int dmnsn_png_optimize_canvas(dmnsn_canvas *canvas);
+int dmnsn_png_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas);
/**
* Write a canvas to a file in PNG format.
diff --git a/libdimension/gl-stubs.c b/libdimension/gl-stubs.c
index ca17056..df31308 100644
--- a/libdimension/gl-stubs.c
+++ b/libdimension/gl-stubs.c
@@ -27,7 +27,7 @@
#include <errno.h>
int
-dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_gl_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
errno = ENOSYS;
return -1;
diff --git a/libdimension/gl.c b/libdimension/gl.c
index 2800484..dd707a9 100644
--- a/libdimension/gl.c
+++ b/libdimension/gl.c
@@ -30,9 +30,9 @@
// Optimize canvas for GL drawing
int
-dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_gl_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
- dmnsn_rgba8_optimize_canvas(canvas);
+ dmnsn_rgba8_optimize_canvas(pool, canvas);
return 0;
}
@@ -44,10 +44,9 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas)
size_t height = canvas->height;
// Check if we can optimize this
- dmnsn_canvas_optimizer *optimizer =
- dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba8_optimizer_fn);
- if (optimizer) {
- glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, optimizer->ptr);
+ dmnsn_rgba8_optimizer *rgba8 = (dmnsn_rgba8_optimizer *)dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba8_optimizer_fn);
+ if (rgba8) {
+ glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, rgba8->data);
return glGetError() == GL_NO_ERROR ? 0 : 1;
}
diff --git a/libdimension/png-stubs.c b/libdimension/png-stubs.c
index d68b543..9c752a5 100644
--- a/libdimension/png-stubs.c
+++ b/libdimension/png-stubs.c
@@ -27,7 +27,7 @@
#include <errno.h>
int
-dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_png_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
errno = ENOSYS;
return -1;
diff --git a/libdimension/png.c b/libdimension/png.c
index 24f8afa..faca080 100644
--- a/libdimension/png.c
+++ b/libdimension/png.c
@@ -31,9 +31,9 @@
#include <stdint.h>
int
-dmnsn_png_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_png_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
- dmnsn_rgba16_optimize_canvas(canvas);
+ dmnsn_rgba16_optimize_canvas(pool, canvas);
return 0;
}
@@ -171,12 +171,11 @@ dmnsn_png_write_canvas_thread(void *ptr)
}
// Check if we can optimize this
- dmnsn_canvas_optimizer *optimizer =
- dmnsn_canvas_find_optimizer(payload->canvas, dmnsn_rgba16_optimizer_fn);
- if (optimizer) {
+ dmnsn_rgba16_optimizer *rgba16 = (dmnsn_rgba16_optimizer *)dmnsn_canvas_find_optimizer(payload->canvas, dmnsn_rgba16_optimizer_fn);
+ if (rgba16) {
for (size_t y = 0; y < height; ++y) {
// Invert the rows. PNG coordinates are fourth quadrant.
- uint16_t *row_opt = (uint16_t *)optimizer->ptr + 4*(height - y - 1)*width;
+ uint16_t *row_opt = rgba16->data + 4*(height - y - 1)*width;
png_write_row(png_ptr, (png_bytep)row_opt);
dmnsn_future_increment(payload->future);
}
diff --git a/libdimension/rgba.c b/libdimension/rgba.c
index 6df124e..367927f 100644
--- a/libdimension/rgba.c
+++ b/libdimension/rgba.c
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2010-2014 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -27,40 +27,45 @@
#include <stdint.h>
void
-dmnsn_rgba8_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_rgba8_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
if (dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba8_optimizer_fn)) {
return;
}
- dmnsn_canvas_optimizer optimizer;
- optimizer.optimizer_fn = dmnsn_rgba8_optimizer_fn;
- optimizer.free_fn = dmnsn_free;
- optimizer.ptr = dmnsn_malloc(4*canvas->width*canvas->height*sizeof(uint8_t));
+ size_t ndata = 4*canvas->width*canvas->height;
+ dmnsn_rgba8_optimizer *rgba8 = dmnsn_palloc(pool, sizeof(dmnsn_rgba8_optimizer) + ndata*sizeof(uint8_t));
- dmnsn_canvas_optimize(canvas, &optimizer);
+ dmnsn_canvas_optimizer *optimizer = &rgba8->optimizer;
+ dmnsn_init_canvas_optimizer(optimizer);
+ optimizer->optimizer_fn = dmnsn_rgba8_optimizer_fn;
+
+ dmnsn_canvas_optimize(canvas, optimizer);
}
void
-dmnsn_rgba16_optimize_canvas(dmnsn_canvas *canvas)
+dmnsn_rgba16_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas)
{
if (dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba16_optimizer_fn)) {
return;
}
- dmnsn_canvas_optimizer optimizer;
- optimizer.optimizer_fn = dmnsn_rgba16_optimizer_fn;
- optimizer.free_fn = dmnsn_free;
- optimizer.ptr = dmnsn_malloc(4*canvas->width*canvas->height*sizeof(uint16_t));
+ size_t ndata = 4*canvas->width*canvas->height;
+ dmnsn_rgba16_optimizer *rgba16 = dmnsn_palloc(pool, sizeof(dmnsn_rgba16_optimizer) + ndata*sizeof(uint16_t));
+
+ dmnsn_canvas_optimizer *optimizer = &rgba16->optimizer;
+ dmnsn_init_canvas_optimizer(optimizer);
+ optimizer->optimizer_fn = dmnsn_rgba16_optimizer_fn;
- dmnsn_canvas_optimize(canvas, &optimizer);
+ dmnsn_canvas_optimize(canvas, optimizer);
}
void
-dmnsn_rgba8_optimizer_fn(const dmnsn_canvas *canvas, void *ptr,
- size_t x, size_t y)
+dmnsn_rgba8_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y)
{
- uint8_t *pixel = (uint8_t *)ptr + 4*(y*canvas->width + x);
+ dmnsn_rgba8_optimizer *rgba8 = (dmnsn_rgba8_optimizer *)optimizer;
+
+ uint8_t *pixel = rgba8->data + 4*(y*canvas->width + x);
dmnsn_tcolor tcolor = dmnsn_canvas_get_pixel(canvas, x, y);
tcolor = dmnsn_tcolor_remove_filter(tcolor);
tcolor.c = dmnsn_color_to_sRGB(tcolor.c);
@@ -73,10 +78,11 @@ dmnsn_rgba8_optimizer_fn(const dmnsn_canvas *canvas, void *ptr,
}
void
-dmnsn_rgba16_optimizer_fn(const dmnsn_canvas *canvas, void *ptr,
- size_t x, size_t y)
+dmnsn_rgba16_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y)
{
- uint16_t *pixel = (uint16_t *)ptr + 4*(y*canvas->width + x);
+ dmnsn_rgba16_optimizer *rgba16 = (dmnsn_rgba16_optimizer *)optimizer;
+
+ uint16_t *pixel = rgba16->data + 4*(y*canvas->width + x);
dmnsn_tcolor tcolor = dmnsn_canvas_get_pixel(canvas, x, y);
tcolor = dmnsn_tcolor_remove_filter(tcolor);
tcolor.c = dmnsn_color_to_sRGB(tcolor.c);
diff --git a/libdimension/rgba.h b/libdimension/rgba.h
index a67caf2..b43ca3f 100644
--- a/libdimension/rgba.h
+++ b/libdimension/rgba.h
@@ -1,5 +1,5 @@
/*************************************************************************
- * Copyright (C) 2010-2011 Tavian Barnes <tavianator@tavianator.com> *
+ * Copyright (C) 2010-2014 Tavian Barnes <tavianator@tavianator.com> *
* *
* This file is part of The Dimension Library. *
* *
@@ -23,16 +23,26 @@
* RGBA canvas optimizer interface, used by image optimizers.
*/
+#include <stdint.h>
+
+/// RGBA8 optimizer type.
+typedef struct dmnsn_rgba8_optimizer {
+ dmnsn_canvas_optimizer optimizer;
+ uint8_t data[];
+} dmnsn_rgba8_optimizer;
+
+/// RGBA16 optimizer type.
+typedef struct dmnsn_rgba16_optimizer {
+ dmnsn_canvas_optimizer optimizer;
+ uint16_t data[];
+} dmnsn_rgba16_optimizer;
+
/// Apply the RGBA8 optimizer to a canvas.
-DMNSN_INTERNAL void dmnsn_rgba8_optimize_canvas(dmnsn_canvas *canvas);
+DMNSN_INTERNAL void dmnsn_rgba8_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas);
/// Apply the RGBA16 optimizer to a canvas.
-DMNSN_INTERNAL void dmnsn_rgba16_optimize_canvas(dmnsn_canvas *canvas);
+DMNSN_INTERNAL void dmnsn_rgba16_optimize_canvas(dmnsn_pool *pool, dmnsn_canvas *canvas);
/// RGBA8 optimizer callback.
-DMNSN_INTERNAL void dmnsn_rgba8_optimizer_fn(const dmnsn_canvas *canvas,
- void *ptr,
- size_t x, size_t y);
+DMNSN_INTERNAL void dmnsn_rgba8_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y);
/// RGBA16 optimizer callback.
-DMNSN_INTERNAL void dmnsn_rgba16_optimizer_fn(const dmnsn_canvas *canvas,
- void *ptr,
- size_t x, size_t y);
+DMNSN_INTERNAL void dmnsn_rgba16_optimizer_fn(dmnsn_canvas_optimizer *optimizer, const dmnsn_canvas *canvas, size_t x, size_t y);
diff --git a/libdimension/tests/gl.c b/libdimension/tests/gl.c
index 262fecf..1546d6c 100644
--- a/libdimension/tests/gl.c
+++ b/libdimension/tests/gl.c
@@ -56,7 +56,7 @@ main(void)
*/
// Optimize the canvas for GL drawing
- if (dmnsn_gl_optimize_canvas(canvas) != 0) {
+ if (dmnsn_gl_optimize_canvas(pool, canvas) != 0) {
dmnsn_delete_pool(pool);
fprintf(stderr, "--- Couldn't optimize canvas for GL! ---\n");
return EXIT_FAILURE;
diff --git a/libdimension/tests/png.c b/libdimension/tests/png.c
index 1feff72..7311e43 100644
--- a/libdimension/tests/png.c
+++ b/libdimension/tests/png.c
@@ -34,7 +34,7 @@ main(void)
dmnsn_canvas *canvas = dmnsn_new_canvas(pool, 768, 480);
// Optimize the canvas for PNG export
- if (dmnsn_png_optimize_canvas(canvas) != 0) {
+ if (dmnsn_png_optimize_canvas(pool, canvas) != 0) {
fprintf(stderr, "--- Couldn't optimize canvas for PNG! ---\n");
ret = EXIT_FAILURE;
goto exit;
diff --git a/libdimension/tests/render.c b/libdimension/tests/render.c
index 866df2d..56a80d3 100644
--- a/libdimension/tests/render.c
+++ b/libdimension/tests/render.c
@@ -316,7 +316,7 @@ main(void)
// Optimize the canvas for PNG export
bool have_png = true;
errno = 0;
- if (dmnsn_png_optimize_canvas(scene->canvas) != 0) {
+ if (dmnsn_png_optimize_canvas(pool, scene->canvas) != 0) {
if (errno == ENOSYS) {
have_png = false;
} else {
@@ -328,7 +328,7 @@ main(void)
// Optimize the canvas for GL drawing
bool have_gl = true;
errno = 0;
- if (dmnsn_gl_optimize_canvas(scene->canvas) != 0) {
+ if (dmnsn_gl_optimize_canvas(pool, scene->canvas) != 0) {
if (errno == ENOSYS) {
have_gl = false;
} else {