summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2019-06-12 13:30:19 -0700
committerVito Caputo <vcaputo@pengaru.com>2019-06-12 13:30:19 -0700
commit8ccec1152ef3080c54e76959413d2b16f231cc38 (patch)
tree40e0091e36e16c4e6a54174c04afc32de40c7bec
parentefda9aa3f0cee82cc3e2968326cf0df804d7e6d6 (diff)
libstage: introduce prepare_func and prepare pass
This effectively makes rendering two passes, with a first pass giving stage nodes an opportunity to maintain caches or other preparatory steps before actual rendering.
-rw-r--r--src/stage.c43
-rw-r--r--src/stage.h5
2 files changed, 39 insertions, 9 deletions
diff --git a/src/stage.c b/src/stage.c
index 6420c87..2b0ee20 100644
--- a/src/stage.c
+++ b/src/stage.c
@@ -33,6 +33,7 @@ struct stage_t {
unsigned locked:1; /* stage is locked */
unsigned dirty:1; /* stage is dirty (since last render) */
+ stage_prepare_func_t *prepare; /* pre-render object */
stage_render_func_t *render; /* render object */
stage_free_func_t *free; /* free object */
stage_lookup_func_t *lookup; /* lookup object against key */
@@ -41,12 +42,13 @@ struct stage_t {
/* minimally initialize a stage to carry an object */
-static void _stage_set_object(stage_t *stage, const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
+static void _stage_set_object(stage_t *stage, const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
{
assert(stage);
assert(name);
strncpy(stage->name, name, sizeof(stage->name));
+ stage->prepare = prepare_func;
stage->render = render_func;
stage->free = free_func;
stage->lookup = lookup_func;
@@ -55,7 +57,7 @@ static void _stage_set_object(stage_t *stage, const char *name, void *object, st
/* allocate a stage, this purely creates a stage in isolation and assigns its associated name, object and functions */
-static stage_t * _stage_new(const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
+static stage_t * _stage_new(const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
{
stage_t *stage;
@@ -67,7 +69,7 @@ static stage_t * _stage_new(const char *name, void *object, stage_render_func_t
for (int i = 0; i < STAGE_LAYERS_MAX; i++)
dll_init(&stage->layers[i]);
- _stage_set_object(stage, name, object, render_func, free_func, lookup_func);
+ _stage_set_object(stage, name, object, prepare_func, render_func, free_func, lookup_func);
return stage;
}
@@ -87,14 +89,14 @@ static void _stage_free(stage_t *stage)
/* returns a new stage, attached at the specified layer under parent if supplied */
/* layer has no effect when parent == NULL */
-stage_t * stage_new(stage_t *parent, int layer, const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
+stage_t * stage_new(stage_t *parent, int layer, const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
{
stage_t *stage;
assert(parent || !layer);
assert(layer < STAGE_LAYERS_MAX);
- stage = _stage_new(name, object, render_func, free_func, lookup_func);
+ stage = _stage_new(name, object, prepare_func, render_func, free_func, lookup_func);
if (!stage)
return NULL;
@@ -108,14 +110,14 @@ stage_t * stage_new(stage_t *parent, int layer, const char *name, void *object,
/* replaces a given stage's object-related properties but otherwise keeping the existing state */
-void stage_replace(stage_t *stage, const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
+void stage_replace(stage_t *stage, const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func)
{
assert(stage);
if (stage->free)
stage->free(stage, stage->object);
- _stage_set_object(stage, name, object, render_func, free_func, lookup_func);
+ _stage_set_object(stage, name, object, prepare_func, render_func, free_func, lookup_func);
}
@@ -255,6 +257,28 @@ void stage_clear(stage_t *stage)
}
+static void _prepare_stage(stage_t *stage, float alpha, void *render_ctxt)
+{
+ float a = alpha * stage->alpha;
+
+ assert(stage);
+
+ if (stage->prepare)
+ stage->prepare(stage, stage->object, a, render_ctxt);
+
+ for (int i = 0; i < STAGE_LAYERS_MAX; i++) {
+ stage_t *s;
+
+ DLL_FOR_EACH_ENTRY(&stage->layers[i], s, stage_t, layer) {
+ if (!s->active)
+ continue;
+
+ _prepare_stage(s, a, render_ctxt);
+ }
+ }
+}
+
+
static void _render_stage(const stage_t *stage, float alpha, void *render_ctxt)
{
float a = alpha * stage->alpha;
@@ -288,6 +312,11 @@ int stage_render(stage_t *stage, void *render_ctxt)
* dirty detection.
*/
+ /* we must always enter the prepare pass, as some nodes may dirty the stage
+ * in the prepare stage.
+ */
+ _prepare_stage(stage, 1.f, render_ctxt);
+
if (stage->dirty) {
if (stage->active)
_render_stage(stage, 1.f, render_ctxt);
diff --git a/src/stage.h b/src/stage.h
index a2a2543..2b5cc91 100644
--- a/src/stage.h
+++ b/src/stage.h
@@ -22,12 +22,13 @@
typedef struct stage_t stage_t;
+typedef void (stage_prepare_func_t)(stage_t *stage, void *object, float alpha, void *render_ctxt);
typedef void (stage_render_func_t)(const stage_t *stage, void *object, float alpha, void *render_ctxt);
typedef void (stage_free_func_t)(const stage_t *stage, void *object);
typedef stage_t * (stage_lookup_func_t)(const stage_t *stage, void *object, void *key);
-stage_t * stage_new(stage_t *parent, int layer, const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func);
-void stage_replace(stage_t *stage, const char *name, void *object, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func);
+stage_t * stage_new(stage_t *parent, int layer, const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func);
+void stage_replace(stage_t *stage, const char *name, void *object, stage_prepare_func_t *prepare_func, stage_render_func_t *render_func, stage_free_func_t *free_func, stage_lookup_func_t *lookup_func);
stage_t * stage_free(stage_t *stage);
int stage_render(stage_t *stage, void *render_ctxt);
void stage_dirty(stage_t *stage);
© All Rights Reserved