summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2014-04-27 14:00:33 -0400
committerTavian Barnes <tavianator@tavianator.com>2014-04-27 14:00:33 -0400
commit12eeb9524aa9421c03f253ab6161634bec66793b (patch)
tree6d1c20e3f27bc76c9b1c30a5980c6e2de3de8f75
parent3f949f8a9705972a4b61532602814b5b47d1a328 (diff)
downloaddimension-12eeb9524aa9421c03f253ab6161634bec66793b.tar.xz
gl: Make drawing faster by using a better pixel format.
-rw-r--r--dimension/preview.py2
-rw-r--r--libdimension/Makefile.am4
-rw-r--r--libdimension/canvas.c14
-rw-r--r--libdimension/dimension-internal.h2
-rw-r--r--libdimension/dimension/canvas.h11
-rw-r--r--libdimension/gl.c26
-rw-r--r--libdimension/png.c30
-rw-r--r--libdimension/rgba.c (renamed from libdimension/rgba16.c)39
-rw-r--r--libdimension/rgba.h (renamed from libdimension/rgba16.h)17
9 files changed, 101 insertions, 44 deletions
diff --git a/dimension/preview.py b/dimension/preview.py
index aa4d032..dcc38f1 100644
--- a/dimension/preview.py
+++ b/dimension/preview.py
@@ -53,7 +53,7 @@ class PreviewWindow(QtGui.QMainWindow):
self.render_timer = QtCore.QTimer(self)
self.render_timer.timeout.connect(self.update_preview)
- self.render_timer.start(0)
+ self.render_timer.start(20)
@QtCore.pyqtSlot()
def update_preview(self):
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);