llvmpipe: Pass fragment context to generated function in a single structure.
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index 77263e4..8b4266b 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -36,6 +36,7 @@
 #include "draw/draw_vertex.h"
 
 #include "lp_tex_sample.h"
+#include "lp_jit.h"
 
 
 struct llvmpipe_vbuf_render;
@@ -139,6 +140,8 @@
    struct llvmpipe_tex_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
 
    unsigned no_rast : 1;
+
+   struct lp_jit_context jit_context;
 };
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
index 87e8623..6a89b74 100644
--- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
+++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c
@@ -61,6 +61,8 @@
    else
       size = 0;
 
+   lp->jit_context.constants = lp->mapped_constants[PIPE_SHADER_FRAGMENT];
+
    draw_set_mapped_constant_buffer(lp->draw,
                                    lp->mapped_constants[PIPE_SHADER_VERTEX],
                                    size);
@@ -80,6 +82,8 @@
 
    draw_set_mapped_constant_buffer(lp->draw, NULL, 0);
 
+   lp->jit_context.constants = NULL;
+
    for (i = 0; i < 2; i++) {
       if (lp->constants[i].buffer && lp->constants[i].buffer->size)
          ws->buffer_unmap(ws, lp->constants[i].buffer);
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
index c3ba03a..92d5d43 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.c
+++ b/src/gallium/drivers/llvmpipe/lp_jit.c
@@ -35,10 +35,42 @@
 
 #include <llvm-c/Transforms/Scalar.h>
 
+#include "util/u_memory.h"
 #include "lp_screen.h"
 #include "lp_jit.h"
 
 
+static void
+lp_jit_init_types(struct llvmpipe_screen *screen)
+{
+   /* struct lp_jit_context */
+   {
+      LLVMTypeRef elem_types[2];
+      LLVMTypeRef context_type;
+
+      elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
+      elem_types[1] = LLVMPointerType(LLVMInt8Type(), 0);  /* samplers */
+
+      context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
+
+      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, constants,
+                             screen->target, context_type, 0);
+      LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, samplers,
+                             screen->target, context_type, 1);
+      LP_CHECK_STRUCT_SIZE(struct lp_jit_context,
+                           screen->target, context_type);
+
+      LLVMAddTypeName(screen->module, "context", context_type);
+
+      screen->context_ptr_type = LLVMPointerType(context_type, 0);
+   }
+
+#ifdef DEBUG
+   LLVMDumpModule(screen->module);
+#endif
+}
+
+
 void
 lp_jit_screen_cleanup(struct llvmpipe_screen *screen)
 {
@@ -65,8 +97,10 @@
       abort();
    }
 
+   screen->target = LLVMGetExecutionEngineTargetData(screen->engine);
+
    screen->pass = LLVMCreateFunctionPassManager(screen->provider);
-   LLVMAddTargetData(LLVMGetExecutionEngineTargetData(screen->engine), screen->pass);
+   LLVMAddTargetData(screen->target, screen->pass);
    /* These are the passes currently listed in llvm-c/Transforms/Scalar.h,
     * but there are more on SVN. */
    LLVMAddConstantPropagationPass(screen->pass);
@@ -74,4 +108,6 @@
    LLVMAddPromoteMemoryToRegisterPass(screen->pass);
    LLVMAddGVNPass(screen->pass);
    LLVMAddCFGSimplificationPass(screen->pass);
+
+   lp_jit_init_types(screen);
 }
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 03ab268..fe36b60 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -36,24 +36,52 @@
 #define LP_JIT_H
 
 
-#include <llvm-c/Core.h>
+#include "lp_bld_struct.h"
 
 
 struct tgsi_sampler;
 struct llvmpipe_screen;
 
 
+/**
+ * This structure is passed directly to the generated fragment shader.
+ *
+ * It contains the derived state.
+ *
+ * Changes here must be reflected in the lp_jit_context_* macros and
+ * lp_jit_init_types function. Changes to the ordering should be avoided.
+ *
+ * Only use types with a clear size and padding here, in particular prefer the
+ * stdint.h types to the basic integer types.
+ */
+struct lp_jit_context
+{
+   const float *constants;
+
+   struct tgsi_sampler **samplers;
+
+   /* TODO: alpha reference value */
+   /* TODO: blend constant color */
+};
+
+
+#define lp_jit_context_constants(_builder, _ptr) \
+   lp_build_struct_get(_builder, _ptr, 0, "context.constants")
+
+#define lp_jit_context_samplers(_builder, _ptr) \
+   lp_build_struct_get(_builder, _ptr, 1, "context.samplers")
+
+
 typedef void
-(*lp_jit_frag_func)(uint32_t x,
+(*lp_jit_frag_func)(struct lp_jit_context *context,
+                    uint32_t x,
                     uint32_t y,
                     const void *a0,
                     const void *dadx,
                     const void *dady,
-                    const void *consts,
                     uint32_t *mask,
                     void *color,
-                    void *depth,
-                    struct tgsi_sampler **samplers);
+                    void *depth);
 
 
 void
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.h b/src/gallium/drivers/llvmpipe/lp_screen.h
index c3ff153..98d2789 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.h
+++ b/src/gallium/drivers/llvmpipe/lp_screen.h
@@ -1,5 +1,6 @@
 /**************************************************************************
  * 
+ * Copyright 2009 VMware, Inc.
  * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
  *
@@ -25,7 +26,9 @@
  * 
  **************************************************************************/
 
-/* Authors:  Keith Whitwell <keith@tungstengraphics.com>
+/**
+ * @author Jose Fonseca <jfonseca@vmware.com>
+ * @author Keith Whitwell <keith@tungstengraphics.com>
  */
 
 #ifndef LP_SCREEN_H
@@ -33,6 +36,7 @@
 
 #include <llvm-c/Core.h>
 #include <llvm-c/Analysis.h>
+#include <llvm-c/Target.h>
 #include <llvm-c/ExecutionEngine.h>
 
 #include "pipe/p_screen.h"
@@ -46,8 +50,11 @@
    LLVMModuleRef module;
    LLVMExecutionEngineRef engine;
    LLVMModuleProviderRef provider;
+   LLVMTargetDataRef target;
    LLVMPassManagerRef pass;
 
+   LLVMTypeRef context_ptr_type;
+
    /* Increments whenever textures are modified.  Contexts can track
     * this.
     */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 421cccd..34bcb99 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -120,8 +120,6 @@
             unsigned nr)
 {
    struct lp_fragment_shader *fs = llvmpipe->fs;
-   void *constants;
-   struct tgsi_sampler **samplers;
    struct quad_header *quad = quads[0];
    const unsigned x = quad->input.x0;
    const unsigned y = quad->input.y0;
@@ -164,8 +162,6 @@
    else
       depth = NULL;
 
-   constants = llvmpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
-   samplers = (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list;
    /* TODO: blend color */
 
    assert((((uintptr_t)mask) & 0xf) == 0);
@@ -174,16 +170,14 @@
    assert((((uintptr_t)llvmpipe->blend_color) & 0xf) == 0);
 
    /* run shader */
-   fs->current->jit_function( x,
-                              y,
+   fs->current->jit_function( &llvmpipe->jit_context,
+                              x, y,
                               quad->coef->a0,
                               quad->coef->dadx,
                               quad->coef->dady,
-                              constants,
                               &mask[0][0],
                               color,
-                              depth,
-                              samplers);
+                              depth);
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 5f800eb..6fbb057 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -216,6 +216,8 @@
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
       lp_tex_tile_cache_validate_texture( llvmpipe->tex_cache[i] );
    }
+
+   llvmpipe->jit_context.samplers = (struct tgsi_sampler **)llvmpipe->tgsi.frag_samplers_list;
 }
 
 /* Hopefully this will remain quite simple, otherwise need to pull in
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index f77b488..15dbfe8 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -378,8 +378,9 @@
    LLVMTypeRef fs_int_vec_type;
    LLVMTypeRef blend_vec_type;
    LLVMTypeRef blend_int_vec_type;
-   LLVMTypeRef arg_types[10];
+   LLVMTypeRef arg_types[9];
    LLVMTypeRef func_type;
+   LLVMValueRef context_ptr;
    LLVMValueRef x;
    LLVMValueRef y;
    LLVMValueRef a0_ptr;
@@ -463,16 +464,15 @@
    blend_vec_type = lp_build_vec_type(blend_type);
    blend_int_vec_type = lp_build_int_vec_type(blend_type);
 
-   arg_types[0] = LLVMInt32Type();                     /* x */
-   arg_types[1] = LLVMInt32Type();                     /* y */
-   arg_types[2] = LLVMPointerType(fs_elem_type, 0);    /* a0 */
-   arg_types[3] = LLVMPointerType(fs_elem_type, 0);    /* dadx */
-   arg_types[4] = LLVMPointerType(fs_elem_type, 0);    /* dady */
-   arg_types[5] = LLVMPointerType(fs_elem_type, 0);    /* consts */
+   arg_types[0] = screen->context_ptr_type;            /* context */
+   arg_types[1] = LLVMInt32Type();                     /* x */
+   arg_types[2] = LLVMInt32Type();                     /* y */
+   arg_types[3] = LLVMPointerType(fs_elem_type, 0);    /* a0 */
+   arg_types[4] = LLVMPointerType(fs_elem_type, 0);    /* dadx */
+   arg_types[5] = LLVMPointerType(fs_elem_type, 0);    /* dady */
    arg_types[6] = LLVMPointerType(fs_int_vec_type, 0); /* mask */
    arg_types[7] = LLVMPointerType(blend_vec_type, 0);  /* color */
    arg_types[8] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
-   arg_types[9] = LLVMPointerType(LLVMInt8Type(), 0);  /* samplers */
 
    func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
 
@@ -482,27 +482,25 @@
       if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
          LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute);
 
-   x            = LLVMGetParam(variant->function, 0);
-   y            = LLVMGetParam(variant->function, 1);
-   a0_ptr       = LLVMGetParam(variant->function, 2);
-   dadx_ptr     = LLVMGetParam(variant->function, 3);
-   dady_ptr     = LLVMGetParam(variant->function, 4);
-   consts_ptr   = LLVMGetParam(variant->function, 5);
+   context_ptr  = LLVMGetParam(variant->function, 0);
+   x            = LLVMGetParam(variant->function, 1);
+   y            = LLVMGetParam(variant->function, 2);
+   a0_ptr       = LLVMGetParam(variant->function, 3);
+   dadx_ptr     = LLVMGetParam(variant->function, 4);
+   dady_ptr     = LLVMGetParam(variant->function, 5);
    mask_ptr     = LLVMGetParam(variant->function, 6);
    color_ptr    = LLVMGetParam(variant->function, 7);
    depth_ptr    = LLVMGetParam(variant->function, 8);
-   samplers_ptr = LLVMGetParam(variant->function, 9);
 
+   lp_build_name(context_ptr, "context");
    lp_build_name(x, "x");
    lp_build_name(y, "y");
    lp_build_name(a0_ptr, "a0");
    lp_build_name(dadx_ptr, "dadx");
    lp_build_name(dady_ptr, "dady");
-   lp_build_name(consts_ptr, "consts");
    lp_build_name(mask_ptr, "mask");
    lp_build_name(color_ptr, "color");
    lp_build_name(depth_ptr, "depth");
-   lp_build_name(samplers_ptr, "samplers");
 
    /*
     * Function body
@@ -512,6 +510,9 @@
    builder = LLVMCreateBuilder();
    LLVMPositionBuilderAtEnd(builder, block);
 
+   consts_ptr = lp_jit_context_constants(builder, context_ptr);
+   samplers_ptr = lp_jit_context_samplers(builder, context_ptr);
+
    for(i = 0; i < num_fs; ++i) {
       LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
       LLVMValueRef out_color[NUM_CHANNELS];