diff options
author | Michal Krol <michal@vmware.com> | 2009-12-12 16:48:32 +0100 |
---|---|---|
committer | Michal Krol <michal@vmware.com> | 2009-12-12 16:48:32 +0100 |
commit | a3eb0f718e19653a2ad8e49396c904183be456f3 (patch) | |
tree | 0092574c469ea586a6cab8b8ebb7ac62b8221a2a /src/mesa/state_tracker | |
parent | 491f384c3958067e6c4c994041f5d8d413b806bc (diff) | |
parent | 784cca9fa527de771754d76545970f78094b9adf (diff) |
Merge branch 'master' into glsl-pp-rework-2
Conflicts:
progs/perf/drawoverhead.c
progs/perf/teximage.c
progs/perf/vbo.c
progs/perf/vertexrate.c
src/mesa/shader/slang/library/slang_common_builtin_gc.h
Diffstat (limited to 'src/mesa/state_tracker')
37 files changed, 1254 insertions, 1265 deletions
diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index ca15ce1b47..73df44d198 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -46,7 +46,8 @@ static const struct st_tracked_state *atoms[] = &st_update_clip, &st_finalize_textures, - &st_update_shader, + &st_update_fp, + &st_update_vp, &st_update_rasterizer, &st_update_polygon_stipple, @@ -137,7 +138,7 @@ void st_validate_state( struct st_context *st ) if (state->st == 0) return; -// _mesa_printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st); + /*_mesa_printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/ if (1) { /* Debug version which enforces various sanity checks on the @@ -152,7 +153,7 @@ void st_validate_state( struct st_context *st ) const struct st_tracked_state *atom = atoms[i]; struct st_state_flags generated; -// _mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st); + /*_mesa_printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);*/ if (!(atom->dirty.mesa || atom->dirty.st) || !atom->update) { @@ -162,7 +163,7 @@ void st_validate_state( struct st_context *st ) if (check_state(state, &atom->dirty)) { atoms[i]->update( st ); -// _mesa_printf("after: %x\n", atom->dirty.mesa); + /*_mesa_printf("after: %x\n", atom->dirty.mesa);*/ } accumulate_state(&examined, &atom->dirty); @@ -175,7 +176,7 @@ void st_validate_state( struct st_context *st ) assert(!check_state(&examined, &generated)); prev = *state; } -// _mesa_printf("\n"); + /*_mesa_printf("\n");*/ } else { diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index c7cffd85c8..f34b49203b 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -47,7 +47,8 @@ void st_validate_state( struct st_context *st ); extern const struct st_tracked_state st_update_framebuffer; extern const struct st_tracked_state st_update_clip; extern const struct st_tracked_state st_update_depth_stencil_alpha; -extern const struct st_tracked_state st_update_shader; +extern const struct st_tracked_state st_update_fp; +extern const struct st_tracked_state st_update_vp; extern const struct st_tracked_state st_update_rasterizer; extern const struct st_tracked_state st_update_polygon_stipple; extern const struct st_tracked_state st_update_viewport; diff --git a/src/mesa/state_tracker/st_atom_constbuf.c b/src/mesa/state_tracker/st_atom_constbuf.c index 5d4d8eee02..77153889b6 100644 --- a/src/mesa/state_tracker/st_atom_constbuf.c +++ b/src/mesa/state_tracker/st_atom_constbuf.c @@ -39,6 +39,7 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" +#include "st_debug.h" #include "st_context.h" #include "st_atom.h" #include "st_atom_constbuf.h" @@ -75,7 +76,7 @@ void st_upload_constants( struct st_context *st, PIPE_BUFFER_USAGE_CONSTANT, paramBytes ); - if (0) { + if (ST_DEBUG & DEBUG_CONSTANTS) { debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n", __FUNCTION__, shader_type, params->NumParameters, params->StateFlags); diff --git a/src/mesa/state_tracker/st_atom_depth.c b/src/mesa/state_tracker/st_atom_depth.c index 0aa128f947..88b80a07fc 100644 --- a/src/mesa/state_tracker/st_atom_depth.c +++ b/src/mesa/state_tracker/st_atom_depth.c @@ -104,10 +104,6 @@ update_depth_stencil_alpha(struct st_context *st) dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func); } - if (ctx->Query.CurrentOcclusionObject && - ctx->Query.CurrentOcclusionObject->Active) - dsa->depth.occlusion_count = 1; - if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) { dsa->stencil[0].enabled = 1; dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]); diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index 5209a6a0c9..8ca4335e33 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -39,6 +39,8 @@ #include "pipe/p_context.h" #include "pipe/p_inlines.h" #include "cso_cache/cso_context.h" +#include "util/u_rect.h" +#include "util/u_math.h" @@ -63,8 +65,8 @@ update_renderbuffer_surface(struct st_context *st, GLuint level; /* find matching mipmap level size */ for (level = 0; level <= texture->last_level; level++) { - if (texture->width[level] == rtt_width && - texture->height[level] == rtt_height) { + if (u_minify(texture->width0, level) == rtt_width && + u_minify(texture->height0, level) == rtt_height) { pipe_surface_reference(&strb->surface, NULL); @@ -162,10 +164,17 @@ update_framebuffer_state( struct st_context *st ) (void) st_get_framebuffer_surface(stfb, ST_SURFACE_FRONT_LEFT, &surf_front); (void) st_get_framebuffer_surface(stfb, ST_SURFACE_BACK_LEFT, &surf_back); - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); + if (st->pipe->surface_copy) { + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); + } else { + util_surface_copy(st->pipe, FALSE, + surf_front, 0, 0, + surf_back, 0, 0, + fb->Width, fb->Height); + } } /* we're assuming we'll really draw to the front buffer */ st->frontbuffer_status = FRONT_STATUS_DIRTY; diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index eff3666ca8..6a5854e9ba 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -122,7 +122,8 @@ create_color_map_texture(GLcontext *ctx) const uint texSize = 256; /* simple, and usually perfect */ /* find an RGBA texture format */ - format = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); + format = st_choose_format(pipe->screen, GL_RGBA, + PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); /* create texture for color map/table */ pt = st_texture_create(ctx->st, PIPE_TEXTURE_2D, format, 0, @@ -144,7 +145,7 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) const GLuint gSize = ctx->PixelMaps.GtoG.Size; const GLuint bSize = ctx->PixelMaps.BtoB.Size; const GLuint aSize = ctx->PixelMaps.AtoA.Size; - const uint texSize = pt->width[0]; + const uint texSize = pt->width0; uint *dest; uint i, j; @@ -161,12 +162,14 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt) */ for (i = 0; i < texSize; i++) { for (j = 0; j < texSize; j++) { + union util_color uc; int k = (i * texSize + j); ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize]; ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize]; ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize]; ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize]; - util_pack_color_ub(r, g, b, a, pt->format, dest + k); + util_pack_color_ub(r, g, b, a, pt->format, &uc); + *(dest + k) = uc.ui; } } diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 50ce82811c..d6e3a3e561 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -209,7 +209,7 @@ update_samplers(struct st_context *st) } xlate_border_color(texobj->BorderColor, - teximg ? teximg->TexFormat->BaseFormat : GL_RGBA, + teximg ? teximg->_BaseFormat : GL_RGBA, sampler->border_color); sampler->max_anisotropy = texobj->MaxAnisotropy; @@ -229,14 +229,23 @@ update_samplers(struct st_context *st) /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/ cso_single_sampler(st->cso_context, su, sampler); + if (su < st->ctx->Const.MaxVertexTextureImageUnits) { + cso_single_vertex_sampler(st->cso_context, su, sampler); + } } else { /*printf("%s su=%u null\n", __FUNCTION__, su);*/ cso_single_sampler(st->cso_context, su, NULL); + if (su < st->ctx->Const.MaxVertexTextureImageUnits) { + cso_single_vertex_sampler(st->cso_context, su, NULL); + } } } cso_single_sampler_done(st->cso_context); + if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { + cso_single_vertex_sampler_done(st->cso_context); + } } diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index ee649be885..09baff875b 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -56,82 +56,18 @@ #include "st_mesa_to_tgsi.h" -/** - * This represents a vertex program, especially translated to match - * the inputs of a particular fragment shader. - */ -struct translated_vertex_program -{ - struct st_vertex_program *master; - - /** The fragment shader "signature" this vertex shader is meant for: */ - GLbitfield frag_inputs; - /** Compared against master vertex program's serialNo: */ - GLuint serialNo; - /** Maps VERT_RESULT_x to slot */ - GLuint output_to_slot[VERT_RESULT_MAX]; - ubyte output_to_semantic_name[VERT_RESULT_MAX]; - ubyte output_to_semantic_index[VERT_RESULT_MAX]; - - /** Pointer to the translated vertex program */ - struct st_vertex_program *vp; - - struct translated_vertex_program *next; /**< next in linked list */ -}; - - -/** - * Given a vertex program output attribute, return the corresponding - * fragment program input attribute. - * \return -1 for vertex outputs that have no corresponding fragment input +/* + * Translate fragment program if needed. */ -static GLint -vp_out_to_fp_in(GLuint vertResult) -{ - if (vertResult >= VERT_RESULT_TEX0 && - vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) - return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0); - - if (vertResult >= VERT_RESULT_VAR0 && - vertResult < VERT_RESULT_VAR0 + MAX_VARYING) - return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0); - - switch (vertResult) { - case VERT_RESULT_HPOS: - return FRAG_ATTRIB_WPOS; - case VERT_RESULT_COL0: - return FRAG_ATTRIB_COL0; - case VERT_RESULT_COL1: - return FRAG_ATTRIB_COL1; - case VERT_RESULT_FOGC: - return FRAG_ATTRIB_FOGC; - default: - /* Back-face colors, edge flags, etc */ - return -1; - } -} - - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. - */ -static struct translated_vertex_program * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp, - struct st_fragment_program *stfp) +static void +translate_fp(struct st_context *st, + struct st_fragment_program *stfp) { - static const GLuint UNUSED = ~0; - struct translated_vertex_program *xvp; const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; - /* - * Translate fragment program if needed. - */ if (!stfp->state.tokens) { GLuint inAttr, numIn = 0; @@ -141,7 +77,7 @@ find_translated_vp(struct st_context *st, numIn++; } else { - stfp->input_to_slot[inAttr] = UNUSED; + stfp->input_to_slot[inAttr] = -1; } } @@ -151,170 +87,63 @@ find_translated_vp(struct st_context *st, st_translate_fragment_program(st, stfp, stfp->input_to_slot); } +} - /* See if we've got a translated vertex program whose outputs match - * the fragment program's inputs. - * XXX This could be a hash lookup, using InputsRead as the key. - */ - for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { - if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { - break; - } - } - /* No? Allocate translated vp object now */ - if (!xvp) { - xvp = ST_CALLOC_STRUCT(translated_vertex_program); - xvp->frag_inputs = fragInputsRead; - xvp->master = stvp; +/** + * Find a translated vertex program that corresponds to stvp and + * has outputs matched to stfp's inputs. + * This performs vertex and fragment translation (to TGSI) when needed. + */ +static struct st_vp_varient * +find_translated_vp(struct st_context *st, + struct st_vertex_program *stvp ) +{ + struct st_vp_varient *vpv; + struct st_vp_varient_key key; - xvp->next = stfp->vertex_programs; - stfp->vertex_programs = xvp; - } + /* Nothing in our key yet. This will change: + */ + memset(&key, 0, sizeof key); + key.dummy = 0; - /* See if we need to translate vertex program to TGSI form */ - if (xvp->serialNo != stvp->serialNo) { - GLuint outAttr; - const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten; - GLuint numVpOuts = 0; - GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; - GLbitfield usedGenerics = 0x0; - GLbitfield usedOutputSlots = 0x0; - - /* Compute mapping of vertex program outputs to slots, which depends - * on the fragment program's input->slot mapping. + /* Do we need to throw away old translations after a change in the + * GL program string? + */ + if (stvp->serialNo != stvp->lastSerialNo) { + /* These may have changed if the program string changed. */ - for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { - /* set defaults: */ - xvp->output_to_slot[outAttr] = UNUSED; - xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; - xvp->output_to_semantic_index[outAttr] = 99; - - if (outAttr == VERT_RESULT_HPOS) { - /* always put xformed position into slot zero */ - GLuint slot = 0; - xvp->output_to_slot[VERT_RESULT_HPOS] = slot; - xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; - xvp->output_to_semantic_index[outAttr] = 0; - numVpOuts++; - usedOutputSlots |= (1 << slot); - } - else if (outputsWritten & (1 << outAttr)) { - /* see if the frag prog wants this vert output */ - GLint fpInAttrib = vp_out_to_fp_in(outAttr); - if (fpInAttrib >= 0) { - GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; - if (fpInSlot != ~0) { - /* match this vp output to the fp input */ - GLuint vpOutSlot = stfp->input_map[fpInSlot]; - xvp->output_to_slot[outAttr] = vpOutSlot; - xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; - xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; - numVpOuts++; - usedOutputSlots |= (1 << vpOutSlot); - } - else { -#if 0 /*debug*/ - printf("VP output %d not used by FP\n", outAttr); -#endif - } - } - else if (outAttr == VERT_RESULT_PSIZ) - emitPntSize = GL_TRUE; - else if (outAttr == VERT_RESULT_BFC0) - emitBFC0 = GL_TRUE; - else if (outAttr == VERT_RESULT_BFC1) - emitBFC1 = GL_TRUE; - } -#if 0 /*debug*/ - printf("assign vp output_to_slot[%d] = %d\n", outAttr, - xvp->output_to_slot[outAttr]); -#endif - } - - /* must do these last */ - if (emitPntSize) { - GLuint slot = numVpOuts++; - xvp->output_to_slot[VERT_RESULT_PSIZ] = slot; - xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; - xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; - usedOutputSlots |= (1 << slot); - } - if (emitBFC0) { - GLuint slot = numVpOuts++; - xvp->output_to_slot[VERT_RESULT_BFC0] = slot; - xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; - xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; - usedOutputSlots |= (1 << slot); - } - if (emitBFC1) { - GLuint slot = numVpOuts++; - xvp->output_to_slot[VERT_RESULT_BFC1] = slot; - xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR; - xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1; - usedOutputSlots |= (1 << slot); - } - - /* build usedGenerics mask */ - usedGenerics = 0x0; - for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { - if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { - usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]); - } - } + st_prepare_vertex_program( st, stvp ); - /* For each vertex program output that doesn't match up to a fragment - * program input, map the vertex program output to a free slot and - * free generic attribute. + /* We are now up-to-date: */ - for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { - if (outputsWritten & (1 << outAttr)) { - if (xvp->output_to_slot[outAttr] == UNUSED) { - GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; - GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; - usedGenerics |= (1 << freeGeneric); - usedOutputSlots |= (1 << freeSlot); - xvp->output_to_slot[outAttr] = freeSlot; - xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; - xvp->output_to_semantic_index[outAttr] = freeGeneric; - } - } - -#if 0 /*debug*/ - printf("vp output_to_slot[%d] = %d\n", outAttr, - xvp->output_to_slot[outAttr]); -#endif + stvp->lastSerialNo = stvp->serialNo; + } + + /* See if we've got a translated vertex program whose outputs match + * the fragment program's inputs. + */ + for (vpv = stvp->varients; vpv; vpv = vpv->next) { + if (memcmp(&vpv->key, &key, sizeof key) == 0) { + break; } + } - assert(stvp->Base.Base.NumInstructions > 1); - - st_translate_vertex_program(st, stvp, xvp->output_to_slot, - xvp->output_to_semantic_name, - xvp->output_to_semantic_index); - - xvp->vp = stvp; - - /* translated VP is up to date now */ - xvp->serialNo = stvp->serialNo; + /* No? Perform new translation here. */ + if (!vpv) { + vpv = st_translate_vertex_program(st, stvp, &key); + if (!vpv) + return NULL; + + vpv->next = stvp->varients; + stvp->varients = vpv; } - return xvp; + return vpv; } -void -st_free_translated_vertex_programs(struct st_context *st, - struct translated_vertex_program *xvp) -{ - struct translated_vertex_program *next; - - while (xvp) { - next = xvp->next; - _mesa_free(xvp); - xvp = next; - } -} static void * @@ -328,32 +157,19 @@ get_passthrough_fs(struct st_context *st) return st->passthrough_fs; } - static void -update_linkage( struct st_context *st ) +update_fp( struct st_context *st ) { - struct st_vertex_program *stvp; struct st_fragment_program *stfp; - struct translated_vertex_program *xvp; - - /* find active shader and params -- Should be covered by - * ST_NEW_VERTEX_PROGRAM - */ - assert(st->ctx->VertexProgram._Current); - stvp = st_vertex_program(st->ctx->VertexProgram._Current); - assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); assert(st->ctx->FragmentProgram._Current); stfp = st_fragment_program(st->ctx->FragmentProgram._Current); assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - xvp = find_translated_vp(st, stvp, stfp); + translate_fp(st, stfp); - st_reference_vertprog(st, &st->vp, stvp); st_reference_fragprog(st, &st->fp, stfp); - cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader); - if (st->missing_textures) { /* use a pass-through frag shader that uses no textures */ void *fs = get_passthrough_fs(st); @@ -362,16 +178,48 @@ update_linkage( struct st_context *st ) else { cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); } +} + +const struct st_tracked_state st_update_fp = { + "st_update_fp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_FRAGMENT_PROGRAM /* st */ + }, + update_fp /* update */ +}; + + + + +static void +update_vp( struct st_context *st ) +{ + struct st_vertex_program *stvp; + + /* find active shader and params -- Should be covered by + * ST_NEW_VERTEX_PROGRAM + */ + assert(st->ctx->VertexProgram._Current); + stvp = st_vertex_program(st->ctx->VertexProgram._Current); + assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); + + st->vp_varient = find_translated_vp(st, stvp); + + st_reference_vertprog(st, &st->vp, stvp); + + cso_set_vertex_shader_handle(st->cso_context, + st->vp_varient->driver_shader); - st->vertex_result_to_slot = xvp->output_to_slot; + st->vertex_result_to_slot = stvp->result_to_output; } -const struct st_tracked_state st_update_shader = { - "st_update_shader", /* name */ +const struct st_tracked_state st_update_vp = { + "st_update_vp", /* name */ { /* dirty */ 0, /* mesa */ - ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM /* st */ + ST_NEW_VERTEX_PROGRAM /* st */ }, - update_linkage /* update */ + update_vp /* update */ }; diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 4d4f97da7e..0b68447d21 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -32,6 +32,8 @@ */ +#include "main/macros.h" + #include "st_context.h" #include "st_atom.h" #include "st_texture.h" @@ -99,6 +101,12 @@ update_textures(struct st_context *st) cso_set_sampler_textures(st->cso_context, st->state.num_textures, st->state.sampler_texture); + if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { + cso_set_vertex_sampler_textures(st->cso_context, + MIN2(st->state.num_textures, + st->ctx->Const.MaxVertexTextureImageUnits), + st->state.sampler_texture); + } } diff --git a/src/mesa/state_tracker/st_cb_accum.c b/src/mesa/state_tracker/st_cb_accum.c index 95181578f6..a6b9765452 100644 --- a/src/mesa/state_tracker/st_cb_accum.c +++ b/src/mesa/state_tracker/st_cb_accum.c @@ -34,6 +34,7 @@ #include "main/image.h" #include "main/macros.h" +#include "st_debug.h" #include "st_context.h" #include "st_cb_accum.h" #include "st_cb_fbo.h" @@ -136,6 +137,9 @@ accum_accum(struct st_context *st, GLfloat value, GLubyte *data = acc_strb->data; GLfloat *buf; + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, xpos, ypos, @@ -181,6 +185,10 @@ accum_load(struct st_context *st, GLfloat value, GLubyte *data = acc_strb->data; GLfloat *buf; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + color_trans = st_cond_flush_get_tex_transfer(st, color_strb->texture, 0, 0, 0, PIPE_TRANSFER_READ, xpos, ypos, @@ -228,6 +236,9 @@ accum_return(GLcontext *ctx, GLfloat value, const GLubyte *data = acc_strb->data; GLfloat *buf; + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + buf = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3]) @@ -241,7 +252,7 @@ accum_return(GLcontext *ctx, GLfloat value, xpos, ypos, width, height); - if (usage != PIPE_TRANSFER_WRITE) + if (usage & PIPE_TRANSFER_READ) pipe_get_tile_rgba(color_trans, 0, 0, width, height, buf); switch (acc_strb->format) { diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 902fb38d1a..1bdeaccda3 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -169,11 +169,6 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex) stfp = (struct st_fragment_program *) p; stfp->Base.UsesKill = GL_TRUE; - /* No need to send this incomplete program down to hardware: - * - * st_translate_fragment_program(ctx->st, stfp, NULL); - */ - return stfp; } @@ -330,7 +325,18 @@ setup_bitmap_vertex_data(struct st_context *st, const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0); const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0); const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0); - const GLuint max_slots = 4096 / sizeof(st->bitmap.vertices); + + /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as + * no_flush) updates to buffers where we know there is no conflict + * with previous data. Currently using max_slots > 1 will cause + * synchronous rendering if the driver flushes its command buffers + * between one bitmap and the next. Our flush hook below isn't + * sufficient to catch this as the driver doesn't tell us when it + * flushes its own command buffers. Until this gets fixed, pay the + * price of allocating a new buffer for each bitmap cache-flush to + * avoid synchronous rendering. + */ + const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */ GLuint i; if (st->bitmap.vbuf_slot >= max_slots) { @@ -515,7 +521,7 @@ reset_cache(struct st_context *st) struct pipe_screen *screen = pipe->screen; struct bitmap_cache *cache = st->bitmap.cache; - //memset(cache->buffer, 0xff, sizeof(cache->buffer)); + /*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/ cache->empty = GL_TRUE; cache->xmin = 1000000; diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index c741940bcf..563615ed0d 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -39,6 +39,7 @@ #include "shader/prog_print.h" #include "st_context.h" +#include "st_texture.h" #include "st_program.h" #include "st_cb_blit.h" #include "st_cb_fbo.h" @@ -63,6 +64,7 @@ st_destroy_blit(struct st_context *st) } +#if FEATURE_EXT_framebuffer_blit static void st_BlitFramebuffer(GLcontext *ctx, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, @@ -110,17 +112,50 @@ st_BlitFramebuffer(GLcontext *ctx, } if (mask & GL_COLOR_BUFFER_BIT) { - struct st_renderbuffer *srcRb = - st_renderbuffer(readFB->_ColorReadBuffer); - struct st_renderbuffer *dstRb = - st_renderbuffer(drawFB->_ColorDrawBuffers[0]); - struct pipe_surface *srcSurf = srcRb->surface; - struct pipe_surface *dstSurf = dstRb->surface; - - util_blit_pixels(st->blit, - srcSurf, srcX0, srcY0, srcX1, srcY1, - dstSurf, dstX0, dstY0, dstX1, dstY1, - 0.0, pFilter); + struct gl_renderbuffer_attachment *srcAtt = + &readFB->Attachment[readFB->_ColorReadBufferIndex]; + + if(srcAtt->Type == GL_TEXTURE) { + struct pipe_screen *screen = ctx->st->pipe->screen; + const struct st_texture_object *srcObj = + st_texture_object(srcAtt->Texture); + struct st_renderbuffer *dstRb = + st_renderbuffer(drawFB->_ColorDrawBuffers[0]); + struct pipe_surface *srcSurf; + struct pipe_surface *dstSurf = dstRb->surface; + + if (!srcObj->pt) + return; + + srcSurf = screen->get_tex_surface(screen, + srcObj->pt, + srcAtt->CubeMapFace, + srcAtt->TextureLevel, + srcAtt->Zoffset, + PIPE_BUFFER_USAGE_GPU_READ); + if(!srcSurf) + return; + + util_blit_pixels(st->blit, + srcSurf, srcX0, srcY0, srcX1, srcY1, + dstSurf, dstX0, dstY0, dstX1, dstY1, + 0.0, pFilter); + + pipe_surface_reference(&srcSurf, NULL); + } + else { + struct st_renderbuffer *srcRb = + st_renderbuffer(readFB->_ColorReadBuffer); + struct st_renderbuffer *dstRb = + st_renderbuffer(drawFB->_ColorDrawBuffers[0]); + struct pipe_surface *srcSurf = srcRb->surface; + struct pipe_surface *dstSurf = dstRb->surface; + + util_blit_pixels(st->blit, + srcSurf, srcX0, srcY0, srcX1, srcY1, + dstSurf, dstX0, dstY0, dstX1, dstY1, + 0.0, pFilter); + } } if (mask & depthStencil) { @@ -172,6 +207,7 @@ st_BlitFramebuffer(GLcontext *ctx, } } } +#endif /* FEATURE_EXT_framebuffer_blit */ diff --git a/src/mesa/state_tracker/st_cb_bufferobjects.c b/src/mesa/state_tracker/st_cb_bufferobjects.c index 8e09d0b932..63196afba9 100644 --- a/src/mesa/state_tracker/st_cb_bufferobjects.c +++ b/src/mesa/state_tracker/st_cb_bufferobjects.c @@ -239,6 +239,9 @@ st_bufferobj_map_range(GLcontext *ctx, GLenum target, if (access & GL_MAP_FLUSH_EXPLICIT_BIT) flags |= PIPE_BUFFER_USAGE_FLUSH_EXPLICIT; + if (access & GL_MAP_UNSYNCHRONIZED_BIT) + flags |= PIPE_BUFFER_USAGE_UNSYNCHRONIZED; + /* ... other flags ... */ diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index 8a8c99f7e1..e83b6c92ef 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -34,6 +34,7 @@ */ #include "main/glheader.h" +#include "main/formats.h" #include "main/macros.h" #include "shader/prog_instruction.h" #include "st_context.h" @@ -116,7 +117,18 @@ draw_quad(GLcontext *ctx, { struct st_context *st = ctx->st; struct pipe_context *pipe = st->pipe; - const GLuint max_slots = 1024 / sizeof(st->clear.vertices); + + /* XXX: Need to improve buffer_write to allow NO_WAIT (as well as + * no_flush) updates to buffers where we know there is no conflict + * with previous data. Currently using max_slots > 1 will cause + * synchronous rendering if the driver flushes its command buffers + * between one bitmap and the next. Our flush hook below isn't + * sufficient to catch this as the driver doesn't tell us when it + * flushes its own command buffers. Until this gets fixed, pay the + * price of allocating a new buffer for each bitmap cache-flush to + * avoid synchronous rendering. + */ + const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */ GLuint i; if (st->clear.vbuf_slot >= max_slots) { @@ -300,10 +312,14 @@ check_clear_color_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) static INLINE GLboolean check_clear_depth_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { - const GLuint stencilMax = (1 << rb->StencilBits) - 1; + const GLuint stencilMax = 0xff; GLboolean maskStencil = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; + assert(rb->Format == MESA_FORMAT_S8 || + rb->Format == MESA_FORMAT_Z24_S8 || + rb->Format == MESA_FORMAT_S8_Z24); + if (ctx->Scissor.Enabled && (ctx->Scissor.X != 0 || ctx->Scissor.Y != 0 || @@ -350,10 +366,14 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) { const struct st_renderbuffer *strb = st_renderbuffer(rb); const GLboolean isDS = pf_is_depth_and_stencil(strb->surface->format); - const GLuint stencilMax = (1 << rb->StencilBits) - 1; + const GLuint stencilMax = 0xff; const GLboolean maskStencil = (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax; + assert(rb->Format == MESA_FORMAT_S8 || + rb->Format == MESA_FORMAT_Z24_S8 || + rb->Format == MESA_FORMAT_S8_Z24); + if (maskStencil) return TRUE; diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 99f3ba678b..1baff19040 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -35,11 +35,13 @@ #include "main/bufferobj.h" #include "main/macros.h" #include "main/texformat.h" +#include "main/texstore.h" #include "main/state.h" #include "shader/program.h" #include "shader/prog_parameter.h" #include "shader/prog_print.h" +#include "st_debug.h" #include "st_context.h" #include "st_atom.h" #include "st_atom_constbuf.h" @@ -58,9 +60,11 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" +#include "tgsi/tgsi_ureg.h" #include "util/u_tile.h" #include "util/u_draw_quad.h" #include "util/u_math.h" +#include "util/u_rect.h" #include "shader/prog_instruction.h" #include "cso_cache/cso_context.h" @@ -233,78 +237,41 @@ make_fragment_shader_z(struct st_context *st) * Create a simple vertex shader that just passes through the * vertex position and texcoord (and optionally, color). */ -static struct st_vertex_program * -st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) +static void * +st_make_passthrough_vertex_shader(struct st_context *st, + GLboolean passColor) { - GLcontext *ctx = st->ctx; - struct st_vertex_program *stvp; - struct gl_program *p; - GLuint ic = 0; - - if (st->drawpix.vert_shaders[passColor]) - return st->drawpix.vert_shaders[passColor]; - - /* - * Create shader now - */ - p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); - if (!p) - return NULL; - - if (passColor) - p->NumInstructions = 4; - else - p->NumInstructions = 3; - - p->Instructions = _mesa_alloc_instructions(p->NumInstructions); - if (!p->Instructions) { - ctx->Driver.DeleteProgram(ctx, p); - return NULL; - } - _mesa_init_instructions(p->Instructions, p->NumInstructions); - /* MOV result.pos, vertex.pos; */ - p->Instructions[0].Opcode = OPCODE_MOV; - p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS; - p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS; - /* MOV result.texcoord0, vertex.texcoord0; */ - p->Instructions[1].Opcode = OPCODE_MOV; - p->Instructions[1].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0; - p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0; - ic = 2; - if (passColor) { - /* MOV result.color0, vertex.color0; */ - p->Instructions[ic].Opcode = OPCODE_MOV; - p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; - p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0; - p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; - p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0; - ic++; - } - - /* END; */ - p->Instructions[ic].Opcode = OPCODE_END; - ic++; - - assert(ic == p->NumInstructions); + if (!st->drawpix.vert_shaders[passColor]) { + struct ureg_program *ureg = + ureg_create( TGSI_PROCESSOR_VERTEX ); + + if (ureg == NULL) + return NULL; + + /* MOV result.pos, vertex.pos; */ + ureg_MOV(ureg, + ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), + ureg_DECL_vs_input( ureg, 0 )); + + /* MOV result.texcoord0, vertex.texcoord0; */ + ureg_MOV(ureg, + ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), + ureg_DECL_vs_input( ureg, 1 )); + + if (passColor) { + /* MOV result.color0, vertex.color0; */ + ureg_MOV(ureg, + ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), + ureg_DECL_vs_input( ureg, 2 )); + } - p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0; - p->OutputsWritten = ((1 << VERT_RESULT_TEX0) | - (1 << VERT_RESULT_HPOS)); - if (passColor) { - p->InputsRead |= VERT_BIT_COLOR0; - p->OutputsWritten |= (1 << VERT_RESULT_COL0); + ureg_END( ureg ); + + st->drawpix.vert_shaders[passColor] = + ureg_create_shader_and_destroy( ureg, st->pipe ); } - stvp = (struct st_vertex_program *) p; - st_translate_vertex_program(st, stvp, NULL, NULL, NULL); - - st->drawpix.vert_shaders[passColor] = stvp; - - return stvp; + return st->drawpix.vert_shaders[passColor]; } @@ -337,7 +304,7 @@ make_texture(struct st_context *st, GLcontext *ctx = st->ctx; struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; - const struct gl_texture_format *mformat; + gl_format mformat; struct pipe_texture *pt; enum pipe_format pipeFormat; GLuint cpp; @@ -349,7 +316,7 @@ make_texture(struct st_context *st, mformat = st_ChooseTextureFormat(ctx, baseFormat, format, type); assert(mformat); - pipeFormat = st_mesa_format_to_pipe_format(mformat->MesaFormat); + pipeFormat = st_mesa_format_to_pipe_format(mformat); assert(pipeFormat); cpp = st_sizeof_format(pipeFormat); @@ -402,21 +369,22 @@ make_texture(struct st_context *st, /* map texture transfer */ dest = screen->transfer_map(screen, transfer); + /* Put image into texture transfer. * Note that the image is actually going to be upside down in * the texture. We deal with that with texcoords. */ - success = mformat->StoreImage(ctx, 2, /* dims */ - baseFormat, /* baseInternalFormat */ - mformat, /* gl_texture_format */ - dest, /* dest */ - 0, 0, 0, /* dstX/Y/Zoffset */ - transfer->stride, /* dstRowStride, bytes */ - &dstImageOffsets, /* dstImageOffsets */ - width, height, 1, /* size */ - format, type, /* src format/type */ - pixels, /* data source */ - unpack); + success = _mesa_texstore(ctx, 2, /* dims */ + baseFormat, /* baseInternalFormat */ + mformat, /* gl_format */ + dest, /* dest */ + 0, 0, 0, /* dstX/Y/Zoffset */ + transfer->stride, /* dstRowStride, bytes */ + &dstImageOffsets, /* dstImageOffsets */ + width, height, 1, /* size */ + format, type, /* src format/type */ + pixels, /* data source */ + unpack); /* unmap */ screen->transfer_unmap(screen, transfer); @@ -535,8 +503,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, GLsizei width, GLsizei height, GLfloat zoomX, GLfloat zoomY, struct pipe_texture *pt, - struct st_vertex_program *stvp, - struct st_fragment_program *stfp, + void *driver_vp, + void *driver_fp, const GLfloat *color, GLboolean invertTex) { @@ -571,10 +539,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, } /* fragment shader state: TEX lookup program */ - cso_set_fragment_shader_handle(cso, stfp->driver_shader); + cso_set_fragment_shader_handle(cso, driver_fp); /* vertex shader state: position + texcoord pass-through */ - cso_set_vertex_shader_handle(cso, stvp->driver_shader); + cso_set_vertex_shader_handle(cso, driver_vp); /* texture sampling state: */ @@ -598,15 +566,15 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, /* viewport state: viewport matching window dims */ { - const float width = (float) ctx->DrawBuffer->Width; - const float height = (float) ctx->DrawBuffer->Height; + const float w = (float) ctx->DrawBuffer->Width; + const float h = (float) ctx->DrawBuffer->Height; struct pipe_viewport_state vp; - vp.scale[0] = 0.5f * width; - vp.scale[1] = -0.5f * height; + vp.scale[0] = 0.5f * w; + vp.scale[1] = -0.5f * h; vp.scale[2] = 1.0f; vp.scale[3] = 1.0f; - vp.translate[0] = 0.5f * width; - vp.translate[1] = 0.5f * height; + vp.translate[0] = 0.5f * w; + vp.translate[1] = 0.5f * h; vp.translate[2] = 0.0f; vp.translate[3] = 0.0f; cso_set_viewport(cso, &vp); @@ -617,10 +585,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, struct pipe_texture *textures[2]; textures[0] = pt; textures[1] = st->pixel_xfer.pixelmap_texture; - pipe->set_sampler_textures(pipe, 2, textures); + pipe->set_fragment_sampler_textures(pipe, 2, textures); } else { - pipe->set_sampler_textures(pipe, 1, &pt); + pipe->set_fragment_sampler_textures(pipe, 1, &pt); } /* Compute window coords (y=0=bottom) with pixel zoom. @@ -633,8 +601,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z, y1 = y + height * ctx->Pixel.ZoomY; draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, - (GLfloat) width / pt->width[0], - (GLfloat) height / pt->height[0]); + (GLfloat) width / pt->width0, + (GLfloat) height / pt->height0); /* restore state */ cso_restore_rasterizer(cso); @@ -661,6 +629,15 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0; GLint skipPixels; ubyte *stmap; + struct gl_pixelstore_attrib clippedUnpack = *unpack; + + if (!zoom) { + if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height, + &clippedUnpack)) { + /* totally clipped */ + return; + } + } strb = st_renderbuffer(ctx->DrawBuffer-> Attachment[BUFFER_STENCIL].Renderbuffer); @@ -681,7 +658,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, stmap = screen->transfer_map(screen, pt); - pixels = _mesa_map_pbo_source(ctx, unpack, pixels); + pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels); assert(pixels); /* if width > MAX_WIDTH, have to process image in chunks */ @@ -694,17 +671,18 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, GLubyte sValues[MAX_WIDTH]; GLuint zValues[MAX_WIDTH]; GLenum destType = GL_UNSIGNED_BYTE; - const GLvoid *source = _mesa_image_address2d(unpack, pixels, + const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels, width, height, format, type, row, skipPixels); _mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues, - type, source, unpack, + type, source, &clippedUnpack, ctx->_ImageTransferState); if (format == GL_DEPTH_STENCIL) { _mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues, - (1 << 24) - 1, type, source, unpack); + (1 << 24) - 1, type, source, + &clippedUnpack); } if (zoom) { @@ -723,7 +701,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* now pack the stencil (and Z) values in the dest format */ - switch (pt->format) { + switch (pt->texture->format) { case PIPE_FORMAT_S8_UNORM: { ubyte *dest = stmap + spanY * pt->stride + spanX; @@ -775,7 +753,7 @@ draw_stencil_pixels(GLcontext *ctx, GLint x, GLint y, skipPixels += spanWidth; } - _mesa_unmap_pbo_source(ctx, unpack); + _mesa_unmap_pbo_source(ctx, &clippedUnpack); /* unmap the stencil buffer */ screen->transfer_unmap(screen, pt); @@ -792,7 +770,7 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels) { struct st_fragment_program *stfp; - struct st_vertex_program *stvp; + void *driver_vp; struct st_context *st = st_context(ctx); struct pipe_surface *ps; const GLfloat *color; @@ -812,13 +790,13 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, if (format == GL_DEPTH_COMPONENT) { ps = st->state.framebuffer.zsbuf; stfp = make_fragment_shader_z(st); - stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); + driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE); color = ctx->Current.RasterColor; } else { ps = st->state.framebuffer.cbufs[0]; stfp = combined_drawpix_fragment_program(ctx); - stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); + driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE); color = NULL; } @@ -829,7 +807,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, if (pt) { draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, stvp, stfp, color, GL_FALSE); + pt, + driver_vp, + stfp->driver_shader, + color, GL_FALSE); pipe_texture_reference(&pt, NULL); } } @@ -875,8 +856,8 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, usage, dstx, dsty, width, height); - assert(ptDraw->block.width == 1); - assert(ptDraw->block.height == 1); + assert(pf_get_blockwidth(ptDraw->texture->format) == 1); + assert(pf_get_blockheight(ptDraw->texture->format) == 1); /* map the stencil buffer */ drawMap = screen->transfer_map(screen, ptDraw); @@ -897,7 +878,7 @@ copy_stencil_pixels(GLcontext *ctx, GLint srcx, GLint srcy, dst = drawMap + y * ptDraw->stride; src = buffer + i * width; - switch (ptDraw->format) { + switch (ptDraw->texture->format) { case PIPE_FORMAT_S8Z24_UNORM: { uint *dst4 = (uint *) dst; @@ -946,7 +927,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; struct st_renderbuffer *rbRead; - struct st_vertex_program *stvp; + void *driver_vp; struct st_fragment_program *stfp; struct pipe_texture *pt; GLfloat *color; @@ -995,14 +976,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, rbRead = st_get_color_read_renderbuffer(ctx); color = NULL; stfp = combined_drawpix_fragment_program(ctx); - stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); + driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE); } else { assert(type == GL_DEPTH); rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer); color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; stfp = make_fragment_shader_z(st); - stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); + driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE); } srcFormat = rbRead->texture->format; @@ -1014,13 +995,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, else { /* srcFormat can't be used as a texture format */ if (type == GL_DEPTH) { - texFormat = st_choose_format(pipe, GL_DEPTH_COMPONENT, PIPE_TEXTURE_2D, + texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT, + PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL); assert(texFormat != PIPE_FORMAT_NONE); /* XXX no depth texture formats??? */ } else { /* default color format */ - texFormat = st_choose_format(pipe, GL_RGBA, PIPE_TEXTURE_2D, + texFormat = st_choose_format(screen, GL_RGBA, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); assert(texFormat != PIPE_FORMAT_NONE); } @@ -1073,11 +1055,19 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, PIPE_BUFFER_USAGE_GPU_READ); struct pipe_surface *psTex = screen->get_tex_surface(screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); - pipe->surface_copy(pipe, - psTex, /* dest */ - 0, 0, /* destx/y */ - psRead, - srcx, srcy, width, height); + if (pipe->surface_copy) { + pipe->surface_copy(pipe, + psTex, /* dest */ + 0, 0, /* destx/y */ + psRead, + srcx, srcy, width, height); + } else { + util_surface_copy(pipe, FALSE, + psTex, + 0, 0, + psRead, + srcx, srcy, width, height); + } pipe_surface_reference(&psRead, NULL); pipe_surface_reference(&psTex, NULL); } @@ -1090,6 +1080,9 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, struct pipe_transfer *ptTex; enum pipe_transfer_usage transfer_usage; + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + if (type == GL_DEPTH && pf_is_depth_and_stencil(pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else @@ -1122,7 +1115,10 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy, /* draw textured quad */ draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2], width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, - pt, stvp, stfp, color, GL_TRUE); + pt, + driver_vp, + stfp->driver_shader, + color, GL_TRUE); pipe_texture_reference(&pt, NULL); } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index a96602878e..ead8e22888 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -49,6 +49,7 @@ #include "st_public.h" #include "st_texture.h" +#include "util/u_rect.h" /** @@ -64,13 +65,7 @@ init_renderbuffer_bits(struct st_renderbuffer *strb, assert( 0 ); } - strb->Base._ActualFormat = info.base_format; - strb->Base.RedBits = info.red_bits; - strb->Base.GreenBits = info.green_bits; - strb->Base.BlueBits = info.blue_bits; - strb->Base.AlphaBits = info.alpha_bits; - strb->Base.DepthBits = info.depth_bits; - strb->Base.StencilBits = info.stencil_bits; + strb->Base.Format = info.mesa_format; strb->Base.DataType = st_format_datatype(pipeFormat); return info.size; @@ -93,7 +88,7 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, if (strb->format != PIPE_FORMAT_NONE) format = strb->format; else - format = st_choose_renderbuffer_format(pipe, internalFormat); + format = st_choose_renderbuffer_format(pipe->screen, internalFormat); /* init renderbuffer fields */ strb->Base.Width = width; @@ -103,16 +98,14 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, strb->defined = GL_FALSE; /* undefined contents now */ if(strb->software) { - struct pipe_format_block block; size_t size; _mesa_free(strb->data); assert(strb->format != PIPE_FORMAT_NONE); - pf_get_block(strb->format, &block); - strb->stride = pf_get_stride(&block, width); - size = pf_get_2d_size(&block, strb->stride, height); + strb->stride = pf_get_stride(strb->format, width); + size = pf_get_2d_size(strb->format, strb->stride, height); strb->data = _mesa_malloc(size); @@ -132,10 +125,9 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; template.format = format; - pf_get_block(format, &template.block); - template.width[0] = width; - template.height[0] = height; - template.depth[0] = 1; + template.width0 = width; + template.height0 = height; + template.depth0 = 1; template.last_level = 0; template.nr_samples = rb->NumSamples; if (pf_is_depth_stencil(format)) { @@ -165,12 +157,12 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, strb->texture, 0, 0, 0, surface_usage ); - - assert(strb->surface->texture); - assert(strb->surface->format); - assert(strb->surface->width == width); - assert(strb->surface->height == height); - + if (strb->surface) { + assert(strb->surface->texture); + assert(strb->surface->format); + assert(strb->surface->width == width); + assert(strb->surface->height == height); + } return strb->surface != NULL; } @@ -258,6 +250,7 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) strb->Base.ClassID = 0x4242; /* just a unique value */ strb->Base.NumSamples = samples; strb->format = format; + init_renderbuffer_bits(strb, format); strb->software = sw; switch (format) { @@ -269,34 +262,29 @@ st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw) case PIPE_FORMAT_A4R4G4B4_UNORM: case PIPE_FORMAT_R5G6B5_UNORM: strb->Base.InternalFormat = GL_RGBA; - strb->Base._BaseFormat = GL_RGBA; break; case PIPE_FORMAT_Z16_UNORM: strb->Base.InternalFormat = GL_DEPTH_COMPONENT16; - strb->Base._BaseFormat = GL_DEPTH_COMPONENT; break; case PIPE_FORMAT_Z32_UNORM: strb->Base.InternalFormat = GL_DEPTH_COMPONENT32; - strb->Base._BaseFormat = GL_DEPTH_COMPONENT; break; case PIPE_FORMAT_S8Z24_UNORM: case PIPE_FORMAT_Z24S8_UNORM: case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_Z24X8_UNORM: strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT; - strb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; break; case PIPE_FORMAT_S8_UNORM: strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT; - strb->Base._BaseFormat = GL_STENCIL_INDEX; break; case PIPE_FORMAT_R16G16B16A16_SNORM: strb->Base.InternalFormat = GL_RGBA16; - strb->Base._BaseFormat = GL_RGBA; break; default: _mesa_problem(NULL, "Unexpected format in st_new_renderbuffer_fb"); + _mesa_free(strb); return NULL; } @@ -382,9 +370,10 @@ st_render_texture(GLcontext *ctx, rb->Width = texImage->Width2; rb->Height = texImage->Height2; + rb->_BaseFormat = texImage->_BaseFormat; /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/ - /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/ + /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/ pipe_texture_reference( &strb->texture, pt ); @@ -535,10 +524,17 @@ copy_back_to_front(struct st_context *st, (void) st_get_framebuffer_surface(stfb, backIndex, &surf_back); if (surf_front && surf_back) { - st->pipe->surface_copy(st->pipe, - surf_front, 0, 0, /* dest */ - surf_back, 0, 0, /* src */ - fb->Width, fb->Height); + if (st->pipe->surface_copy) { + st->pipe->surface_copy(st->pipe, + surf_front, 0, 0, /* dest */ + surf_back, 0, 0, /* src */ + fb->Width, fb->Height); + } else { + util_surface_copy(st->pipe, FALSE, + surf_front, 0, 0, + surf_back, 0, 0, + fb->Width, fb->Height); + } } } diff --git a/src/mesa/state_tracker/st_cb_get.c b/src/mesa/state_tracker/st_cb_get.c deleted file mode 100644 index e7d7f03bc9..0000000000 --- a/src/mesa/state_tracker/st_cb_get.c +++ /dev/null @@ -1,97 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -/** - * glGet functions - * - * \author Brian Paul - */ - -#include "main/imports.h" -#include "main/context.h" - -#include "pipe/p_defines.h" - -#include "st_cb_fbo.h" -#include "st_cb_get.h" - - - -/** - * Examine the current color read buffer format to determine - * which GL pixel format/type combo is the best match. - */ -static void -get_preferred_read_format_type(GLcontext *ctx, GLint *format, GLint *type) -{ - struct gl_framebuffer *fb = ctx->ReadBuffer; - struct st_renderbuffer *strb = st_renderbuffer(fb->_ColorReadBuffer); - - /* defaults */ - *format = ctx->Const.ColorReadFormat; - *type = ctx->Const.ColorReadType; - - if (strb) { - /* XXX could add more cases here... */ - if (strb->format == PIPE_FORMAT_A8R8G8B8_UNORM) { - *format = GL_BGRA; - if (_mesa_little_endian()) - *type = GL_UNSIGNED_INT_8_8_8_8_REV; - else - *type = GL_UNSIGNED_INT_8_8_8_8; - } - } -} - - -/** - * We only intercept the OES preferred ReadPixels format/type. - * Everything else goes to the default _mesa_GetIntegerv. - */ -static GLboolean -st_GetIntegerv(GLcontext *ctx, GLenum pname, GLint *params) -{ - GLint dummy; - - switch (pname) { - case GL_IMPLEMENTATION_COLOR_READ_TYPE_OES: - get_preferred_read_format_type(ctx, &dummy, params); - return GL_TRUE; - case GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES: - get_preferred_read_format_type(ctx, params, &dummy); - return GL_TRUE; - default: - return GL_FALSE; - } -} - - -void st_init_get_functions(struct dd_function_table *functions) -{ - functions->GetIntegerv = st_GetIntegerv; -} diff --git a/src/mesa/state_tracker/st_cb_get.h b/src/mesa/state_tracker/st_cb_get.h deleted file mode 100644 index 8e9f3e9306..0000000000 --- a/src/mesa/state_tracker/st_cb_get.h +++ /dev/null @@ -1,37 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#ifndef ST_CB_GET_H -#define ST_CB_GET_H - - -extern void -st_init_get_functions(struct dd_function_table *functions); - - -#endif diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index 4398ab2839..8c276f8128 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -45,6 +45,7 @@ #include "st_context.h" #include "st_program.h" #include "st_atom_shader.h" +#include "st_mesa_to_tgsi.h" #include "st_cb_program.h" @@ -137,24 +138,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog) case GL_VERTEX_PROGRAM_ARB: { struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - - if (stvp->driver_shader) { - cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); - stvp->driver_shader = NULL; - } - - if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix - /* this would only have been allocated for the RasterPos path */ - draw_delete_vertex_shader(st->draw, stvp->draw_shader); - stvp->draw_shader = NULL; -#endif - } - - if (stvp->state.tokens) { - _mesa_free((void *) stvp->state.tokens); - stvp->state.tokens = NULL; - } + st_vp_release_varients( st, stvp ); } break; case GL_FRAGMENT_PROGRAM_ARB: @@ -167,7 +151,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog) } if (stfp->state.tokens) { - _mesa_free((void *) stfp->state.tokens); + st_free_tokens(stfp->state.tokens); stfp->state.tokens = NULL; } @@ -176,8 +160,6 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog) _mesa_reference_program(ctx, &prg, NULL); stfp->bitmap_program = NULL; } - - st_free_translated_vertex_programs(st, stfp->vertex_programs); } break; default: @@ -214,12 +196,10 @@ static void st_program_string_notify( GLcontext *ctx, } if (stfp->state.tokens) { - _mesa_free((void *) stfp->state.tokens); + st_free_tokens(stfp->state.tokens); stfp->state.tokens = NULL; } - stfp->param_state = stfp->Base.Base.Parameters->StateFlags; - if (st->fp == stfp) st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; } @@ -228,25 +208,7 @@ static void st_program_string_notify( GLcontext *ctx, stvp->serialNo++; - if (stvp->driver_shader) { - cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); - stvp->driver_shader = NULL; - } - - if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix - /* this would only have been allocated for the RasterPos path */ - draw_delete_vertex_shader(st->draw, stvp->draw_shader); - stvp->draw_shader = NULL; -#endif - } - - if (stvp->state.tokens) { - _mesa_free((void *) stvp->state.tokens); - stvp->state.tokens = NULL; - } - - stvp->param_state = stvp->Base.Base.Parameters->StateFlags; + st_vp_release_varients( st, stvp ); if (st->vp == stvp) st->dirty.st |= ST_NEW_VERTEX_PROGRAM; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 75424aa2e7..6fa7bb64f2 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -43,6 +43,7 @@ #include "pipe/p_inlines.h" #include "util/u_tile.h" +#include "st_debug.h" #include "st_context.h" #include "st_cb_bitmap.h" #include "st_cb_readpixels.h" @@ -102,7 +103,7 @@ st_read_stencil_pixels(GLcontext *ctx, GLint x, GLint y, } /* get stencil (and Z) values */ - switch (pt->format) { + switch (pt->texture->format) { case PIPE_FORMAT_S8_UNORM: { const ubyte *src = stmap + srcY * pt->stride; @@ -242,7 +243,7 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb, GLint row, col, dy, dstStride; if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { - y = strb->texture->height[0] - y - height; + y = strb->texture->height0 - y - height; } trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, @@ -416,6 +417,9 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, yStep = 1; } + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); + /* * Copy pixels from pipe_transfer to user memory */ @@ -427,8 +431,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width, format, type); - if (trans->format == PIPE_FORMAT_S8Z24_UNORM || - trans->format == PIPE_FORMAT_X8Z24_UNORM) { + if (trans->texture->format == PIPE_FORMAT_S8Z24_UNORM || + trans->texture->format == PIPE_FORMAT_X8Z24_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -459,8 +463,8 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } } - else if (trans->format == PIPE_FORMAT_Z24S8_UNORM || - trans->format == PIPE_FORMAT_Z24X8_UNORM) { + else if (trans->texture->format == PIPE_FORMAT_Z24S8_UNORM || + trans->texture->format == PIPE_FORMAT_Z24X8_UNORM) { if (format == GL_DEPTH_COMPONENT) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; @@ -486,7 +490,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, } } } - else if (trans->format == PIPE_FORMAT_Z16_UNORM) { + else if (trans->texture->format == PIPE_FORMAT_Z16_UNORM) { for (i = 0; i < height; i++) { GLushort ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; @@ -501,7 +505,7 @@ st_readpixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height, dst += dstStride; } } - else if (trans->format == PIPE_FORMAT_Z32_UNORM) { + else if (trans->texture->format == PIPE_FORMAT_Z32_UNORM) { for (i = 0; i < height; i++) { GLuint ztemp[MAX_WIDTH]; GLfloat zfloat[MAX_WIDTH]; diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index c0ace3b9ea..6d136f5abf 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -31,18 +31,21 @@ #include "main/convolve.h" #endif #include "main/enums.h" +#include "main/formats.h" #include "main/image.h" #include "main/imports.h" #include "main/macros.h" #include "main/mipmap.h" #include "main/pixel.h" #include "main/texcompress.h" +#include "main/texfetch.h" #include "main/texformat.h" #include "main/texgetimage.h" #include "main/teximage.h" #include "main/texobj.h" #include "main/texstore.h" +#include "state_tracker/st_debug.h" #include "state_tracker/st_context.h" #include "state_tracker/st_cb_fbo.h" #include "state_tracker/st_cb_texture.h" @@ -90,51 +93,6 @@ gl_target_to_pipe(GLenum target) } -/** - * Return nominal bytes per texel for a compressed format, 0 for non-compressed - * format. - */ -static GLuint -compressed_num_bytes(GLuint mesaFormat) -{ - switch(mesaFormat) { -#if FEATURE_texture_fxt1 - case MESA_FORMAT_RGB_FXT1: - case MESA_FORMAT_RGBA_FXT1: -#endif -#if FEATURE_texture_s3tc - case MESA_FORMAT_RGB_DXT1: - case MESA_FORMAT_RGBA_DXT1: - return 2; - case MESA_FORMAT_RGBA_DXT3: - case MESA_FORMAT_RGBA_DXT5: - return 4; -#endif - default: - return 0; - } -} - - -static GLboolean -is_compressed_mesa_format(const struct gl_texture_format *format) -{ - switch (format->MesaFormat) { - case MESA_FORMAT_RGB_DXT1: - case MESA_FORMAT_RGBA_DXT1: - case MESA_FORMAT_RGBA_DXT3: - case MESA_FORMAT_RGBA_DXT5: - case MESA_FORMAT_SRGB_DXT1: - case MESA_FORMAT_SRGBA_DXT1: - case MESA_FORMAT_SRGBA_DXT3: - case MESA_FORMAT_SRGBA_DXT5: - return GL_TRUE; - default: - return GL_FALSE; - } -} - - /** called via ctx->Driver.NewTextureImage() */ static struct gl_texture_image * st_NewTextureImage(GLcontext * ctx) @@ -328,17 +286,20 @@ guess_and_alloc_texture(struct st_context *st, stObj->base.MinFilter == GL_LINEAR || stImage->base._BaseFormat == GL_DEPTH_COMPONENT || stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) && + !stObj->base.GenerateMipmap && stImage->level == firstLevel) { + /* only alloc space for a single mipmap level */ lastLevel = firstLevel; } else { + /* alloc space for a full mipmap */ GLuint l2width = util_logbase2(width); GLuint l2height = util_logbase2(height); GLuint l2depth = util_logbase2(depth); lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); } - fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat->MesaFormat); + fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat); usage = default_usage(fmt); @@ -411,14 +372,13 @@ compress_with_blit(GLcontext * ctx, const GLuint dstImageOffsets[1] = {0}; struct st_texture_image *stImage = st_texture_image(texImage); struct pipe_screen *screen = ctx->st->pipe->screen; - const struct gl_texture_format *mesa_format; + gl_format mesa_format; struct pipe_texture templ; struct pipe_texture *src_tex; struct pipe_surface *dst_surface; struct pipe_transfer *tex_xfer; void *map; - if (!stImage->pt) { /* XXX: Can this happen? Should we assert? */ return GL_FALSE; @@ -444,11 +404,10 @@ compress_with_blit(GLcontext * ctx, */ memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; - templ.format = st_mesa_format_to_pipe_format(mesa_format->MesaFormat); - pf_get_block(templ.format, &templ.block); - templ.width[0] = width; - templ.height[0] = height; - templ.depth[0] = 1; + templ.format = st_mesa_format_to_pipe_format(mesa_format); + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; templ.last_level = 0; templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; src_tex = screen->texture_create(screen, &templ); @@ -464,15 +423,15 @@ compress_with_blit(GLcontext * ctx, 0, 0, width, height); /* x, y, w, h */ map = screen->transfer_map(screen, tex_xfer); - mesa_format->StoreImage(ctx, 2, GL_RGBA, mesa_format, - map, /* dest ptr */ - 0, 0, 0, /* dest x/y/z offset */ - tex_xfer->stride, /* dest row stride (bytes) */ - dstImageOffsets, /* image offsets (for 3D only) */ - width, height, 1, /* size */ - format, type, /* source format/type */ - pixels, /* source data */ - unpack); /* source data packing */ + _mesa_texstore(ctx, 2, GL_RGBA, mesa_format, + map, /* dest ptr */ + 0, 0, 0, /* dest x/y/z offset */ + tex_xfer->stride, /* dest row stride (bytes) */ + dstImageOffsets, /* image offsets (for 3D only) */ + width, height, 1, /* size */ + format, type, /* source format/type */ + pixels, /* source data */ + unpack); /* source data packing */ screen->transfer_unmap(screen, tex_xfer); screen->tex_transfer_destroy(tex_xfer); @@ -554,23 +513,14 @@ st_TexImage(GLcontext * ctx, } #endif - /* choose the texture format */ - texImage->TexFormat = st_ChooseTextureFormat(ctx, internalFormat, - format, type); - _mesa_set_fetch_functions(texImage, dims); - if (texImage->TexFormat->TexelBytes == 0) { + if (_mesa_is_format_compressed(texImage->TexFormat)) { /* must be a compressed format */ texelBytes = 0; - texImage->IsCompressed = GL_TRUE; - texImage->CompressedSize = - ctx->Driver.CompressedTextureSize(ctx, texImage->Width, - texImage->Height, texImage->Depth, - texImage->TexFormat->MesaFormat); } else { - texelBytes = texImage->TexFormat->TexelBytes; + texelBytes = _mesa_get_format_bytes(texImage->TexFormat); /* Minimum pitch of 32 bytes */ if (postConvWidth * texelBytes < 32) { @@ -658,18 +608,23 @@ st_TexImage(GLcontext * ctx, format, type, pixels, unpack, "glTexImage"); } - if (!pixels) - return; + + /* Note: we can't check for pixels==NULL until after we've allocated + * memory for the texture. + */ /* See if we can do texture compression with a blit/render. */ if (!compressed_src && !ctx->Mesa_DXTn && - is_compressed_mesa_format(texImage->TexFormat) && + _mesa_is_format_compressed(texImage->TexFormat) && screen->is_format_supported(screen, stImage->pt->format, stImage->pt->target, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + if (!pixels) + goto done; + if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth, format, type, pixels, unpack, texImage)) { goto done; @@ -692,10 +647,12 @@ st_TexImage(GLcontext * ctx, } else { /* Allocate regular memory and store the image there temporarily. */ - if (texImage->IsCompressed) { - sizeInBytes = texImage->CompressedSize; - dstRowStride = - _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); + if (_mesa_is_format_compressed(texImage->TexFormat)) { + sizeInBytes = _mesa_format_image_size(texImage->TexFormat, + texImage->Width, + texImage->Height, + texImage->Depth); + dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width); assert(dims != 3); } else { @@ -711,6 +668,9 @@ st_TexImage(GLcontext * ctx, return; } + if (!pixels) + goto done; + DBG("Upload image %dx%dx%d row_len %x pitch %x\n", width, height, depth, width * texelBytes, dstRowStride); @@ -728,15 +688,15 @@ st_TexImage(GLcontext * ctx, const GLubyte *src = (const GLubyte *) pixels; for (i = 0; i < depth; i++) { - if (!texImage->TexFormat->StoreImage(ctx, dims, - texImage->_BaseFormat, - texImage->TexFormat, - texImage->Data, - 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - texImage->ImageOffsets, - width, height, 1, - format, type, src, unpack)) { + if (!_mesa_texstore(ctx, dims, + texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, + texImage->ImageOffsets, + width, height, 1, + format, type, src, unpack)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); } @@ -753,9 +713,9 @@ st_TexImage(GLcontext * ctx, } } +done: _mesa_unmap_teximage_pbo(ctx, unpack); -done: if (stImage->pt && texImage->Data) { st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; @@ -872,7 +832,7 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, /* copy/pack data into user buffer */ if (st_equal_formats(stImage->pt->format, format, type)) { /* memcpy */ - const uint bytesPerRow = width * pf_get_size(stImage->pt->format); + const uint bytesPerRow = width * pf_get_blocksize(stImage->pt->format); ubyte *map = screen->transfer_map(screen, tex_xfer); GLuint row; for (row = 0; row < height; row++) { @@ -892,6 +852,9 @@ decompress_with_blit(GLcontext * ctx, GLenum target, GLint level, GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width, height, format, type, row, 0); + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback format translation\n", __FUNCTION__); + /* get float[4] rgba row from surface */ pipe_get_tile_rgba(tex_xfer, 0, row, width, 1, rgba); @@ -951,7 +914,7 @@ st_get_tex_image(GLcontext * ctx, GLenum target, GLint level, PIPE_TRANSFER_READ, 0, 0, stImage->base.Width, stImage->base.Height); - texImage->RowStride = stImage->transfer->stride / stImage->pt->block.size; + texImage->RowStride = stImage->transfer->stride / pf_get_blocksize(stImage->pt->format); } else { /* Otherwise, the image should actually be stored in @@ -1057,7 +1020,7 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, /* See if we can do texture compression with a blit/render. */ if (!ctx->Mesa_DXTn && - is_compressed_mesa_format(texImage->TexFormat) && + _mesa_is_format_compressed(texImage->TexFormat) && screen->is_format_supported(screen, stImage->pt->format, stImage->pt->target, @@ -1092,21 +1055,21 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, if (!texImage->Data) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); - return; + goto done; } src = (const GLubyte *) pixels; dstRowStride = stImage->transfer->stride; for (i = 0; i < depth; i++) { - if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, - texImage->TexFormat, - texImage->Data, - 0, 0, 0, - dstRowStride, - texImage->ImageOffsets, - width, height, 1, - format, type, src, packing)) { + if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + 0, 0, 0, + dstRowStride, + texImage->ImageOffsets, + width, height, 1, + format, type, src, packing)) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); } @@ -1123,9 +1086,9 @@ st_TexSubimage(GLcontext *ctx, GLint dims, GLenum target, GLint level, } } +done: _mesa_unmap_teximage_pbo(ctx, packing); -done: if (stImage->pt) { st_texture_image_unmap(ctx->st, stImage); texImage->Data = NULL; @@ -1199,10 +1162,10 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, struct gl_texture_image *texImage) { struct st_texture_image *stImage = st_texture_image(texImage); - struct pipe_format_block block; int srcBlockStride; int dstBlockStride; int y; + enum pipe_format pformat= stImage->pt->format; if (stImage->pt) { unsigned face = _mesa_tex_target_to_face(target); @@ -1214,8 +1177,7 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, xoffset, yoffset, width, height); - block = stImage->pt->block; - srcBlockStride = pf_get_stride(&block, width); + srcBlockStride = pf_get_stride(pformat, width); dstBlockStride = stImage->transfer->stride; } else { assert(stImage->pt); @@ -1229,16 +1191,16 @@ st_CompressedTexSubImage2D(GLcontext *ctx, GLenum target, GLint level, return; } - assert(xoffset % block.width == 0); - assert(yoffset % block.height == 0); - assert(width % block.width == 0); - assert(height % block.height == 0); + assert(xoffset % pf_get_blockwidth(pformat) == 0); + assert(yoffset % pf_get_blockheight(pformat) == 0); + assert(width % pf_get_blockwidth(pformat) == 0); + assert(height % pf_get_blockheight(pformat) == 0); - for (y = 0; y < height; y += block.height) { + for (y = 0; y < height; y += pf_get_blockheight(pformat)) { /* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */ - const char *src = (const char*)data + srcBlockStride * pf_get_nblocksy(&block, y); - char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(&block, y); - memcpy(dst, src, pf_get_stride(&block, width)); + const char *src = (const char*)data + srcBlockStride * pf_get_nblocksy(pformat, y); + char *dst = (char*)texImage->Data + dstBlockStride * pf_get_nblocksy(pformat, y); + memcpy(dst, src, pf_get_stride(pformat, width)); } if (stImage->pt) { @@ -1283,6 +1245,9 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, struct pipe_transfer *src_trans; GLvoid *texDest; enum pipe_transfer_usage transfer_usage; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); assert(width <= MAX_WIDTH); @@ -1297,7 +1262,8 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, srcX, srcY, width, height); - if (baseFormat == GL_DEPTH_COMPONENT && + if ((baseFormat == GL_DEPTH_COMPONENT || + baseFormat == GL_DEPTH_STENCIL) && pf_is_depth_and_stencil(stImage->pt->format)) transfer_usage = PIPE_TRANSFER_READ_WRITE; else @@ -1310,7 +1276,7 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, destX, destY, width, height); if (baseFormat == GL_DEPTH_COMPONENT || - baseFormat == GL_DEPTH24_STENCIL8) { + baseFormat == GL_DEPTH_STENCIL) { const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F || ctx->Pixel.DepthBias != 0.0F); GLint row, yStep; @@ -1362,16 +1328,16 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level, * is actually RGBA but the user created the texture as GL_RGB we * need to fill-in/override the alpha channel with 1.0. */ - texImage->TexFormat->StoreImage(ctx, dims, - texImage->_BaseFormat, - texImage->TexFormat, - texDest, - 0, 0, 0, - dstRowStride, - texImage->ImageOffsets, - width, height, 1, - GL_RGBA, GL_FLOAT, tempSrc, /* src */ - &unpack); + _mesa_texstore(ctx, dims, + texImage->_BaseFormat, + texImage->TexFormat, + texDest, + 0, 0, 0, + dstRowStride, + texImage->ImageOffsets, + width, height, 1, + GL_RGBA, GL_FLOAT, tempSrc, /* src */ + &unpack); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage"); @@ -1390,8 +1356,8 @@ static unsigned compatible_src_dst_formats(const struct gl_renderbuffer *src, const struct gl_texture_image *dst) { - const GLenum srcFormat = src->_BaseFormat; - const GLenum dstLogicalFormat = dst->_BaseFormat; + const GLenum srcFormat = _mesa_get_format_base_format(src->Format); + const GLenum dstLogicalFormat = _mesa_get_format_base_format(dst->TexFormat); if (srcFormat == dstLogicalFormat) { /* This is the same as matching_base_formats, which should @@ -1408,6 +1374,12 @@ compatible_src_dst_formats(const struct gl_renderbuffer *src, return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */ } else { + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s failed for src %s, dst %s\n", + __FUNCTION__, + _mesa_lookup_enum_by_nr(srcFormat), + _mesa_lookup_enum_by_nr(dstLogicalFormat)); + /* Otherwise fail. */ return 0; @@ -1437,7 +1409,7 @@ st_copy_texsubimage(GLcontext *ctx, struct gl_texture_image *texImage = _mesa_select_tex_image(ctx, texObj, target, level); struct st_texture_image *stImage = st_texture_image(texImage); - const GLenum texBaseFormat = texImage->InternalFormat; + const GLenum texBaseFormat = texImage->_BaseFormat; struct gl_framebuffer *fb = ctx->ReadBuffer; struct st_renderbuffer *strb; struct pipe_context *pipe = ctx->st->pipe; @@ -1458,12 +1430,9 @@ st_copy_texsubimage(GLcontext *ctx, /* determine if copying depth or color data */ if (texBaseFormat == GL_DEPTH_COMPONENT || - texBaseFormat == GL_DEPTH24_STENCIL8) { + texBaseFormat == GL_DEPTH_STENCIL) { strb = st_renderbuffer(fb->_DepthBuffer); } - else if (texBaseFormat == GL_DEPTH_STENCIL_EXT) { - strb = st_renderbuffer(fb->_StencilBuffer); - } else { /* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */ strb = st_renderbuffer(fb->_ColorReadBuffer); @@ -1517,12 +1486,15 @@ st_copy_texsubimage(GLcontext *ctx, * framebuffer's alpha values). We can't do that with the blit or * textured-quad paths. */ - matching_base_formats = (strb->Base._BaseFormat == texImage->_BaseFormat); + matching_base_formats = + (_mesa_get_format_base_format(strb->Base.Format) == + _mesa_get_format_base_format(texImage->TexFormat)); format_writemask = compatible_src_dst_formats(&strb->Base, texImage); if (ctx->_ImageTransferState == 0x0) { - if (matching_base_formats && + if (pipe->surface_copy && + matching_base_formats && src_format == dest_format && !do_flip) { @@ -1546,6 +1518,8 @@ st_copy_texsubimage(GLcontext *ctx, use_fallback = GL_FALSE; } else if (format_writemask && + texBaseFormat != GL_DEPTH_COMPONENT && + texBaseFormat != GL_DEPTH_STENCIL && screen->is_format_supported(screen, src_format, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, @@ -1685,53 +1659,6 @@ st_CopyTexSubImage3D(GLcontext * ctx, GLenum target, GLint level, } -/** - * Compute which mipmap levels that really need to be sent to the hardware. - * This depends on the base image size, GL_TEXTURE_MIN_LOD, - * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. - */ -static void -calculate_first_last_level(struct st_texture_object *stObj) -{ - struct gl_texture_object *tObj = &stObj->base; - - /* These must be signed values. MinLod and MaxLod can be negative numbers, - * and having firstLevel and lastLevel as signed prevents the need for - * extra sign checks. - */ - GLint firstLevel; - GLint lastLevel; - - /* Yes, this looks overly complicated, but it's all needed. - */ - switch (tObj->Target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_CUBE_MAP: - if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { - /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. - */ - firstLevel = lastLevel = tObj->BaseLevel; - } - else { - firstLevel = 0; - lastLevel = MIN2(tObj->MaxLevel, - (int) tObj->Image[0][tObj->BaseLevel]->WidthLog2); - } - break; - case GL_TEXTURE_RECTANGLE_NV: - case GL_TEXTURE_4D_SGIS: - firstLevel = lastLevel = 0; - break; - default: - return; - } - - stObj->lastLevel = lastLevel; -} - - static void copy_image_data_to_texture(struct st_context *st, struct st_texture_object *stObj, @@ -1750,8 +1677,6 @@ copy_image_data_to_texture(struct st_context *st, pipe_texture_reference(&stImage->pt, NULL); } else if (stImage->base.Data) { - assert(stImage->base.Data != NULL); - /* More straightforward upload. */ @@ -1765,10 +1690,10 @@ copy_image_data_to_texture(struct st_context *st, dstLevel, stImage->base.Data, stImage->base.RowStride * - stObj->pt->block.size, + pf_get_blocksize(stObj->pt->format), stImage->base.RowStride * stImage->base.Height * - stObj->pt->block.size); + pf_get_blocksize(stObj->pt->format)); _mesa_align_free(stImage->base.Data); stImage->base.Data = NULL; } @@ -1790,18 +1715,25 @@ st_finalize_texture(GLcontext *ctx, { struct st_texture_object *stObj = st_texture_object(tObj); const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLuint cpp, face; + GLuint blockSize, face; struct st_texture_image *firstImage; *needFlush = GL_FALSE; - /* We know/require this is true by now: - */ - assert(stObj->base._Complete); + if (stObj->base._Complete) { + /* The texture is complete and we know exactly how many mipmap levels + * are present/needed. This is conditional because we may be called + * from the st_generate_mipmap() function when the texture object is + * incomplete. In that case, we'll have set stObj->lastLevel before + * we get here. + */ + if (stObj->base.MinFilter == GL_LINEAR || + stObj->base.MinFilter == GL_NEAREST) + stObj->lastLevel = stObj->base.BaseLevel; + else + stObj->lastLevel = stObj->base._MaxLevel - stObj->base.BaseLevel; + } - /* What levels must the texture include at a minimum? - */ - calculate_first_last_level(stObj); firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]); /* If both firstImage and stObj point to a texture which can contain @@ -1815,28 +1747,21 @@ st_finalize_texture(GLcontext *ctx, pipe_texture_reference(&stObj->pt, firstImage->pt); } - /* FIXME: determine format block instead of cpp */ - if (firstImage->base.IsCompressed) { - cpp = compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); - } - else { - cpp = firstImage->base.TexFormat->TexelBytes; - } + /* bytes per pixel block (blocks are usually 1x1) */ + blockSize = _mesa_get_format_bytes(firstImage->base.TexFormat); /* If we already have a gallium texture, check that it matches the texture * object's format, target, size, num_levels, etc. */ if (stObj->pt) { const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat); + st_mesa_format_to_pipe_format(firstImage->base.TexFormat); if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) || stObj->pt->format != fmt || stObj->pt->last_level < stObj->lastLevel || - stObj->pt->width[0] != firstImage->base.Width2 || - stObj->pt->height[0] != firstImage->base.Height2 || - stObj->pt->depth[0] != firstImage->base.Depth2 || - /* Nominal bytes per pixel: */ - stObj->pt->block.size / stObj->pt->block.width != cpp) + stObj->pt->width0 != firstImage->base.Width2 || + stObj->pt->height0 != firstImage->base.Height2 || + stObj->pt->depth0 != firstImage->base.Depth2) { pipe_texture_reference(&stObj->pt, NULL); ctx->st->dirty.st |= ST_NEW_FRAMEBUFFER; @@ -1847,7 +1772,7 @@ st_finalize_texture(GLcontext *ctx, */ if (!stObj->pt) { const enum pipe_format fmt = - st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat); + st_mesa_format_to_pipe_format(firstImage->base.TexFormat); GLuint usage = default_usage(fmt); stObj->pt = st_texture_create(ctx->st, @@ -1964,7 +1889,6 @@ st_init_texture_functions(struct dd_function_table *functions) /* compressed texture functions */ functions->CompressedTexImage2D = st_CompressedTexImage2D; functions->GetCompressedTexImage = st_GetCompressedTexImage; - functions->CompressedTextureSize = _mesa_compressed_texture_size; functions->NewTextureObject = st_NewTextureObject; functions->NewTextureImage = st_NewTextureImage; diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 8514b6b375..d18a25ab51 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -36,6 +36,7 @@ #include "shader/shader_api.h" #include "glapi/glapi.h" #include "st_public.h" +#include "st_debug.h" #include "st_context.h" #include "st_cb_accum.h" #include "st_cb_bitmap.h" @@ -50,7 +51,6 @@ #include "st_cb_drawtex.h" #endif #include "st_cb_fbo.h" -#include "st_cb_get.h" #if FEATURE_feedback #include "st_cb_feedback.h" #endif @@ -113,6 +113,9 @@ st_create_context_priv( GLcontext *ctx, struct pipe_context *pipe ) st->ctx = ctx; st->pipe = pipe; + /* XXX: this is one-off, per-screen init: */ + st_debug_init(); + /* state tracker needs the VBO module */ _vbo_CreateContext(ctx); @@ -327,12 +330,11 @@ void st_init_driver_functions(struct dd_function_table *functions) st_init_rasterpos_functions(functions); #endif st_init_fbo_functions(functions); - st_init_get_functions(functions); #if FEATURE_feedback st_init_feedback_functions(functions); #endif st_init_program_functions(functions); -#if FEATURE_ARB_occlusion_query +#if FEATURE_queryobj st_init_query_functions(functions); #endif st_init_readpixels_functions(functions); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 18adb35e87..b760728658 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -127,6 +127,8 @@ struct st_context struct st_vertex_program *vp; /**< Currently bound vertex program */ struct st_fragment_program *fp; /**< Currently bound fragment program */ + struct st_vp_varient *vp_varient; + struct gl_texture_object *default_texture; struct { diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index c7d26ce33c..6e699ca552 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -41,6 +41,32 @@ +#ifdef DEBUG +int ST_DEBUG = 0; + +static const struct debug_named_value st_debug_flags[] = { + { "mesa", DEBUG_MESA }, + { "tgsi", DEBUG_TGSI }, + { "pipe", DEBUG_PIPE }, + { "tex", DEBUG_TEX }, + { "fallback", DEBUG_FALLBACK }, + { "screen", DEBUG_SCREEN }, + { "query", DEBUG_QUERY }, + {NULL, 0} +}; +#endif + + +void +st_debug_init(void) +{ +#ifdef DEBUG + ST_DEBUG = debug_get_flags_option("ST_DEBUG", st_debug_flags, 0 ); +#endif +} + + + /** * Print current state. May be called from inside gdb to see currently * bound vertex/fragment shaders and associated constants. @@ -60,7 +86,8 @@ st_print_current(void) } #endif - tgsi_dump( st->vp->state.tokens, 0 ); + if (st->vp->varients) + tgsi_dump( st->vp->varients[0].state.tokens, 0 ); if (st->vp->Base.Base.Parameters) _mesa_print_parameter_list(st->vp->Base.Base.Parameters); @@ -68,3 +95,5 @@ st_print_current(void) if (st->fp->Base.Base.Parameters) _mesa_print_parameter_list(st->fp->Base.Base.Parameters); } + + diff --git a/src/mesa/state_tracker/st_debug.h b/src/mesa/state_tracker/st_debug.h index 49d752e1b2..4a060d7759 100644 --- a/src/mesa/state_tracker/st_debug.h +++ b/src/mesa/state_tracker/st_debug.h @@ -29,8 +29,44 @@ #ifndef ST_DEBUG_H #define ST_DEBUG_H +#include "pipe/p_compiler.h" +#include "util/u_debug.h" + extern void st_print_current(void); +#define DEBUG_MESA 0x1 +#define DEBUG_TGSI 0x2 +#define DEBUG_CONSTANTS 0x4 +#define DEBUG_PIPE 0x8 +#define DEBUG_TEX 0x10 +#define DEBUG_FALLBACK 0x20 +#define DEBUG_QUERY 0x40 +#define DEBUG_SCREEN 0x80 + +#ifdef DEBUG +extern int ST_DEBUG; +#define DBSTR(x) x +#else +#define ST_DEBUG 0 +#define DBSTR(x) "" +#endif + +void st_debug_init( void ); + +static INLINE void +ST_DBG( unsigned flag, const char *fmt, ... ) +{ + if (ST_DEBUG & flag) + { + va_list args; + + va_start( args, fmt ); + debug_vprintf( fmt, args ); + va_end( args ); + } +} + + #endif /* ST_DEBUG_H */ diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 503a5f34a3..e13ae57a0e 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -25,10 +25,20 @@ * **************************************************************************/ - /* - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ +/* + * This file implements the st_draw_vbo() function which is called from + * Mesa's VBO module. All point/line/triangle rendering is done through + * this function whether the user called glBegin/End, glDrawArrays, + * glDrawElements, glEvalMesh, or glCalList, etc. + * + * We basically convert the VBO's vertex attribute/array information into + * Gallium vertex state, bind the vertex buffer objects and call + * pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays(). + * + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + #include "main/imports.h" #include "main/image.h" @@ -328,23 +338,29 @@ get_arrays_bounds(const struct st_vertex_program *vp, const GLubyte **low, const GLubyte **high) { const GLubyte *low_addr = NULL; + const GLubyte *high_addr = NULL; GLuint attr; - GLint stride; for (attr = 0; attr < vp->num_inputs; attr++) { const GLuint mesaAttr = vp->index_to_input[attr]; + const GLint stride = arrays[mesaAttr]->StrideB; const GLubyte *start = arrays[mesaAttr]->Ptr; - stride = arrays[mesaAttr]->StrideB; + const unsigned sz = (arrays[mesaAttr]->Size * + _mesa_sizeof_type(arrays[mesaAttr]->Type)); + const GLubyte *end = start + (max_index * stride) + sz; + if (attr == 0) { low_addr = start; + high_addr = end; } else { low_addr = MIN2(low_addr, start); + high_addr = MAX2(high_addr, end); } } *low = low_addr; - *high = low_addr + (max_index + 1) * stride; + *high = high_addr; } @@ -557,7 +573,7 @@ st_draw_vbo(GLcontext *ctx, /* must get these after state validation! */ vp = ctx->st->vp; - vs = &ctx->st->vp->state; + vs = &ctx->st->vp_varient->state; #if 0 if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index b2d682ef64..d793f820bc 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -120,10 +120,10 @@ st_feedback_draw_vbo(GLcontext *ctx, /* must get these after state validation! */ vp = ctx->st->vp; - vs = &st->vp->state; + vs = &st->vp_varient->state; - if (!st->vp->draw_shader) { - st->vp->draw_shader = draw_create_vertex_shader(draw, vs); + if (!st->vp_varient->draw_shader) { + st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs); } /* @@ -136,7 +136,7 @@ st_feedback_draw_vbo(GLcontext *ctx, draw_set_viewport_state(draw, &st->state.viewport); draw_set_clip_state(draw, &st->state.clip); draw_set_rasterizer_state(draw, &st->state.rasterizer); - draw_bind_vertex_shader(draw, st->vp->draw_shader); + draw_bind_vertex_shader(draw, st->vp_varient->draw_shader); set_feedback_vertex_format(ctx); /* loop over TGSI shader inputs to determine vertex buffer diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 3f835d38dd..ef3cbc53ee 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -92,6 +92,10 @@ void st_init_limits(struct st_context *st) = _min(screen->get_param(screen, PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS), MAX_VERTEX_TEXTURE_IMAGE_UNITS); + c->MaxCombinedTextureImageUnits + = _min(screen->get_param(screen, PIPE_CAP_MAX_COMBINED_SAMPLERS), + MAX_COMBINED_TEXTURE_IMAGE_UNITS); + c->MaxTextureCoordUnits = _min(c->MaxTextureImageUnits, MAX_TEXTURE_COORD_UNITS); @@ -284,6 +288,7 @@ void st_init_extensions(struct st_context *st) PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER, 0)) { ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; + ctx->Extensions.S3_s3tc = GL_TRUE; } /* ycbcr support */ diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c index dcb90a3107..93125afe9e 100644 --- a/src/mesa/state_tracker/st_format.c +++ b/src/mesa/state_tracker/st_format.c @@ -99,10 +99,11 @@ st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo) if (format == PIPE_FORMAT_A1R5G5B5_UNORM || format == PIPE_FORMAT_R5G6B5_UNORM) { pinfo->datatype = GL_UNSIGNED_SHORT; } + else if (format == PIPE_FORMAT_S8Z24_UNORM) { + pinfo->datatype = GL_UNSIGNED_INT_24_8; + } else { - GLuint size; - - size = format_max_bits( info ); + const GLuint size = format_max_bits( info ); if (size == 8) { if (pf_type(info) == PIPE_FORMAT_TYPE_UNORM) pinfo->datatype = GL_UNSIGNED_BYTE; @@ -150,24 +151,10 @@ st_get_format_info(enum pipe_format format, struct pipe_format_info *pinfo) pinfo->red_bits = 0; } - /* Base format */ - if (pinfo->depth_bits) { - if (pinfo->stencil_bits) { - pinfo->base_format = GL_DEPTH_STENCIL_EXT; - } - else { - pinfo->base_format = GL_DEPTH_COMPONENT; - } - } - else if (pinfo->stencil_bits) { - pinfo->base_format = GL_STENCIL_INDEX; - } - else { - pinfo->base_format = GL_RGBA; - } + pinfo->mesa_format = st_pipe_format_to_mesa_format(format); } else if (pf_layout(format) == PIPE_FORMAT_LAYOUT_YCBCR) { - pinfo->base_format = GL_YCBCR_MESA; + pinfo->mesa_format = MESA_FORMAT_YCBCR; pinfo->datatype = GL_UNSIGNED_SHORT; pinfo->size = 2; /* two bytes per "texel" */ } @@ -224,13 +211,15 @@ st_format_datatype(enum pipe_format format) enum pipe_format -st_mesa_format_to_pipe_format(GLuint mesaFormat) +st_mesa_format_to_pipe_format(gl_format mesaFormat) { switch (mesaFormat) { /* fix this */ case MESA_FORMAT_ARGB8888_REV: case MESA_FORMAT_ARGB8888: return PIPE_FORMAT_A8R8G8B8_UNORM; + case MESA_FORMAT_XRGB8888: + return PIPE_FORMAT_X8R8G8B8_UNORM; case MESA_FORMAT_ARGB1555: return PIPE_FORMAT_A1R5G5B5_UNORM; case MESA_FORMAT_ARGB4444: @@ -293,6 +282,88 @@ st_mesa_format_to_pipe_format(GLuint mesaFormat) } } + +gl_format +st_pipe_format_to_mesa_format(enum pipe_format pipeFormat) +{ + switch (pipeFormat) { + case PIPE_FORMAT_A8R8G8B8_UNORM: + return MESA_FORMAT_ARGB8888; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return MESA_FORMAT_XRGB8888; + case PIPE_FORMAT_A1R5G5B5_UNORM: + return MESA_FORMAT_ARGB1555; + case PIPE_FORMAT_A4R4G4B4_UNORM: + return MESA_FORMAT_ARGB4444; + case PIPE_FORMAT_R5G6B5_UNORM: + return MESA_FORMAT_RGB565; + case PIPE_FORMAT_A8L8_UNORM: + return MESA_FORMAT_AL88; + case PIPE_FORMAT_A8_UNORM: + return MESA_FORMAT_A8; + case PIPE_FORMAT_L8_UNORM: + return MESA_FORMAT_L8; + case PIPE_FORMAT_I8_UNORM: + return MESA_FORMAT_I8; + case PIPE_FORMAT_Z16_UNORM: + return MESA_FORMAT_Z16; + case PIPE_FORMAT_Z32_UNORM: + return MESA_FORMAT_Z32; + case PIPE_FORMAT_Z24X8_UNORM: + return MESA_FORMAT_Z24_X8; + case PIPE_FORMAT_Z24S8_UNORM: + return MESA_FORMAT_Z24_S8; + case PIPE_FORMAT_X8Z24_UNORM: + return MESA_FORMAT_X8_Z24; + case PIPE_FORMAT_S8Z24_UNORM: + return MESA_FORMAT_S8_Z24; + case PIPE_FORMAT_S8_UNORM: + return MESA_FORMAT_S8; + + case PIPE_FORMAT_YCBCR: + return MESA_FORMAT_YCBCR; + case PIPE_FORMAT_R16G16B16A16_SNORM: + return MESA_FORMAT_SIGNED_RGBA_16; + +#if FEATURE_texture_s3tc + case PIPE_FORMAT_DXT1_RGB: + return MESA_FORMAT_RGB_DXT1; + case PIPE_FORMAT_DXT1_RGBA: + return MESA_FORMAT_RGBA_DXT1; + case PIPE_FORMAT_DXT3_RGBA: + return MESA_FORMAT_RGBA_DXT3; + case PIPE_FORMAT_DXT5_RGBA: + return MESA_FORMAT_RGBA_DXT5; +#if FEATURE_EXT_texture_sRGB + case PIPE_FORMAT_DXT1_SRGB: + return MESA_FORMAT_SRGB_DXT1; + case PIPE_FORMAT_DXT1_SRGBA: + return MESA_FORMAT_SRGBA_DXT1; + case PIPE_FORMAT_DXT3_SRGBA: + return MESA_FORMAT_SRGBA_DXT3; + case PIPE_FORMAT_DXT5_SRGBA: + return MESA_FORMAT_SRGBA_DXT5; +#endif +#endif +#if FEATURE_EXT_texture_sRGB + case PIPE_FORMAT_A8L8_SRGB: + return MESA_FORMAT_SLA8; + case PIPE_FORMAT_L8_SRGB: + return MESA_FORMAT_SL8; + case PIPE_FORMAT_R8G8B8_SRGB: + return MESA_FORMAT_SRGB8; + case PIPE_FORMAT_R8G8B8A8_SRGB: + return MESA_FORMAT_SRGBA8; + case PIPE_FORMAT_A8R8G8B8_SRGB: + return MESA_FORMAT_SARGB8; +#endif + default: + assert(0); + return 0; + } +} + + /** * Find an RGBA format supported by the context/winsys. */ @@ -318,6 +389,33 @@ default_rgba_format(struct pipe_screen *screen, } /** + * Find an RGB format supported by the context/winsys. + */ +static enum pipe_format +default_rgb_format(struct pipe_screen *screen, + enum pipe_texture_target target, + unsigned tex_usage, + unsigned geom_flags) +{ + static const enum pipe_format colorFormats[] = { + PIPE_FORMAT_X8R8G8B8_UNORM, + PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_FORMAT_R8G8B8X8_UNORM, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_R5G6B5_UNORM + }; + uint i; + for (i = 0; i < Elements(colorFormats); i++) { + if (screen->is_format_supported( screen, colorFormats[i], target, tex_usage, geom_flags )) { + return colorFormats[i]; + } + } + return PIPE_FORMAT_NONE; +} + +/** * Find an sRGBA format supported by the context/winsys. */ static enum pipe_format @@ -392,23 +490,23 @@ default_depth_format(struct pipe_screen *screen, * or PIPE_TEXTURE_USAGE_SAMPLER */ enum pipe_format -st_choose_format(struct pipe_context *pipe, GLenum internalFormat, +st_choose_format(struct pipe_screen *screen, GLenum internalFormat, enum pipe_texture_target target, unsigned tex_usage) { - struct pipe_screen *screen = pipe->screen; unsigned geom_flags = 0; switch (internalFormat) { case 4: case GL_RGBA: case GL_COMPRESSED_RGBA: - case 3: - case GL_RGB: - case GL_COMPRESSED_RGB: case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: return default_rgba_format( screen, target, tex_usage, geom_flags ); + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + return default_rgb_format( screen, target, tex_usage, geom_flags ); case GL_RGBA16: if (tex_usage & PIPE_TEXTURE_USAGE_RENDER_TARGET) return default_deep_rgba_format( screen, target, tex_usage, geom_flags ); @@ -430,7 +528,7 @@ st_choose_format(struct pipe_context *pipe, GLenum internalFormat, case GL_RGB10: case GL_RGB12: case GL_RGB16: - return default_rgba_format( screen, target, tex_usage, geom_flags ); + return default_rgb_format( screen, target, tex_usage, geom_flags ); case GL_RGB5: case GL_RGB4: @@ -618,85 +716,90 @@ is_depth_or_stencil_format(GLenum internalFormat) * Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces. */ enum pipe_format -st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat) +st_choose_renderbuffer_format(struct pipe_screen *screen, + GLenum internalFormat) { uint usage; if (is_depth_or_stencil_format(internalFormat)) usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; else usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - return st_choose_format(pipe, internalFormat, PIPE_TEXTURE_2D, usage); + return st_choose_format(screen, internalFormat, PIPE_TEXTURE_2D, usage); } -static const struct gl_texture_format * +static gl_format translate_gallium_format_to_mesa_format(enum pipe_format format) { switch (format) { case PIPE_FORMAT_A8R8G8B8_UNORM: - return &_mesa_texformat_argb8888; + return MESA_FORMAT_ARGB8888; + case PIPE_FORMAT_X8R8G8B8_UNORM: + return MESA_FORMAT_XRGB8888; case PIPE_FORMAT_A1R5G5B5_UNORM: - return &_mesa_texformat_argb1555; + return MESA_FORMAT_ARGB1555; case PIPE_FORMAT_A4R4G4B4_UNORM: - return &_mesa_texformat_argb4444; + return MESA_FORMAT_ARGB4444; case PIPE_FORMAT_R5G6B5_UNORM: - return &_mesa_texformat_rgb565; + return MESA_FORMAT_RGB565; case PIPE_FORMAT_A8L8_UNORM: - return &_mesa_texformat_al88; + return MESA_FORMAT_AL88; case PIPE_FORMAT_A8_UNORM: - return &_mesa_texformat_a8; + return MESA_FORMAT_A8; case PIPE_FORMAT_L8_UNORM: - return &_mesa_texformat_l8; + return MESA_FORMAT_L8; case PIPE_FORMAT_I8_UNORM: - return &_mesa_texformat_i8; + return MESA_FORMAT_I8; case PIPE_FORMAT_Z16_UNORM: - return &_mesa_texformat_z16; + return MESA_FORMAT_Z16; case PIPE_FORMAT_Z32_UNORM: - return &_mesa_texformat_z32; + return MESA_FORMAT_Z32; case PIPE_FORMAT_Z24S8_UNORM: - return &_mesa_texformat_z24_s8; + return MESA_FORMAT_Z24_S8; + case PIPE_FORMAT_X8Z24_UNORM: + return MESA_FORMAT_X8_Z24; case PIPE_FORMAT_S8Z24_UNORM: - return &_mesa_texformat_s8_z24; + return MESA_FORMAT_S8_Z24; case PIPE_FORMAT_YCBCR: - return &_mesa_texformat_ycbcr; + return MESA_FORMAT_YCBCR; case PIPE_FORMAT_YCBCR_REV: - return &_mesa_texformat_ycbcr_rev; + return MESA_FORMAT_YCBCR_REV; #if FEATURE_texture_s3tc case PIPE_FORMAT_DXT1_RGB: - return &_mesa_texformat_rgb_dxt1; + return MESA_FORMAT_RGB_DXT1; case PIPE_FORMAT_DXT1_RGBA: - return &_mesa_texformat_rgba_dxt1; + return MESA_FORMAT_RGBA_DXT1; case PIPE_FORMAT_DXT3_RGBA: - return &_mesa_texformat_rgba_dxt3; + return MESA_FORMAT_RGBA_DXT3; case PIPE_FORMAT_DXT5_RGBA: - return &_mesa_texformat_rgba_dxt5; + return MESA_FORMAT_RGBA_DXT5; #if FEATURE_EXT_texture_sRGB case PIPE_FORMAT_DXT1_SRGB: - return &_mesa_texformat_srgb_dxt1; + return MESA_FORMAT_SRGB_DXT1; case PIPE_FORMAT_DXT1_SRGBA: - return &_mesa_texformat_srgba_dxt1; + return MESA_FORMAT_SRGBA_DXT1; case PIPE_FORMAT_DXT3_SRGBA: - return &_mesa_texformat_srgba_dxt3; + return MESA_FORMAT_SRGBA_DXT3; case PIPE_FORMAT_DXT5_SRGBA: - return &_mesa_texformat_srgba_dxt5; + return MESA_FORMAT_SRGBA_DXT5; #endif #endif #if FEATURE_EXT_texture_sRGB case PIPE_FORMAT_A8L8_SRGB: - return &_mesa_texformat_sla8; + return MESA_FORMAT_SLA8; case PIPE_FORMAT_L8_SRGB: - return &_mesa_texformat_sl8; + return MESA_FORMAT_SL8; case PIPE_FORMAT_R8G8B8_SRGB: - return &_mesa_texformat_srgb8; + return MESA_FORMAT_SRGB8; case PIPE_FORMAT_R8G8B8A8_SRGB: - return &_mesa_texformat_srgba8; + return MESA_FORMAT_SRGBA8; case PIPE_FORMAT_A8R8G8B8_SRGB: - return &_mesa_texformat_sargb8; + return MESA_FORMAT_SARGB8; #endif /* XXX add additional cases */ default: assert(0); - return NULL; + return MESA_FORMAT_NONE; } } @@ -704,7 +807,7 @@ translate_gallium_format_to_mesa_format(enum pipe_format format) /** * Called via ctx->Driver.chooseTextureFormat(). */ -const struct gl_texture_format * +gl_format st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat, GLenum format, GLenum type) { @@ -713,10 +816,10 @@ st_ChooseTextureFormat(GLcontext *ctx, GLint internalFormat, (void) format; (void) type; - pFormat = st_choose_format(ctx->st->pipe, internalFormat, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER); + pFormat = st_choose_format(ctx->st->pipe->screen, internalFormat, + PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_SAMPLER); if (pFormat == PIPE_FORMAT_NONE) - return NULL; + return MESA_FORMAT_NONE; return translate_gallium_format_to_mesa_format(pFormat); } diff --git a/src/mesa/state_tracker/st_format.h b/src/mesa/state_tracker/st_format.h index 9d9e02fe9b..7cddf5aa66 100644 --- a/src/mesa/state_tracker/st_format.h +++ b/src/mesa/state_tracker/st_format.h @@ -29,11 +29,12 @@ #ifndef ST_FORMAT_H #define ST_FORMAT_H +#include "main/formats.h" struct pipe_format_info { enum pipe_format format; - GLenum base_format; + gl_format mesa_format; GLenum datatype; GLubyte red_bits; GLubyte green_bits; @@ -60,18 +61,22 @@ st_format_datatype(enum pipe_format format); extern enum pipe_format -st_mesa_format_to_pipe_format(GLuint mesaFormat); +st_mesa_format_to_pipe_format(gl_format mesaFormat); + +extern gl_format +st_pipe_format_to_mesa_format(enum pipe_format pipeFormat); extern enum pipe_format -st_choose_format(struct pipe_context *pipe, GLenum internalFormat, +st_choose_format(struct pipe_screen *screen, GLenum internalFormat, enum pipe_texture_target target, unsigned tex_usage); extern enum pipe_format -st_choose_renderbuffer_format(struct pipe_context *pipe, GLenum internalFormat); +st_choose_renderbuffer_format(struct pipe_screen *screen, + GLenum internalFormat); -extern const struct gl_texture_format * +extern gl_format st_ChooseTextureFormat(GLcontext * ctx, GLint internalFormat, GLenum format, GLenum type); diff --git a/src/mesa/state_tracker/st_framebuffer.c b/src/mesa/state_tracker/st_framebuffer.c index ca32b2e573..a5d1ae3b03 100644 --- a/src/mesa/state_tracker/st_framebuffer.c +++ b/src/mesa/state_tracker/st_framebuffer.c @@ -52,6 +52,7 @@ st_create_framebuffer( const __GLcontextModes *visual, struct st_framebuffer *stfb = ST_CALLOC_STRUCT(st_framebuffer); if (stfb) { int samples = st_get_msaa(); + int i; if (visual->sampleBuffers) samples = visual->samples; @@ -66,7 +67,7 @@ st_create_framebuffer( const __GLcontextModes *visual, else { /* Only allocate front buffer right now if we're single buffered. * If double-buffered, allocate front buffer on demand later. - * See check_create_front_buffers(). + * See check_create_front_buffers() and st_set_framebuffer_surface(). */ struct gl_renderbuffer *rb = st_new_renderbuffer_fb(colorFormat, samples, FALSE); @@ -119,6 +120,12 @@ st_create_framebuffer( const __GLcontextModes *visual, _mesa_add_renderbuffer(&stfb->Base, BUFFER_ACCUM, accumRb); } + for (i = 0; i < visual->numAuxBuffers; i++) { + struct gl_renderbuffer *aux + = st_new_renderbuffer_fb(colorFormat, 0, FALSE); + _mesa_add_renderbuffer(&stfb->Base, BUFFER_AUX0 + i, aux); + } + stfb->Base.Initialized = GL_TRUE; stfb->InitWidth = width; stfb->InitHeight = height; @@ -170,8 +177,20 @@ st_set_framebuffer_surface(struct st_framebuffer *stfb, strb = st_renderbuffer(stfb->Base.Attachment[surfIndex].Renderbuffer); - /* fail */ - if (!strb) return; + if (!strb) { + if (surfIndex == ST_SURFACE_FRONT_LEFT) { + /* Delayed creation when the window system supplies a fake front buffer */ + struct st_renderbuffer *strb_back + = st_renderbuffer(stfb->Base.Attachment[ST_SURFACE_BACK_LEFT].Renderbuffer); + struct gl_renderbuffer *rb + = st_new_renderbuffer_fb(surf->format, strb_back->Base.NumSamples, FALSE); + _mesa_add_renderbuffer(&stfb->Base, BUFFER_FRONT_LEFT, rb); + strb = st_renderbuffer(rb); + } else { + /* fail */ + return; + } + } /* replace the renderbuffer's surface/texture pointers */ pipe_surface_reference( &strb->surface, surf ); diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 58f6933652..7700551830 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -27,6 +27,7 @@ #include "main/imports.h" +#include "main/macros.h" #include "main/mipmap.h" #include "main/teximage.h" #include "main/texformat.h" @@ -37,10 +38,12 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_gen_mipmap.h" +#include "util/u_math.h" #include "cso_cache/cso_cache.h" #include "cso_cache/cso_context.h" +#include "st_debug.h" #include "st_context.h" #include "st_draw.h" #include "st_gen_mipmap.h" @@ -112,6 +115,9 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, uint dstLevel; GLenum datatype; GLuint comps; + + if (ST_DEBUG & DEBUG_FALLBACK) + debug_printf("%s: fallback processing\n", __FUNCTION__); assert(target != GL_TEXTURE_3D); /* not done yet */ @@ -128,29 +134,33 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, srcLevel, zslice, PIPE_TRANSFER_READ, 0, 0, - pt->width[srcLevel], - pt->height[srcLevel]); + u_minify(pt->width0, srcLevel), + u_minify(pt->height0, srcLevel)); dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face, dstLevel, zslice, PIPE_TRANSFER_WRITE, 0, 0, - pt->width[dstLevel], - pt->height[dstLevel]); + u_minify(pt->width0, dstLevel), + u_minify(pt->height0, dstLevel)); srcData = (ubyte *) screen->transfer_map(screen, srcTrans); dstData = (ubyte *) screen->transfer_map(screen, dstTrans); - srcStride = srcTrans->stride / srcTrans->block.size; - dstStride = dstTrans->stride / dstTrans->block.size; + srcStride = srcTrans->stride / pf_get_blocksize(srcTrans->texture->format); + dstStride = dstTrans->stride / pf_get_blocksize(dstTrans->texture->format); _mesa_generate_mipmap_level(target, datatype, comps, - 0 /*border*/, - pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], - srcData, - srcStride, /* stride in texels */ - pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], - dstData, - dstStride); /* stride in texels */ + 0 /*border*/, + u_minify(pt->width0, srcLevel), + u_minify(pt->height0, srcLevel), + u_minify(pt->depth0, srcLevel), + srcData, + srcStride, /* stride in texels */ + u_minify(pt->width0, dstLevel), + u_minify(pt->height0, dstLevel), + u_minify(pt->depth0, dstLevel), + dstData, + dstStride); /* stride in texels */ screen->transfer_unmap(screen, srcTrans); screen->transfer_unmap(screen, dstTrans); @@ -161,6 +171,43 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target, } +/** + * Compute the expected number of mipmap levels in the texture given + * the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/ + * GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap + * level should be generated. + */ +static GLuint +compute_num_levels(GLcontext *ctx, + struct gl_texture_object *texObj, + GLenum target) +{ + if (target == GL_TEXTURE_RECTANGLE_ARB) { + return 1; + } + else { + const GLuint maxLevels = texObj->MaxLevel - texObj->BaseLevel + 1; + const struct gl_texture_image *baseImage = + _mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel); + GLuint size, numLevels; + + size = MAX2(baseImage->Width2, baseImage->Height2); + size = MAX2(size, baseImage->Depth2); + + numLevels = 0; + + while (size > 0) { + numLevels++; + size >>= 1; + } + + numLevels = MIN2(numLevels, maxLevels); + + return numLevels; + } +} + + void st_generate_mipmap(GLcontext *ctx, GLenum target, struct gl_texture_object *texObj) @@ -174,9 +221,49 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, if (!pt) return; - lastLevel = pt->last_level; + /* find expected last mipmap level */ + lastLevel = compute_num_levels(ctx, texObj, target) - 1; + + if (pt->last_level < lastLevel) { + /* The current gallium texture doesn't have space for all the + * mipmap levels we need to generate. So allocate a new texture. + */ + struct st_texture_object *stObj = st_texture_object(texObj); + struct pipe_texture *oldTex = stObj->pt; + GLboolean needFlush; + + /* create new texture with space for more levels */ + stObj->pt = st_texture_create(st, + oldTex->target, + oldTex->format, + lastLevel, + oldTex->width0, + oldTex->height0, + oldTex->depth0, + oldTex->tex_usage); + + /* The texture isn't in a "complete" state yet so set the expected + * lastLevel here, since it won't get done in st_finalize_texture(). + */ + stObj->lastLevel = lastLevel; + + /* This will copy the old texture's base image into the new texture + * which we just allocated. + */ + st_finalize_texture(ctx, st->pipe, texObj, &needFlush); + + /* release the old tex (will likely be freed too) */ + pipe_texture_reference(&oldTex, NULL); + + pt = stObj->pt; + } + + assert(lastLevel <= pt->last_level); - if (!st_render_mipmap(st, target, pt, baseLevel, lastLevel)) { + /* Recall that the Mesa BaseLevel image is stored in the gallium + * texture's level[0] position. So pass baseLevel=0 here. + */ + if (!st_render_mipmap(st, target, pt, 0, lastLevel)) { fallback_generate_mipmap(ctx, target, texObj); } @@ -187,9 +274,9 @@ st_generate_mipmap(GLcontext *ctx, GLenum target, = _mesa_get_tex_image(ctx, texObj, target, srcLevel); struct gl_texture_image *dstImage; struct st_texture_image *stImage; - uint dstWidth = pt->width[dstLevel]; - uint dstHeight = pt->height[dstLevel]; - uint dstDepth = pt->depth[dstLevel]; + uint dstWidth = u_minify(pt->width0, dstLevel); + uint dstHeight = u_minify(pt->height0, dstLevel); + uint dstDepth = u_minify(pt->depth0, dstLevel); uint border = srcImage->Border; dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 04be57f8ff..1611d53e2f 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -151,7 +151,7 @@ dst_register( struct st_translate *t, return t->address[index]; default: - assert( 0 ); + debug_assert( 0 ); return ureg_dst_undef(); } } @@ -173,8 +173,9 @@ src_register( struct st_translate *t, case PROGRAM_STATE_VAR: case PROGRAM_NAMED_PARAM: + case PROGRAM_ENV_PARAM: case PROGRAM_UNIFORM: - case PROGRAM_CONSTANT: + case PROGRAM_CONSTANT: /* ie, immediate */ return t->constants[index]; case PROGRAM_INPUT: @@ -187,7 +188,7 @@ src_register( struct st_translate *t, return ureg_src(t->address[index]); default: - assert( 0 ); + debug_assert( 0 ); return ureg_src_undef(); } } @@ -216,7 +217,7 @@ translate_texture_target( GLuint textarget, case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE; case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT; default: - assert( 0 ); + debug_assert( 0 ); return TGSI_TEXTURE_1D; } } @@ -277,7 +278,7 @@ static struct ureg_src swizzle_4v( struct ureg_src src, /** - * Translate SWZ instructions into a single MAD. EG: + * Translate a SWZ instruction into a MOV, MUL or MAD instruction. EG: * * SWZ dst, src.x-y10 * @@ -386,7 +387,7 @@ static void emit_swz( struct st_translate *t, swizzle_4v( imm, add_swizzle ) ); } else { - assert(0); + debug_assert(0); } #undef IMM_ZERO @@ -395,6 +396,23 @@ static void emit_swz( struct st_translate *t, } +/** + * Negate the value of DDY to match GL semantics where (0,0) is the + * lower-left corner of the window. + * Note that the GL_ARB_fragment_coord_conventions extension will + * effect this someday. + */ +static void emit_ddy( struct st_translate *t, + struct ureg_dst dst, + const struct prog_src_register *SrcReg ) +{ + struct ureg_program *ureg = t->ureg; + struct ureg_src src = translate_src( t, SrcReg ); + src = ureg_negate( src ); + ureg_DDY( ureg, dst, src ); +} + + static unsigned translate_opcode( unsigned op ) @@ -480,14 +498,6 @@ translate_opcode( unsigned op ) return TGSI_OPCODE_MOV; case OPCODE_MUL: return TGSI_OPCODE_MUL; - case OPCODE_NOISE1: - return TGSI_OPCODE_NOISE1; - case OPCODE_NOISE2: - return TGSI_OPCODE_NOISE2; - case OPCODE_NOISE3: - return TGSI_OPCODE_NOISE3; - case OPCODE_NOISE4: - return TGSI_OPCODE_NOISE4; case OPCODE_NOP: return TGSI_OPCODE_NOP; case OPCODE_NRM3: @@ -522,8 +532,6 @@ translate_opcode( unsigned op ) return TGSI_OPCODE_SSG; case OPCODE_SUB: return TGSI_OPCODE_SUB; - case OPCODE_SWZ: - return TGSI_OPCODE_SWZ; case OPCODE_TEX: return TGSI_OPCODE_TEX; case OPCODE_TXB: @@ -539,7 +547,7 @@ translate_opcode( unsigned op ) case OPCODE_END: return TGSI_OPCODE_END; default: - assert( 0 ); + debug_assert( 0 ); return TGSI_OPCODE_NOP; } } @@ -578,7 +586,7 @@ compile_instruction( case OPCODE_ELSE: case OPCODE_ENDLOOP: case OPCODE_IF: - assert(num_dst == 0); + debug_assert(num_dst == 0); ureg_label_insn( ureg, translate_opcode( inst->Opcode ), src, num_src, @@ -615,6 +623,23 @@ compile_instruction( src, num_src ); break; + case OPCODE_NOISE1: + case OPCODE_NOISE2: + case OPCODE_NOISE3: + case OPCODE_NOISE4: + /* At some point, a motivated person could add a better + * implementation of noise. Currently not even the nvidia + * binary drivers do anything more than this. In any case, the + * place to do this is in the GL state tracker, not the poor + * driver. + */ + ureg_MOV( ureg, dst[0], ureg_imm1f(ureg, 0.5) ); + break; + + case OPCODE_DDY: + emit_ddy( t, dst[0], &inst->SrcReg[0] ); + break; + default: ureg_insn( ureg, translate_opcode( inst->Opcode ), @@ -670,6 +695,31 @@ emit_inverted_wpos( struct st_translate *t, /** + * OpenGL's fragment gl_FrontFace input is 1 for front-facing, 0 for back. + * TGSI uses +1 for front, -1 for back. + * This function converts the TGSI value to the GL value. Simply clamping/ + * saturating the value to [0,1] does the job. + */ +static void +emit_face_var( struct st_translate *t, + const struct gl_program *program ) +{ + struct ureg_program *ureg = t->ureg; + struct ureg_dst face_temp = ureg_DECL_temporary( ureg ); + struct ureg_src face_input = t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]]; + + /* MOV_SAT face_temp, input[face] + */ + face_temp = ureg_saturate( face_temp ); + ureg_MOV( ureg, face_temp, face_input ); + + /* Use face_temp as face input from here on: + */ + t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]] = ureg_src(face_temp); +} + + +/** * Translate Mesa program to TGSI format. * \param program the program to translate * \param numInputs number of input registers used @@ -698,12 +748,10 @@ st_translate_mesa_program( const ubyte inputSemanticName[], const ubyte inputSemanticIndex[], const GLuint interpMode[], - const GLbitfield inputFlags[], GLuint numOutputs, const GLuint outputMapping[], const ubyte outputSemanticName[], - const ubyte outputSemanticIndex[], - const GLbitfield outputFlags[] ) + const ubyte outputSemanticIndex[] ) { struct st_translate translate, *t; struct ureg_program *ureg; @@ -742,6 +790,10 @@ st_translate_mesa_program( emit_inverted_wpos( t, program ); } + if (program->InputsRead & FRAG_BIT_FACE) { + emit_face_var( t, program ); + } + /* * Declare output attributes. */ @@ -761,7 +813,7 @@ st_translate_mesa_program( outputSemanticIndex[i] ); break; default: - assert(0); + debug_assert(0); return 0; } } @@ -781,7 +833,7 @@ st_translate_mesa_program( /* Declare address register. */ if (program->NumAddressRegs > 0) { - assert( program->NumAddressRegs == 1 ); + debug_assert( program->NumAddressRegs == 1 ); t->address[0] = ureg_DECL_address( ureg ); } @@ -864,8 +916,19 @@ out: if (!tokens) { debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__); _mesa_print_program(program); - assert(0); + debug_assert(0); } return tokens; } + + +/** + * Tokens cannot be free with _mesa_free otherwise the builtin gallium + * malloc debugging will get confused. + */ +void +st_free_tokens(const struct tgsi_token *tokens) +{ + FREE((void *)tokens); +} diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h index 679d0ddd41..dc0362fe79 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.h +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h @@ -49,12 +49,13 @@ st_translate_mesa_program( const ubyte inputSemanticName[], const ubyte inputSemanticIndex[], const GLuint interpMode[], - const GLbitfield inputFlags[], GLuint numOutputs, const GLuint outputMapping[], const ubyte outputSemanticName[], - const ubyte outputSemanticIndex[], - const GLbitfield outputFlags[] ); + const ubyte outputSemanticIndex[] ); + +void +st_free_tokens(const struct tgsi_token *tokens); #if defined __cplusplus diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 5f9d2a6dad..5c81a033f9 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -42,6 +42,7 @@ #include "draw/draw_context.h" #include "tgsi/tgsi_dump.h" +#include "st_debug.h" #include "st_context.h" #include "st_atom.h" #include "st_program.h" @@ -49,7 +50,37 @@ #include "cso_cache/cso_context.h" -#define TGSI_DEBUG 0 + +/** + * Clean out any old compilations: + */ +void +st_vp_release_varients( struct st_context *st, + struct st_vertex_program *stvp ) +{ + struct st_vp_varient *vpv; + + for (vpv = stvp->varients; vpv; ) { + struct st_vp_varient *next = vpv->next; + + if (vpv->driver_shader) + cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); + + if (vpv->draw_shader) + draw_delete_vertex_shader( st->draw, vpv->draw_shader ); + + if (vpv->state.tokens) + st_free_tokens(vpv->state.tokens); + + FREE( vpv ); + + vpv = next; + } + + stvp->varients = NULL; +} + + /** @@ -60,31 +91,13 @@ * \return pointer to cached pipe_shader object. */ void -st_translate_vertex_program(struct st_context *st, - struct st_vertex_program *stvp, - const GLuint outputMapping[], - const ubyte *outputSemanticName, - const ubyte *outputSemanticIndex) +st_prepare_vertex_program(struct st_context *st, + struct st_vertex_program *stvp) { - struct pipe_context *pipe = st->pipe; - GLuint defaultOutputMapping[VERT_RESULT_MAX]; - GLuint attr, i; - GLuint num_generic = 0; - - ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; - ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; - uint vs_num_inputs = 0; - - ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; - ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; - uint vs_num_outputs = 0; - - GLbitfield input_flags[MAX_PROGRAM_INPUTS]; - GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; + GLuint attr; -// memset(&vs, 0, sizeof(vs)); - memset(input_flags, 0, sizeof(input_flags)); - memset(output_flags, 0, sizeof(output_flags)); + stvp->num_inputs = 0; + stvp->num_outputs = 0; if (stvp->Base.IsPositionInvariant) _mesa_insert_mvp_code(st->ctx, &stvp->Base); @@ -95,162 +108,56 @@ st_translate_vertex_program(struct st_context *st, */ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { if (stvp->Base.Base.InputsRead & (1 << attr)) { - const GLuint slot = vs_num_inputs; - - vs_num_inputs++; - - stvp->input_to_index[attr] = slot; - stvp->index_to_input[slot] = attr; - - switch (attr) { - case VERT_ATTRIB_POS: - vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - vs_input_semantic_index[slot] = 0; - break; - case VERT_ATTRIB_WEIGHT: - /* fall-through */ - case VERT_ATTRIB_NORMAL: - /* just label as a generic */ - vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_input_semantic_index[slot] = 0; - break; - case VERT_ATTRIB_COLOR0: - vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - vs_input_semantic_index[slot] = 0; - break; - case VERT_ATTRIB_COLOR1: - vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - vs_input_semantic_index[slot] = 1; - break; - case VERT_ATTRIB_FOG: - vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; - vs_input_semantic_index[slot] = 0; - break; - case VERT_ATTRIB_POINT_SIZE: - vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; - vs_input_semantic_index[slot] = 0; - break; - case VERT_ATTRIB_TEX0: - case VERT_ATTRIB_TEX1: - case VERT_ATTRIB_TEX2: - case VERT_ATTRIB_TEX3: - case VERT_ATTRIB_TEX4: - case VERT_ATTRIB_TEX5: - case VERT_ATTRIB_TEX6: - case VERT_ATTRIB_TEX7: - assert(slot < Elements(vs_input_semantic_name)); - vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_input_semantic_index[slot] = num_generic++; - break; - case VERT_ATTRIB_GENERIC0: - case VERT_ATTRIB_GENERIC1: - case VERT_ATTRIB_GENERIC2: - case VERT_ATTRIB_GENERIC3: - case VERT_ATTRIB_GENERIC4: - case VERT_ATTRIB_GENERIC5: - case VERT_ATTRIB_GENERIC6: - case VERT_ATTRIB_GENERIC7: - case VERT_ATTRIB_GENERIC8: - case VERT_ATTRIB_GENERIC9: - case VERT_ATTRIB_GENERIC10: - case VERT_ATTRIB_GENERIC11: - case VERT_ATTRIB_GENERIC12: - case VERT_ATTRIB_GENERIC13: - case VERT_ATTRIB_GENERIC14: - case VERT_ATTRIB_GENERIC15: - assert(attr < VERT_ATTRIB_MAX); - assert(slot < Elements(vs_input_semantic_name)); - vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_input_semantic_index[slot] = num_generic++; - break; - default: - assert(0); - } - - input_flags[slot] = stvp->Base.Base.InputFlags[attr]; + stvp->input_to_index[attr] = stvp->num_inputs; + stvp->index_to_input[stvp->num_inputs] = attr; + stvp->num_inputs++; } } -#if 0 - if (outputMapping && outputSemanticName) { - printf("VERT_RESULT written out_slot semantic_name semantic_index\n"); - for (attr = 0; attr < VERT_RESULT_MAX; attr++) { - printf(" %-2d %c %3d %2d %2d\n", - attr, - ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '), - outputMapping[attr], - outputSemanticName[attr], - outputSemanticIndex[attr]); - } - } -#endif - - /* initialize output semantics to defaults */ - for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { - assert(i < Elements(vs_output_semantic_name)); - vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; - vs_output_semantic_index[i] = 0; - output_flags[i] = 0x0; - } - - num_generic = 0; - /* - * Determine number of outputs, the (default) output register - * mapping and the semantic information for each output. + /* Compute mapping of vertex program outputs to slots. */ for (attr = 0; attr < VERT_RESULT_MAX; attr++) { - if (stvp->Base.Base.OutputsWritten & (1 << attr)) { - GLuint slot; - - /* XXX - * Pass in the fragment program's input's semantic info. - * Use the generic semantic indexes from there, instead of - * guessing below. - */ - - if (outputMapping) { - slot = outputMapping[attr]; - assert(slot != ~0); - } - else { - slot = vs_num_outputs; - vs_num_outputs++; - defaultOutputMapping[attr] = slot; - } + if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) { + stvp->result_to_output[attr] = ~0; + } + else { + unsigned slot = stvp->num_outputs++; + + stvp->result_to_output[attr] = slot; switch (attr) { case VERT_RESULT_HPOS: - assert(slot == 0); - vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; - vs_output_semantic_index[slot] = 0; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; + stvp->output_semantic_index[slot] = 0; break; case VERT_RESULT_COL0: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - vs_output_semantic_index[slot] = 0; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + stvp->output_semantic_index[slot] = 0; break; case VERT_RESULT_COL1: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; - vs_output_semantic_index[slot] = 1; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; + stvp->output_semantic_index[slot] = 1; break; case VERT_RESULT_BFC0: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; - vs_output_semantic_index[slot] = 0; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; + stvp->output_semantic_index[slot] = 0; break; case VERT_RESULT_BFC1: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; - vs_output_semantic_index[slot] = 1; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; + stvp->output_semantic_index[slot] = 1; break; case VERT_RESULT_FOGC: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; - vs_output_semantic_index[slot] = 0; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG; + stvp->output_semantic_index[slot] = 0; break; case VERT_RESULT_PSIZ: - vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; - vs_output_semantic_index[slot] = 0; + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; + stvp->output_semantic_index[slot] = 0; break; case VERT_RESULT_EDGE: assert(0); break; + case VERT_RESULT_TEX0: case VERT_RESULT_TEX1: case VERT_RESULT_TEX2: @@ -259,98 +166,62 @@ st_translate_vertex_program(struct st_context *st, case VERT_RESULT_TEX5: case VERT_RESULT_TEX6: case VERT_RESULT_TEX7: - /* fall-through */ + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0; + break; + case VERT_RESULT_VAR0: - /* fall-through */ default: - assert(slot < Elements(vs_output_semantic_name)); - if (outputSemanticName) { - /* use provided semantic into */ - assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); - vs_output_semantic_name[slot] = outputSemanticName[attr]; - vs_output_semantic_index[slot] = outputSemanticIndex[attr]; - } - else { - /* use default semantic info */ - vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - vs_output_semantic_index[slot] = num_generic++; - } + assert(attr < VERT_RESULT_MAX); + stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; + stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 - + FRAG_ATTRIB_TEX0 + + attr - + VERT_RESULT_VAR0); + break; } - - assert(slot < Elements(output_flags)); - output_flags[slot] = stvp->Base.Base.OutputFlags[attr]; } } +} - if (outputMapping) { - /* find max output slot referenced to compute vs_num_outputs */ - GLuint maxSlot = 0; - for (attr = 0; attr < VERT_RESULT_MAX; attr++) { - if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) - maxSlot = outputMapping[attr]; - } - vs_num_outputs = maxSlot + 1; - } - else { - outputMapping = defaultOutputMapping; - } - -#if 0 /* debug */ - { - GLuint i; - printf("outputMapping? %d\n", outputMapping ? 1 : 0); - if (outputMapping) { - printf("attr -> slot\n"); - for (i = 0; i < 16; i++) { - printf(" %2d %3d\n", i, outputMapping[i]); - } - } - printf("slot sem_name sem_index\n"); - for (i = 0; i < vs_num_outputs; i++) { - printf(" %2d %d %d\n", - i, - vs_output_semantic_name[i], - vs_output_semantic_index[i]); - } - } -#endif - /* free old shader state, if any */ - if (stvp->state.tokens) { - _mesa_free((void *) stvp->state.tokens); - stvp->state.tokens = NULL; - } - if (stvp->driver_shader) { - cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); - stvp->driver_shader = NULL; - } +struct st_vp_varient * +st_translate_vertex_program(struct st_context *st, + struct st_vertex_program *stvp, + const struct st_vp_varient_key *key) +{ + struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); + struct pipe_context *pipe = st->pipe; - stvp->state.tokens = + vpv->state.tokens = st_translate_mesa_program(st->ctx, TGSI_PROCESSOR_VERTEX, &stvp->Base.Base, /* inputs */ - vs_num_inputs, + stvp->num_inputs, stvp->input_to_index, - vs_input_semantic_name, - vs_input_semantic_index, + NULL, /* input semantic name */ + NULL, /* input semantic index */ NULL, - input_flags, /* outputs */ - vs_num_outputs, - outputMapping, - vs_output_semantic_name, - vs_output_semantic_index, - output_flags ); + stvp->num_outputs, + stvp->result_to_output, + stvp->output_semantic_name, + stvp->output_semantic_index ); - stvp->num_inputs = vs_num_inputs; - stvp->driver_shader = pipe->create_vs_state(pipe, &stvp->state); + vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state); - if (0) + if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stvp->Base.Base); + debug_printf("\n"); + } + + if (ST_DEBUG & DEBUG_TGSI) { + tgsi_dump( vpv->state.tokens, 0 ); + debug_printf("\n"); + } - if (TGSI_DEBUG) - tgsi_dump( stvp->state.tokens, 0 ); + return vpv; } @@ -373,7 +244,6 @@ st_translate_fragment_program(struct st_context *st, GLuint attr; const GLbitfield inputsRead = stfp->Base.Base.InputsRead; GLuint vslot = 0; - GLuint num_generic = 0; uint fs_num_inputs = 0; @@ -381,13 +251,6 @@ st_translate_fragment_program(struct st_context *st, ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; uint fs_num_outputs = 0; - GLbitfield input_flags[MAX_PROGRAM_INPUTS]; - GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; - -// memset(&fs, 0, sizeof(fs)); - memset(input_flags, 0, sizeof(input_flags)); - memset(output_flags, 0, sizeof(output_flags)); - /* which vertex output goes to the first fragment input: */ if (inputsRead & FRAG_BIT_WPOS) vslot = 0; @@ -430,14 +293,25 @@ st_translate_fragment_program(struct st_context *st, break; case FRAG_ATTRIB_FACE: stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; - stfp->input_semantic_index[slot] = num_generic++; + stfp->input_semantic_index[slot] = 0; interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; break; - case FRAG_ATTRIB_PNTC: - stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - stfp->input_semantic_index[slot] = num_generic++; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; + + /* In most cases, there is nothing special about these + * inputs, so adopt a convention to use the generic + * semantic name and the mesa FRAG_ATTRIB_ number as the + * index. + * + * All that is required is that the vertex shader labels + * its own outputs similarly, and that the vertex shader + * generates at least every output required by the + * fragment shader plus fixed-function hardware (such as + * BFC). + * + * There is no requirement that semantic indexes start at + * zero or be restricted to a particular range -- nobody + * should be building tables based on semantic index. + */ case FRAG_ATTRIB_TEX0: case FRAG_ATTRIB_TEX1: case FRAG_ATTRIB_TEX2: @@ -446,19 +320,18 @@ st_translate_fragment_program(struct st_context *st, case FRAG_ATTRIB_TEX5: case FRAG_ATTRIB_TEX6: case FRAG_ATTRIB_TEX7: - stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - stfp->input_semantic_index[slot] = num_generic++; - interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; - break; + case FRAG_ATTRIB_PNTC: case FRAG_ATTRIB_VAR0: - /* fall-through */ default: + /* Actually, let's try and zero-base this just for + * readability of the generated TGSI. + */ + assert(attr >= FRAG_ATTRIB_TEX0); + stfp->input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; - stfp->input_semantic_index[slot] = num_generic++; interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; + break; } - - input_flags[slot] = stfp->Base.Base.InputFlags[attr]; } } @@ -467,7 +340,7 @@ st_translate_fragment_program(struct st_context *st, */ { uint numColors = 0; - GLbitfield outputsWritten = stfp->Base.Base.OutputsWritten; + GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; /* if z is written, emit that first */ if (outputsWritten & (1 << FRAG_RESULT_DEPTH)) { @@ -496,8 +369,6 @@ st_translate_fragment_program(struct st_context *st, break; } - output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr]; - fs_num_outputs++; } } @@ -516,21 +387,23 @@ st_translate_fragment_program(struct st_context *st, stfp->input_semantic_name, stfp->input_semantic_index, interpMode, - input_flags, /* outputs */ fs_num_outputs, outputMapping, fs_output_semantic_name, - fs_output_semantic_index, - output_flags ); + fs_output_semantic_index ); stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state); - if (0) + if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { _mesa_print_program(&stfp->Base.Base); + debug_printf("\n"); + } - if (TGSI_DEBUG) + if (ST_DEBUG & DEBUG_TGSI) { tgsi_dump( stfp->state.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); + debug_printf("\n"); + } } diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index e2e5eddef2..88aadbd751 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -64,41 +64,70 @@ struct st_fragment_program struct pipe_shader_state state; void *driver_shader; - GLuint param_state; - - /** List of vertex programs which have been translated such that their - * outputs match this fragment program's inputs. - */ - struct translated_vertex_program *vertex_programs; - /** Program prefixed with glBitmap prologue */ struct st_fragment_program *bitmap_program; uint bitmap_sampler; }; + +struct st_vp_varient_key +{ + char dummy; /* currently unused */ +}; + + +/** + * This represents a vertex program, especially translated to match + * the inputs of a particular fragment shader. + */ +struct st_vp_varient +{ + /* Parameters which generated this translated version of a vertex + * shader: + */ + struct st_vp_varient_key key; + + /** TGSI tokens -- why? + */ + struct pipe_shader_state state; + + /** Driver's compiled shader */ + void *driver_shader; + + /** For using our private draw module (glRasterPos) */ + struct draw_vertex_shader *draw_shader; + + /** Next in linked list */ + struct st_vp_varient *next; +}; + + + + /** * Derived from Mesa gl_fragment_program: */ struct st_vertex_program { struct gl_vertex_program Base; /**< The Mesa vertex program */ - GLuint serialNo; + GLuint serialNo, lastSerialNo; /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ GLuint input_to_index[VERT_ATTRIB_MAX]; /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */ GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; - GLuint num_inputs; - struct pipe_shader_state state; - void *driver_shader; + /** Maps VERT_RESULT_x to slot */ + GLuint result_to_output[VERT_RESULT_MAX]; + ubyte output_semantic_name[VERT_RESULT_MAX]; + ubyte output_semantic_index[VERT_RESULT_MAX]; + GLuint num_outputs; - /** For using our private draw module (glRasterPos) */ - struct draw_vertex_shader *draw_shader; - - GLuint param_state; + /** List of translated varients of this vertex program. + */ + struct st_vp_varient *varients; }; @@ -143,13 +172,21 @@ st_translate_fragment_program(struct st_context *st, const GLuint inputMapping[]); +/* Called after program string change, discard all previous + * compilation results. + */ extern void +st_prepare_vertex_program(struct st_context *st, + struct st_vertex_program *stvp); + +extern struct st_vp_varient * st_translate_vertex_program(struct st_context *st, - struct st_vertex_program *vp, - const GLuint vert_output_to_slot[], - const ubyte *fs_input_semantic_name, - const ubyte *fs_input_semantic_index); + struct st_vertex_program *stvp, + const struct st_vp_varient_key *key); +void +st_vp_release_varients( struct st_context *st, + struct st_vertex_program *stvp ); extern void st_print_shaders(GLcontext *ctx); diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index bbc2830e69..3035d78b61 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -32,8 +32,9 @@ #include "st_cb_fbo.h" #include "st_inlines.h" #include "main/enums.h" -#include "main/texobj.h" +#include "main/texfetch.h" #include "main/teximage.h" +#include "main/texobj.h" #include "main/texstore.h" #undef Elements /* fix re-defined macro warning */ @@ -43,6 +44,7 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" #include "util/u_rect.h" +#include "util/u_math.h" #define DBG if(0) printf @@ -99,10 +101,9 @@ st_texture_create(struct st_context *st, pt.target = target; pt.format = format; pt.last_level = last_level; - pt.width[0] = width0; - pt.height[0] = height0; - pt.depth[0] = depth0; - pf_get_block(format, &pt.block); + pt.width0 = width0; + pt.height0 = height0; + pt.depth0 = depth0; pt.tex_usage = usage; newtex = screen->texture_create(screen, &pt); @@ -128,15 +129,15 @@ st_texture_match_image(const struct pipe_texture *pt, /* Check if this image's format matches the established texture's format. */ - if (st_mesa_format_to_pipe_format(image->TexFormat->MesaFormat) != pt->format) + if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format) return GL_FALSE; /* Test if this image's size matches what's expected in the * established texture. */ - if (image->Width != pt->width[level] || - image->Height != pt->height[level] || - image->Depth != pt->depth[level]) + if (image->Width != u_minify(pt->width0, level) || + image->Height != u_minify(pt->height0, level) || + image->Depth != u_minify(pt->depth0, level)) return GL_FALSE; return GL_TRUE; @@ -240,8 +241,9 @@ st_surface_data(struct pipe_context *pipe, struct pipe_screen *screen = pipe->screen; void *map = screen->transfer_map(screen, dst); + assert(dst->texture); util_copy_rect(map, - &dst->block, + dst->texture->format, dst->stride, dstx, dsty, width, height, @@ -264,7 +266,7 @@ st_texture_image_data(struct st_context *st, { struct pipe_context *pipe = st->pipe; struct pipe_screen *screen = pipe->screen; - GLuint depth = dst->depth[level]; + GLuint depth = u_minify(dst->depth0, level); GLuint i; const GLubyte *srcUB = src; struct pipe_transfer *dst_transfer; @@ -274,15 +276,16 @@ st_texture_image_data(struct st_context *st, for (i = 0; i < depth; i++) { dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i, PIPE_TRANSFER_WRITE, 0, 0, - dst->width[level], - dst->height[level]); + u_minify(dst->width0, level), + u_minify(dst->height0, level)); st_surface_data(pipe, dst_transfer, 0, 0, /* dstx, dsty */ srcUB, src_row_stride, 0, 0, /* source x, y */ - dst->width[level], dst->height[level]); /* width, height */ + u_minify(dst->width0, level), + u_minify(dst->height0, level)); /* width, height */ screen->tex_transfer_destroy(dst_transfer); @@ -300,9 +303,9 @@ st_texture_image_copy(struct pipe_context *pipe, GLuint face) { struct pipe_screen *screen = pipe->screen; - GLuint width = dst->width[dstLevel]; - GLuint height = dst->height[dstLevel]; - GLuint depth = dst->depth[dstLevel]; + GLuint width = u_minify(dst->width0, dstLevel); + GLuint height = u_minify(dst->height0, dstLevel); + GLuint depth = u_minify(dst->depth0, dstLevel); struct pipe_surface *src_surface; struct pipe_surface *dst_surface; GLuint i; @@ -312,13 +315,13 @@ st_texture_image_copy(struct pipe_context *pipe, /* find src texture level of needed size */ for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) { - if (src->width[srcLevel] == width && - src->height[srcLevel] == height) { + if (u_minify(src->width0, srcLevel) == width && + u_minify(src->height0, srcLevel) == height) { break; } } - assert(src->width[srcLevel] == width); - assert(src->height[srcLevel] == height); + assert(u_minify(src->width0, srcLevel) == width); + assert(u_minify(src->height0, srcLevel) == height); #if 0 { @@ -342,12 +345,21 @@ st_texture_image_copy(struct pipe_context *pipe, src_surface = screen->get_tex_surface(screen, src, face, srcLevel, i, PIPE_BUFFER_USAGE_GPU_READ); - pipe->surface_copy(pipe, - dst_surface, - 0, 0, /* destX, Y */ - src_surface, - 0, 0, /* srcX, Y */ - width, height); + if (pipe->surface_copy) { + pipe->surface_copy(pipe, + dst_surface, + 0, 0, /* destX, Y */ + src_surface, + 0, 0, /* srcX, Y */ + width, height); + } else { + util_surface_copy(pipe, FALSE, + dst_surface, + 0, 0, /* destX, Y */ + src_surface, + 0, 0, /* srcX, Y */ + width, height); + } pipe_surface_reference(&src_surface, NULL); pipe_surface_reference(&dst_surface, NULL); @@ -577,7 +589,6 @@ st_teximage_flush_before_map(struct st_context *st, pipe->is_texture_referenced(pipe, pt, face, level); if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || - usage == PIPE_TRANSFER_WRITE || - usage == PIPE_TRANSFER_READ_WRITE)) - st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL); + (usage & PIPE_TRANSFER_WRITE))) + st->pipe->flush(st->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); } |