summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.c48
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h34
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h5
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c67
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.h7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_context.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_line.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_point.c11
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup_tri.c15
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_derived.c12
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c64
13 files changed, 255 insertions, 29 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
index fa0f128ee3f..fa36fd3512e 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.c
+++ b/src/gallium/drivers/llvmpipe/lp_jit.c
@@ -45,7 +45,33 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
{
struct gallivm_state *gallivm = lp->gallivm;
LLVMContextRef lc = gallivm->context;
- LLVMTypeRef texture_type, sampler_type;
+ LLVMTypeRef viewport_type, texture_type, sampler_type;
+
+ /* struct lp_jit_viewport */
+ {
+ LLVMTypeRef elem_types[LP_JIT_VIEWPORT_NUM_FIELDS];
+
+ elem_types[LP_JIT_VIEWPORT_MIN_DEPTH] =
+ elem_types[LP_JIT_VIEWPORT_MAX_DEPTH] = LLVMFloatTypeInContext(lc);
+
+ viewport_type = LLVMStructTypeInContext(lc, elem_types,
+ Elements(elem_types), 0);
+
+#if HAVE_LLVM < 0x0300
+ LLVMAddTypeName(gallivm->module, "viewport", viewport_type);
+
+ LLVMInvalidateStructLayout(gallivm->target, viewport_type);
+#endif
+
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, min_depth,
+ gallivm->target, viewport_type,
+ LP_JIT_VIEWPORT_MIN_DEPTH);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_viewport, max_depth,
+ gallivm->target, viewport_type,
+ LP_JIT_VIEWPORT_MAX_DEPTH);
+ LP_CHECK_STRUCT_SIZE(struct lp_jit_viewport,
+ gallivm->target, viewport_type);
+ }
/* struct lp_jit_texture */
{
@@ -101,8 +127,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
gallivm->target, texture_type);
}
- {
/* struct lp_jit_sampler */
+ {
LLVMTypeRef elem_types[LP_JIT_SAMPLER_NUM_FIELDS];
elem_types[LP_JIT_SAMPLER_MIN_LOD] =
elem_types[LP_JIT_SAMPLER_MAX_LOD] =
@@ -113,22 +139,22 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
sampler_type = LLVMStructTypeInContext(lc, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
- LLVMAddTypeName(gallivm->module, "texture", texture_type);
+ LLVMAddTypeName(gallivm->module, "sampler", sampler_type);
- LLVMInvalidateStructLayout(gallivm->target, texture_type);
+ LLVMInvalidateStructLayout(gallivm->target, sampler_type);
#endif
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, min_lod,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_MIN_LOD);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, max_lod,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_MAX_LOD);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, lod_bias,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_LOD_BIAS);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_sampler, border_color,
- gallivm->target, texture_type,
+ gallivm->target, sampler_type,
LP_JIT_SAMPLER_BORDER_COLOR);
LP_CHECK_STRUCT_SIZE(struct lp_jit_sampler,
gallivm->target, sampler_type);
@@ -146,6 +172,7 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
elem_types[LP_JIT_CTX_STENCIL_REF_BACK] = LLVMInt32TypeInContext(lc);
elem_types[LP_JIT_CTX_U8_BLEND_COLOR] = LLVMPointerType(LLVMInt8TypeInContext(lc), 0);
elem_types[LP_JIT_CTX_F_BLEND_COLOR] = LLVMPointerType(LLVMFloatTypeInContext(lc), 0);
+ elem_types[LP_JIT_CTX_VIEWPORTS] = LLVMPointerType(viewport_type, 0);
elem_types[LP_JIT_CTX_TEXTURES] = LLVMArrayType(texture_type,
PIPE_MAX_SHADER_SAMPLER_VIEWS);
elem_types[LP_JIT_CTX_SAMPLERS] = LLVMArrayType(sampler_type,
@@ -178,6 +205,9 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, f_blend_color,
gallivm->target, context_type,
LP_JIT_CTX_F_BLEND_COLOR);
+ LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, viewports,
+ gallivm->target, context_type,
+ LP_JIT_CTX_VIEWPORTS);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
gallivm->target, context_type,
LP_JIT_CTX_TEXTURES);
@@ -196,6 +226,8 @@ lp_jit_create_types(struct lp_fragment_shader_variant *lp)
LLVMTypeRef thread_data_type;
elem_types[LP_JIT_THREAD_DATA_COUNTER] = LLVMInt64TypeInContext(lc);
+ elem_types[LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX] =
+ LLVMInt32TypeInContext(lc);
thread_data_type = LLVMStructTypeInContext(lc, elem_types,
Elements(elem_types), 0);
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 30cfaaef5d6..8eefa7c8479 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -70,6 +70,13 @@ struct lp_jit_sampler
};
+struct lp_jit_viewport
+{
+ float min_depth;
+ float max_depth;
+};
+
+
enum {
LP_JIT_TEXTURE_WIDTH = 0,
LP_JIT_TEXTURE_HEIGHT,
@@ -93,6 +100,13 @@ enum {
};
+enum {
+ LP_JIT_VIEWPORT_MIN_DEPTH,
+ LP_JIT_VIEWPORT_MAX_DEPTH,
+ LP_JIT_VIEWPORT_NUM_FIELDS /* number of fields above */
+};
+
+
/**
* This structure is passed directly to the generated fragment shader.
*
@@ -115,6 +129,8 @@ struct lp_jit_context
uint8_t *u8_blend_color;
float *f_blend_color;
+ struct lp_jit_viewport *viewports;
+
struct lp_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
struct lp_jit_sampler samplers[PIPE_MAX_SAMPLERS];
};
@@ -131,6 +147,7 @@ enum {
LP_JIT_CTX_STENCIL_REF_BACK,
LP_JIT_CTX_U8_BLEND_COLOR,
LP_JIT_CTX_F_BLEND_COLOR,
+ LP_JIT_CTX_VIEWPORTS,
LP_JIT_CTX_TEXTURES,
LP_JIT_CTX_SAMPLERS,
LP_JIT_CTX_COUNT
@@ -155,6 +172,9 @@ enum {
#define lp_jit_context_f_blend_color(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_F_BLEND_COLOR, "f_blend_color")
+#define lp_jit_context_viewports(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, LP_JIT_CTX_VIEWPORTS, "viewports")
+
#define lp_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_CTX_TEXTURES, "textures")
@@ -165,11 +185,19 @@ enum {
struct lp_jit_thread_data
{
uint64_t vis_counter;
+
+ /*
+ * Non-interpolated rasterizer state passed through to the fragment shader.
+ */
+ struct {
+ uint32_t viewport_index;
+ } raster_state;
};
enum {
LP_JIT_THREAD_DATA_COUNTER = 0,
+ LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX,
LP_JIT_THREAD_DATA_COUNT
};
@@ -177,7 +205,11 @@ enum {
#define lp_jit_thread_data_counter(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, LP_JIT_THREAD_DATA_COUNTER, "counter")
-
+#define lp_jit_thread_data_raster_state_viewport_index(_gallivm, _ptr) \
+ lp_build_struct_get(_gallivm, _ptr, \
+ LP_JIT_THREAD_DATA_RASTER_STATE_VIEWPORT_INDEX, \
+ "raster_state.viewport_index")
+
/**
* typedef for fragment shader function
*
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 0cd62c2d99f..6feec947137 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -367,6 +367,9 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
depth_stride = scene->zsbuf.stride;
}
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
@@ -462,6 +465,9 @@ lp_rast_shade_quads_mask(struct lp_rasterizer_task *task,
/* always count this not worth bothering? */
task->ps_invocations += 1 * variant->ps_inv_multiplier;
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_EDGE_TEST](&state->jit_context,
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index b81d94f50f0..e2a9ec20892 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -102,7 +102,7 @@ struct lp_rast_shader_inputs {
unsigned pad0:29; /* wasted space */
unsigned stride; /* how much to advance data between a0, dadx, dady */
unsigned layer; /* the layer to render to (from gs, already clamped) */
- unsigned pad2; /* wasted space */
+ unsigned viewport_index; /* the active viewport index (from gs, already clamped) */
/* followed by a0, dadx, dady and planes[] */
};
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index 77ec329485d..bc361b6f1b9 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -97,7 +97,7 @@ struct lp_rasterizer_task
/** "my" index */
unsigned thread_index;
- /* occlude counter for visible pixels */
+ /** Non-interpolated passthru state and occlude counter for visible pixels */
struct lp_jit_thread_data thread_data;
uint64_t ps_invocations;
uint8_t ps_inv_multiplier;
@@ -311,6 +311,9 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
/* always count this not worth bothering? */
task->ps_invocations += 1 * variant->ps_inv_multiplier;
+ /* Propagate non-interpolated raster state. */
+ task->thread_data.raster_state.viewport_index = inputs->viewport_index;
+
/* run shader on 4x4 block */
BEGIN_JIT_CALL(state, task);
variant->jit_function[RAST_WHOLE]( &state->jit_context,
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 9b277d32ddc..31aaf963fe9 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -649,6 +649,41 @@ lp_setup_set_vertex_info( struct lp_setup_context *setup,
/**
+ * Called during state validation when LP_NEW_VIEWPORT is set.
+ */
+void
+lp_setup_set_viewports(struct lp_setup_context *setup,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports)
+{
+ unsigned i;
+
+ LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
+
+ assert(num_viewports <= PIPE_MAX_VIEWPORTS);
+ assert(viewports);
+
+ /*
+ * For use in lp_state_fs.c, propagate the viewport values for all viewports.
+ */
+ for (i = 0; i < num_viewports; i++) {
+ float min_depth;
+ float max_depth;
+
+ min_depth = viewports[i].translate[2];
+ max_depth = viewports[i].translate[2] + viewports[i].scale[2];
+
+ if (setup->viewports[i].min_depth != min_depth ||
+ setup->viewports[i].max_depth != max_depth) {
+ setup->viewports[i].min_depth = min_depth;
+ setup->viewports[i].max_depth = max_depth;
+ setup->dirty |= LP_SETUP_NEW_VIEWPORTS;
+ }
+ }
+}
+
+
+/**
* Called during state validation when LP_NEW_SAMPLER_VIEW is set.
*/
void
@@ -863,6 +898,15 @@ lp_setup_is_resource_referenced( const struct lp_setup_context *setup,
/**
* Called by vbuf code when we're about to draw something.
+ *
+ * This function stores all dirty state in the current scene's display list
+ * memory, via lp_scene_alloc(). We can not pass pointers of mutable state to
+ * the JIT functions, as the JIT functions will be called later on, most likely
+ * on a different thread.
+ *
+ * When processing dirty state it is imperative that we don't refer to any
+ * pointers previously allocated with lp_scene_alloc() in this function (or any
+ * function) as they may belong to a scene freed since then.
*/
static boolean
try_update_scene_state( struct lp_setup_context *setup )
@@ -873,6 +917,29 @@ try_update_scene_state( struct lp_setup_context *setup )
assert(scene);
+ if (setup->dirty & LP_SETUP_NEW_VIEWPORTS) {
+ /*
+ * Record new depth range state for changes due to viewport updates.
+ *
+ * TODO: Collapse the existing viewport and depth range information
+ * into one structure, for access by JIT.
+ */
+ struct lp_jit_viewport *stored;
+
+ stored = (struct lp_jit_viewport *)
+ lp_scene_alloc(scene, sizeof setup->viewports);
+
+ if (!stored) {
+ assert(!new_scene);
+ return FALSE;
+ }
+
+ memcpy(stored, setup->viewports, sizeof setup->viewports);
+
+ setup->fs.current.jit_context.viewports = stored;
+ setup->dirty |= LP_SETUP_NEW_FS;
+ }
+
if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) {
uint8_t *stored;
float* fstored;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 712ed145d8e..f4fbd3dbf65 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -121,6 +121,11 @@ lp_setup_set_scissors( struct lp_setup_context *setup,
const struct pipe_scissor_state *scissors );
void
+lp_setup_set_viewports(struct lp_setup_context *setup,
+ unsigned num_viewports,
+ const struct pipe_viewport_state *viewports);
+
+void
lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup,
unsigned num,
struct pipe_sampler_view **views);
@@ -155,7 +160,7 @@ lp_setup_end_query(struct lp_setup_context *setup,
struct llvmpipe_query *pq);
static INLINE unsigned
-lp_clamp_scissor_idx(int idx)
+lp_clamp_viewport_idx(int idx)
{
return (PIPE_MAX_VIEWPORTS > idx && idx >= 0) ? idx : 0;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index 44be85fde1a..8bb95c15697 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -47,6 +47,7 @@
#define LP_SETUP_NEW_CONSTANTS 0x02
#define LP_SETUP_NEW_BLEND_COLOR 0x04
#define LP_SETUP_NEW_SCISSOR 0x08
+#define LP_SETUP_NEW_VIEWPORTS 0x10
struct lp_setup_variant;
@@ -112,6 +113,7 @@ struct lp_setup_context
struct u_rect framebuffer;
struct u_rect scissors[PIPE_MAX_VIEWPORTS];
struct u_rect draw_regions[PIPE_MAX_VIEWPORTS]; /* intersection of fb & scissor */
+ struct lp_jit_viewport viewports[PIPE_MAX_VIEWPORTS];
struct {
unsigned flags;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_line.c b/src/gallium/drivers/llvmpipe/lp_setup_line.c
index 9b3321e3ec1..7e1f6a36745 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_line.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_line.c
@@ -294,7 +294,7 @@ try_setup_line( struct lp_setup_context *setup,
int y[4];
int i;
int nr_planes = 4;
- unsigned scissor_index = 0;
+ unsigned viewport_index = 0;
unsigned layer = 0;
/* linewidth should be interpreted as integer */
@@ -324,7 +324,7 @@ try_setup_line( struct lp_setup_context *setup,
nr_planes = 8;
if (setup->viewport_index_slot > 0) {
unsigned *udata = (unsigned*)v1[setup->viewport_index_slot];
- scissor_index = lp_clamp_scissor_idx(*udata);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
}
else {
@@ -573,7 +573,7 @@ try_setup_line( struct lp_setup_context *setup,
return TRUE;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
@@ -635,6 +635,7 @@ try_setup_line( struct lp_setup_context *setup,
line->inputs.disable = FALSE;
line->inputs.opaque = FALSE;
line->inputs.layer = layer;
+ line->inputs.viewport_index = viewport_index;
for (i = 0; i < 4; i++) {
@@ -697,7 +698,7 @@ try_setup_line( struct lp_setup_context *setup,
*/
if (nr_planes == 8) {
const struct u_rect *scissor =
- &setup->scissors[scissor_index];
+ &setup->scissors[viewport_index];
plane[4].dcdx = -1;
plane[4].dcdy = 0;
@@ -720,7 +721,7 @@ try_setup_line( struct lp_setup_context *setup,
plane[7].eo = 0;
}
- return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, scissor_index);
+ return lp_setup_bin_triangle(setup, line, &bbox, nr_planes, viewport_index);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_point.c b/src/gallium/drivers/llvmpipe/lp_setup_point.c
index 45068ec6df3..4b31495a5c8 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_point.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_point.c
@@ -330,12 +330,12 @@ try_setup_point( struct lp_setup_context *setup,
struct u_rect bbox;
unsigned nr_planes = 4;
struct point_info info;
- unsigned scissor_index = 0;
+ unsigned viewport_index = 0;
unsigned layer = 0;
if (setup->viewport_index_slot > 0) {
unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
- scissor_index = lp_clamp_scissor_idx(*udata);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
if (setup->layer_slot > 0) {
layer = *(unsigned*)v0[setup->layer_slot];
@@ -362,13 +362,13 @@ try_setup_point( struct lp_setup_context *setup,
bbox.y1--;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
}
- u_rect_find_intersection(&setup->draw_regions[scissor_index], &bbox);
+ u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox);
point = lp_setup_alloc_triangle(scene,
key->num_inputs,
@@ -413,6 +413,7 @@ try_setup_point( struct lp_setup_context *setup,
point->inputs.disable = FALSE;
point->inputs.opaque = FALSE;
point->inputs.layer = layer;
+ point->inputs.viewport_index = viewport_index;
{
struct lp_rast_plane *plane = GET_PLANES(point);
@@ -438,7 +439,7 @@ try_setup_point( struct lp_setup_context *setup,
plane[3].eo = 0;
}
- return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, scissor_index);
+ return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, viewport_index);
}
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 53ab1f1f0c0..e22f14c9ca0 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -274,7 +274,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
struct u_rect bbox;
unsigned tri_bytes;
int nr_planes = 3;
- unsigned scissor_index = 0;
+ unsigned viewport_index = 0;
unsigned layer = 0;
/* Area should always be positive here */
@@ -287,7 +287,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
nr_planes = 7;
if (setup->viewport_index_slot > 0) {
unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
- scissor_index = lp_clamp_scissor_idx(*udata);
+ viewport_index = lp_clamp_viewport_idx(*udata);
}
}
else {
@@ -323,7 +323,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
return TRUE;
}
- if (!u_rect_test_intersection(&setup->draw_regions[scissor_index], &bbox)) {
+ if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
if (0) debug_printf("offscreen\n");
LP_COUNT(nr_culled_tris);
return TRUE;
@@ -368,6 +368,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
tri->inputs.disable = FALSE;
tri->inputs.opaque = setup->fs.current.variant->opaque;
tri->inputs.layer = layer;
+ tri->inputs.viewport_index = viewport_index;
if (0)
lp_dump_setup_coef(&setup->setup.variant->key,
@@ -547,7 +548,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
* these planes elsewhere.
*/
if (nr_planes == 7) {
- const struct u_rect *scissor = &setup->scissors[scissor_index];
+ const struct u_rect *scissor = &setup->scissors[viewport_index];
plane[3].dcdx = -1;
plane[3].dcdy = 0;
@@ -570,7 +571,7 @@ do_triangle_ccw(struct lp_setup_context *setup,
plane[6].eo = 0;
}
- return lp_setup_bin_triangle(setup, tri, &bbox, nr_planes, scissor_index);
+ return lp_setup_bin_triangle(setup, tri, &bbox, nr_planes, viewport_index);
}
/*
@@ -605,7 +606,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
struct lp_rast_triangle *tri,
const struct u_rect *bbox,
int nr_planes,
- unsigned scissor_index )
+ unsigned viewport_index )
{
struct lp_scene *scene = setup->scene;
struct u_rect trimmed_box = *bbox;
@@ -628,7 +629,7 @@ lp_setup_bin_triangle( struct lp_setup_context *setup,
* the rasterizer to also respect scissor, etc, just for the rare
* cases where a small triangle extends beyond the scissor.
*/
- u_rect_find_intersection(&setup->draw_regions[scissor_index],
+ u_rect_find_intersection(&setup->draw_regions[viewport_index],
&trimmed_box);
/* Determine which tile(s) intersect the triangle's bounding box
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 47e413b776c..5c3a3a8e3a9 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -219,6 +219,18 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
llvmpipe->num_samplers[PIPE_SHADER_FRAGMENT],
llvmpipe->samplers[PIPE_SHADER_FRAGMENT]);
+ if (llvmpipe->dirty & LP_NEW_VIEWPORT) {
+ /*
+ * Update setup and fragment's view of the active viewport state.
+ *
+ * XXX TODO: It is possible to only loop over the active viewports
+ * instead of all viewports (PIPE_MAX_VIEWPORTS).
+ */
+ lp_setup_set_viewports(llvmpipe->setup,
+ PIPE_MAX_VIEWPORTS,
+ llvmpipe->viewports);
+ }
+
llvmpipe->dirty = 0;
}
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index b5816e038f1..74c7360bfbb 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -215,6 +215,30 @@ find_output_by_semantic( const struct tgsi_shader_info *info,
/**
+ * Fetch the specified lp_jit_viewport structure for a given viewport_index.
+ */
+static LLVMValueRef
+lp_llvm_viewport(LLVMValueRef context_ptr,
+ struct gallivm_state *gallivm,
+ LLVMValueRef viewport_index)
+{
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef ptr;
+ LLVMValueRef res;
+ struct lp_type viewport_type =
+ lp_type_float_vec(32, 32 * LP_JIT_VIEWPORT_NUM_FIELDS);
+
+ ptr = lp_jit_context_viewports(gallivm, context_ptr);
+ ptr = LLVMBuildPointerCast(builder, ptr,
+ LLVMPointerType(lp_build_vec_type(gallivm, viewport_type), 0), "");
+
+ res = lp_build_pointer_get(builder, ptr, viewport_index);
+
+ return res;
+}
+
+
+/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
*/
static void
@@ -421,7 +445,47 @@ generate_fs_loop(struct gallivm_state *gallivm,
0);
if (pos0 != -1 && outputs[pos0][2]) {
+ LLVMValueRef viewport, min_depth, max_depth;
+ LLVMValueRef viewport_index;
+ struct lp_build_context f32_bld;
+
+ assert(type.floating);
+ lp_build_context_init(&f32_bld, gallivm, type);
+
+ /*
+ * Assumes clamping of the viewport index will occur in setup/gs. Value
+ * is passed through the rasterization stage via lp_rast_shader_inputs.
+ *
+ * See: draw_clamp_viewport_idx and lp_clamp_viewport_idx for clamping
+ * semantics.
+ */
+ viewport_index = lp_jit_thread_data_raster_state_viewport_index(gallivm,
+ thread_data_ptr);
+
+ /*
+ * Load the min and max depth from the lp_jit_context.viewports
+ * array of lp_jit_viewport structures.
+ */
+ viewport = lp_llvm_viewport(context_ptr, gallivm, viewport_index);
+
+ /* viewports[viewport_index].min_depth */
+ min_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MIN_DEPTH),
+ "");
+ min_depth = lp_build_broadcast_scalar(&f32_bld, min_depth);
+
+ /* viewports[viewport_index].max_depth */
+ max_depth = LLVMBuildExtractElement(builder, viewport,
+ lp_build_const_int32(gallivm, LP_JIT_VIEWPORT_MAX_DEPTH),
+ "");
+ max_depth = lp_build_broadcast_scalar(&f32_bld, max_depth);
+
z = LLVMBuildLoad(builder, outputs[pos0][2], "output.z");
+
+ /*
+ * Clamp to the min and max depth values for the given viewport.
+ */
+ z = lp_build_clamp(&f32_bld, z, min_depth, max_depth);
}
lp_build_depth_stencil_load_swizzled(gallivm, type,