Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / drivers / i965 / brw_wm_pass1.c
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_wm.h"
34 #include "brw_debug.h"
35
36
37 static GLuint get_tracked_mask(struct brw_wm_compile *c,
38                                struct brw_wm_instruction *inst)
39 {
40    GLuint i;
41    for (i = 0; i < 4; i++) {
42       if (inst->writemask & (1<<i)) {
43          if (!inst->dst[i]->contributes_to_output) {
44             inst->writemask &= ~(1<<i);
45             inst->dst[i] = 0;
46          }
47       }
48    }
49
50    return inst->writemask;
51 }
52
53 /* Remove a reference from a value's usage chain.
54  */
55 static void unlink_ref(struct brw_wm_ref *ref)
56 {
57    struct brw_wm_value *value = ref->value;
58
59    if (ref == value->lastuse) {
60       value->lastuse = ref->prevuse;
61    }
62    else {
63       struct brw_wm_ref *i = value->lastuse;
64       while (i->prevuse != ref) i = i->prevuse;
65       i->prevuse = ref->prevuse;
66    }
67 }
68
69 static void track_arg(struct brw_wm_compile *c,
70                       struct brw_wm_instruction *inst,
71                       GLuint arg,
72                       GLuint readmask)
73 {
74    GLuint i;
75
76    for (i = 0; i < 4; i++) {
77       struct brw_wm_ref *ref = inst->src[arg][i];
78       if (ref) {
79          if (readmask & (1<<i)) {
80             ref->value->contributes_to_output = 1;
81          }
82          else {
83             unlink_ref(ref);
84             inst->src[arg][i] = NULL;
85          }
86       }
87    }
88 }
89
90 static GLuint get_texcoord_mask( GLuint tex_idx )
91 {
92    switch (tex_idx) {
93    case TGSI_TEXTURE_1D:
94       return BRW_WRITEMASK_X;
95    case TGSI_TEXTURE_2D:
96    case TGSI_TEXTURE_RECT:
97       return BRW_WRITEMASK_XY;
98    case TGSI_TEXTURE_3D:
99       return BRW_WRITEMASK_XYZ;
100    case TGSI_TEXTURE_CUBE:
101       return BRW_WRITEMASK_XYZ;
102
103    case TGSI_TEXTURE_SHADOW1D:
104       return BRW_WRITEMASK_XZ;
105    case TGSI_TEXTURE_SHADOW2D:
106    case TGSI_TEXTURE_SHADOWRECT:
107       return BRW_WRITEMASK_XYZ;
108    default: 
109       assert(0);
110       return 0;
111    }
112 }
113
114
115 /* Step two: Basically this is dead code elimination.  
116  *
117  * Iterate backwards over instructions, noting which values
118  * contribute to the final result.  Adjust writemasks to only
119  * calculate these values.
120  */
121 void brw_wm_pass1( struct brw_wm_compile *c )
122 {
123    GLint insn;
124
125    for (insn = c->nr_insns-1; insn >= 0; insn--) {
126       struct brw_wm_instruction *inst = &c->instruction[insn];
127       GLuint writemask;
128       GLuint read0, read1, read2;
129
130       if (inst->opcode == TGSI_OPCODE_KIL) {
131          track_arg(c, inst, 0, BRW_WRITEMASK_XYZW); /* All args contribute to final */
132          continue;
133       }
134
135       if (inst->opcode == WM_FB_WRITE) {
136          track_arg(c, inst, 0, BRW_WRITEMASK_XYZW); 
137          track_arg(c, inst, 1, BRW_WRITEMASK_XYZW); 
138          if (c->key.source_depth_to_render_target &&
139              c->key.computes_depth)
140             track_arg(c, inst, 2, BRW_WRITEMASK_Z); 
141          else
142             track_arg(c, inst, 2, 0); 
143          continue;
144       }
145
146       /* Lookup all the registers which were written by this
147        * instruction and get a mask of those that contribute to the output:
148        */
149       writemask = get_tracked_mask(c, inst);
150       if (!writemask) {
151          GLuint arg;
152          for (arg = 0; arg < 3; arg++)
153             track_arg(c, inst, arg, 0);
154          continue;
155       }
156
157       read0 = 0;
158       read1 = 0;
159       read2 = 0;
160
161       /* Mark all inputs which contribute to the marked outputs:
162        */
163       switch (inst->opcode) {
164       case TGSI_OPCODE_ABS:
165       case TGSI_OPCODE_FLR:
166       case TGSI_OPCODE_FRC:
167       case TGSI_OPCODE_MOV:
168       case TGSI_OPCODE_TRUNC:
169          read0 = writemask;
170          break;
171
172       case TGSI_OPCODE_SUB:
173       case TGSI_OPCODE_SLT:
174       case TGSI_OPCODE_SLE:
175       case TGSI_OPCODE_SGE:
176       case TGSI_OPCODE_SGT:
177       case TGSI_OPCODE_SEQ:
178       case TGSI_OPCODE_SNE:
179       case TGSI_OPCODE_ADD:
180       case TGSI_OPCODE_MAX:
181       case TGSI_OPCODE_MIN:
182       case TGSI_OPCODE_MUL:
183          read0 = writemask;
184          read1 = writemask;
185          break;
186
187       case TGSI_OPCODE_DDX:
188       case TGSI_OPCODE_DDY:
189          read0 = writemask;
190          break;
191
192       case TGSI_OPCODE_MAD:     
193       case TGSI_OPCODE_CMP:
194       case TGSI_OPCODE_LRP:
195          read0 = writemask;
196          read1 = writemask;     
197          read2 = writemask;     
198          break;
199
200       case TGSI_OPCODE_XPD: 
201          if (writemask & BRW_WRITEMASK_X) read0 |= BRW_WRITEMASK_YZ;     
202          if (writemask & BRW_WRITEMASK_Y) read0 |= BRW_WRITEMASK_XZ;     
203          if (writemask & BRW_WRITEMASK_Z) read0 |= BRW_WRITEMASK_XY;
204          read1 = read0;
205          break;
206
207       case TGSI_OPCODE_COS:
208       case TGSI_OPCODE_EX2:
209       case TGSI_OPCODE_LG2:
210       case TGSI_OPCODE_RCP:
211       case TGSI_OPCODE_RSQ:
212       case TGSI_OPCODE_SIN:
213       case TGSI_OPCODE_SCS:
214       case WM_CINTERP:
215       case WM_PIXELXY:
216          read0 = BRW_WRITEMASK_X;
217          break;
218
219       case TGSI_OPCODE_POW:
220          read0 = BRW_WRITEMASK_X;
221          read1 = BRW_WRITEMASK_X;
222          break;
223
224       case TGSI_OPCODE_TEX:
225       case TGSI_OPCODE_TXP:
226          read0 = get_texcoord_mask(inst->target);
227          break;
228
229       case TGSI_OPCODE_TXB:
230          read0 = get_texcoord_mask(inst->target) | BRW_WRITEMASK_W;
231          break;
232
233       case WM_WPOSXY:
234          read0 = writemask & BRW_WRITEMASK_XY;
235          break;
236
237       case WM_DELTAXY:
238          read0 = writemask & BRW_WRITEMASK_XY;
239          read1 = BRW_WRITEMASK_X;
240          break;
241
242       case WM_PIXELW:
243          read0 = BRW_WRITEMASK_X;
244          read1 = BRW_WRITEMASK_XY;
245          break;
246
247       case WM_LINTERP:
248          read0 = BRW_WRITEMASK_X;
249          read1 = BRW_WRITEMASK_XY;
250          break;
251
252       case WM_PINTERP:
253          read0 = BRW_WRITEMASK_X; /* interpolant */
254          read1 = BRW_WRITEMASK_XY; /* deltas */
255          read2 = BRW_WRITEMASK_W; /* pixel w */
256          break;
257
258       case TGSI_OPCODE_DP3:     
259          read0 = BRW_WRITEMASK_XYZ;
260          read1 = BRW_WRITEMASK_XYZ;
261          break;
262
263       case TGSI_OPCODE_DPH:
264          read0 = BRW_WRITEMASK_XYZ;
265          read1 = BRW_WRITEMASK_XYZW;
266          break;
267
268       case TGSI_OPCODE_DP4:
269          read0 = BRW_WRITEMASK_XYZW;
270          read1 = BRW_WRITEMASK_XYZW;
271          break;
272
273       case TGSI_OPCODE_LIT: 
274          read0 = BRW_WRITEMASK_XYW;
275          break;
276
277       case TGSI_OPCODE_DST:
278       case WM_FRONTFACING:
279       case TGSI_OPCODE_KILP:
280       default:
281          break;
282       }
283
284       track_arg(c, inst, 0, read0);
285       track_arg(c, inst, 1, read1);
286       track_arg(c, inst, 2, read2);
287    }
288
289    if (BRW_DEBUG & DEBUG_WM) {
290       brw_wm_print_program(c, "pass1");
291    }
292 }