/** * Compute the offset of a pixel block. * * x, y, z, y_stride, z_stride are vectors, and they refer to pixels. * * Returns the relative offset and i,j sub-block coordinates */ void lp_build_sample_offset(struct lp_build_context *bld, const struct util_format_description *format_desc, LLVMValueRef x, LLVMValueRef y, LLVMValueRef z, LLVMValueRef y_stride, LLVMValueRef z_stride, LLVMValueRef *out_offset, LLVMValueRef *out_i, LLVMValueRef *out_j) { LLVMValueRef x_stride; LLVMValueRef offset; x_stride = lp_build_const_vec(bld->gallivm, bld->type, format_desc->block.bits/8); lp_build_sample_partial_offset(bld, format_desc->block.width, x, x_stride, &offset, out_i); if (y && y_stride) { LLVMValueRef y_offset; lp_build_sample_partial_offset(bld, format_desc->block.height, y, y_stride, &y_offset, out_j); offset = lp_build_add(bld, offset, y_offset); } else { *out_j = bld->zero; } if (z && z_stride) { LLVMValueRef z_offset; LLVMValueRef k; lp_build_sample_partial_offset(bld, 1, /* pixel blocks are always 2D */ z, z_stride, &z_offset, &k); offset = lp_build_add(bld, offset, z_offset); } *out_offset = offset; }
/** * Build LLVM code for texture coord wrapping, for nearest filtering, * for scaled integer texcoords. * \param block_length is the length of the pixel block along the * coordinate axis * \param coord the incoming texcoord (s,t,r or q) scaled to the texture size * \param length the texture size along one dimension * \param stride pixel stride along the coordinate axis (in bytes) * \param is_pot if TRUE, length is a power of two * \param wrap_mode one of PIPE_TEX_WRAP_x * \param out_offset byte offset for the wrapped coordinate * \param out_i resulting sub-block pixel coordinate for coord0 */ static void lp_build_sample_wrap_nearest_int(struct lp_build_sample_context *bld, unsigned block_length, LLVMValueRef coord, LLVMValueRef length, LLVMValueRef stride, boolean is_pot, unsigned wrap_mode, LLVMValueRef *out_offset, LLVMValueRef *out_i) { struct lp_build_context *int_coord_bld = &bld->int_coord_bld; LLVMBuilderRef builder = bld->gallivm->builder; LLVMValueRef length_minus_one; length_minus_one = lp_build_sub(int_coord_bld, length, int_coord_bld->one); switch(wrap_mode) { case PIPE_TEX_WRAP_REPEAT: if(is_pot) coord = LLVMBuildAnd(builder, coord, length_minus_one, ""); else { /* Add a bias to the texcoord to handle negative coords */ LLVMValueRef bias = lp_build_mul_imm(int_coord_bld, length, 1024); coord = LLVMBuildAdd(builder, coord, bias, ""); coord = LLVMBuildURem(builder, coord, length, ""); } break; case PIPE_TEX_WRAP_CLAMP_TO_EDGE: coord = lp_build_max(int_coord_bld, coord, int_coord_bld->zero); coord = lp_build_min(int_coord_bld, coord, length_minus_one); break; case PIPE_TEX_WRAP_CLAMP: case PIPE_TEX_WRAP_CLAMP_TO_BORDER: case PIPE_TEX_WRAP_MIRROR_REPEAT: case PIPE_TEX_WRAP_MIRROR_CLAMP: case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE: case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER: default: assert(0); } lp_build_sample_partial_offset(int_coord_bld, block_length, coord, stride, out_offset, out_i); }