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