brw_vs_constval.c revision 7db7ff878d3e5a6b345228e6eaee4797bb68b360
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 "main/macros.h"
34#include "brw_context.h"
35#include "brw_vs.h"
36
37/* Component is active if it may diverge from [0,0,0,1].  Undef values
38 * are promoted to [0,0,0,1] for the purposes of this analysis.
39 */
40struct tracker {
41   GLboolean twoside;
42   GLubyte active[PROGRAM_OUTPUT+1][128];
43   GLuint size_masks[4];
44};
45
46
47static void set_active_component( struct tracker *t,
48				  GLuint file,
49				  GLuint index,
50				  GLubyte active )
51{
52   switch (file) {
53   case PROGRAM_TEMPORARY:
54   case PROGRAM_INPUT:
55   case PROGRAM_OUTPUT:
56      t->active[file][index] |= active;
57
58   default:
59      break;
60   }
61}
62
63static void set_active( struct tracker *t,
64			struct prog_dst_register dst,
65			GLuint active )
66{
67   set_active_component( t, dst.File, dst.Index, active & dst.WriteMask );
68}
69
70
71static GLubyte get_active_component( struct tracker *t,
72				     GLuint file,
73				     GLuint index,
74				     GLuint component,
75				     GLubyte swz )
76{
77   switch (swz) {
78   case SWIZZLE_ZERO:
79      return component < 3 ? 0 : (1<<component);
80   case SWIZZLE_ONE:
81      return component == 3 ? 0 : (1<<component);
82   default:
83      switch (file) {
84      case PROGRAM_TEMPORARY:
85      case PROGRAM_INPUT:
86      case PROGRAM_OUTPUT:
87	 return t->active[file][index] & (1<<component);
88      default:
89	 return 1 << component;
90      }
91   }
92}
93
94
95static GLubyte get_active( struct tracker *t,
96			   struct prog_src_register src )
97{
98   GLuint i;
99   GLubyte active = src.Negate; /* NOTE! */
100
101   if (src.RelAddr)
102      return 0xf;
103
104   for (i = 0; i < 4; i++)
105      active |= get_active_component(t, src.File, src.Index, i,
106				     GET_SWZ(src.Swizzle, i));
107
108   return active;
109}
110
111static GLubyte get_output_size( struct tracker *t,
112				GLuint idx )
113{
114   GLubyte active = t->active[PROGRAM_OUTPUT][idx];
115   if (active & (1<<3)) return 4;
116   if (active & (1<<2)) return 3;
117   if (active & (1<<1)) return 2;
118   if (active & (1<<0)) return 1;
119   return 0;
120}
121
122/* Note the potential copying that occurs in the setup program:
123 */
124static void calc_sizes( struct tracker *t )
125{
126   GLuint i;
127
128   if (t->twoside) {
129      t->active[PROGRAM_OUTPUT][VERT_RESULT_COL0] |=
130	 t->active[PROGRAM_OUTPUT][VERT_RESULT_BFC0];
131
132      t->active[PROGRAM_OUTPUT][VERT_RESULT_COL1] |=
133	 t->active[PROGRAM_OUTPUT][VERT_RESULT_BFC1];
134   }
135
136   for (i = 0; i < FRAG_ATTRIB_MAX; i++) {
137      switch (get_output_size(t, i)) {
138      case 4: t->size_masks[4-1] |= 1<<i;
139      case 3: t->size_masks[3-1] |= 1<<i;
140      case 2: t->size_masks[2-1] |= 1<<i;
141      case 1: t->size_masks[1-1] |= 1<<i;
142	 break;
143      }
144   }
145}
146
147static GLubyte szflag[4+1] = {
148   0,
149   0x1,
150   0x3,
151   0x7,
152   0xf
153};
154
155/* Pull a size out of the packed array:
156 */
157static GLuint get_input_size(struct brw_context *brw,
158			     GLuint attr)
159{
160   GLuint sizes_dword = brw->vb.info.sizes[attr/16];
161   GLuint sizes_bits = (sizes_dword>>((attr%16)*2)) & 0x3;
162   return sizes_bits + 1;
163/*    return brw->vb.inputs[attr].glarray->Size; */
164}
165
166/* Calculate sizes of vertex program outputs.  Size is the largest
167 * component index which might vary from [0,0,0,1]
168 */
169static void calc_wm_input_sizes( struct brw_context *brw )
170{
171   GLcontext *ctx = &brw->intel.ctx;
172   /* BRW_NEW_VERTEX_PROGRAM */
173   const struct brw_vertex_program *vp =
174      brw_vertex_program_const(brw->vertex_program);
175   /* BRW_NEW_INPUT_DIMENSIONS */
176   struct tracker t;
177   GLuint insn;
178   GLuint i;
179
180   memset(&t, 0, sizeof(t));
181
182   /* _NEW_LIGHT */
183   if (ctx->Light.Model.TwoSide)
184      t.twoside = 1;
185
186   for (i = 0; i < VERT_ATTRIB_MAX; i++)
187      if (vp->program.Base.InputsRead & (1<<i))
188	 set_active_component(&t, PROGRAM_INPUT, i,
189			      szflag[get_input_size(brw, i)]);
190
191   for (insn = 0; insn < vp->program.Base.NumInstructions; insn++) {
192      struct prog_instruction *inst = &vp->program.Base.Instructions[insn];
193
194      switch (inst->Opcode) {
195      case OPCODE_ARL:
196	 break;
197
198      case OPCODE_MOV:
199	 set_active(&t, inst->DstReg, get_active(&t, inst->SrcReg[0]));
200	 break;
201
202      default:
203	 set_active(&t, inst->DstReg, 0xf);
204	 break;
205      }
206   }
207
208   calc_sizes(&t);
209
210   if (memcmp(brw->wm.input_size_masks, t.size_masks, sizeof(t.size_masks)) != 0) {
211      memcpy(brw->wm.input_size_masks, t.size_masks, sizeof(t.size_masks));
212      brw->state.dirty.brw |= BRW_NEW_WM_INPUT_DIMENSIONS;
213   }
214}
215
216const struct brw_tracked_state brw_wm_input_sizes = {
217   .dirty = {
218      .mesa  = _NEW_LIGHT,
219      .brw   = BRW_NEW_VERTEX_PROGRAM | BRW_NEW_INPUT_DIMENSIONS,
220      .cache = 0
221   },
222   .prepare = calc_wm_input_sizes
223};
224
225