gallium: fix some render to texture bugs

Before, we were sometimes rendering into a stale texture because
st_finalize_texture() would discard the old texture and create a new one.

Moved st_update_framebuffer atom after texture validation so that we
can create a new renderbuffer surface if the texture changes.

Also, split texture validation into two parts: finalize_textures and
update_textures.  Do finalize_textures first to avoid getting into the
situtation where we're doing a pipe->surface_copy() mid-way through
state validation.

Some debug code still in place, but disabled...
This commit is contained in:
Brian Paul
2008-05-07 16:44:33 -06:00
parent 8f76459f62
commit 1a82d9648b
11 changed files with 189 additions and 40 deletions

View File

@@ -39,34 +39,13 @@
#include "pipe/p_context.h"
#include "pipe/p_inlines.h"
#include "cso_cache/cso_context.h"
#include "util/u_simple_shaders.h"
static void *
get_passthrough_fs(struct st_context *st)
{
struct pipe_shader_state shader;
if (!st->passthrough_fs) {
st->passthrough_fs =
util_make_fragment_passthrough_shader(st->pipe, &shader);
free((void *) shader.tokens);
}
return st->passthrough_fs;
}
/**
* XXX This needs some work yet....
* Need to "upload" texture images at appropriate times.
*/
static void
update_textures(struct st_context *st)
{
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
GLuint su;
GLboolean missing_textures = GL_FALSE;
st->state.num_textures = 0;
@@ -85,13 +64,11 @@ update_textures(struct st_context *st)
retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
if (!retval) {
/* out of mem */
missing_textures = GL_TRUE;
/* missing texture */
continue;
}
st->state.num_textures = su + 1;
stObj->teximage_realloc = TRUE;
}
pt = st_get_stobj_texture(stObj);
@@ -103,12 +80,6 @@ update_textures(struct st_context *st)
cso_set_sampler_textures(st->cso_context,
st->state.num_textures,
st->state.sampler_texture);
if (missing_textures) {
/* use a pass-through frag shader that uses no textures */
void *fs = get_passthrough_fs(st);
cso_set_fragment_shader_handle(st->cso_context, fs);
}
}
@@ -120,3 +91,52 @@ const struct st_tracked_state st_update_texture = {
},
update_textures /* update */
};
static void
finalize_textures(struct st_context *st)
{
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
const GLboolean prev_missing_textures = st->missing_textures;
GLuint su;
st->missing_textures = GL_FALSE;
for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
if (fprog->Base.SamplersUsed & (1 << su)) {
const GLuint texUnit = fprog->Base.SamplerUnits[su];
struct gl_texture_object *texObj
= st->ctx->Texture.Unit[texUnit]._Current;
struct st_texture_object *stObj = st_texture_object(texObj);
if (texObj) {
GLboolean flush, retval;
retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
if (!retval) {
/* out of mem */
st->missing_textures = GL_TRUE;
continue;
}
stObj->teximage_realloc = TRUE;
}
}
}
if (prev_missing_textures != st->missing_textures)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
}
const struct st_tracked_state st_finalize_textures = {
"st_finalize_textures", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
0, /* st */
},
finalize_textures /* update */
};