brw_wm.c revision 064ae479a770bf434958d673baf6f7530f642697
1/* 2 Copyright (C) Intel Corp. 2006. All Rights Reserved. 3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to 4 develop this 3D driver. 5 6 Permission is hereby granted, free of charge, to any person obtaining 7 a 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, sublicense, 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 16 portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 26 **********************************************************************/ 27 /* 28 * Authors: 29 * Keith Whitwell <keith@tungstengraphics.com> 30 */ 31 32 33#include "brw_context.h" 34#include "brw_util.h" 35#include "brw_wm.h" 36#include "brw_state.h" 37#include "brw_hal.h" 38 39 40GLuint brw_wm_nr_args( GLuint opcode ) 41{ 42 switch (opcode) { 43 44 case WM_PIXELXY: 45 case OPCODE_ABS: 46 case OPCODE_FLR: 47 case OPCODE_FRC: 48 case OPCODE_SWZ: 49 case OPCODE_MOV: 50 case OPCODE_COS: 51 case OPCODE_EX2: 52 case OPCODE_LG2: 53 case OPCODE_RCP: 54 case OPCODE_RSQ: 55 case OPCODE_SIN: 56 case OPCODE_SCS: 57 case OPCODE_TEX: 58 case OPCODE_TXB: 59 case OPCODE_TXP: 60 case OPCODE_KIL: 61 case OPCODE_LIT: 62 case WM_CINTERP: 63 case WM_WPOSXY: 64 return 1; 65 66 case OPCODE_POW: 67 case OPCODE_SUB: 68 case OPCODE_SGE: 69 case OPCODE_SLT: 70 case OPCODE_ADD: 71 case OPCODE_MAX: 72 case OPCODE_MIN: 73 case OPCODE_MUL: 74 case OPCODE_XPD: 75 case OPCODE_DP3: 76 case OPCODE_DP4: 77 case OPCODE_DPH: 78 case OPCODE_DST: 79 case WM_LINTERP: 80 case WM_DELTAXY: 81 case WM_PIXELW: 82 return 2; 83 84 case WM_FB_WRITE: 85 case WM_PINTERP: 86 case OPCODE_MAD: 87 case OPCODE_CMP: 88 case OPCODE_LRP: 89 return 3; 90 91 default: 92 return 0; 93 } 94} 95 96 97GLuint brw_wm_is_scalar_result( GLuint opcode ) 98{ 99 switch (opcode) { 100 case OPCODE_COS: 101 case OPCODE_EX2: 102 case OPCODE_LG2: 103 case OPCODE_POW: 104 case OPCODE_RCP: 105 case OPCODE_RSQ: 106 case OPCODE_SIN: 107 case OPCODE_DP3: 108 case OPCODE_DP4: 109 case OPCODE_DPH: 110 case OPCODE_DST: 111 return 1; 112 113 default: 114 return 0; 115 } 116} 117 118 119static void brw_wm_pass_hal (struct brw_wm_compile *c) 120{ 121 static void (*hal_wm_pass) (struct brw_wm_compile *c); 122 static GLboolean hal_tried; 123 124 if (!hal_tried) 125 { 126 hal_wm_pass = brw_hal_find_symbol ("intel_hal_wm_pass"); 127 hal_tried = 1; 128 } 129 if (hal_wm_pass) 130 (*hal_wm_pass) (c); 131} 132 133static void do_wm_prog( struct brw_context *brw, 134 struct brw_fragment_program *fp, 135 struct brw_wm_prog_key *key) 136{ 137 struct brw_wm_compile *c; 138 const GLuint *program; 139 GLuint program_size; 140 141 c = brw->wm.compile_data; 142 if (c == NULL) { 143 brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data)); 144 c = brw->wm.compile_data; 145 } else { 146 memset(c, 0, sizeof(*brw->wm.compile_data)); 147 } 148 memcpy(&c->key, key, sizeof(*key)); 149 150 c->fp = fp; 151 c->env_param = brw->intel.ctx.FragmentProgram.Parameters; 152 153 154 /* Augment fragment program. Add instructions for pre- and 155 * post-fragment-program tasks such as interpolation and fogging. 156 */ 157 brw_wm_pass_fp(c); 158 159 /* Translate to intermediate representation. Build register usage 160 * chains. 161 */ 162 brw_wm_pass0(c); 163 164 /* Dead code removal. 165 */ 166 brw_wm_pass1(c); 167 168 /* Hal optimization 169 */ 170 brw_wm_pass_hal (c); 171 172 /* Register allocation. 173 */ 174 c->grf_limit = BRW_WM_MAX_GRF/2; 175 176 /* This is where we start emitting gen4 code: 177 */ 178 brw_init_compile(&c->func); 179 180 brw_wm_pass2(c); 181 182 c->prog_data.total_grf = c->max_wm_grf; 183 if (c->last_scratch) { 184 c->prog_data.total_scratch = 185 c->last_scratch + 0x40; 186 } else { 187 c->prog_data.total_scratch = 0; 188 } 189 190 /* Emit GEN4 code. 191 */ 192 brw_wm_emit(c); 193 194 /* get the program 195 */ 196 program = brw_get_program(&c->func, &program_size); 197 198 /* 199 */ 200 brw->wm.prog_gs_offset = brw_upload_cache( &brw->cache[BRW_WM_PROG], 201 &c->key, 202 sizeof(c->key), 203 program, 204 program_size, 205 &c->prog_data, 206 &brw->wm.prog_data ); 207} 208 209 210 211static void brw_wm_populate_key( struct brw_context *brw, 212 struct brw_wm_prog_key *key ) 213{ 214 /* BRW_NEW_FRAGMENT_PROGRAM */ 215 struct brw_fragment_program *fp = 216 (struct brw_fragment_program *)brw->fragment_program; 217 GLuint lookup = 0; 218 GLuint line_aa; 219 GLuint i; 220 221 memset(key, 0, sizeof(*key)); 222 223 /* Build the index for table lookup 224 */ 225 /* _NEW_COLOR */ 226 if (fp->program.UsesKill || 227 brw->attribs.Color->AlphaEnabled) 228 lookup |= IZ_PS_KILL_ALPHATEST_BIT; 229 230 if (fp->program.Base.OutputsWritten & (1<<FRAG_RESULT_DEPR)) 231 lookup |= IZ_PS_COMPUTES_DEPTH_BIT; 232 233 /* _NEW_DEPTH */ 234 if (brw->attribs.Depth->Test) 235 lookup |= IZ_DEPTH_TEST_ENABLE_BIT; 236 237 if (brw->attribs.Depth->Test && 238 brw->attribs.Depth->Mask) /* ?? */ 239 lookup |= IZ_DEPTH_WRITE_ENABLE_BIT; 240 241 /* _NEW_STENCIL */ 242 if (brw->attribs.Stencil->Enabled) { 243 lookup |= IZ_STENCIL_TEST_ENABLE_BIT; 244 245 if (brw->attribs.Stencil->WriteMask[0] || 246 (brw->attribs.Stencil->TestTwoSide && brw->attribs.Stencil->WriteMask[1])) 247 lookup |= IZ_STENCIL_WRITE_ENABLE_BIT; 248 } 249 250 /* XXX: when should this be disabled? 251 */ 252 if (1) 253 lookup |= IZ_EARLY_DEPTH_TEST_BIT; 254 255 256 line_aa = AA_NEVER; 257 258 /* _NEW_LINE, _NEW_POLYGON, BRW_NEW_REDUCED_PRIMITIVE */ 259 if (brw->attribs.Line->SmoothFlag) { 260 if (brw->intel.reduced_primitive == GL_LINES) { 261 line_aa = AA_ALWAYS; 262 } 263 else if (brw->intel.reduced_primitive == GL_TRIANGLES) { 264 if (brw->attribs.Polygon->FrontMode == GL_LINE) { 265 line_aa = AA_SOMETIMES; 266 267 if (brw->attribs.Polygon->BackMode == GL_LINE || 268 (brw->attribs.Polygon->CullFlag && 269 brw->attribs.Polygon->CullFaceMode == GL_BACK)) 270 line_aa = AA_ALWAYS; 271 } 272 else if (brw->attribs.Polygon->BackMode == GL_LINE) { 273 line_aa = AA_SOMETIMES; 274 275 if ((brw->attribs.Polygon->CullFlag && 276 brw->attribs.Polygon->CullFaceMode == GL_FRONT)) 277 line_aa = AA_ALWAYS; 278 } 279 } 280 } 281 282 brw_wm_lookup_iz(line_aa, 283 lookup, 284 key); 285 286 287 /* BRW_NEW_WM_INPUT_DIMENSIONS */ 288 key->projtex_mask = brw->wm.input_size_masks[4-1]; 289 290 /* _NEW_LIGHT */ 291 key->flat_shade = (brw->attribs.Light->ShadeModel == GL_FLAT); 292 293 /* _NEW_TEXTURE */ 294 for (i = 0; i < BRW_MAX_TEX_UNIT; i++) { 295 const struct gl_texture_unit *unit = &brw->attribs.Texture->Unit[i]; 296 const struct gl_texture_object *t = unit->_Current; 297 298 if (unit->_ReallyEnabled) { 299 300 if (t->CompareMode == GL_COMPARE_R_TO_TEXTURE_ARB && 301 t->Image[0][t->BaseLevel]->_BaseFormat == GL_DEPTH_COMPONENT) { 302 key->shadowtex_mask |= 1<<i; 303 } 304 305 if (t->Image[0][t->BaseLevel]->InternalFormat == GL_YCBCR_MESA) 306 key->yuvtex_mask |= 1<<i; 307 } 308 } 309 310 311 /* Extra info: 312 */ 313 key->program_string_id = fp->id; 314 315} 316 317 318static void brw_upload_wm_prog( struct brw_context *brw ) 319{ 320 struct brw_wm_prog_key key; 321 struct brw_fragment_program *fp = (struct brw_fragment_program *) 322 brw->fragment_program; 323 324 brw_wm_populate_key(brw, &key); 325 326 /* Make an early check for the key. 327 */ 328 if (brw_search_cache(&brw->cache[BRW_WM_PROG], 329 &key, sizeof(key), 330 &brw->wm.prog_data, 331 &brw->wm.prog_gs_offset)) 332 return; 333 334 do_wm_prog(brw, fp, &key); 335} 336 337 338/* See brw_wm.c: 339 */ 340const struct brw_tracked_state brw_wm_prog = { 341 .dirty = { 342 .mesa = (_NEW_COLOR | 343 _NEW_DEPTH | 344 _NEW_STENCIL | 345 _NEW_POLYGON | 346 _NEW_LINE | 347 _NEW_LIGHT | 348 _NEW_TEXTURE), 349 .brw = (BRW_NEW_FRAGMENT_PROGRAM | 350 BRW_NEW_WM_INPUT_DIMENSIONS | 351 BRW_NEW_REDUCED_PRIMITIVE), 352 .cache = 0 353 }, 354 .update = brw_upload_wm_prog 355}; 356 357