OSDN Git Service

mesa: Remove support for named parameters.
[android-x86/external-mesa.git] / src / mesa / drivers / dri / i965 / brw_fs_fp.cpp
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23
24 /** @file brw_fs_fp.cpp
25  *
26  * Implementation of the compiler for GL_ARB_fragment_program shaders on top
27  * of the GLSL compiler backend.
28  */
29
30 #include "brw_context.h"
31 #include "brw_fs.h"
32
33 static fs_reg
34 regoffset(fs_reg reg, int i)
35 {
36    reg.reg_offset += i;
37    return reg;
38 }
39
40 void
41 fs_visitor::emit_fp_alu1(enum opcode opcode,
42                          const struct prog_instruction *fpi,
43                          fs_reg dst, fs_reg src)
44 {
45    for (int i = 0; i < 4; i++) {
46       if (fpi->DstReg.WriteMask & (1 << i))
47          emit(opcode, regoffset(dst, i), regoffset(src, i));
48    }
49 }
50
51 void
52 fs_visitor::emit_fp_alu2(enum opcode opcode,
53                          const struct prog_instruction *fpi,
54                          fs_reg dst, fs_reg src0, fs_reg src1)
55 {
56    for (int i = 0; i < 4; i++) {
57       if (fpi->DstReg.WriteMask & (1 << i))
58          emit(opcode, regoffset(dst, i),
59               regoffset(src0, i), regoffset(src1, i));
60    }
61 }
62
63 void
64 fs_visitor::emit_fp_minmax(const prog_instruction *fpi,
65                            fs_reg dst, fs_reg src0, fs_reg src1)
66 {
67    uint32_t conditionalmod;
68    if (fpi->Opcode == OPCODE_MIN)
69       conditionalmod = BRW_CONDITIONAL_L;
70    else
71       conditionalmod = BRW_CONDITIONAL_GE;
72
73    for (int i = 0; i < 4; i++) {
74       if (fpi->DstReg.WriteMask & (1 << i)) {
75          emit_minmax(conditionalmod, regoffset(dst, i),
76                      regoffset(src0, i), regoffset(src1, i));
77       }
78    }
79 }
80
81 void
82 fs_visitor::emit_fp_sop(uint32_t conditional_mod,
83                         const struct prog_instruction *fpi,
84                         fs_reg dst, fs_reg src0, fs_reg src1,
85                         fs_reg one)
86 {
87    for (int i = 0; i < 4; i++) {
88       if (fpi->DstReg.WriteMask & (1 << i)) {
89          fs_inst *inst;
90
91          inst = emit(BRW_OPCODE_CMP, fs_reg(brw_null_reg()),
92                      regoffset(src0, i), regoffset(src1, i));
93          inst->conditional_mod = conditional_mod;
94
95          inst = emit(BRW_OPCODE_SEL, regoffset(dst, i), one, fs_reg(0.0f));
96          inst->predicated = true;
97       }
98    }
99 }
100
101 void
102 fs_visitor::emit_fp_scalar_write(const struct prog_instruction *fpi,
103                                  fs_reg dst, fs_reg src)
104 {
105    for (int i = 0; i < 4; i++) {
106       if (fpi->DstReg.WriteMask & (1 << i))
107          emit(BRW_OPCODE_MOV, regoffset(dst, i), src);
108    }
109 }
110
111 void
112 fs_visitor::emit_fp_scalar_math(enum opcode opcode,
113                                 const struct prog_instruction *fpi,
114                                 fs_reg dst, fs_reg src)
115 {
116    fs_reg temp = fs_reg(this, glsl_type::float_type);
117    emit_math(opcode, temp, src);
118    emit_fp_scalar_write(fpi, dst, temp);
119 }
120
121 void
122 fs_visitor::emit_fragment_program_code()
123 {
124    setup_fp_regs();
125
126    fs_reg null = fs_reg(brw_null_reg());
127
128    /* Keep a reg with 1.0 around, for reuse by emit_fp_sop so that it can just
129     * be:
130     *
131     * sel.f0 dst 1.0 0.0
132     *
133     * instead of
134     *
135     * mov    dst 0.0
136     * mov.f0 dst 1.0
137     */
138    fs_reg one = fs_reg(this, glsl_type::float_type);
139    emit(BRW_OPCODE_MOV, one, fs_reg(1.0f));
140
141    for (unsigned int insn = 0; insn < fp->Base.NumInstructions; insn++) {
142       const struct prog_instruction *fpi = &fp->Base.Instructions[insn];
143       base_ir = fpi;
144
145       //_mesa_print_instruction(fpi);
146
147       fs_reg dst;
148       fs_reg src[3];
149
150       /* We always emit into a temporary destination register to avoid
151        * aliasing issues.
152        */
153       dst = fs_reg(this, glsl_type::vec4_type);
154
155       for (int i = 0; i < 3; i++)
156          src[i] = get_fp_src_reg(&fpi->SrcReg[i]);
157
158       switch (fpi->Opcode) {
159       case OPCODE_ABS:
160          src[0].abs = true;
161          src[0].negate = false;
162          emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]);
163          break;
164
165       case OPCODE_ADD:
166          emit_fp_alu2(BRW_OPCODE_ADD, fpi, dst, src[0], src[1]);
167          break;
168
169       case OPCODE_CMP:
170          for (int i = 0; i < 4; i++) {
171             if (fpi->DstReg.WriteMask & (1 << i)) {
172                fs_inst *inst;
173
174                inst = emit(BRW_OPCODE_CMP, null,
175                            regoffset(src[0], i), fs_reg(0.0f));
176                inst->conditional_mod = BRW_CONDITIONAL_L;
177
178                inst = emit(BRW_OPCODE_SEL, regoffset(dst, i),
179                            regoffset(src[1], i), regoffset(src[2], i));
180                inst->predicated = true;
181             }
182          }
183          break;
184
185       case OPCODE_COS:
186          emit_fp_scalar_math(SHADER_OPCODE_COS, fpi, dst, src[0]);
187          break;
188
189       case OPCODE_DP2:
190       case OPCODE_DP3:
191       case OPCODE_DP4:
192       case OPCODE_DPH: {
193          fs_reg mul = fs_reg(this, glsl_type::float_type);
194          fs_reg acc = fs_reg(this, glsl_type::float_type);
195          int count;
196
197          switch (fpi->Opcode) {
198          case OPCODE_DP2: count = 2; break;
199          case OPCODE_DP3: count = 3; break;
200          case OPCODE_DP4: count = 4; break;
201          case OPCODE_DPH: count = 3; break;
202          default: assert(!"not reached"); count = 0; break;
203          }
204
205          emit(BRW_OPCODE_MUL, acc,
206               regoffset(src[0], 0), regoffset(src[1], 0));
207          for (int i = 1; i < count; i++) {
208             emit(BRW_OPCODE_MUL, mul,
209                  regoffset(src[0], i), regoffset(src[1], i));
210             emit(BRW_OPCODE_ADD, acc, acc, mul);
211          }
212
213          if (fpi->Opcode == OPCODE_DPH)
214             emit(BRW_OPCODE_ADD, acc, acc, regoffset(src[1], 3));
215
216          emit_fp_scalar_write(fpi, dst, acc);
217          break;
218       }
219
220       case OPCODE_DST:
221          if (fpi->DstReg.WriteMask & WRITEMASK_X)
222             emit(BRW_OPCODE_MOV, dst, fs_reg(1.0f));
223          if (fpi->DstReg.WriteMask & WRITEMASK_Y) {
224             emit(BRW_OPCODE_MUL, regoffset(dst, 1),
225                  regoffset(src[0], 1), regoffset(src[1], 1));
226          }
227          if (fpi->DstReg.WriteMask & WRITEMASK_Z)
228             emit(BRW_OPCODE_MOV, regoffset(dst, 2), regoffset(src[0], 2));
229          if (fpi->DstReg.WriteMask & WRITEMASK_W)
230             emit(BRW_OPCODE_MOV, regoffset(dst, 3), regoffset(src[1], 3));
231          break;
232
233       case OPCODE_EX2:
234          emit_fp_scalar_math(SHADER_OPCODE_EXP2, fpi, dst, src[0]);
235          break;
236
237       case OPCODE_FLR:
238          emit_fp_alu1(BRW_OPCODE_RNDD, fpi, dst, src[0]);
239          break;
240
241       case OPCODE_FRC:
242          emit_fp_alu1(BRW_OPCODE_FRC, fpi, dst, src[0]);
243          break;
244
245       case OPCODE_KIL: {
246          for (int i = 0; i < 4; i++) {
247             /* In most cases the argument to a KIL will be something like
248              * TEMP[0].wwww, so there's no point in checking whether .w is < 0
249              * 4 times in a row.
250              */
251             if (i > 0 &&
252                 GET_SWZ(fpi->SrcReg[0].Swizzle, i) ==
253                 GET_SWZ(fpi->SrcReg[0].Swizzle, i - 1) &&
254                 ((fpi->SrcReg[0].Negate >> i) & 1) ==
255                 ((fpi->SrcReg[0].Negate >> (i - 1)) & 1)) {
256                continue;
257             }
258
259             fs_inst *inst = emit(BRW_OPCODE_CMP, null,
260                                  regoffset(src[0], i), 0.0f);
261             inst->conditional_mod = BRW_CONDITIONAL_L;
262
263             inst = emit(BRW_OPCODE_IF);
264             inst->predicated = true;
265             emit(FS_OPCODE_DISCARD);
266             emit(BRW_OPCODE_ENDIF);
267          }
268          break;
269       }
270
271       case OPCODE_LG2:
272          emit_fp_scalar_math(SHADER_OPCODE_LOG2, fpi, dst, src[0]);
273          break;
274
275       case OPCODE_LIT:
276          /* From the ARB_fragment_program spec:
277           *
278           *      tmp = VectorLoad(op0);
279           *      if (tmp.x < 0) tmp.x = 0;
280           *      if (tmp.y < 0) tmp.y = 0;
281           *      if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
282           *      else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
283           *      result.x = 1.0;
284           *      result.y = tmp.x;
285           *      result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
286           *      result.w = 1.0;
287           *
288           * Note that we don't do the clamping to +/- 128.  We didn't in
289           * brw_wm_emit.c either.
290           */
291          if (fpi->DstReg.WriteMask & WRITEMASK_X)
292             emit(BRW_OPCODE_MOV, regoffset(dst, 0), fs_reg(1.0f));
293
294          if (fpi->DstReg.WriteMask & WRITEMASK_YZ) {
295             fs_inst *inst;
296             inst = emit(BRW_OPCODE_CMP, null,
297                         regoffset(src[0], 0), fs_reg(0.0f));
298             inst->conditional_mod = BRW_CONDITIONAL_LE;
299
300             if (fpi->DstReg.WriteMask & WRITEMASK_Y) {
301                emit(BRW_OPCODE_MOV, regoffset(dst, 1), regoffset(src[0], 0));
302                inst = emit(BRW_OPCODE_MOV, regoffset(dst, 1), fs_reg(0.0f));
303                inst->predicated = true;
304             }
305
306             if (fpi->DstReg.WriteMask & WRITEMASK_Z) {
307                emit_math(SHADER_OPCODE_POW, regoffset(dst, 2),
308                          regoffset(src[0], 1), regoffset(src[0], 3));
309
310                inst = emit(BRW_OPCODE_MOV, regoffset(dst, 2), fs_reg(0.0f));
311                inst->predicated = true;
312             }
313          }
314
315          if (fpi->DstReg.WriteMask & WRITEMASK_W)
316             emit(BRW_OPCODE_MOV, regoffset(dst, 3), fs_reg(1.0f));
317
318          break;
319
320       case OPCODE_LRP:
321          for (int i = 0; i < 4; i++) {
322             if (fpi->DstReg.WriteMask & (1 << i)) {
323                fs_reg neg_src0 = regoffset(src[0], i);
324                neg_src0.negate = !neg_src0.negate;
325                fs_reg temp = fs_reg(this, glsl_type::float_type);
326                fs_reg temp2 = fs_reg(this, glsl_type::float_type);
327                emit(BRW_OPCODE_ADD, temp, neg_src0, fs_reg(1.0f));
328                emit(BRW_OPCODE_MUL, temp, temp, regoffset(src[2], i));
329                emit(BRW_OPCODE_MUL, temp2,
330                     regoffset(src[0], i), regoffset(src[1], i));
331                emit(BRW_OPCODE_ADD, regoffset(dst, i), temp, temp2);
332             }
333          }
334          break;
335
336       case OPCODE_MAD:
337          for (int i = 0; i < 4; i++) {
338             if (fpi->DstReg.WriteMask & (1 << i)) {
339                fs_reg temp = fs_reg(this, glsl_type::float_type);
340                emit(BRW_OPCODE_MUL, temp,
341                     regoffset(src[0], i), regoffset(src[1], i));
342                emit(BRW_OPCODE_ADD, regoffset(dst, i),
343                     temp, regoffset(src[2], i));
344             }
345          }
346          break;
347
348       case OPCODE_MAX:
349          emit_fp_minmax(fpi, dst, src[0], src[1]);
350          break;
351
352       case OPCODE_MOV:
353          emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]);
354          break;
355
356       case OPCODE_MIN:
357          emit_fp_minmax(fpi, dst, src[0], src[1]);
358          break;
359
360       case OPCODE_MUL:
361          emit_fp_alu2(BRW_OPCODE_MUL, fpi, dst, src[0], src[1]);
362          break;
363
364       case OPCODE_POW: {
365          fs_reg temp = fs_reg(this, glsl_type::float_type);
366          emit_math(SHADER_OPCODE_POW, temp, src[0], src[1]);
367          emit_fp_scalar_write(fpi, dst, temp);
368          break;
369       }
370
371       case OPCODE_RCP:
372          emit_fp_scalar_math(SHADER_OPCODE_RCP, fpi, dst, src[0]);
373          break;
374
375       case OPCODE_RSQ:
376          emit_fp_scalar_math(SHADER_OPCODE_RSQ, fpi, dst, src[0]);
377          break;
378
379       case OPCODE_SCS:
380          if (fpi->DstReg.WriteMask & WRITEMASK_X) {
381             emit_math(SHADER_OPCODE_COS, regoffset(dst, 0),
382                       regoffset(src[0], 0));
383          }
384
385          if (fpi->DstReg.WriteMask & WRITEMASK_Y) {
386             emit_math(SHADER_OPCODE_SIN, regoffset(dst, 1),
387                       regoffset(src[0], 1));
388          }
389          break;
390
391       case OPCODE_SGE:
392          emit_fp_sop(BRW_CONDITIONAL_GE, fpi, dst, src[0], src[1], one);
393          break;
394
395       case OPCODE_SIN:
396          emit_fp_scalar_math(SHADER_OPCODE_SIN, fpi, dst, src[0]);
397          break;
398
399       case OPCODE_SLT:
400          emit_fp_sop(BRW_CONDITIONAL_L, fpi, dst, src[0], src[1], one);
401          break;
402
403       case OPCODE_SUB: {
404          fs_reg neg_src1 = src[1];
405          neg_src1.negate = !src[1].negate;
406
407          emit_fp_alu2(BRW_OPCODE_ADD, fpi, dst, src[0], neg_src1);
408          break;
409       }
410
411       case OPCODE_TEX:
412       case OPCODE_TXB:
413       case OPCODE_TXP: {
414          /* We piggy-back on the GLSL IR support for texture setup.  To do so,
415           * we have to cook up an ir_texture that has the coordinate field
416           * with appropriate type, and shadow_comparitor set or not.  All the
417           * other properties of ir_texture are passed in as arguments to the
418           * emit_texture_gen* function.
419           */
420          ir_texture *ir = NULL;
421
422          fs_reg lod;
423          fs_reg dpdy;
424          fs_reg coordinate = src[0];
425          fs_reg shadow_c;
426
427          switch (fpi->Opcode) {
428          case OPCODE_TEX:
429             ir = new(mem_ctx) ir_texture(ir_tex);
430             break;
431          case OPCODE_TXP: {
432             ir = new(mem_ctx) ir_texture(ir_tex);
433
434             coordinate = fs_reg(this, glsl_type::vec3_type);
435             fs_reg invproj = fs_reg(this, glsl_type::float_type);
436             emit_math(SHADER_OPCODE_RCP, invproj, regoffset(src[0], 3));
437             for (int i = 0; i < 3; i++) {
438                emit(BRW_OPCODE_MUL, regoffset(coordinate, i),
439                     regoffset(src[0], i), invproj);
440             }
441             break;
442          }
443          case OPCODE_TXB:
444             ir = new(mem_ctx) ir_texture(ir_txb);
445             lod = regoffset(src[0], 3);
446             break;
447          default:
448             assert(!"not reached");
449             break;
450          }
451
452          const glsl_type *coordinate_type;
453          switch (fpi->TexSrcTarget) {
454          case TEXTURE_1D_INDEX:
455             coordinate_type = glsl_type::float_type;
456             break;
457
458          case TEXTURE_2D_INDEX:
459          case TEXTURE_1D_ARRAY_INDEX:
460          case TEXTURE_RECT_INDEX:
461          case TEXTURE_EXTERNAL_INDEX:
462             coordinate_type = glsl_type::vec2_type;
463             break;
464
465          case TEXTURE_3D_INDEX:
466          case TEXTURE_2D_ARRAY_INDEX:
467             coordinate_type = glsl_type::vec3_type;
468             break;
469
470          case TEXTURE_CUBE_INDEX: {
471             coordinate_type = glsl_type::vec3_type;
472
473             fs_reg temp = fs_reg(this, glsl_type::float_type);
474             fs_reg cubecoord = fs_reg(this, glsl_type::vec3_type);
475             fs_reg abscoord = coordinate;
476             abscoord.negate = false;
477             abscoord.abs = true;
478             emit_minmax(BRW_CONDITIONAL_GE, temp,
479                         regoffset(abscoord, 0), regoffset(abscoord, 1));
480             emit_minmax(BRW_CONDITIONAL_GE, temp,
481                         temp, regoffset(abscoord, 2));
482             emit_math(SHADER_OPCODE_RCP, temp, temp);
483             for (int i = 0; i < 3; i++) {
484                emit(BRW_OPCODE_MUL, regoffset(cubecoord, i),
485                     regoffset(coordinate, i), temp);
486             }
487
488             coordinate = cubecoord;
489             break;
490          }
491
492          default:
493             assert(!"not reached");
494             coordinate_type = glsl_type::vec2_type;
495             break;
496          }
497
498          ir_constant_data junk_data;
499          ir->coordinate = new(mem_ctx) ir_constant(coordinate_type, &junk_data);
500
501          coordinate = rescale_texcoord(ir, coordinate,
502                                        fpi->TexSrcTarget == TEXTURE_RECT_INDEX,
503                                        fpi->TexSrcUnit, fpi->TexSrcUnit);
504
505          if (fpi->TexShadow) {
506             shadow_c = regoffset(coordinate, 2);
507             ir->shadow_comparitor = new(mem_ctx) ir_constant(0.0f);
508          }
509
510          fs_inst *inst;
511          if (intel->gen >= 7) {
512             inst = emit_texture_gen7(ir, dst, coordinate, shadow_c, lod, dpdy);
513          } else if (intel->gen >= 5) {
514             inst = emit_texture_gen5(ir, dst, coordinate, shadow_c, lod, dpdy);
515          } else {
516             inst = emit_texture_gen4(ir, dst, coordinate, shadow_c, lod, dpdy);
517          }
518
519          inst->sampler = fpi->TexSrcUnit;
520          inst->shadow_compare = fpi->TexShadow;
521
522          /* Reuse the GLSL swizzle_result() handler. */
523          swizzle_result(ir, dst, fpi->TexSrcUnit);
524          dst = this->result;
525
526          break;
527       }
528
529       case OPCODE_SWZ:
530          /* Note that SWZ's extended swizzles are handled in the general
531           * get_src_reg() code.
532           */
533          emit_fp_alu1(BRW_OPCODE_MOV, fpi, dst, src[0]);
534          break;
535
536       case OPCODE_XPD:
537          for (int i = 0; i < 3; i++) {
538             if (fpi->DstReg.WriteMask & (1 << i)) {
539                int i1 = (i + 1) % 3;
540                int i2 = (i + 2) % 3;
541
542                fs_reg temp = fs_reg(this, glsl_type::float_type);
543                fs_reg neg_src1_1 = regoffset(src[1], i1);
544                neg_src1_1.negate = !neg_src1_1.negate;
545                emit(BRW_OPCODE_MUL, temp,
546                     regoffset(src[0], i2), neg_src1_1);
547                emit(BRW_OPCODE_MUL, regoffset(dst, i),
548                     regoffset(src[0], i1), regoffset(src[1], i2));
549                emit(BRW_OPCODE_ADD, regoffset(dst, i),
550                     regoffset(dst, i), temp);
551             }
552          }
553          break;
554
555       case OPCODE_END:
556          break;
557
558       default:
559          _mesa_problem(ctx, "Unsupported opcode %s in fragment program\n",
560                        _mesa_opcode_string(fpi->Opcode));
561       }
562
563       /* To handle saturates, we emit a MOV with a saturate bit, which
564        * optimization should fold into the preceding instructions when safe.
565        */
566       if (fpi->Opcode != OPCODE_END) {
567          fs_reg real_dst = get_fp_dst_reg(&fpi->DstReg);
568
569          for (int i = 0; i < 4; i++) {
570             if (fpi->DstReg.WriteMask & (1 << i)) {
571                fs_inst *inst = emit(BRW_OPCODE_MOV,
572                                     regoffset(real_dst, i),
573                                     regoffset(dst, i));
574                inst->saturate = fpi->SaturateMode;
575             }
576          }
577       }
578    }
579
580    /* Epilogue:
581     *
582     * Fragment depth has this strange convention of being the .z component of
583     * a vec4.  emit_fb_write() wants to see a float value, instead.
584     */
585    this->current_annotation = "result.depth write";
586    if (frag_depth.file != BAD_FILE) {
587       fs_reg temp = fs_reg(this, glsl_type::float_type);
588       emit(BRW_OPCODE_MOV, temp, regoffset(frag_depth, 2));
589       frag_depth = temp;
590    }
591 }
592
593 void
594 fs_visitor::setup_fp_regs()
595 {
596    /* PROGRAM_TEMPORARY */
597    int num_temp = fp->Base.NumTemporaries;
598    fp_temp_regs = rzalloc_array(mem_ctx, fs_reg, num_temp);
599    for (int i = 0; i < num_temp; i++)
600       fp_temp_regs[i] = fs_reg(this, glsl_type::vec4_type);
601
602    /* PROGRAM_STATE_VAR etc. */
603    if (c->dispatch_width == 8) {
604       for (unsigned p = 0;
605            p < c->fp->program.Base.Parameters->NumParameters; p++) {
606          for (unsigned int i = 0; i < 4; i++) {
607             this->param_index[c->prog_data.nr_params] = p;
608             this->param_offset[c->prog_data.nr_params] = i;
609             c->prog_data.nr_params++;
610          }
611       }
612    }
613
614    fp_input_regs = rzalloc_array(mem_ctx, fs_reg, FRAG_ATTRIB_MAX);
615    for (int i = 0; i < FRAG_ATTRIB_MAX; i++) {
616       if (fp->Base.InputsRead & BITFIELD64_BIT(i)) {
617          /* Make up a dummy instruction to reuse code for emitting
618           * interpolation.
619           */
620          ir_variable *ir = new(mem_ctx) ir_variable(glsl_type::vec4_type,
621                                                     "fp_input",
622                                                     ir_var_in);
623          ir->location = i;
624
625          this->current_annotation = ralloc_asprintf(ctx, "interpolate input %d",
626                                                     i);
627
628          switch (i) {
629          case FRAG_ATTRIB_WPOS:
630             ir->pixel_center_integer = fp->PixelCenterInteger;
631             ir->origin_upper_left = fp->OriginUpperLeft;
632             fp_input_regs[i] = *emit_fragcoord_interpolation(ir);
633             break;
634          case FRAG_ATTRIB_FACE:
635             fp_input_regs[i] = *emit_frontfacing_interpolation(ir);
636             break;
637          default:
638             fp_input_regs[i] = *emit_general_interpolation(ir);
639
640             if (i == FRAG_ATTRIB_FOGC) {
641                emit(BRW_OPCODE_MOV,
642                     regoffset(fp_input_regs[i], 1), fs_reg(0.0f));
643                emit(BRW_OPCODE_MOV,
644                     regoffset(fp_input_regs[i], 2), fs_reg(0.0f));
645                emit(BRW_OPCODE_MOV,
646                     regoffset(fp_input_regs[i], 3), fs_reg(1.0f));
647             }
648
649             break;
650          }
651
652          this->current_annotation = NULL;
653       }
654    }
655 }
656
657 fs_reg
658 fs_visitor::get_fp_dst_reg(const prog_dst_register *dst)
659 {
660    switch (dst->File) {
661    case PROGRAM_TEMPORARY:
662       return fp_temp_regs[dst->Index];
663
664    case PROGRAM_OUTPUT:
665       if (dst->Index == FRAG_RESULT_DEPTH) {
666          if (frag_depth.file == BAD_FILE)
667             frag_depth = fs_reg(this, glsl_type::vec4_type);
668          return frag_depth;
669       } else if (dst->Index == FRAG_RESULT_COLOR) {
670          if (outputs[0].file == BAD_FILE) {
671             outputs[0] = fs_reg(this, glsl_type::vec4_type);
672             output_components[0] = 4;
673
674             /* Tell emit_fb_writes() to smear fragment.color across all the
675              * color attachments.
676              */
677             for (int i = 1; i < c->key.nr_color_regions; i++) {
678                outputs[i] = outputs[0];
679                output_components[i] = output_components[0];
680             }
681          }
682          return outputs[0];
683       } else {
684          int output_index = dst->Index - FRAG_RESULT_DATA0;
685          if (outputs[output_index].file == BAD_FILE) {
686             outputs[output_index] = fs_reg(this, glsl_type::vec4_type);
687          }
688          output_components[output_index] = 4;
689          return outputs[output_index];
690       }
691
692    case PROGRAM_UNDEFINED:
693       return fs_reg();
694
695    default:
696       _mesa_problem(ctx, "bad dst register file: %s\n",
697                     _mesa_register_file_name((gl_register_file)dst->File));
698       return fs_reg(this, glsl_type::vec4_type);
699    }
700 }
701
702 fs_reg
703 fs_visitor::get_fp_src_reg(const prog_src_register *src)
704 {
705    struct gl_program_parameter_list *plist = c->fp->program.Base.Parameters;
706
707    fs_reg result;
708
709    assert(!src->Abs);
710
711    switch (src->File) {
712    case PROGRAM_UNDEFINED:
713       return fs_reg();
714    case PROGRAM_TEMPORARY:
715       result = fp_temp_regs[src->Index];
716       break;
717
718    case PROGRAM_INPUT:
719       result = fp_input_regs[src->Index];
720       break;
721
722    case PROGRAM_STATE_VAR:
723    case PROGRAM_UNIFORM:
724    case PROGRAM_CONSTANT:
725       /* We actually want to look at the type in the Parameters list for this,
726        * because this lets us upload constant builtin uniforms, as actual
727        * constants.
728        */
729       switch (plist->Parameters[src->Index].Type) {
730       case PROGRAM_CONSTANT: {
731          result = fs_reg(this, glsl_type::vec4_type);
732
733          for (int i = 0; i < 4; i++) {
734             emit(BRW_OPCODE_MOV, regoffset(result, i),
735                  fs_reg(plist->ParameterValues[src->Index][i].f));
736          }
737          break;
738       }
739
740       case PROGRAM_STATE_VAR:
741       case PROGRAM_UNIFORM:
742          result = fs_reg(UNIFORM, src->Index * 4);
743          break;
744
745       default:
746          _mesa_problem(ctx, "bad uniform src register file: %s\n",
747                        _mesa_register_file_name((gl_register_file)src->File));
748          return fs_reg(this, glsl_type::vec4_type);
749       }
750       break;
751
752    default:
753       _mesa_problem(ctx, "bad src register file: %s\n",
754                     _mesa_register_file_name((gl_register_file)src->File));
755       return fs_reg(this, glsl_type::vec4_type);
756    }
757
758    if (src->Swizzle != SWIZZLE_NOOP || src->Negate) {
759       fs_reg unswizzled = result;
760       result = fs_reg(this, glsl_type::vec4_type);
761       for (int i = 0; i < 4; i++) {
762          bool negate = src->Negate & (1 << i);
763          /* The ZERO, ONE, and Negate options are only used for OPCODE_SWZ,
764           * but it costs us nothing to support it.
765           */
766          int src_swiz = GET_SWZ(src->Swizzle, i);
767          if (src_swiz == SWIZZLE_ZERO) {
768             emit(BRW_OPCODE_MOV, regoffset(result, i), fs_reg(0.0f));
769          } else if (src_swiz == SWIZZLE_ONE) {
770             emit(BRW_OPCODE_MOV, regoffset(result, i),
771                  negate ? fs_reg(-1.0f) : fs_reg(1.0f));
772          } else {
773             fs_reg src = regoffset(unswizzled, src_swiz);
774             if (negate)
775                src.negate = !src.negate;
776             emit(BRW_OPCODE_MOV, regoffset(result, i), src);
777          }
778       }
779    }
780
781    return result;
782 }