+ return coordinate;
+}
+
+/* Sample from the MCS surface attached to this multisample texture. */
+fs_reg
+fs_visitor::emit_mcs_fetch(ir_texture *ir, fs_reg coordinate, int sampler)
+{
+ int reg_width = dispatch_width / 8;
+ int length = ir->coordinate->type->vector_elements;
+ fs_reg payload = fs_reg(GRF, virtual_grf_alloc(length),
+ BRW_REGISTER_TYPE_F);
+ fs_reg dest = fs_reg(this, glsl_type::uvec4_type);
+ fs_reg *sources = ralloc_array(mem_ctx, fs_reg, length);
+
+ /* parameters are: u, v, r; missing parameters are treated as zero */
+ for (int i = 0; i < length; i++) {
+ sources[i] = fs_reg(this, glsl_type::float_type);
+ emit(MOV(retype(sources[i], BRW_REGISTER_TYPE_D), coordinate));
+ coordinate.reg_offset++;
+ }
+
+ emit(LOAD_PAYLOAD(payload, sources, length));
+
+ fs_inst *inst = emit(SHADER_OPCODE_TXF_MCS, dest, payload);
+ inst->base_mrf = -1;
+ inst->mlen = length * reg_width;
+ inst->header_present = false;
+ inst->regs_written = 4; /* we only care about one reg of response,
+ * but the sampler always writes 4/8
+ */
+ inst->sampler = sampler;
+
+ return dest;
+}
+
+void
+fs_visitor::visit(ir_texture *ir)
+{
+ fs_inst *inst = NULL;
+
+ int sampler =
+ _mesa_get_sampler_uniform_value(ir->sampler, shader_prog, prog);
+ /* FINISHME: We're failing to recompile our programs when the sampler is
+ * updated. This only matters for the texture rectangle scale parameters
+ * (pre-gen6, or gen6+ with GL_CLAMP).
+ */
+ int texunit = prog->SamplerUnits[sampler];
+
+ if (ir->op == ir_tg4) {
+ /* When tg4 is used with the degenerate ZERO/ONE swizzles, don't bother
+ * emitting anything other than setting up the constant result.
+ */
+ ir_constant *chan = ir->lod_info.component->as_constant();
+ int swiz = GET_SWZ(key->tex.swizzles[sampler], chan->value.i[0]);
+ if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) {
+
+ fs_reg res = fs_reg(this, glsl_type::vec4_type);
+ this->result = res;
+
+ for (int i=0; i<4; i++) {
+ emit(MOV(res, fs_reg(swiz == SWIZZLE_ZERO ? 0.0f : 1.0f)));
+ res.reg_offset++;
+ }
+ return;
+ }
+ }
+
+ /* Should be lowered by do_lower_texture_projection */
+ assert(!ir->projector);
+
+ /* Should be lowered */
+ assert(!ir->offset || !ir->offset->type->is_array());
+
+ /* Generate code to compute all the subexpression trees. This has to be
+ * done before loading any values into MRFs for the sampler message since
+ * generating these values may involve SEND messages that need the MRFs.
+ */
+ fs_reg coordinate;
+ if (ir->coordinate) {
+ ir->coordinate->accept(this);
+
+ coordinate = rescale_texcoord(ir, this->result,
+ ir->sampler->type->sampler_dimensionality ==
+ GLSL_SAMPLER_DIM_RECT,
+ sampler, texunit);
+ }
+
+ fs_reg shadow_comparitor;
+ if (ir->shadow_comparitor) {
+ ir->shadow_comparitor->accept(this);
+ shadow_comparitor = this->result;
+ }
+
+ fs_reg lod, lod2, sample_index, mcs;
+ switch (ir->op) {
+ case ir_tex:
+ case ir_lod:
+ case ir_tg4:
+ case ir_query_levels:
+ break;
+ case ir_txb:
+ ir->lod_info.bias->accept(this);
+ lod = this->result;
+ break;
+ case ir_txd:
+ ir->lod_info.grad.dPdx->accept(this);
+ lod = this->result;
+
+ ir->lod_info.grad.dPdy->accept(this);
+ lod2 = this->result;
+ break;
+ case ir_txf:
+ case ir_txl:
+ case ir_txs:
+ ir->lod_info.lod->accept(this);
+ lod = this->result;
+ break;
+ case ir_txf_ms:
+ ir->lod_info.sample_index->accept(this);
+ sample_index = this->result;
+
+ if (brw->gen >= 7 && key->tex.compressed_multisample_layout_mask & (1<<sampler))
+ mcs = emit_mcs_fetch(ir, coordinate, sampler);
+ else
+ mcs = fs_reg(0u);
+ break;
+ default:
+ assert(!"Unrecognized texture opcode");
+ };