summaryrefslogtreecommitdiff
path: root/src/cache-node.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cache-node.c')
-rw-r--r--src/cache-node.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/src/cache-node.c b/src/cache-node.c
new file mode 100644
index 0000000..6bcb85d
--- /dev/null
+++ b/src/cache-node.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018-2019 - Vito Caputo - <vcaputo@pengaru.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <stage.h>
+
+#include "cache.h"
+#include "cache-node.h"
+#include "macros.h"
+
+
+typedef struct cache_node_t {
+ cache_t *cache;
+ const m4f_t *model_x, *view_x, *projection_x;
+} cache_node_t;
+
+
+/* Prepare is where the cache node maintains the cache. It calls a stage
+ * render on the attached stage as part of the outer stage's prepare phase.
+ */
+static void cache_node_prepare(stage_t *stage, void *object, float alpha, void *render_ctxt)
+{
+ cache_node_t *cache_node = object;
+
+ assert(cache_node);
+
+ if (cache_update(cache_node->cache, alpha, render_ctxt))
+ stage_dirty(stage);
+}
+
+
+/* Render simply renders a cached texture onto the screen */
+static void cache_node_render(const stage_t *stage, void *object, float alpha, void *render_ctxt)
+{
+ cache_node_t *cache_node = object;
+
+ assert(stage);
+ assert(cache_node);
+
+ cache_render(cache_node->cache, alpha, cache_node->model_x, cache_node->view_x, cache_node->projection_x);
+}
+
+
+static void cache_node_free(const stage_t *stage, void *object)
+{
+ cache_node_t *cache_node = object;
+
+ assert(cache_node);
+
+ cache_free(cache_node->cache);
+ free(cache_node);
+}
+
+
+static const stage_ops_t cache_node_ops = {
+ .prepare_func = cache_node_prepare,
+ .render_func = cache_node_render,
+ .free_func = cache_node_free,
+};
+
+
+/* return a cache node from an already established cache, with a potentially unique transform */
+stage_t * cache_node_new_cache(stage_conf_t *conf, cache_t *cache, const m4f_t *model_x, const m4f_t *view_x, const m4f_t *projection_x)
+{
+ cache_node_t *cache_node;
+ stage_t *s;
+
+ assert(conf);
+
+ cache_node = calloc(1, sizeof(cache_node_t));
+ fatal_if(!cache_node, "Unable to allocate cache node \"%s\"", conf->name);
+
+ cache_node->cache = cache;
+ cache_node->model_x = model_x;
+ cache_node->view_x = view_x;
+ cache_node->projection_x = projection_x;
+
+ s = stage_new(conf, &cache_node_ops, cache_node);
+ fatal_if(!s, "Unable to create stage \"%s\"", conf->name);
+
+ cache_ref(cache);
+
+ return s;
+}
+
+
+/* return a cache node from a stage
+ * The cache node takes ownership of the supplied stage, and will
+ * free it when the cache node is freed.
+ * When the associated stage is dirty, the cache gets updated with its rendered
+ * output on a subsequent render, in the prepare hook.
+ *
+ * region specifies, in ndc coordinates, the region of the canvas as rendered by the associated stage to cache.
+ * transform specifies the transformation to apply to the two triangles used for mapping the cached texture.
+ * The triangles used for mapping the texture form a section of a unit cube @ coordinates -1,-1,0 .. +1,+1,0, so
+ * if you supply an identity matrix for transform, the cached texture is drawn fullscreen.
+ *
+ * Either region and/or transform may be NULL. When region is NULL, it's assumed to be -1,-1..+1,+1. When
+ * transform is NULL, it's assumed to be an identity matrix. So supplying NULL for both caches the full canvas,
+ * and draws it directly back into the full canvas.
+ */
+stage_t * cache_node_new_stage(stage_conf_t *conf, stage_t *stage, const bb2f_t *region, const m4f_t *model_x, const m4f_t *view_x, const m4f_t *projection_x)
+{
+ cache_t *cache;
+
+ assert(conf);
+
+ cache = cache_new(stage, region);
+ fatal_if(!cache, "Unable to allocate cache \"%s\"", conf->name);
+
+ return cache_node_new_cache(conf, cache, model_x, view_x, projection_x);
+}
© All Rights Reserved