diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2020-09-22 01:12:28 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2020-09-22 01:12:28 -0700 |
commit | f8d142c8c03faadff939846a1acb35be4588b453 (patch) | |
tree | e04f75efcbc87dee47c1fead5bd7127b6068ea07 /src/cache.c | |
parent | b3d320c16333346d11108922dc62fa83992a75e5 (diff) |
cache-node: drop cache{,-node}.[ch]
I'd originally intended to reuse this cache code for the checkered
background, but I don't think it's really necessary so just remove it.
It can always be brought back from the dead if desired.
Diffstat (limited to 'src/cache.c')
-rw-r--r-- | src/cache.c | 308 |
1 files changed, 0 insertions, 308 deletions
diff --git a/src/cache.c b/src/cache.c deleted file mode 100644 index 69c5504..0000000 --- a/src/cache.c +++ /dev/null @@ -1,308 +0,0 @@ -/* - * 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/>. - */ - -/* This implements a simple texture-based 2D cache of a stage. So you can - * construct a stage of costly stuff to render that doesn't change every frame, - * give that to a cache, then stick the cache in the actual stage being - * rendered every frame. - * - * When the associated stage is dirty, the cache will render it into the cached - * texture in the prepare pass of the render. When it's not dirty, the cached - * texture will be used as-is. - */ - -#include <assert.h> -#include <stdlib.h> - -#include <stdio.h> // FIXME testing - -#include <stage.h> - -#include "bb2f.h" -#include "cache.h" -#include "pig.h" -#include "glad.h" -#include "m4f.h" -#include "shader.h" - -struct cache_t { - stage_t *stage; - const bb2f_t *region; - unsigned tex; - int x, y, w, h; - - unsigned refcnt; -}; - -static unsigned vbo, tcbo; -static shader_t *cache_shader; - -static const float vertices[] = { - +1.f, +1.f, 0.f, - +1.f, -1.f, 0.f, - -1.f, +1.f, 0.f, - +1.f, -1.f, 0.f, - -1.f, -1.f, 0.f, - -1.f, +1.f, 0.f, -}; - -static const float texcoords[] = { - 1.f, 1.f, - 1.f, 0.f, - 0.f, 1.f, - 1.f, 0.f, - 0.f, 0.f, - 0.f, 1.f, -}; - - -static const char *cache_vs = "" - "#version 120\n" - - "attribute vec3 vertex;" - "attribute vec2 texcoord;" - - "uniform mat4 model_x, view_x, projection_x;" - - "void main()" - "{" - " gl_TexCoord[0].xy = texcoord;" - " gl_Position = projection_x * view_x * model_x * vec4(vertex, 1.f);" - "}" -""; - - -static const char *cache_fs = "" - "#version 120\n" - - "uniform sampler2D tex0;" - "uniform float alpha;" - - "void main()" - "{" - " gl_FragColor = texture2D(tex0, gl_TexCoord[0].st);" - " gl_FragColor.a *= alpha;" - "}" -""; - - -/* update is where the cache maintains the cache. It calls a stage - * render on the attached stage as part of the outer stage's prepare phase. - * 1 is returned if the cache needed updating, 0 if not. - */ -int cache_update(cache_t *cache, float alpha, void *render_ctxt) -{ - pig_t *pig = render_ctxt; - int w, h; - - assert(pig); - assert(cache); - - /* On a more modern GL this is where an FBO would be setup for off-screen rendering - * of the cached stage, leaving the contents in a texture for cache_render to use. - * - * On old GL, which eon is targeting, all we can do here is render into the backbuffer, - * and read it back out into memory for a texture upload. Then just clear the backbuffer - * for the next user, the contents never get flipped to. - * - * I've read that this can be buggy to do, so this whole approach may be useless without FBOs. - */ - - /* FIXME TODO: this is lifted from eon, I've mechanically converted the eon API to pig API, - * but it feels like this should be in libplay. - */ - - /* determine the cache'd region dimensions in pixels */ - if (!cache->region) { - pig_canvas_size(pig, &w, &h); - cache->x = cache->y = 0; - } else { - int xmin, ymin, xmax, ymax; - - /* compute texture 1:1 dimensions in pixels for the region */ - pig_canvas_from_ndc(pig, cache->region->min.x, cache->region->min.y, &xmin, &ymin); - pig_canvas_from_ndc(pig, cache->region->max.x, cache->region->max.y, &xmax, &ymax); - - assert(ymax >= ymin); - assert(xmax >= xmin); - - w = xmax - xmin; - h = ymax - ymin; - - cache->x = xmin; - cache->y = ymin; - } - - /* if the dimensions changed, (re)create the texture, and ensure the cached stage is dirty */ - if (w != cache->w || h != cache->h) { - cache->w = w; - cache->h = h; - - glBindTexture(GL_TEXTURE_2D, cache->tex); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); - - stage_dirty(cache->stage); - } - - if (stage_render(cache->stage, render_ctxt)) { - - glFinish(); /* XXX: ensures all outstanding rendering is done before reading into the cache */ - glBindTexture(GL_TEXTURE_2D, cache->tex); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, cache->x, cache->y, w, h); - glBindTexture(GL_TEXTURE_2D, 0); - - return 1; - } - - return 0; -} - - -/* Render simply renders a cached texture onto the screen */ -void cache_render(cache_t *cache, float alpha, const m4f_t *model_x, const m4f_t *view_x, const m4f_t *projection_x) -{ - m4f_t identity = m4f_identity(); - int *uniforms, *attributes; - - assert(cache); - - glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - shader_use(cache_shader, NULL, &uniforms, NULL, &attributes); - - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glVertexAttribPointer(attributes[0], 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); - glEnableVertexAttribArray(attributes[0]); - - glBindBuffer(GL_ARRAY_BUFFER, tcbo); - glEnableVertexAttribArray(attributes[1]); - glVertexAttribPointer(attributes[1], 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, cache->tex); - glUniform1i(uniforms[0], 0); - - glUniform1f(uniforms[1], alpha); - - if (!model_x) - model_x = &identity; - - if (!view_x) - view_x = &identity; - - if (!projection_x) - projection_x = &identity; - - glUniformMatrix4fv(uniforms[2], 1, GL_FALSE, &model_x->m[0][0]); - glUniformMatrix4fv(uniforms[3], 1, GL_FALSE, &view_x->m[0][0]); - glUniformMatrix4fv(uniforms[4], 1, GL_FALSE, &projection_x->m[0][0]); - - glDrawArrays(GL_TRIANGLES, 0, 6); - - glBindTexture(GL_TEXTURE_2D, 0); - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); -} - - -void cache_free(cache_t *cache) -{ - assert(cache); - - cache->refcnt--; - if (cache->refcnt > 0) - return; - - stage_free(cache->stage); - glDeleteTextures(1, &cache->tex); - free(cache); -} - - -/* return a cache for a stage - * The cache takes ownership of the supplied stage, and will - * free it when the cache is freed w/cache_free(). - * 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. - */ -cache_t * cache_new(stage_t *stage, const bb2f_t *region) -{ - cache_t *cache; - - assert(stage); - - if (!vbo) { - /* common to all cache nodes */ - cache_shader = shader_pair_new(cache_vs, cache_fs, - 5, - (const char *[]) { - "tex0", - "alpha", - "model_x", - "view_x", - "projection_x", - }, - 2, - (const char *[]) { - "vertex", - "texcoord", - }); - - glGenBuffers(1, &vbo); - glBindBuffer(GL_ARRAY_BUFFER, vbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - - glGenBuffers(1, &tcbo); - glBindBuffer(GL_ARRAY_BUFFER, tcbo); - glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - - cache = calloc(1, sizeof(cache_t)); - if (!cache) - return NULL; - - cache->stage = stage; - cache->region = region; - - glGenTextures(1, &cache->tex); - glBindTexture(GL_TEXTURE_2D, cache->tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glBindTexture(GL_TEXTURE_2D, 0); - - cache->refcnt++; - - return cache; -} - - -void cache_ref(cache_t *cache) -{ - cache->refcnt++; -} |