fix mesa fb binding
[mesa.git] / src / mesa / drivers / dri / nouveau / nv30_vertprog.c
1 #include "nouveau_context.h"
2 #include "nouveau_object.h"
3 #include "nouveau_fifo.h"
4 #include "nouveau_reg.h"
5
6 #include "nouveau_shader.h"
7 #include "nv30_shader.h"
8
9 /*****************************************************************************
10 * Support routines
11 */
12 static void
13 NV30VPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
14 {
15 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
16 int i;
17
18 /* We can do better here and keep more than one VP on the hardware, and
19 * switch between them with PROGRAM_START_ID..
20 */
21 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_FROM_ID, 1);
22 OUT_RING(0);
23 for (i=0; i<nvs->program_size; i+=4) {
24 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_INST0, 4);
25 OUT_RING(nvs->program[i + 0]);
26 OUT_RING(nvs->program[i + 1]);
27 OUT_RING(nvs->program[i + 2]);
28 OUT_RING(nvs->program[i + 3]);
29 }
30 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_PROGRAM_START_ID, 1);
31 OUT_RING(0);
32
33 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_IN_REG, 2);
34 OUT_RING(nvs->card_priv.NV30VP.vp_in_reg);
35 OUT_RING(nvs->card_priv.NV30VP.vp_out_reg);
36
37 BEGIN_RING_CACHE(NvSub3D, NV30_TCL_PRIMITIVE_3D_SET_CLIPPING_PLANES, 1);
38 OUT_RING_CACHE (nvs->card_priv.NV30VP.clip_enables);
39 }
40
41 static void
42 NV30VPUpdateConst(GLcontext *ctx, nouveauShader *nvs, int id)
43 {
44 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
45 GLfloat *val;
46
47 val = nvs->params[id].source_val ?
48 nvs->params[id].source_val : nvs->params[id].val;
49
50 BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_VP_UPLOAD_CONST_ID, 5);
51 OUT_RING (id);
52 OUT_RINGp(val, 4);
53 }
54
55 /*****************************************************************************
56 * Assembly routines
57 */
58 static void
59 NV30VPSetBranchTarget(nvsFunc *shader, int addr)
60 {
61 shader->inst[2] &= ~NV30_VP_INST_IADDR_MASK;
62 shader->inst[2] |= (addr << NV30_VP_INST_IADDR_SHIFT);
63 }
64
65 /*****************************************************************************
66 * Disassembly routines
67 */
68 static unsigned int
69 NV30VPGetOpcodeHW(nvsFunc * shader, int slot)
70 {
71 int op;
72
73 if (slot) {
74 op = (shader->inst[1] & NV30_VP_INST_SCA_OPCODEL_MASK)
75 >> NV30_VP_INST_SCA_OPCODEL_SHIFT;
76 op |= ((shader->inst[0] & NV30_VP_INST_SCA_OPCODEH_MASK)
77 >> NV30_VP_INST_SCA_OPCODEH_SHIFT) << 4;
78 }
79 else {
80 op = (shader->inst[1] & NV30_VP_INST_VEC_OPCODE_MASK)
81 >> NV30_VP_INST_VEC_OPCODE_SHIFT;
82 }
83
84 return op;
85 }
86
87 static nvsRegFile
88 NV30VPGetDestFile(nvsFunc * shader, int merged)
89 {
90 switch (shader->GetOpcode(shader, merged)) {
91 case NVS_OP_ARL:
92 case NVS_OP_ARR:
93 case NVS_OP_ARA:
94 return NVS_FILE_ADDRESS;
95 default:
96 /*FIXME: This probably isn't correct.. */
97 if ((shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK) != 0)
98 return NVS_FILE_RESULT;
99 if ((shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK) != 0)
100 return NVS_FILE_RESULT;
101 return NVS_FILE_TEMP;
102 }
103 }
104
105 static unsigned int
106 NV30VPGetDestID(nvsFunc * shader, int merged)
107 {
108 int id;
109
110 switch (shader->GetDestFile(shader, merged)) {
111 case NVS_FILE_RESULT:
112 id = ((shader->inst[3] & NV30_VP_INST_DEST_ID_MASK)
113 >> NV30_VP_INST_DEST_ID_SHIFT);
114 switch (id) {
115 case NV30_VP_INST_DEST_POS : return NVS_FR_POSITION;
116 case NV30_VP_INST_DEST_COL0 : return NVS_FR_COL0;
117 case NV30_VP_INST_DEST_COL1 : return NVS_FR_COL1;
118 case NV30_VP_INST_DEST_TC(0): return NVS_FR_TEXCOORD0;
119 case NV30_VP_INST_DEST_TC(1): return NVS_FR_TEXCOORD1;
120 case NV30_VP_INST_DEST_TC(2): return NVS_FR_TEXCOORD2;
121 case NV30_VP_INST_DEST_TC(3): return NVS_FR_TEXCOORD3;
122 case NV30_VP_INST_DEST_TC(4): return NVS_FR_TEXCOORD4;
123 case NV30_VP_INST_DEST_TC(5): return NVS_FR_TEXCOORD5;
124 case NV30_VP_INST_DEST_TC(6): return NVS_FR_TEXCOORD6;
125 case NV30_VP_INST_DEST_TC(7): return NVS_FR_TEXCOORD7;
126 default:
127 return -1;
128 }
129 case NVS_FILE_ADDRESS:
130 case NVS_FILE_TEMP:
131 return (shader->inst[0] & NV30_VP_INST_DEST_TEMP_ID_MASK)
132 >> NV30_VP_INST_DEST_TEMP_ID_SHIFT;
133 default:
134 return -1;
135 }
136 }
137
138 static unsigned int
139 NV30VPGetDestMask(nvsFunc * shader, int merged)
140 {
141 int hwmask, mask = 0;
142
143 if (shader->GetDestFile(shader, merged) == NVS_FILE_RESULT)
144 if (shader->GetOpcodeSlot(shader, merged))
145 hwmask = (shader->inst[3] & NV30_VP_INST_SDEST_WRITEMASK_MASK)
146 >> NV30_VP_INST_SDEST_WRITEMASK_SHIFT;
147 else
148 hwmask = (shader->inst[3] & NV30_VP_INST_VDEST_WRITEMASK_MASK)
149 >> NV30_VP_INST_VDEST_WRITEMASK_SHIFT;
150 else if (shader->GetOpcodeSlot(shader, merged))
151 hwmask = (shader->inst[3] & NV30_VP_INST_STEMP_WRITEMASK_MASK)
152 >> NV30_VP_INST_STEMP_WRITEMASK_SHIFT;
153 else
154 hwmask = (shader->inst[3] & NV30_VP_INST_VTEMP_WRITEMASK_MASK)
155 >> NV30_VP_INST_VTEMP_WRITEMASK_SHIFT;
156
157 if (hwmask & (1 << 3)) mask |= SMASK_X;
158 if (hwmask & (1 << 2)) mask |= SMASK_Y;
159 if (hwmask & (1 << 1)) mask |= SMASK_Z;
160 if (hwmask & (1 << 0)) mask |= SMASK_W;
161
162 return mask;
163 }
164
165 static int
166 NV30VPGetSourceID(nvsFunc * shader, int merged, int pos)
167 {
168 unsigned int src;
169
170 switch (shader->GetSourceFile(shader, merged, pos)) {
171 case NVS_FILE_TEMP:
172 src = shader->GetSourceHW(shader, merged, pos);
173 return ((src & NV30_VP_SRC_REG_TEMP_ID_MASK) >>
174 NV30_VP_SRC_REG_TEMP_ID_SHIFT);
175 case NVS_FILE_CONST:
176 return ((shader->inst[1] & NV30_VP_INST_CONST_SRC_MASK)
177 >> NV30_VP_INST_CONST_SRC_SHIFT);
178 case NVS_FILE_ATTRIB:
179 src = ((shader->inst[1] & NV30_VP_INST_INPUT_SRC_MASK)
180 >> NV30_VP_INST_INPUT_SRC_SHIFT);
181 switch (src) {
182 case NV30_VP_INST_IN_POS : return NVS_FR_POSITION;
183 case NV30_VP_INST_IN_COL0 : return NVS_FR_COL0;
184 case NV30_VP_INST_IN_COL1 : return NVS_FR_COL1;
185 case NV30_VP_INST_IN_TC(0): return NVS_FR_TEXCOORD0;
186 case NV30_VP_INST_IN_TC(1): return NVS_FR_TEXCOORD1;
187 case NV30_VP_INST_IN_TC(2): return NVS_FR_TEXCOORD2;
188 case NV30_VP_INST_IN_TC(3): return NVS_FR_TEXCOORD3;
189 case NV30_VP_INST_IN_TC(4): return NVS_FR_TEXCOORD4;
190 case NV30_VP_INST_IN_TC(5): return NVS_FR_TEXCOORD5;
191 case NV30_VP_INST_IN_TC(6): return NVS_FR_TEXCOORD6;
192 case NV30_VP_INST_IN_TC(7): return NVS_FR_TEXCOORD7;
193 default:
194 return NVS_FR_UNKNOWN;
195 }
196 default:
197 return -1;
198 }
199 }
200
201 static int
202 NV30VPGetSourceAbs(nvsFunc * shader, int merged, int pos)
203 {
204 struct _op_xlat *opr;
205 static unsigned int abspos[3] = {
206 NV30_VP_INST_SRC0_ABS,
207 NV30_VP_INST_SRC1_ABS,
208 NV30_VP_INST_SRC2_ABS,
209 };
210
211 opr = shader->GetOPTXRec(shader, merged);
212 if (!opr || opr->srcpos[pos] == -1 || opr->srcpos[pos] > 2)
213 return 0;
214
215 return ((shader->inst[0] & abspos[opr->srcpos[pos]]) ? 1 : 0);
216 }
217
218 static int
219 NV30VPGetRelAddressRegID(nvsFunc * shader)
220 {
221 return ((shader->inst[0] & NV30_VP_INST_ADDR_REG_SELECT_1) ? 1 : 0);
222 }
223
224 static nvsSwzComp
225 NV30VPGetRelAddressSwizzle(nvsFunc * shader)
226 {
227 nvsSwzComp swz;
228
229 swz = NV20VP_TX_SWIZZLE[(shader->inst[0] & NV30_VP_INST_ADDR_SWZ_MASK)
230 >> NV30_VP_INST_ADDR_SWZ_SHIFT];
231 return swz;
232 }
233
234 static int
235 NV30VPSupportsConditional(nvsFunc * shader)
236 {
237 /*FIXME: Is this true of all ops? */
238 return 1;
239 }
240
241 static int
242 NV30VPGetConditionUpdate(nvsFunc * shader)
243 {
244 return ((shader->inst[0] & NV30_VP_INST_COND_UPDATE_ENABLE) ? 1 : 0);
245 }
246
247 static int
248 NV30VPGetConditionTest(nvsFunc * shader)
249 {
250 int op;
251
252 /* The condition test is unconditionally enabled on some
253 * instructions. ie: the condition test bit does *NOT* have
254 * to be set.
255 *
256 * FIXME: check other relevant ops for this situation.
257 */
258 op = shader->GetOpcodeHW(shader, 1);
259 switch (op) {
260 case NV30_VP_INST_OP_BRA:
261 return 1;
262 default:
263 return ((shader->inst[0] & NV30_VP_INST_COND_TEST_ENABLE) ? 1 : 0);
264 }
265 }
266
267 static nvsCond
268 NV30VPGetCondition(nvsFunc * shader)
269 {
270 int cond;
271
272 cond = ((shader->inst[0] & NV30_VP_INST_COND_MASK)
273 >> NV30_VP_INST_COND_SHIFT);
274
275 switch (cond) {
276 case NV30_VP_INST_COND_FL: return NVS_COND_FL;
277 case NV30_VP_INST_COND_LT: return NVS_COND_LT;
278 case NV30_VP_INST_COND_EQ: return NVS_COND_EQ;
279 case NV30_VP_INST_COND_LE: return NVS_COND_LE;
280 case NV30_VP_INST_COND_GT: return NVS_COND_GT;
281 case NV30_VP_INST_COND_NE: return NVS_COND_NE;
282 case NV30_VP_INST_COND_GE: return NVS_COND_GE;
283 case NV30_VP_INST_COND_TR: return NVS_COND_TR;
284 default:
285 return NVS_COND_UNKNOWN;
286 }
287 }
288
289 static void
290 NV30VPGetCondRegSwizzle(nvsFunc * shader, nvsSwzComp *swz)
291 {
292 int swzbits;
293
294 swzbits = (shader->inst[0] & NV30_VP_INST_COND_SWZ_ALL_MASK)
295 >> NV30_VP_INST_COND_SWZ_ALL_SHIFT;
296 NV20VPTXSwizzle(swzbits, swz);
297 }
298
299 static int
300 NV30VPGetCondRegID(nvsFunc * shader)
301 {
302 return 0;
303 }
304
305
306 static int
307 NV30VPGetBranch(nvsFunc * shader)
308 {
309 return ((shader->inst[2] & NV30_VP_INST_IADDR_MASK)
310 >> NV30_VP_INST_IADDR_SHIFT);
311 }
312
313 void
314 NV30VPInitShaderFuncs(nvsFunc * shader)
315 {
316 /* Inherit NV20 code, a lot of it is the same */
317 NV20VPInitShaderFuncs(shader);
318
319 /* Increase max valid opcode ID, and add new instructions */
320 NVVP_TX_VOP_COUNT = NVVP_TX_NVS_OP_COUNT = 32;
321
322 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FRC, NVS_OP_FRC, 0, -1, -1);
323 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_FLR, NVS_OP_FLR, 0, -1, -1);
324 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SEQ, NVS_OP_SEQ, 0, 1, -1);
325 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SFL, NVS_OP_SFL, 0, 1, -1);
326 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SGT, NVS_OP_SGT, 0, 1, -1);
327 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SLE, NVS_OP_SLE, 0, 1, -1);
328 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SNE, NVS_OP_SNE, 0, 1, -1);
329 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_STR, NVS_OP_STR, 0, 1, -1);
330 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_SSG, NVS_OP_SSG, 0, -1, -1);
331 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARR, NVS_OP_ARR, 0, -1, -1);
332 MOD_OPCODE(NVVP_TX_VOP, NV30_VP_INST_OP_ARA, NVS_OP_ARA, 3, -1, -1);
333
334 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_BRA, NVS_OP_BRA, -1, -1, -1);
335 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_CAL, NVS_OP_CAL, -1, -1, -1);
336 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_RET, NVS_OP_RET, -1, -1, -1);
337 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_LG2, NVS_OP_LG2, 2, -1, -1);
338 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_EX2, NVS_OP_EX2, 2, -1, -1);
339 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_SIN, NVS_OP_SIN, 2, -1, -1);
340 MOD_OPCODE(NVVP_TX_SOP, NV30_VP_INST_OP_COS, NVS_OP_COS, 2, -1, -1);
341
342 shader->UploadToHW = NV30VPUploadToHW;
343 shader->UpdateConst = NV30VPUpdateConst;
344
345 shader->GetOpcodeHW = NV30VPGetOpcodeHW;
346
347 shader->GetDestFile = NV30VPGetDestFile;
348 shader->GetDestID = NV30VPGetDestID;
349 shader->GetDestMask = NV30VPGetDestMask;
350
351 shader->GetSourceID = NV30VPGetSourceID;
352 shader->GetSourceAbs = NV30VPGetSourceAbs;
353
354 shader->GetRelAddressRegID = NV30VPGetRelAddressRegID;
355 shader->GetRelAddressSwizzle = NV30VPGetRelAddressSwizzle;
356
357 shader->SupportsConditional = NV30VPSupportsConditional;
358 shader->GetConditionUpdate = NV30VPGetConditionUpdate;
359 shader->GetConditionTest = NV30VPGetConditionTest;
360 shader->GetCondition = NV30VPGetCondition;
361 shader->GetCondRegSwizzle = NV30VPGetCondRegSwizzle;
362 shader->GetCondRegID = NV30VPGetCondRegID;
363
364 shader->GetBranch = NV30VPGetBranch;
365 shader->SetBranchTarget = NV30VPSetBranchTarget;
366 }
367