svga_state_fs.c revision 8d38ef455196e6ddda22536e435638a02a7b48f3
1/********************************************************** 2 * Copyright 2008-2009 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 * 24 **********************************************************/ 25 26#include "pipe/p_inlines.h" 27#include "pipe/p_defines.h" 28#include "util/u_math.h" 29#include "util/u_bitmask.h" 30 31#include "svga_context.h" 32#include "svga_state.h" 33#include "svga_cmd.h" 34#include "svga_tgsi.h" 35 36#include "svga_hw_reg.h" 37 38 39 40static INLINE int compare_fs_keys( const struct svga_fs_compile_key *a, 41 const struct svga_fs_compile_key *b ) 42{ 43 unsigned keysize_a = svga_fs_key_size( a ); 44 unsigned keysize_b = svga_fs_key_size( b ); 45 46 if (keysize_a != keysize_b) { 47 return (int)(keysize_a - keysize_b); 48 } 49 return memcmp( a, b, keysize_a ); 50} 51 52 53static struct svga_shader_result *search_fs_key( struct svga_fragment_shader *fs, 54 const struct svga_fs_compile_key *key ) 55{ 56 struct svga_shader_result *result = fs->base.results; 57 58 assert(key); 59 60 for ( ; result; result = result->next) { 61 if (compare_fs_keys( key, &result->key.fkey ) == 0) 62 return result; 63 } 64 65 return NULL; 66} 67 68 69static enum pipe_error compile_fs( struct svga_context *svga, 70 struct svga_fragment_shader *fs, 71 const struct svga_fs_compile_key *key, 72 struct svga_shader_result **out_result ) 73{ 74 struct svga_shader_result *result; 75 enum pipe_error ret; 76 77 result = svga_translate_fragment_program( fs, key ); 78 if (result == NULL) { 79 ret = PIPE_ERROR_OUT_OF_MEMORY; 80 goto fail; 81 } 82 83 result->id = util_bitmask_add(svga->fs_bm); 84 if(result->id == UTIL_BITMASK_INVALID_INDEX) 85 goto fail; 86 87 ret = SVGA3D_DefineShader(svga->swc, 88 result->id, 89 SVGA3D_SHADERTYPE_PS, 90 result->tokens, 91 result->nr_tokens * sizeof result->tokens[0]); 92 if (ret) 93 goto fail; 94 95 *out_result = result; 96 result->next = fs->base.results; 97 fs->base.results = result; 98 return PIPE_OK; 99 100fail: 101 if (result) { 102 if (result->id != UTIL_BITMASK_INVALID_INDEX) 103 util_bitmask_clear( svga->fs_bm, result->id ); 104 svga_destroy_shader_result( result ); 105 } 106 return ret; 107} 108 109/* The blend workaround for simulating logicop xor behaviour requires 110 * that the incoming fragment color be white. This change achieves 111 * that by hooking up a hard-wired fragment shader that just emits 112 * color 1,1,1,1 113 * 114 * This is a slightly incomplete solution as it assumes that the 115 * actual bound shader has no other effects beyond generating a 116 * fragment color. In particular shaders containing TEXKIL and/or 117 * depth-write will not have the correct behaviour, nor will those 118 * expecting to use alphatest. 119 * 120 * These are avoidable issues, but they are not much worse than the 121 * unavoidable ones associated with this technique, so it's not clear 122 * how much effort should be expended trying to resolve them - the 123 * ultimate result will still not be correct in most cases. 124 * 125 * Shader below was generated with: 126 * SVGA_DEBUG=tgsi ./mesa/progs/fp/fp-tri white.txt 127 */ 128static int emit_white_fs( struct svga_context *svga ) 129{ 130 int ret = PIPE_ERROR; 131 132 /* ps_3_0 133 * def c0, 1.000000, 0.000000, 0.000000, 1.000000 134 * mov oC0, c0.x 135 * end 136 */ 137 static const unsigned white_tokens[] = { 138 0xffff0300, 139 0x05000051, 140 0xa00f0000, 141 0x3f800000, 142 0x00000000, 143 0x00000000, 144 0x3f800000, 145 0x02000001, 146 0x800f0800, 147 0xa0000000, 148 0x0000ffff, 149 }; 150 151 assert(SVGA3D_INVALID_ID == UTIL_BITMASK_INVALID_INDEX); 152 svga->state.white_fs_id = util_bitmask_add(svga->fs_bm); 153 if(svga->state.white_fs_id == SVGA3D_INVALID_ID) 154 goto no_fs_id; 155 156 ret = SVGA3D_DefineShader(svga->swc, 157 svga->state.white_fs_id, 158 SVGA3D_SHADERTYPE_PS, 159 white_tokens, 160 sizeof(white_tokens)); 161 if (ret) 162 goto no_definition; 163 164 return 0; 165 166no_definition: 167 util_bitmask_clear(svga->fs_bm, svga->state.white_fs_id); 168 svga->state.white_fs_id = SVGA3D_INVALID_ID; 169no_fs_id: 170 return ret; 171} 172 173 174/* SVGA_NEW_TEXTURE_BINDING 175 * SVGA_NEW_RAST 176 * SVGA_NEW_NEED_SWTNL 177 * SVGA_NEW_SAMPLER 178 */ 179static int make_fs_key( const struct svga_context *svga, 180 struct svga_fs_compile_key *key ) 181{ 182 int i; 183 int idx = 0; 184 185 memset(key, 0, sizeof *key); 186 187 /* Only need fragment shader fixup for twoside lighting if doing 188 * hwtnl. Otherwise the draw module does the whole job for us. 189 * 190 * SVGA_NEW_SWTNL 191 */ 192 if (!svga->state.sw.need_swtnl) { 193 /* SVGA_NEW_RAST 194 */ 195 key->light_twoside = svga->curr.rast->templ.light_twoside; 196 key->front_cw = (svga->curr.rast->templ.front_winding == 197 PIPE_WINDING_CW); 198 } 199 200 201 /* XXX: want to limit this to the textures that the shader actually 202 * refers to. 203 * 204 * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER 205 */ 206 for (i = 0; i < svga->curr.num_textures; i++) { 207 if (svga->curr.texture[i]) { 208 assert(svga->curr.sampler[i]); 209 key->tex[i].texture_target = svga->curr.texture[i]->target; 210 if (!svga->curr.sampler[i]->normalized_coords) { 211 key->tex[i].width_height_idx = idx++; 212 key->tex[i].unnormalized = TRUE; 213 ++key->num_unnormalized_coords; 214 } 215 } 216 } 217 key->num_textures = svga->curr.num_textures; 218 219 idx = 0; 220 for (i = 0; i < svga->curr.num_samplers; ++i) { 221 if (svga->curr.sampler[i]) { 222 key->tex[i].compare_mode = svga->curr.sampler[i]->compare_mode; 223 key->tex[i].compare_func = svga->curr.sampler[i]->compare_func; 224 } 225 } 226 227 return 0; 228} 229 230 231 232static int emit_hw_fs( struct svga_context *svga, 233 unsigned dirty ) 234{ 235 struct svga_shader_result *result = NULL; 236 unsigned id = SVGA3D_INVALID_ID; 237 int ret = 0; 238 239 /* SVGA_NEW_BLEND 240 */ 241 if (svga->curr.blend->need_white_fragments) { 242 if (svga->state.white_fs_id == SVGA3D_INVALID_ID) { 243 ret = emit_white_fs( svga ); 244 if (ret) 245 return ret; 246 } 247 id = svga->state.white_fs_id; 248 } 249 else { 250 struct svga_fragment_shader *fs = svga->curr.fs; 251 struct svga_fs_compile_key key; 252 253 /* SVGA_NEW_TEXTURE_BINDING 254 * SVGA_NEW_RAST 255 * SVGA_NEW_NEED_SWTNL 256 * SVGA_NEW_SAMPLER 257 */ 258 ret = make_fs_key( svga, &key ); 259 if (ret) 260 return ret; 261 262 result = search_fs_key( fs, &key ); 263 if (!result) { 264 ret = compile_fs( svga, fs, &key, &result ); 265 if (ret) 266 return ret; 267 } 268 269 assert (result); 270 id = result->id; 271 } 272 273 assert(id != SVGA3D_INVALID_ID); 274 275 if (result != svga->state.hw_draw.fs) { 276 ret = SVGA3D_SetShader(svga->swc, 277 SVGA3D_SHADERTYPE_PS, 278 id ); 279 if (ret) 280 return ret; 281 282 svga->dirty |= SVGA_NEW_FS_RESULT; 283 svga->state.hw_draw.fs = result; 284 } 285 286 return 0; 287} 288 289struct svga_tracked_state svga_hw_fs = 290{ 291 "fragment shader (hwtnl)", 292 (SVGA_NEW_FS | 293 SVGA_NEW_TEXTURE_BINDING | 294 SVGA_NEW_NEED_SWTNL | 295 SVGA_NEW_RAST | 296 SVGA_NEW_SAMPLER | 297 SVGA_NEW_BLEND), 298 emit_hw_fs 299}; 300 301 302 303