diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2019-06-12 13:30:19 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2019-06-12 13:30:19 -0700 |
commit | 8ccec1152ef3080c54e76959413d2b16f231cc38 (patch) | |
tree | 40e0091e36e16c4e6a54174c04afc32de40c7bec | |
parent | efda9aa3f0cee82cc3e2968326cf0df804d7e6d6 (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.c | 43 | ||||
-rw-r--r-- | src/stage.h | 5 |
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); |