+ switch (inst->Texture.Texture) {
+ case TGSI_TEXTURE_1D:
+ case TGSI_TEXTURE_BUFFER:
+ num_coords = 1;
+ dims = 1;
+ break;
+ case TGSI_TEXTURE_1D_ARRAY:
+ num_coords = 2;
+ dims = 1;
+ break;
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_RECT:
+ num_coords = 2;
+ dims = 2;
+ break;
+ case TGSI_TEXTURE_2D_ARRAY:
+ num_coords = 3;
+ dims = 2;
+ break;
+ case TGSI_TEXTURE_3D:
+ num_coords = 3;
+ dims = 3;
+ break;
+ default:
+ assert(0);
+ return;
+ }
+
+ /* always have lod except for buffers ? */
+ if (inst->Texture.Texture != TGSI_TEXTURE_BUFFER) {
+ explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 3 );
+ }
+
+ for (i = 0; i < num_coords; i++) {
+ coords[i] = lp_build_emit_fetch( &bld->bld_base, inst, 0, i );
+ }
+ for (i = num_coords; i < 3; i++) {
+ coords[i] = coord_undef;
+ }
+
+ unit = inst->Src[1].Register.Index;
+
+ if (inst->Texture.NumOffsets == 1) {
+ unsigned dim;
+ for (dim = 0; dim < dims; dim++) {
+ offsets[dim] = lp_build_emit_fetch_texoffset(&bld->bld_base, inst, 0, dim );
+ }
+ }
+
+ bld->sampler->emit_fetch_texel(bld->sampler,
+ bld->bld_base.base.gallivm,
+ bld->bld_base.base.type,
+ TRUE,
+ unit, coords,
+ offsets,
+ &derivs,
+ NULL, explicit_lod,
+ texel);
+}
+
+static void
+emit_txq( struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ LLVMValueRef *sizes_out)
+{
+ LLVMValueRef explicit_lod;
+ unsigned num_coords, has_lod;
+ unsigned i;
+
+ switch (inst->Texture.Texture) {
+ case TGSI_TEXTURE_1D:
+ case TGSI_TEXTURE_SHADOW1D:
+ case TGSI_TEXTURE_SHADOW2D:
+ case TGSI_TEXTURE_SHADOWCUBE:
+ num_coords = 1;
+ has_lod = 1;
+ break;
+ case TGSI_TEXTURE_2D:
+ case TGSI_TEXTURE_CUBE:
+ case TGSI_TEXTURE_1D_ARRAY:
+ case TGSI_TEXTURE_SHADOW1D_ARRAY:
+ num_coords = 2;
+ has_lod = 1;
+ break;
+ case TGSI_TEXTURE_3D:
+// case TGSI_TEXTURE_CUBE_ARRAY:
+// case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
+ case TGSI_TEXTURE_2D_ARRAY:
+ case TGSI_TEXTURE_SHADOW2D_ARRAY:
+ num_coords = 3;
+ has_lod = 1;
+ break;
+
+ case TGSI_TEXTURE_BUFFER:
+ num_coords = 1;
+ has_lod = 0;
+ break;
+
+ case TGSI_TEXTURE_RECT:
+ case TGSI_TEXTURE_SHADOWRECT:
+// case TGSI_TEXTURE_2D_MS:
+ num_coords = 2;
+ has_lod = 0;
+ break;
+
+// case TGSI_TEXTURE_2D_MS_ARRAY:
+// num_coords = 3;
+// has_lod = 0;
+// break;
+
+ default:
+ assert(0);
+ return;
+ }
+
+ if (!bld->sampler) {
+ _debug_printf("warning: found texture query instruction but no sampler generator supplied\n");
+ for (i = 0; i < num_coords; i++)
+ sizes_out[i] = bld->bld_base.base.undef;
+ return;
+ }
+
+ if (has_lod)
+ explicit_lod = lp_build_emit_fetch( &bld->bld_base, inst, 0, 2 );
+ else
+ explicit_lod = NULL;
+
+ bld->sampler->emit_size_query(bld->sampler,
+ bld->bld_base.base.gallivm,
+ bld->bld_base.int_bld.type,
+ inst->Src[1].Register.Index,
+ explicit_lod,
+ sizes_out);
+}
+
+static boolean
+near_end_of_shader(struct lp_build_tgsi_soa_context *bld,
+ int pc)
+{
+ int i;
+
+ for (i = 0; i < 5; i++) {
+ unsigned opcode;
+
+ if (pc + i >= bld->bld_base.info->num_instructions)
+ return TRUE;
+
+ opcode = bld->bld_base.instructions[pc + i].Instruction.Opcode;
+
+ if (opcode == TGSI_OPCODE_END)
+ return TRUE;
+
+ if (opcode == TGSI_OPCODE_TEX ||
+ opcode == TGSI_OPCODE_TXP ||
+ opcode == TGSI_OPCODE_TXD ||
+ opcode == TGSI_OPCODE_TXB ||
+ opcode == TGSI_OPCODE_TXL ||
+ opcode == TGSI_OPCODE_TXF ||
+ opcode == TGSI_OPCODE_TXQ ||
+ opcode == TGSI_OPCODE_CAL ||
+ opcode == TGSI_OPCODE_CALLNZ ||
+ opcode == TGSI_OPCODE_IF ||
+ opcode == TGSI_OPCODE_IFC ||
+ opcode == TGSI_OPCODE_BGNLOOP ||
+ opcode == TGSI_OPCODE_SWITCH)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+
+/**
+ * Kill fragment if any of the src register values are negative.
+ */
+static void
+emit_kil(
+ struct lp_build_tgsi_soa_context *bld,
+ const struct tgsi_full_instruction *inst,
+ int pc)
+{
+ LLVMBuilderRef builder = bld->bld_base.base.gallivm->builder;
+ const struct tgsi_full_src_register *reg = &inst->Src[0];
+ LLVMValueRef terms[TGSI_NUM_CHANNELS];
+ LLVMValueRef mask;
+ unsigned chan_index;
+
+ memset(&terms, 0, sizeof terms);
+
+ TGSI_FOR_EACH_CHANNEL( chan_index ) {
+ unsigned swizzle;
+
+ /* Unswizzle channel */
+ swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
+
+ /* Check if the component has not been already tested. */
+ assert(swizzle < TGSI_NUM_CHANNELS);
+ if( !terms[swizzle] )
+ /* TODO: change the comparison operator instead of setting the sign */
+ terms[swizzle] = lp_build_emit_fetch(&bld->bld_base, inst, 0, chan_index );
+ }
+
+ mask = NULL;
+ TGSI_FOR_EACH_CHANNEL( chan_index ) {
+ if(terms[chan_index]) {
+ LLVMValueRef chan_mask;
+
+ /*
+ * If term < 0 then mask = 0 else mask = ~0.