This adds support for multiple viewports to the draw module.
Multiple viewports depend on the presence of geometry shaders
which can write the viewport index.
Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: José Fonseca<jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
struct draw_vertex_info *info )
{
struct vertex_header *out = info->verts;
- const float *scale = pvs->draw->viewport.scale;
- const float *trans = pvs->draw->viewport.translate;
/* const */ float (*plane)[4] = pvs->draw->plane;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
unsigned j;
unsigned i;
bool have_cd = false;
+ unsigned viewport_index_output =
+ draw_current_shader_viewport_index_output(pvs->draw);
+
cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
+ int viewport_index =
+ draw_current_shader_uses_viewport_index(pvs->draw) ?
+ *((unsigned*)out->data[viewport_index_output]): 0;
unsigned mask = 0x0;
+ const float *scale = pvs->draw->viewports[viewport_index].scale;
+ const float *trans = pvs->draw->viewports[viewport_index].translate;
initialize_vertex_header(out);
{
const struct pipe_viewport_state *viewport = vps;
draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
- draw->viewport = *viewport; /* struct copy */
- draw->identity_viewport = (viewport->scale[0] == 1.0f &&
- viewport->scale[1] == 1.0f &&
- viewport->scale[2] == 1.0f &&
- viewport->scale[3] == 1.0f &&
- viewport->translate[0] == 0.0f &&
- viewport->translate[1] == 0.0f &&
- viewport->translate[2] == 0.0f &&
- viewport->translate[3] == 0.0f);
- draw_vs_set_viewport( draw, viewport );
+ if (start_slot > PIPE_MAX_VIEWPORTS)
+ return;
+
+ if ((start_slot + num_viewports) > PIPE_MAX_VIEWPORTS)
+ num_viewports = PIPE_MAX_VIEWPORTS - start_slot;
+
+ memcpy(draw->viewports + start_slot, vps,
+ sizeof(struct pipe_viewport_state) * num_viewports);
+ draw->identity_viewport = (num_viewports == 1) &&
+ (viewport->scale[0] == 1.0f &&
+ viewport->scale[1] == 1.0f &&
+ viewport->scale[2] == 1.0f &&
+ viewport->scale[3] == 1.0f &&
+ viewport->translate[0] == 0.0f &&
+ viewport->translate[1] == 0.0f &&
+ viewport->translate[2] == 0.0f &&
+ viewport->translate[3] == 0.0f);
}
}
+/**
+ * Return the index of the shader output which will contain the
+ * viewport index.
+ */
+uint
+draw_current_shader_viewport_index_output(const struct draw_context *draw)
+{
+ if (draw->gs.geometry_shader)
+ return draw->gs.geometry_shader->viewport_index_output;
+ return 0;
+}
+
+/**
+ * Returns true if there's a geometry shader bound and the geometry
+ * shader writes out a viewport index.
+ */
+boolean
+draw_current_shader_uses_viewport_index(const struct draw_context *draw)
+{
+ if (draw->gs.geometry_shader)
+ return draw->gs.geometry_shader->info.writes_viewport_index;
+ return FALSE;
+}
+
+
/**
* Return the index of the shader output which will contain the
* vertex position.
int i;
for (i = 0; i < total_verts; ++i) {
struct vertex_header *vh = (struct vertex_header *)(output_ptr + shader->vertex_size * i);
- debug_printf("%d) [%f, %f, %f, %f]\n", i,
- vh->data[0][0], vh->data[0][1], vh->data[0][2], vh->data[0][3]);
+ debug_printf("%d) Vertex:\n", i);
+ for (j = 0; j < shader->info.num_outputs; ++j) {
+ unsigned *udata = (unsigned*)vh->data[j];
+ debug_printf(" %d) [%f, %f, %f, %f] [%d, %d, %d, %d]\n", j,
+ vh->data[j][0], vh->data[j][1], vh->data[j][2], vh->data[j][3],
+ udata[0], udata[1], udata[2], udata[3]);
+ }
}
}
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
gs->info.output_semantic_index[i] == 0)
gs->position_output = i;
+ if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
+ gs->viewport_index_output = i;
}
gs->machine = draw->gs.tgsi.machine;
struct tgsi_shader_info info;
unsigned position_output;
+ unsigned viewport_index_output;
unsigned max_output_vertices;
unsigned primitive_boundary;
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
unsigned j;
float t_nopersp;
+ unsigned viewport_index_output =
+ draw_current_shader_viewport_index_output(clip->stage.draw);
/* Vertex header.
*/
* new window coordinates:
*/
{
+ int viewport_index =
+ draw_current_shader_uses_viewport_index(clip->stage.draw) ?
+ *((unsigned*)in->data[viewport_index_output]) : 0;
const float *pos = dst->pre_clip_pos;
- const float *scale = clip->stage.draw->viewport.scale;
- const float *trans = clip->stage.draw->viewport.translate;
+ const float *scale =
+ clip->stage.draw->viewports[viewport_index].scale;
+ const float *trans =
+ clip->stage.draw->viewports[viewport_index].translate;
const float oow = 1.0f / pos[3];
dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];
/** Rasterizer CSOs without culling/stipple/etc */
void *rasterizer_no_cull[2][2];
- struct pipe_viewport_state viewport;
+ struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
boolean identity_viewport;
/** Vertex shader state */
boolean draw_vs_init( struct draw_context *draw );
void draw_vs_destroy( struct draw_context *draw );
-void draw_vs_set_viewport( struct draw_context *,
- const struct pipe_viewport_state * );
-
/*******************************************************************************
* Geometry shading code:
*/
uint draw_current_shader_outputs(const struct draw_context *draw);
uint draw_current_shader_position_output(const struct draw_context *draw);
+uint draw_current_shader_viewport_index_output(const struct draw_context *draw);
uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index);
void draw_remove_extra_vertex_attribs(struct draw_context *draw);
+boolean draw_current_shader_uses_viewport_index(
+ const struct draw_context *draw);
/*******************************************************************************
fpme->llvm->gs_jit_context.planes =
(float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
- fpme->llvm->jit_context.viewport = (float *) draw->viewport.scale;
- fpme->llvm->gs_jit_context.viewport = (float *) draw->viewport.scale;
+ fpme->llvm->jit_context.viewport = (float *) draw->viewports[0].scale;
+ fpme->llvm->gs_jit_context.viewport = (float *) draw->viewports[0].scale;
}
DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE)
-void draw_vs_set_viewport( struct draw_context *draw,
- const struct pipe_viewport_state *viewport )
-{
-}
-
-
-
struct draw_vertex_shader *
draw_create_vertex_shader(struct draw_context *draw,
const struct pipe_shader_state *shader)
max_index );
}
+static const struct pipe_viewport_state *
+find_viewport(struct draw_context *draw,
+ char *buffer,
+ unsigned vertex_idx,
+ unsigned stride)
+{
+ int viewport_index_output =
+ draw_current_shader_viewport_index_output(draw);
+ char *ptr = buffer + vertex_idx * stride;
+ unsigned *data = (unsigned *)ptr;
+ int viewport_index =
+ draw_current_shader_uses_viewport_index(draw) ?
+ data[viewport_index_output * 4] : 0;
+
+ debug_assert(viewport_index < PIPE_MAX_VIEWPORTS);
+ viewport_index = MIN2(viewport_index, PIPE_MAX_VIEWPORTS - 1);
+
+ return &draw->viewports[viewport_index];
+}
+
/* Mainly for debug at this stage:
*/
void *output_buffer )
{
char *ptr = (char *)output_buffer;
- const float *scale = vsvg->base.vs->draw->viewport.scale;
- const float *trans = vsvg->base.vs->draw->viewport.translate;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
for (j = 0; j < count; j++, ptr += stride) {
+ const struct pipe_viewport_state *viewport =
+ find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
+ j, stride);
+ const float *scale = viewport->scale;
+ const float *trans = viewport->translate;
float *data = (float *)ptr;
float w = 1.0f / data[3];
void *output_buffer )
{
char *ptr = (char *)output_buffer;
- const float *scale = vsvg->base.vs->draw->viewport.scale;
- const float *trans = vsvg->base.vs->draw->viewport.translate;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
for (j = 0; j < count; j++, ptr += stride) {
+ const struct pipe_viewport_state *viewport =
+ find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
+ j, stride);
+ const float *scale = viewport->scale;
+ const float *trans = viewport->translate;
float *data = (float *)ptr;
data[0] = data[0] * scale[0] + trans[0];