From 4f5e6c8d18ae2fe2c5aa7d0792aa6fa4e1c92719 Mon Sep 17 00:00:00 2001
From: Robin Watts <robin.watts@artifex.com>
Date: Mon, 30 Dec 2013 12:51:47 +0000
Subject: Bug 694585: Further improve mesh rendering times

Add a cached color converter mechanism. Use this for rendering meshes
to speed repeated conversions.

This reduces a (release build to ppm at default resolution) run from
23.5s to 13.2 seconds.
---
 source/fitz/colorspace.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
 source/fitz/draw-mesh.c  |  8 +++--
 2 files changed, 88 insertions(+), 2 deletions(-)

(limited to 'source/fitz')

diff --git a/source/fitz/colorspace.c b/source/fitz/colorspace.c
index 33fa07fb..3426e26f 100644
--- a/source/fitz/colorspace.c
+++ b/source/fitz/colorspace.c
@@ -1274,3 +1274,85 @@ fz_expand_indexed_pixmap(fz_context *ctx, fz_pixmap *src)
 
 	return dst;
 }
+
+typedef struct fz_cached_color_converter
+{
+	fz_color_converter base;
+	fz_hash_table *hash;
+
+}
+fz_cached_color_converter;
+
+static void fz_cached_color_convert(fz_color_converter *cc_, float *ds, float *ss)
+{
+	fz_cached_color_converter *cc = cc_->opaque;
+	fz_context *ctx = cc->base.ctx;
+	void *val = fz_hash_find(ctx, cc->hash, ss);
+	int n = cc->base.ds->n * sizeof(float);
+	fz_color_converter *base_cc = &cc->base;
+
+	if (val)
+	{
+		memcpy(ds, val, n);
+		return;
+	}
+
+	base_cc->convert(base_cc, ds, ss);
+	val = fz_malloc(ctx, n);
+	memcpy(val, ds, n);
+	fz_try(ctx)
+	{
+		fz_hash_insert(ctx, cc->hash, ss, val);
+	}
+	fz_catch(ctx)
+	{
+		fz_free(ctx, val);
+	}
+}
+
+void fz_init_cached_color_converter(fz_context *ctx, fz_color_converter *cc, fz_colorspace *ds, fz_colorspace *ss)
+{
+	int n = ss->n;
+	fz_cached_color_converter *cached = fz_malloc_struct(ctx, fz_cached_color_converter);
+
+	fz_try(ctx)
+	{
+		fz_lookup_color_converter(&cached->base, ctx, ds, ss);
+		cached->hash = fz_new_hash_table(ctx, 256, n * sizeof(float), -1);
+		cc->convert = fz_cached_color_convert;
+		cc->ctx = ctx;
+		cc->ds = ds;
+		cc->ss = ss;
+		cc->opaque = cached;
+	}
+	fz_catch(ctx)
+	{
+		fz_free_hash(ctx, cached->hash);
+		fz_rethrow(ctx);
+	}
+}
+
+void fz_fin_cached_color_converter(fz_color_converter *cc_)
+{
+	fz_cached_color_converter *cc;
+	fz_context *ctx;
+	int i, n;
+
+	if (cc_ == NULL)
+		return;
+	cc = cc_->opaque;
+	if (cc == NULL)
+		return;
+	cc_->opaque = NULL;
+	ctx = cc_->ctx;
+
+	n = fz_hash_len(ctx, cc->hash);
+	for (i = 0; i < n; i++)
+	{
+		void *v = fz_hash_get_val(ctx, cc->hash, i);
+		if (v)
+			fz_free(ctx, v);
+	}
+	fz_free_hash(ctx, cc->hash);
+	fz_free(ctx, cc);
+}
diff --git a/source/fitz/draw-mesh.c b/source/fitz/draw-mesh.c
index 26d496d2..1bb93369 100644
--- a/source/fitz/draw-mesh.c
+++ b/source/fitz/draw-mesh.c
@@ -205,7 +205,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
 	fz_pixmap *temp = NULL;
 	fz_pixmap *conv = NULL;
 	float color[FZ_MAX_COLORS];
-	struct paint_tri_data ptd;
+	struct paint_tri_data ptd = { 0 };
 	int i, k;
 	fz_matrix local_ctm;
 
@@ -241,7 +241,7 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
 		ptd.shade = shade;
 		ptd.bbox = bbox;
 
-		fz_lookup_color_converter(&ptd.cc, ctx, temp->colorspace, shade->colorspace);
+		fz_init_cached_color_converter(ctx, &ptd.cc, temp->colorspace, shade->colorspace);
 		fz_process_mesh(ctx, shade, &local_ctm, &prepare_vertex, &do_paint_tri, &ptd);
 
 		if (shade->use_function)
@@ -262,6 +262,10 @@ fz_paint_shade(fz_context *ctx, fz_shade *shade, const fz_matrix *ctm, fz_pixmap
 			fz_drop_pixmap(ctx, temp);
 		}
 	}
+	fz_always(ctx)
+	{
+		fz_fin_cached_color_converter(&ptd.cc);
+	}
 	fz_catch(ctx)
 	{
 		fz_drop_pixmap(ctx, conv);
-- 
cgit v1.2.3