+/**
+ * Fetch the specified member of the lp_jit_image structure.
+ * \param emit_load if TRUE, emit the LLVM load instruction to actually
+ * fetch the field's value. Otherwise, just emit the
+ * GEP code to address the field.
+ *
+ * @sa http://llvm.org/docs/GetElementPtr.html
+ */
+static LLVMValueRef
+lp_llvm_image_member(const struct lp_sampler_dynamic_state *base,
+ struct gallivm_state *gallivm,
+ LLVMValueRef context_ptr,
+ unsigned image_unit,
+ unsigned member_index,
+ const char *member_name,
+ boolean emit_load)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef indices[4];
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+
+ assert(image_unit < PIPE_MAX_SHADER_IMAGES);
+
+ /* context[0] */
+ indices[0] = lp_build_const_int32(gallivm, 0);
+ /* context[0].images */
+ indices[1] = lp_build_const_int32(gallivm, LP_JIT_CTX_IMAGES);
+ /* context[0].images[unit] */
+ indices[2] = lp_build_const_int32(gallivm, image_unit);
+ /* context[0].images[unit].member */
+ indices[3] = lp_build_const_int32(gallivm, member_index);
+
+ ptr = LLVMBuildGEP(builder, context_ptr, indices, ARRAY_SIZE(indices), "");
+
+ if (emit_load)
+ res = LLVMBuildLoad(builder, ptr, "");
+ else
+ res = ptr;
+
+ lp_build_name(res, "context.image%u.%s", image_unit, member_name);
+
+ return res;
+}
+
+
+/**
+ * Helper macro to instantiate the functions that generate the code to
+ * fetch the members of lp_jit_image to fulfill the sampler code
+ * generator requests.
+ *
+ * This complexity is the price we have to pay to keep the image
+ * sampler code generator a reusable module without dependencies to
+ * llvmpipe internals.
+ */
+#define LP_LLVM_IMAGE_MEMBER(_name, _index, _emit_load) \
+ static LLVMValueRef \
+ lp_llvm_image_##_name( const struct lp_sampler_dynamic_state *base, \
+ struct gallivm_state *gallivm, \
+ LLVMValueRef context_ptr, \
+ unsigned image_unit) \
+ { \
+ return lp_llvm_image_member(base, gallivm, context_ptr, \
+ image_unit, _index, #_name, _emit_load ); \
+ }
+
+
+LP_LLVM_IMAGE_MEMBER(width, LP_JIT_IMAGE_WIDTH, TRUE)
+LP_LLVM_IMAGE_MEMBER(height, LP_JIT_IMAGE_HEIGHT, TRUE)
+LP_LLVM_IMAGE_MEMBER(depth, LP_JIT_IMAGE_DEPTH, TRUE)
+LP_LLVM_IMAGE_MEMBER(base_ptr, LP_JIT_IMAGE_BASE, TRUE)
+LP_LLVM_IMAGE_MEMBER(row_stride, LP_JIT_IMAGE_ROW_STRIDE, TRUE)
+LP_LLVM_IMAGE_MEMBER(img_stride, LP_JIT_IMAGE_IMG_STRIDE, TRUE)
+LP_LLVM_IMAGE_MEMBER(num_samples, LP_JIT_IMAGE_NUM_SAMPLES, TRUE)
+LP_LLVM_IMAGE_MEMBER(sample_stride, LP_JIT_IMAGE_SAMPLE_STRIDE, TRUE)
+
+#if LP_USE_TEXTURE_CACHE
+static LLVMValueRef
+lp_llvm_texture_cache_ptr(const struct lp_sampler_dynamic_state *base,
+ struct gallivm_state *gallivm,
+ LLVMValueRef thread_data_ptr,
+ unsigned unit)
+{
+ /* We use the same cache for all units */
+ (void)unit;
+
+ return lp_jit_thread_data_cache(gallivm, thread_data_ptr);
+}
+#endif
+
+