1 /************************************************************************** 2 * 3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /** 29 * State validation for vertex/fragment shaders. 30 * Note that we have to delay most vertex/fragment shader translation 31 * until rendering time since the linkage between the vertex outputs and 32 * fragment inputs can vary depending on the pairing of shaders. 33 * 34 * Authors: 35 * Brian Paul 36 */ 37 38 #include "main/imports.h" 39 #include "main/mtypes.h" 40 #include "program/program.h" 41 42 #include "pipe/p_context.h" 43 44 #include "util/u_simple_shaders.h" 45 46 #include "cso_cache/cso_context.h" 47 48 #include "st_context.h" 49 #include "st_atom.h" 50 #include "st_program.h" 51 52 53 /** 54 * Return pointer to a pass-through fragment shader. 55 * This shader is used when a texture is missing/incomplete. 56 */ 57 static void * 58 get_passthrough_fs(struct st_context *st) 59 { 60 if (!st->passthrough_fs) { 61 st->passthrough_fs = 62 util_make_fragment_passthrough_shader(st->pipe); 63 } 64 65 return st->passthrough_fs; 66 } 67 68 69 /** 70 * Update fragment program state/atom. This involves translating the 71 * Mesa fragment program into a gallium fragment program and binding it. 72 */ 73 static void 74 update_fp( struct st_context *st ) 75 { 76 struct st_fragment_program *stfp; 77 struct st_fp_variant_key key; 78 79 assert(st->ctx->FragmentProgram._Current); 80 stfp = st_fragment_program(st->ctx->FragmentProgram._Current); 81 assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); 82 83 memset(&key, 0, sizeof(key)); 84 key.st = st; 85 86 /* _NEW_FRAG_CLAMP */ 87 key.clamp_color = st->clamp_frag_color_in_shader && 88 st->ctx->Color._ClampFragmentColor && 89 !st->ctx->DrawBuffer->_IntegerColor; 90 91 st->fp_variant = st_get_fp_variant(st, stfp, &key); 92 93 st_reference_fragprog(st, &st->fp, stfp); 94 95 if (st->missing_textures) { 96 /* use a pass-through frag shader that uses no textures */ 97 void *fs = get_passthrough_fs(st); 98 cso_set_fragment_shader_handle(st->cso_context, fs); 99 } 100 else { 101 cso_set_fragment_shader_handle(st->cso_context, 102 st->fp_variant->driver_shader); 103 } 104 } 105 106 107 const struct st_tracked_state st_update_fp = { 108 "st_update_fp", /* name */ 109 { /* dirty */ 110 _NEW_BUFFERS, /* mesa */ 111 ST_NEW_FRAGMENT_PROGRAM /* st */ 112 }, 113 update_fp /* update */ 114 }; 115 116 117 118 /** 119 * Update vertex program state/atom. This involves translating the 120 * Mesa vertex program into a gallium fragment program and binding it. 121 */ 122 static void 123 update_vp( struct st_context *st ) 124 { 125 struct st_vertex_program *stvp; 126 struct st_vp_variant_key key; 127 128 /* find active shader and params -- Should be covered by 129 * ST_NEW_VERTEX_PROGRAM 130 */ 131 assert(st->ctx->VertexProgram._Current); 132 stvp = st_vertex_program(st->ctx->VertexProgram._Current); 133 assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); 134 135 memset(&key, 0, sizeof key); 136 key.st = st; /* variants are per-context */ 137 138 /* When this is true, we will add an extra input to the vertex 139 * shader translation (for edgeflags), an extra output with 140 * edgeflag semantics, and extend the vertex shader to pass through 141 * the input to the output. We'll need to use similar logic to set 142 * up the extra vertex_element input for edgeflags. 143 * _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA 144 */ 145 key.passthrough_edgeflags = (st->vertdata_edgeflags && ( 146 st->ctx->Polygon.FrontMode != GL_FILL || 147 st->ctx->Polygon.BackMode != GL_FILL)); 148 149 key.clamp_color = st->clamp_vert_color_in_shader && 150 st->ctx->Light._ClampVertexColor; 151 152 st->vp_variant = st_get_vp_variant(st, stvp, &key); 153 154 st_reference_vertprog(st, &st->vp, stvp); 155 156 cso_set_vertex_shader_handle(st->cso_context, 157 st->vp_variant->driver_shader); 158 159 st->vertex_result_to_slot = stvp->result_to_output; 160 } 161 162 163 const struct st_tracked_state st_update_vp = { 164 "st_update_vp", /* name */ 165 { /* dirty */ 166 _NEW_POLYGON, /* mesa */ 167 ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */ 168 }, 169 update_vp /* update */ 170 }; 171 172 173 174 static void 175 update_gp( struct st_context *st ) 176 { 177 struct st_geometry_program *stgp; 178 struct st_gp_variant_key key; 179 180 if (!st->ctx->GeometryProgram._Current) { 181 cso_set_geometry_shader_handle(st->cso_context, NULL); 182 return; 183 } 184 185 stgp = st_geometry_program(st->ctx->GeometryProgram._Current); 186 assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM); 187 188 memset(&key, 0, sizeof(key)); 189 key.st = st; 190 191 st->gp_variant = st_get_gp_variant(st, stgp, &key); 192 193 st_reference_geomprog(st, &st->gp, stgp); 194 195 cso_set_geometry_shader_handle(st->cso_context, 196 st->gp_variant->driver_shader); 197 } 198 199 const struct st_tracked_state st_update_gp = { 200 "st_update_gp", /* name */ 201 { /* dirty */ 202 0, /* mesa */ 203 ST_NEW_GEOMETRY_PROGRAM /* st */ 204 }, 205 update_gp /* update */ 206 }; 207