X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_atom_shader.c;h=fee15a980f30d60af729820825d45da0eb339548;hb=6e3730452152ca74ad3b51bf1dd4b69b20dbc019;hp=629bf8953ebf5d32e125ac76e9d64f45b44eab27;hpb=a0127b6ced257919180ba3a1bf534b68d9c750be;p=mesa.git diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 629bf8953eb..fee15a980f3 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 + * IN NO EVENT SHALL VMWARE 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. @@ -35,77 +35,84 @@ * Brian Paul */ - - #include "main/imports.h" #include "main/mtypes.h" -#include "main/macros.h" -#include "shader/program.h" +#include "program/program.h" #include "pipe/p_context.h" #include "pipe/p_shader_tokens.h" - #include "util/u_simple_shaders.h" - #include "cso_cache/cso_context.h" #include "st_context.h" #include "st_atom.h" #include "st_program.h" -#include "st_atom_shader.h" -#include "st_mesa_to_tgsi.h" - - - -/* - * Translate fragment program if needed. +/** + * Update fragment program state/atom. This involves translating the + * Mesa fragment program into a gallium fragment program and binding it. */ static void -translate_fp(struct st_context *st, - struct st_fragment_program *stfp) +update_fp( struct st_context *st ) { - const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; + struct st_fragment_program *stfp; + struct st_fp_variant_key key; - if (!stfp->state.tokens) { - GLuint inAttr, numIn = 0; + assert(st->ctx->FragmentProgram._Current); + stfp = st_fragment_program(st->ctx->FragmentProgram._Current); + assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); - for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) { - if (fragInputsRead & (1 << inAttr)) { - stfp->input_to_slot[inAttr] = numIn; - numIn++; - } - else { - stfp->input_to_slot[inAttr] = -1; - } - } + memset(&key, 0, sizeof(key)); + key.st = st; - stfp->num_input_slots = numIn; + /* _NEW_FRAG_CLAMP */ + key.clamp_color = st->clamp_frag_color_in_shader && + st->ctx->Color._ClampFragmentColor; - assert(stfp->Base.Base.NumInstructions > 1); + /* Ignore sample qualifier while computing this flag. */ + key.persample_shading = + _mesa_get_min_invocations_per_fragment(st->ctx, &stfp->Base, true) > 1; - st_translate_fragment_program(st, stfp, stfp->input_to_slot); - } + st->fp_variant = st_get_fp_variant(st, stfp, &key); + + st_reference_fragprog(st, &st->fp, stfp); + + cso_set_fragment_shader_handle(st->cso_context, + st->fp_variant->driver_shader); } +const struct st_tracked_state st_update_fp = { + "st_update_fp", /* name */ + { /* dirty */ + _NEW_BUFFERS | _NEW_MULTISAMPLE, /* mesa */ + ST_NEW_FRAGMENT_PROGRAM /* st */ + }, + update_fp /* update */ +}; + + /** - * 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. + * Update vertex program state/atom. This involves translating the + * Mesa vertex program into a gallium fragment program and binding it. */ -static struct st_vp_varient * -find_translated_vp(struct st_context *st, - struct st_vertex_program *stvp ) +static void +update_vp( struct st_context *st ) { - struct st_vp_varient *vpv; - struct st_vp_varient_key key; + struct st_vertex_program *stvp; + struct st_vp_variant_key key; - /* Nothing in our key yet. This will change: + /* 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); + memset(&key, 0, sizeof key); + key.st = st; /* variants are per-context */ /* When this is true, we will add an extra input to the vertex * shader translation (for edgeflags), an extra output with @@ -113,122 +120,140 @@ find_translated_vp(struct st_context *st, * the input to the output. We'll need to use similar logic to set * up the extra vertex_element input for edgeflags. */ - key.passthrough_edgeflags = (st->ctx->Polygon.FrontMode != GL_FILL || - st->ctx->Polygon.BackMode != GL_FILL); - + key.passthrough_edgeflags = st->vertdata_edgeflags; - /* 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. - */ - st_prepare_vertex_program( st, stvp ); - - /* We are now up-to-date: - */ - 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; - } - } + key.clamp_color = st->clamp_vert_color_in_shader && + st->ctx->Light._ClampVertexColor && + (stvp->Base.Base.OutputsWritten & + (VARYING_SLOT_COL0 | + VARYING_SLOT_COL1 | + VARYING_SLOT_BFC0 | + VARYING_SLOT_BFC1)); - /* 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; - } + st->vp_variant = st_get_vp_variant(st, stvp, &key); + + st_reference_vertprog(st, &st->vp, stvp); + + cso_set_vertex_shader_handle(st->cso_context, + st->vp_variant->driver_shader); - return vpv; + st->vertex_result_to_slot = stvp->result_to_output; } +const struct st_tracked_state st_update_vp = { + "st_update_vp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_VERTEX_PROGRAM /* st */ + }, + update_vp /* update */ +}; + -static void * -get_passthrough_fs(struct st_context *st) +static void +update_gp( struct st_context *st ) { - if (!st->passthrough_fs) { - st->passthrough_fs = - util_make_fragment_passthrough_shader(st->pipe); + struct st_geometry_program *stgp; + struct st_gp_variant_key key; + + if (!st->ctx->GeometryProgram._Current) { + cso_set_geometry_shader_handle(st->cso_context, NULL); + return; } - return st->passthrough_fs; + stgp = st_geometry_program(st->ctx->GeometryProgram._Current); + assert(stgp->Base.Base.Target == GL_GEOMETRY_PROGRAM_NV); + + memset(&key, 0, sizeof(key)); + key.st = st; + + st->gp_variant = st_get_gp_variant(st, stgp, &key); + + st_reference_geomprog(st, &st->gp, stgp); + + cso_set_geometry_shader_handle(st->cso_context, + st->gp_variant->driver_shader); } +const struct st_tracked_state st_update_gp = { + "st_update_gp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_GEOMETRY_PROGRAM /* st */ + }, + update_gp /* update */ +}; + + + static void -update_fp( struct st_context *st ) +update_tcp( struct st_context *st ) { - struct st_fragment_program *stfp; + struct st_tessctrl_program *sttcp; + struct st_tcp_variant_key key; - assert(st->ctx->FragmentProgram._Current); - stfp = st_fragment_program(st->ctx->FragmentProgram._Current); - assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); + if (!st->ctx->TessCtrlProgram._Current) { + cso_set_tessctrl_shader_handle(st->cso_context, NULL); + return; + } - translate_fp(st, stfp); + sttcp = st_tessctrl_program(st->ctx->TessCtrlProgram._Current); + assert(sttcp->Base.Base.Target == GL_TESS_CONTROL_PROGRAM_NV); - st_reference_fragprog(st, &st->fp, stfp); + memset(&key, 0, sizeof(key)); + key.st = st; - if (st->missing_textures) { - /* use a pass-through frag shader that uses no textures */ - void *fs = get_passthrough_fs(st); - cso_set_fragment_shader_handle(st->cso_context, fs); - } - else { - cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader); - } + st->tcp_variant = st_get_tcp_variant(st, sttcp, &key); + + st_reference_tesscprog(st, &st->tcp, sttcp); + + cso_set_tessctrl_shader_handle(st->cso_context, + st->tcp_variant->driver_shader); } -const struct st_tracked_state st_update_fp = { - "st_update_fp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_FRAGMENT_PROGRAM /* st */ +const struct st_tracked_state st_update_tcp = { + "st_update_tcp", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_TESSCTRL_PROGRAM /* st */ }, - update_fp /* update */ + update_tcp /* update */ }; - static void -update_vp( struct st_context *st ) +update_tep( struct st_context *st ) { - struct st_vertex_program *stvp; + struct st_tesseval_program *sttep; + struct st_tep_variant_key key; - /* 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); + if (!st->ctx->TessEvalProgram._Current) { + cso_set_tesseval_shader_handle(st->cso_context, NULL); + return; + } - st->vp_varient = find_translated_vp(st, stvp); + sttep = st_tesseval_program(st->ctx->TessEvalProgram._Current); + assert(sttep->Base.Base.Target == GL_TESS_EVALUATION_PROGRAM_NV); - st_reference_vertprog(st, &st->vp, stvp); + memset(&key, 0, sizeof(key)); + key.st = st; - cso_set_vertex_shader_handle(st->cso_context, - st->vp_varient->driver_shader); + st->tep_variant = st_get_tep_variant(st, sttep, &key); - st->vertex_result_to_slot = stvp->result_to_output; -} + st_reference_tesseprog(st, &st->tep, sttep); + cso_set_tesseval_shader_handle(st->cso_context, + st->tep_variant->driver_shader); +} -const struct st_tracked_state st_update_vp = { - "st_update_vp", /* name */ - { /* dirty */ - 0, /* mesa */ - ST_NEW_VERTEX_PROGRAM /* st */ +const struct st_tracked_state st_update_tep = { + "st_update_tep", /* name */ + { /* dirty */ + 0, /* mesa */ + ST_NEW_TESSEVAL_PROGRAM /* st */ }, - update_vp /* update */ + update_tep /* update */ };