diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2014-04-27 14:00:33 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2014-04-27 14:00:33 -0400 |
commit | 12eeb9524aa9421c03f253ab6161634bec66793b (patch) | |
tree | 6d1c20e3f27bc76c9b1c30a5980c6e2de3de8f75 /libdimension | |
parent | 3f949f8a9705972a4b61532602814b5b47d1a328 (diff) | |
download | dimension-12eeb9524aa9421c03f253ab6161634bec66793b.tar.xz |
gl: Make drawing faster by using a better pixel format.
Diffstat (limited to 'libdimension')
-rw-r--r-- | libdimension/Makefile.am | 4 | ||||
-rw-r--r-- | libdimension/canvas.c | 14 | ||||
-rw-r--r-- | libdimension/dimension-internal.h | 2 | ||||
-rw-r--r-- | libdimension/dimension/canvas.h | 11 | ||||
-rw-r--r-- | libdimension/gl.c | 26 | ||||
-rw-r--r-- | libdimension/png.c | 30 | ||||
-rw-r--r-- | libdimension/rgba.c (renamed from libdimension/rgba16.c) | 39 | ||||
-rw-r--r-- | libdimension/rgba.h (renamed from libdimension/rgba16.h) | 17 |
8 files changed, 100 insertions, 43 deletions
diff --git a/libdimension/Makefile.am b/libdimension/Makefile.am index 3e3cb86..06fa7b8 100644 --- a/libdimension/Makefile.am +++ b/libdimension/Makefile.am @@ -106,8 +106,8 @@ libdimension_la_SOURCES = $(nobase_include_HEADERS) \ ray_trace.c \ refcount-internal.h \ reflection.c \ - rgba16.c \ - rgba16.h \ + rgba.c \ + rgba.h \ scene.c \ solid_pigment.c \ sphere.c \ diff --git a/libdimension/canvas.c b/libdimension/canvas.c index c7c1994..1ee68e2 100644 --- a/libdimension/canvas.c +++ b/libdimension/canvas.c @@ -66,6 +66,20 @@ dmnsn_canvas_optimize(dmnsn_canvas *canvas, 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_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) { + if (i->optimizer_fn == optimizer_fn) { + return i; + } + } + + return NULL; +} + /* Set the value of a pixel */ void dmnsn_canvas_set_pixel(dmnsn_canvas *canvas, size_t x, size_t y, diff --git a/libdimension/dimension-internal.h b/libdimension/dimension-internal.h index c8d728e..a0bbe61 100644 --- a/libdimension/dimension-internal.h +++ b/libdimension/dimension-internal.h @@ -36,6 +36,6 @@ #include "threads.h" #include "bvh.h" #include "prtree.h" -#include "rgba16.h" +#include "rgba.h" #endif /* DIMENSION_INTERNAL_H */ diff --git a/libdimension/dimension/canvas.h b/libdimension/dimension/canvas.h index 2000141..ba549ad 100644 --- a/libdimension/dimension/canvas.h +++ b/libdimension/dimension/canvas.h @@ -83,6 +83,17 @@ void dmnsn_delete_canvas(dmnsn_canvas *canvas); void dmnsn_canvas_optimize(dmnsn_canvas *canvas, const dmnsn_canvas_optimizer *optimizer); +/** + * Find a canvas optimizer by its callback. + * @param[in] canvas The canvas to check. + * @param[in] optimizer_fn The callback to search for for. + * @return A pointer to the canvas optimizer with the callback \p optimizer_fn, + * or NULL if none is found. + */ +dmnsn_canvas_optimizer * +dmnsn_canvas_find_optimizer(const dmnsn_canvas *canvas, + dmnsn_canvas_optimizer_fn *optimizer_fn); + /* Pixel accessors */ /** diff --git a/libdimension/gl.c b/libdimension/gl.c index e2d222c..0b6b0b0 100644 --- a/libdimension/gl.c +++ b/libdimension/gl.c @@ -32,7 +32,7 @@ int dmnsn_gl_optimize_canvas(dmnsn_canvas *canvas) { - dmnsn_rgba16_optimize_canvas(canvas); + dmnsn_rgba8_optimize_canvas(canvas); return 0; } @@ -44,33 +44,33 @@ dmnsn_gl_write_canvas(const dmnsn_canvas *canvas) size_t height = canvas->height; /* Check if we can optimize this */ - DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) { - if (i->optimizer_fn == dmnsn_rgba16_optimizer_fn) { - glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_SHORT, i->ptr); - return glGetError() == GL_NO_ERROR ? 0 : 1; - } + 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); + return glGetError() == GL_NO_ERROR ? 0 : 1; } /* We couldn't, so transform the canvas to RGB now */ - GLushort *pixels = dmnsn_malloc(4*width*height*sizeof(GLushort)); + GLubyte *pixels = dmnsn_malloc(4*width*height*sizeof(GLubyte)); for (size_t y = 0; y < height; ++y) { for (size_t x = 0; x < width; ++x) { - GLushort *pixel = pixels + 4*(y*width + x); + GLubyte *pixel = pixels + 4*(y*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); tcolor = dmnsn_tcolor_saturate(tcolor); - pixel[0] = lround(tcolor.c.R*UINT16_MAX); - pixel[1] = lround(tcolor.c.G*UINT16_MAX); - pixel[2] = lround(tcolor.c.B*UINT16_MAX); - pixel[3] = lround(tcolor.T*UINT16_MAX); + pixel[0] = lround(tcolor.c.R*UINT8_MAX); + pixel[1] = lround(tcolor.c.G*UINT8_MAX); + pixel[2] = lround(tcolor.c.B*UINT8_MAX); + pixel[3] = lround(tcolor.T*UINT8_MAX); } } - glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_SHORT, pixels); + glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); dmnsn_free(pixels); return glGetError() == GL_NO_ERROR ? 0 : 1; diff --git a/libdimension/png.c b/libdimension/png.c index cc8b34f..ab5ea5c 100644 --- a/libdimension/png.c +++ b/libdimension/png.c @@ -175,23 +175,21 @@ dmnsn_png_write_canvas_thread(void *ptr) } /* Check if we can optimize this */ - DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, - payload->canvas->optimizers) - { - if (i->optimizer_fn == dmnsn_rgba16_optimizer_fn) { - for (size_t y = 0; y < height; ++y) { - /* Invert the rows. PNG coordinates are fourth quadrant. */ - uint16_t *row_opt = (uint16_t *)i->ptr + 4*(height - y - 1)*width; - png_write_row(png_ptr, (png_bytep)row_opt); - dmnsn_future_increment(payload->future); - } - - /* Finish the PNG file */ - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - dmnsn_free(payload); - return 0; + dmnsn_canvas_optimizer *optimizer = + dmnsn_canvas_find_optimizer(payload->canvas, dmnsn_rgba16_optimizer_fn); + if (optimizer) { + 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; + png_write_row(png_ptr, (png_bytep)row_opt); + dmnsn_future_increment(payload->future); } + + /* Finish the PNG file */ + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + dmnsn_free(payload); + return 0; } /* Allocate the temporary row of RGBA values */ diff --git a/libdimension/rgba16.c b/libdimension/rgba.c index 2198677..6df124e 100644 --- a/libdimension/rgba16.c +++ b/libdimension/rgba.c @@ -27,13 +27,25 @@ #include <stdint.h> void +dmnsn_rgba8_optimize_canvas(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)); + + dmnsn_canvas_optimize(canvas, &optimizer); +} + +void dmnsn_rgba16_optimize_canvas(dmnsn_canvas *canvas) { - /* Check if we've already optimized this canvas */ - DMNSN_ARRAY_FOREACH (dmnsn_canvas_optimizer *, i, canvas->optimizers) { - if (i->optimizer_fn == dmnsn_rgba16_optimizer_fn) { - return; - } + if (dmnsn_canvas_find_optimizer(canvas, dmnsn_rgba16_optimizer_fn)) { + return; } dmnsn_canvas_optimizer optimizer; @@ -44,7 +56,22 @@ dmnsn_rgba16_optimize_canvas(dmnsn_canvas *canvas) dmnsn_canvas_optimize(canvas, &optimizer); } -/* RGBA16 optimizer callback */ +void +dmnsn_rgba8_optimizer_fn(const dmnsn_canvas *canvas, void *ptr, + size_t x, size_t y) +{ + uint8_t *pixel = (uint8_t *)ptr + 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); + tcolor = dmnsn_tcolor_saturate(tcolor); + + pixel[0] = lround(tcolor.c.R*UINT8_MAX); + pixel[1] = lround(tcolor.c.G*UINT8_MAX); + pixel[2] = lround(tcolor.c.B*UINT8_MAX); + pixel[3] = lround(tcolor.T*UINT8_MAX); +} + void dmnsn_rgba16_optimizer_fn(const dmnsn_canvas *canvas, void *ptr, size_t x, size_t y) diff --git a/libdimension/rgba16.h b/libdimension/rgba.h index 86f5bf7..21d5044 100644 --- a/libdimension/rgba16.h +++ b/libdimension/rgba.h @@ -20,12 +20,19 @@ /** * @file - * 16-bit RGBA canvas optimizer interface, used by image optimizers. + * RGBA canvas optimizer interface, used by image optimizers. */ -/** Apply the rgba16 optimizer to a canvas. */ -void dmnsn_rgba16_optimize_canvas(dmnsn_canvas *canvas); +/** Apply the RGBA8 optimizer to a canvas. */ +DMNSN_INTERNAL void dmnsn_rgba8_optimize_canvas(dmnsn_canvas *canvas); +/** Apply the RGBA16 optimizer to a canvas. */ +DMNSN_INTERNAL void dmnsn_rgba16_optimize_canvas(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); /** RGBA16 optimizer callback. */ -void dmnsn_rgba16_optimizer_fn(const dmnsn_canvas *canvas, void *ptr, - size_t x, size_t y); +DMNSN_INTERNAL void dmnsn_rgba16_optimizer_fn(const dmnsn_canvas *canvas, + void *ptr, + size_t x, size_t y); |