summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/llvmpipe
diff options
context:
space:
mode:
authorKeith Whitwell <keithw@vmware.com>2010-11-22 10:36:01 +0000
committerKeith Whitwell <keithw@vmware.com>2010-11-22 10:36:01 +0000
commitb2ddb93ff3b8c88682634ccdef247967e31fab84 (patch)
tree495da09bbeddd9fdb51e4301c113bcf4ae94c8e4 /src/gallium/drivers/llvmpipe
parentd5aadf0d80e8c973ef5cf9d82e97f23f0e3c032b (diff)
parent546c5ffa11d70631348e5776df7a4168f07600f6 (diff)
Merge branch 'lp-offset-twoside'
Diffstat (limited to 'src/gallium/drivers/llvmpipe')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h9
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c24
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_rasterizer.c99
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_setup.c229
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_setup.h13
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_surface.c1
6 files changed, 306 insertions, 69 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h
index db09c95b27..a35e09e8b4 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_context.h
@@ -104,9 +104,18 @@ struct llvmpipe_context {
/** Vertex format */
struct vertex_info vertex_info;
+ /** Which vertex shader output slot contains color */
+ int color_slot[2];
+
+ /** Which vertex shader output slot contains bcolor */
+ int bcolor_slot[2];
+
/** Which vertex shader output slot contains point size */
int psize_slot;
+ /**< minimum resolvable depth value, for polygon offset */
+ double mrd;
+
/** The tiling engine */
struct lp_setup_context *setup;
struct lp_setup_variant setup_variant;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 0f5f7369e0..8725ea39fe 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -53,6 +53,11 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
unsigned vs_index;
uint i;
+ llvmpipe->color_slot[0] = ~0;
+ llvmpipe->color_slot[1] = ~0;
+ llvmpipe->bcolor_slot[0] = ~0;
+ llvmpipe->bcolor_slot[1] = ~0;
+
/*
* Match FS inputs against VS outputs, emitting the necessary
* attributes. Could cache these structs and look them up with a
@@ -76,12 +81,31 @@ compute_vertex_info(struct llvmpipe_context *llvmpipe)
lpfs->info.base.input_semantic_name[i],
lpfs->info.base.input_semantic_index[i]);
+ if (lpfs->info.base.input_semantic_name[i] == TGSI_SEMANTIC_COLOR &&
+ lpfs->info.base.input_semantic_index[i] < 2) {
+ int idx = lpfs->info.base.input_semantic_index[i];
+ llvmpipe->color_slot[idx] = vinfo->num_attribs;
+ }
+
/*
* Emit the requested fs attribute for all but position.
*/
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
}
+ /* Figure out if we need bcolor as well.
+ */
+ for (i = 0; i < 2; i++) {
+ vs_index = draw_find_shader_output(llvmpipe->draw,
+ TGSI_SEMANTIC_BCOLOR, i);
+
+ if (vs_index > 0) {
+ llvmpipe->bcolor_slot[i] = vinfo->num_attribs;
+ draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, vs_index);
+ }
+ }
+
+
/* Figure out if we need pointsize as well.
*/
vs_index = draw_find_shader_output(llvmpipe->draw,
diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
index dbd73812e4..574f9e940e 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c
@@ -32,16 +32,64 @@
#include "lp_setup.h"
#include "draw/draw_context.h"
+struct lp_rast_state {
+ struct pipe_rasterizer_state lp_state;
+ struct pipe_rasterizer_state draw_state;
+};
+
+/* State which might be handled in either the draw module or locally.
+ * This function is used to turn that state off in one of the two
+ * places.
+ */
+static void
+clear_flags(struct pipe_rasterizer_state *rast)
+{
+ rast->light_twoside = 0;
+ rast->offset_tri = 0;
+}
+
static void *
llvmpipe_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *rast)
{
- /* We do nothing special with rasterizer state.
- * The CSO handle is just a pointer to a pipe_rasterizer_state object.
+ boolean need_pipeline;
+
+ /* Partition rasterizer state into what we want the draw module to
+ * handle, and what we'll look after ourselves.
+ */
+ struct lp_rast_state *state = MALLOC_STRUCT(lp_rast_state);
+ if (state == NULL)
+ return NULL;
+
+ memcpy(&state->draw_state, rast, sizeof *rast);
+ memcpy(&state->lp_state, rast, sizeof *rast);
+
+ /* We rely on draw module to do unfilled polyons, AA lines and
+ * points and stipple.
+ *
+ * Over time, reduce this list of conditions, and expand the list
+ * of flags which get cleared in clear_flags().
*/
- return mem_dup(rast, sizeof(*rast));
+ need_pipeline = (rast->fill_front != PIPE_POLYGON_MODE_FILL ||
+ rast->fill_back != PIPE_POLYGON_MODE_FILL ||
+ rast->point_smooth ||
+ rast->line_smooth ||
+ rast->line_stipple_enable ||
+ rast->poly_stipple_enable);
+
+ /* If not using the pipeline, clear out the flags which we can
+ * handle ourselves. If we *are* using the pipeline, do everything
+ * on the pipeline and clear those flags on our internal copy of
+ * the state.
+ */
+ if (need_pipeline)
+ clear_flags(&state->lp_state);
+ else
+ clear_flags(&state->draw_state);
+
+ return state;
}
@@ -50,36 +98,33 @@ static void
llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
- const struct pipe_rasterizer_state *rasterizer =
- (const struct pipe_rasterizer_state *) handle;
-
- if (llvmpipe->rasterizer == rasterizer)
- return;
+ const struct lp_rast_state *state =
+ (const struct lp_rast_state *) handle;
- /* pass-through to draw module */
- draw_set_rasterizer_state(llvmpipe->draw, rasterizer, handle);
+ if (state) {
+ llvmpipe->rasterizer = &state->lp_state;
+ draw_set_rasterizer_state(llvmpipe->draw, &state->draw_state, handle);
- llvmpipe->rasterizer = rasterizer;
-
- /* Note: we can immediately set the triangle state here and
- * not worry about binning because we handle culling during
- * triangle setup, not when rasterizing the bins.
- */
- if (llvmpipe->rasterizer) {
+ /* XXX: just pass lp_state directly to setup.
+ */
lp_setup_set_triangle_state( llvmpipe->setup,
- llvmpipe->rasterizer->cull_face,
- llvmpipe->rasterizer->front_ccw,
- llvmpipe->rasterizer->scissor,
- llvmpipe->rasterizer->gl_rasterization_rules);
+ state->lp_state.cull_face,
+ state->lp_state.front_ccw,
+ state->lp_state.scissor,
+ state->lp_state.gl_rasterization_rules);
lp_setup_set_flatshade_first( llvmpipe->setup,
- llvmpipe->rasterizer->flatshade_first);
+ state->lp_state.flatshade_first);
lp_setup_set_line_state( llvmpipe->setup,
- llvmpipe->rasterizer->line_width);
+ state->lp_state.line_width);
lp_setup_set_point_state( llvmpipe->setup,
- llvmpipe->rasterizer->point_size,
- llvmpipe->rasterizer->point_size_per_vertex,
- llvmpipe->rasterizer->sprite_coord_enable,
- llvmpipe->rasterizer->sprite_coord_mode);
+ state->lp_state.point_size,
+ state->lp_state.point_size_per_vertex,
+ state->lp_state.sprite_coord_enable,
+ state->lp_state.sprite_coord_mode);
+ }
+ else {
+ llvmpipe->rasterizer = NULL;
+ draw_set_rasterizer_state(llvmpipe->draw, NULL, handle);
}
llvmpipe->dirty |= LP_NEW_RASTERIZER;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c
index 2c8b8b9a92..194b014436 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c
@@ -30,9 +30,12 @@
#include "util/u_memory.h"
#include "util/u_simple_list.h"
#include "os/os_time.h"
+#include "gallivm/lp_bld_arit.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_intr.h"
+#include "gallivm/lp_bld_flow.h"
+#include "gallivm/lp_bld_type.h"
#include <llvm-c/Analysis.h> /* for LLVMVerifyFunction */
#include "lp_perf.h"
@@ -74,6 +77,12 @@ struct lp_setup_args
LLVMValueRef dy01_ooa;
LLVMValueRef dx20_ooa;
LLVMValueRef dx01_ooa;
+
+ /* Temporary, per-attribute:
+ */
+ LLVMValueRef v0a;
+ LLVMValueRef v1a;
+ LLVMValueRef v2a;
};
static LLVMTypeRef type4f(void)
@@ -149,16 +158,11 @@ static void
emit_constant_coef4( LLVMBuilderRef builder,
struct lp_setup_args *args,
unsigned slot,
- LLVMValueRef vert,
- unsigned attr)
+ LLVMValueRef vert)
{
LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
LLVMValueRef zerovec = vec4f_from_scalar(builder, zero, "zero");
- LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), attr, 0);
- LLVMValueRef attr_ptr = LLVMBuildGEP(builder, vert, &idx, 1, "attr_ptr");
- LLVMValueRef vert_attr = LLVMBuildLoad(builder, attr_ptr, "vert_attr");
-
- store_coef(builder, args, slot, vert_attr, zerovec, zerovec);
+ store_coef(builder, args, slot, vert, zerovec, zerovec);
}
@@ -195,7 +199,150 @@ vert_attrib(LLVMBuilderRef b,
return LLVMBuildLoad(b, LLVMBuildGEP(b, vert, idx, 2, ""), name);
}
+static LLVMValueRef
+vert_clamp(LLVMBuilderRef b,
+ LLVMValueRef x,
+ LLVMValueRef min,
+ LLVMValueRef max)
+{
+ LLVMValueRef min_result = LLVMBuildFCmp(b, LLVMRealUGT, min, x, "");
+ LLVMValueRef max_result = LLVMBuildFCmp(b, LLVMRealUGT, x, max, "");
+ LLVMValueRef clamp_value;
+
+ clamp_value = LLVMBuildSelect(b, min_result, min, x, "");
+ clamp_value = LLVMBuildSelect(b, max_result, max, x, "");
+
+ return clamp_value;
+}
+
+static void
+lp_twoside(LLVMBuilderRef b,
+ struct lp_setup_args *args,
+ const struct lp_setup_variant_key *key,
+ int bcolor_slot)
+{
+ LLVMValueRef a0_back, a1_back, a2_back;
+ LLVMValueRef idx2 = LLVMConstInt(LLVMInt32Type(), bcolor_slot, 0);
+
+ LLVMValueRef facing = args->facing;
+ LLVMValueRef front_facing = LLVMBuildICmp(b, LLVMIntEQ, facing, LLVMConstInt(LLVMInt32Type(), 0, 0), ""); /** need i1 for if condition */
+
+ a0_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx2, 1, ""), "v0a_back");
+ a1_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx2, 1, ""), "v1a_back");
+ a2_back = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx2, 1, ""), "v2a_back");
+
+ /* Possibly swap the front and back attrib values,
+ *
+ * Prefer select to if so we don't have to worry about phis or
+ * allocas.
+ */
+ args->v0a = LLVMBuildSelect(b, front_facing, a0_back, args->v0a, "");
+ args->v1a = LLVMBuildSelect(b, front_facing, a1_back, args->v1a, "");
+ args->v2a = LLVMBuildSelect(b, front_facing, a2_back, args->v2a, "");
+
+}
+static void
+lp_do_offset_tri(LLVMBuilderRef b,
+ struct lp_setup_args *args,
+ const struct lp_setup_variant_key *key)
+{
+ struct lp_build_context bld;
+ LLVMValueRef zoffset, mult;
+ LLVMValueRef z0_new, z1_new, z2_new;
+ LLVMValueRef dzdx0, dzdx, dzdy0, dzdy;
+ LLVMValueRef max, max_value;
+
+ LLVMValueRef one = LLVMConstReal(LLVMFloatType(), 1.0);
+ LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0);
+
+ /* edge vectors: e = v0 - v2, f = v1 - v2 */
+ LLVMValueRef v0_x = vert_attrib(b, args->v0, 0, 0, "v0_x");
+ LLVMValueRef v1_x = vert_attrib(b, args->v1, 0, 0, "v1_x");
+ LLVMValueRef v2_x = vert_attrib(b, args->v2, 0, 0, "v2_x");
+ LLVMValueRef v0_y = vert_attrib(b, args->v0, 0, 1, "v0_y");
+ LLVMValueRef v1_y = vert_attrib(b, args->v1, 0, 1, "v1_y");
+ LLVMValueRef v2_y = vert_attrib(b, args->v2, 0, 1, "v2_y");
+ LLVMValueRef v0_z = vert_attrib(b, args->v0, 0, 2, "v0_z");
+ LLVMValueRef v1_z = vert_attrib(b, args->v1, 0, 2, "v1_z");
+ LLVMValueRef v2_z = vert_attrib(b, args->v2, 0, 2, "v2_z");
+
+ /* edge vectors: e = v0 - v2, f = v1 - v2 */
+ LLVMValueRef dx02 = LLVMBuildFSub(b, v0_x, v2_x, "dx02");
+ LLVMValueRef dy02 = LLVMBuildFSub(b, v0_y, v2_y, "dy02");
+ LLVMValueRef dz02 = LLVMBuildFSub(b, v0_z, v2_z, "dz02");
+ LLVMValueRef dx12 = LLVMBuildFSub(b, v1_x, v2_x, "dx12");
+ LLVMValueRef dy12 = LLVMBuildFSub(b, v1_y, v2_y, "dy12");
+ LLVMValueRef dz12 = LLVMBuildFSub(b, v1_z, v2_z, "dz12");
+
+ /* det = cross(e,f).z */
+ LLVMValueRef dx02_dy12 = LLVMBuildFMul(b, dx02, dy12, "dx02_dy12");
+ LLVMValueRef dy02_dx12 = LLVMBuildFMul(b, dy02, dx12, "dy02_dx12");
+ LLVMValueRef det = LLVMBuildFSub(b, dx02_dy12, dy02_dx12, "det");
+ LLVMValueRef inv_det = LLVMBuildFDiv(b, one, det, "inv_det");
+
+ /* (res1,res2) = cross(e,f).xy */
+ LLVMValueRef dy02_dz12 = LLVMBuildFMul(b, dy02, dz12, "dy02_dz12");
+ LLVMValueRef dz02_dy12 = LLVMBuildFMul(b, dz02, dy12, "dz02_dy12");
+ LLVMValueRef dz02_dx12 = LLVMBuildFMul(b, dz02, dx12, "dz02_dx12");
+ LLVMValueRef dx02_dz12 = LLVMBuildFMul(b, dx02, dz12, "dx02_dz12");
+ LLVMValueRef res1 = LLVMBuildFSub(b, dy02_dz12, dz02_dy12, "res1");
+ LLVMValueRef res2 = LLVMBuildFSub(b, dz02_dx12, dx02_dz12, "res2");
+
+ /* dzdx = fabsf(res1 * inv_det), dydx = fabsf(res2 * inv_det)*/
+ lp_build_context_init(&bld, b, lp_type_float(32));
+ dzdx0 = LLVMBuildFMul(b, res1, inv_det, "dzdx");
+ dzdx = lp_build_abs(&bld, dzdx0);
+ dzdy0 = LLVMBuildFMul(b, res2, inv_det, "dzdy");
+ dzdy = lp_build_abs(&bld, dzdy0);
+
+ /* zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale */
+ max = LLVMBuildFCmp(b, LLVMRealUGT, dzdx, dzdy, "");
+ max_value = LLVMBuildSelect(b, max, dzdx, dzdy, "max");
+
+ mult = LLVMBuildFMul(b, max_value, LLVMConstReal(LLVMFloatType(), key->scale), "");
+ zoffset = LLVMBuildFAdd(b, LLVMConstReal(LLVMFloatType(), key->units), mult, "zoffset");
+
+ /* clamp and do offset */
+ z0_new = vert_clamp(b, LLVMBuildFAdd(b, v0_z, zoffset, ""), zero, one);
+ z1_new = vert_clamp(b, LLVMBuildFAdd(b, v1_z, zoffset, ""), zero, one);
+ z2_new = vert_clamp(b, LLVMBuildFAdd(b, v2_z, zoffset, ""), zero, one);
+
+ /* insert into args->a0.z, a1.z, a2.z:
+ */
+ args->v0a = LLVMBuildInsertElement(b, args->v0a, z0_new, LLVMConstInt(LLVMInt32Type(), 2, 0), "");
+ args->v1a = LLVMBuildInsertElement(b, args->v1a, z1_new, LLVMConstInt(LLVMInt32Type(), 2, 0), "");
+ args->v2a = LLVMBuildInsertElement(b, args->v2a, z2_new, LLVMConstInt(LLVMInt32Type(), 2, 0), "");
+}
+
+static void
+load_attribute(LLVMBuilderRef b,
+ struct lp_setup_args *args,
+ const struct lp_setup_variant_key *key,
+ unsigned vert_attr)
+{
+ LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), vert_attr, 0);
+
+ /* Load the vertex data
+ */
+ args->v0a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a");
+ args->v1a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a");
+ args->v2a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a");
+
+
+ /* Potentially modify it according to twoside, offset, etc:
+ */
+ if (vert_attr == 0 && (key->scale != 0.0f || key->units != 0.0f)) {
+ lp_do_offset_tri(b, args, key);
+ }
+
+ if (key->twoside) {
+ if (vert_attr == key->color_slot && key->bcolor_slot != ~0)
+ lp_twoside(b, args, key, key->bcolor_slot);
+ else if (vert_attr == key->spec_slot && key->bspec_slot != ~0)
+ lp_twoside(b, args, key, key->bspec_slot);
+ }
+}
static void
emit_coef4( LLVMBuilderRef b,
@@ -243,20 +390,17 @@ emit_coef4( LLVMBuilderRef b,
static void
emit_linear_coef( LLVMBuilderRef b,
struct lp_setup_args *args,
- unsigned slot,
- unsigned vert_attr)
+ unsigned slot)
{
- LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), vert_attr, 0);
-
- LLVMValueRef a0 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a");
- LLVMValueRef a1 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a");
- LLVMValueRef a2 = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a");
-
- emit_coef4(b, args, slot, a0, a1, a2);
+ /* nothing to do anymore */
+ emit_coef4(b,
+ args, slot,
+ args->v0a,
+ args->v1a,
+ args->v2a);
}
-
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a triangle.
@@ -268,24 +412,17 @@ emit_linear_coef( LLVMBuilderRef b,
static void
emit_perspective_coef( LLVMBuilderRef b,
struct lp_setup_args *args,
- unsigned slot,
- unsigned vert_attr)
+ unsigned slot)
{
/* premultiply by 1/w (v[0][3] is always 1/w):
*/
- LLVMValueRef idx = LLVMConstInt(LLVMInt32Type(), vert_attr, 0);
-
- LLVMValueRef v0a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v0, &idx, 1, ""), "v0a");
- LLVMValueRef v1a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v1, &idx, 1, ""), "v1a");
- LLVMValueRef v2a = LLVMBuildLoad(b, LLVMBuildGEP(b, args->v2, &idx, 1, ""), "v2a");
-
LLVMValueRef v0_oow = vec4f_from_scalar(b, vert_attrib(b, args->v0, 0, 3, ""), "v0_oow");
LLVMValueRef v1_oow = vec4f_from_scalar(b, vert_attrib(b, args->v1, 0, 3, ""), "v1_oow");
LLVMValueRef v2_oow = vec4f_from_scalar(b, vert_attrib(b, args->v2, 0, 3, ""), "v2_oow");
- LLVMValueRef v0_oow_v0a = LLVMBuildFMul(b, v0a, v0_oow, "v0_oow_v0a");
- LLVMValueRef v1_oow_v1a = LLVMBuildFMul(b, v1a, v1_oow, "v1_oow_v1a");
- LLVMValueRef v2_oow_v2a = LLVMBuildFMul(b, v2a, v2_oow, "v2_oow_v2a");
+ LLVMValueRef v0_oow_v0a = LLVMBuildFMul(b, args->v0a, v0_oow, "v0_oow_v0a");
+ LLVMValueRef v1_oow_v1a = LLVMBuildFMul(b, args->v1a, v1_oow, "v1_oow_v1a");
+ LLVMValueRef v2_oow_v2a = LLVMBuildFMul(b, args->v2a, v2_oow, "v2_oow_v2a");
emit_coef4(b, args, slot, v0_oow_v0a, v1_oow_v1a, v2_oow_v2a);
}
@@ -294,9 +431,9 @@ emit_perspective_coef( LLVMBuilderRef b,
static void
emit_position_coef( LLVMBuilderRef builder,
struct lp_setup_args *args,
- int slot, int attrib )
+ int slot )
{
- emit_linear_coef(builder, args, slot, attrib);
+ emit_linear_coef(builder, args, slot);
}
@@ -314,29 +451,34 @@ emit_tri_coef( LLVMBuilderRef builder,
/* The internal position input is in slot zero:
*/
- emit_position_coef(builder, args, 0, 0);
+ load_attribute(builder, args, key, 0);
+ emit_position_coef(builder, args, 0);
/* setup interpolation for all the remaining attributes:
*/
for (slot = 0; slot < key->num_inputs; slot++) {
- unsigned vert_attr = key->inputs[slot].src_index;
+
+ if (key->inputs[slot].interp == LP_INTERP_CONSTANT ||
+ key->inputs[slot].interp == LP_INTERP_LINEAR ||
+ key->inputs[slot].interp == LP_INTERP_PERSPECTIVE)
+ load_attribute(builder, args, key, key->inputs[slot].src_index);
switch (key->inputs[slot].interp) {
case LP_INTERP_CONSTANT:
if (key->flatshade_first) {
- emit_constant_coef4(builder, args, slot+1, args->v0, vert_attr);
+ emit_constant_coef4(builder, args, slot+1, args->v0a);
}
else {
- emit_constant_coef4(builder, args, slot+1, args->v2, vert_attr);
+ emit_constant_coef4(builder, args, slot+1, args->v2a);
}
break;
case LP_INTERP_LINEAR:
- emit_linear_coef(builder, args, slot+1, vert_attr);
+ emit_linear_coef(builder, args, slot+1);
break;
case LP_INTERP_PERSPECTIVE:
- emit_perspective_coef(builder, args, slot+1, vert_attr);
+ emit_perspective_coef(builder, args, slot+1);
break;
case LP_INTERP_POSITION:
@@ -478,7 +620,8 @@ init_args(LLVMBuilderRef b,
*/
static struct lp_setup_variant *
generate_setup_variant(struct llvmpipe_screen *screen,
- struct lp_setup_variant_key *key)
+ struct lp_setup_variant_key *key,
+ struct llvmpipe_context *lp)
{
struct lp_setup_variant *variant = NULL;
struct lp_setup_args args;
@@ -605,14 +748,20 @@ lp_make_setup_variant_key(struct llvmpipe_context *lp,
key->num_inputs = fs->info.base.num_inputs;
key->flatshade_first = lp->rasterizer->flatshade_first;
key->pixel_center_half = lp->rasterizer->gl_rasterization_rules;
+ key->twoside = lp->rasterizer->light_twoside;
key->size = Offset(struct lp_setup_variant_key,
inputs[key->num_inputs]);
+ key->color_slot = lp->color_slot[0];
+ key->bcolor_slot = lp->bcolor_slot[0];
+ key->spec_slot = lp->color_slot[1];
+ key->bspec_slot = lp->bcolor_slot[1];
+ key->units = (float) (lp->rasterizer->offset_units * lp->mrd);
+ key->scale = lp->rasterizer->offset_scale;
key->pad = 0;
-
memcpy(key->inputs, fs->inputs, key->num_inputs * sizeof key->inputs[0]);
for (i = 0; i < key->num_inputs; i++) {
if (key->inputs[i].interp == LP_INTERP_COLOR) {
- if (lp->rasterizer->flatshade)
+ if (lp->rasterizer->flatshade)
key->inputs[i].interp = LP_INTERP_CONSTANT;
else
key->inputs[i].interp = LP_INTERP_LINEAR;
@@ -702,7 +851,7 @@ llvmpipe_update_setup(struct llvmpipe_context *lp)
cull_setup_variants(lp);
}
- variant = generate_setup_variant(screen, key);
+ variant = generate_setup_variant(screen, key, lp);
insert_at_head(&lp->setup_variants_list, &variant->list_item_global);
lp->nr_setup_variants++;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.h b/src/gallium/drivers/llvmpipe/lp_state_setup.h
index b0c81baa75..90c55ca4ce 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_state_setup.h
@@ -15,11 +15,20 @@ struct lp_setup_variant_list_item
struct lp_setup_variant_key {
+ unsigned size:16;
unsigned num_inputs:8;
+ unsigned color_slot:8;
+
+ unsigned bcolor_slot:8;
+ unsigned spec_slot:8;
+ unsigned bspec_slot:8;
unsigned flatshade_first:1;
unsigned pixel_center_half:1;
- unsigned pad:7;
- unsigned size:16;
+ unsigned twoside:1;
+ unsigned pad:5;
+
+ float units;
+ float scale;
struct lp_shader_input inputs[PIPE_MAX_SHADER_INPUTS];
};
diff --git a/src/gallium/drivers/llvmpipe/lp_state_surface.c b/src/gallium/drivers/llvmpipe/lp_state_surface.c
index cd1a5b1980..375ceb2b94 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_surface.c
@@ -77,6 +77,7 @@ llvmpipe_set_framebuffer_state(struct pipe_context *pipe,
else {
mrd = 0.00002;
}
+ lp->mrd = mrd;
draw_set_mrd(lp->draw, mrd);
}