draw/draw_pipe_clip.c \
draw/draw_pipe_cull.c \
draw/draw_pipe_flatshade.c \
- draw/draw_pipe_ia.c \
draw/draw_pipe_offset.c \
draw/draw_pipe_pstipple.c \
draw/draw_pipe_stipple.c \
#include "util/u_prim.h"
#include "draw_context.h"
#include "draw_pipe.h"
+#include "draw_prim_assembler.h"
#include "draw_vs.h"
#include "draw_gs.h"
if (!draw_init(draw))
goto err_destroy;
+ draw->ia = draw_prim_assembler_create(draw);
+ if (!draw->ia)
+ goto err_destroy;
+
return draw;
err_destroy:
draw->render->destroy( draw->render );
*/
+ draw_prim_assembler_destroy(draw->ia);
draw_pipeline_destroy( draw );
draw_pt_destroy( draw );
draw_vs_destroy( draw );
draw_prepare_shader_outputs(struct draw_context *draw)
{
draw_remove_extra_vertex_attribs(draw);
- draw_ia_prepare_outputs(draw, draw->pipeline.ia);
+ draw_prim_assembler_prepare_outputs(draw->ia);
draw_unfilled_prepare_outputs(draw, draw->pipeline.unfilled);
}
draw->pipeline.clip = draw_clip_stage( draw );
draw->pipeline.flatshade = draw_flatshade_stage( draw );
draw->pipeline.cull = draw_cull_stage( draw );
- draw->pipeline.ia = draw_ia_stage( draw );
draw->pipeline.validate = draw_validate_stage( draw );
draw->pipeline.first = draw->pipeline.validate;
!draw->pipeline.clip ||
!draw->pipeline.flatshade ||
!draw->pipeline.cull ||
- !draw->pipeline.ia ||
!draw->pipeline.validate)
return FALSE;
draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
if (draw->pipeline.cull)
draw->pipeline.cull->destroy( draw->pipeline.cull );
- if (draw->pipeline.ia)
- draw->pipeline.ia->destroy( draw->pipeline.ia );
if (draw->pipeline.validate)
draw->pipeline.validate->destroy( draw->pipeline.validate );
if (draw->pipeline.aaline)
extern struct draw_stage *draw_wide_line_stage( struct draw_context *context );
extern struct draw_stage *draw_wide_point_stage( struct draw_context *context );
extern struct draw_stage *draw_validate_stage( struct draw_context *context );
-extern struct draw_stage *draw_ia_stage(struct draw_context *context);
-
-boolean draw_ia_stage_required(const struct draw_context *context,
- unsigned prim);
extern void draw_free_temp_verts( struct draw_stage *stage );
extern boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr );
void draw_unfilled_prepare_outputs(struct draw_context *context,
struct draw_stage *stage);
-void draw_ia_prepare_outputs(struct draw_context *context,
- struct draw_stage *stage);
-
/**
* Get a writeable copy of a vertex.
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2013 VMware
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * \brief Used to decompose adjacency primitives and inject the prim id
- */
-
-#include "util/u_math.h"
-#include "util/u_memory.h"
-#include "pipe/p_defines.h"
-#include "draw_pipe.h"
-#include "draw_fs.h"
-#include "draw_gs.h"
-
-
-struct ia_stage {
- struct draw_stage stage;
- int primid_slot;
- unsigned primid;
-};
-
-
-static INLINE struct ia_stage *
-ia_stage(struct draw_stage *stage)
-{
- return (struct ia_stage *)stage;
-}
-
-
-static void
-inject_primid(struct draw_stage *stage,
- struct prim_header *header,
- unsigned num_verts)
-{
- struct ia_stage *ia = ia_stage(stage);
- unsigned slot = ia->primid_slot;
- unsigned i;
- unsigned primid = ia->primid;
-
- /* In case the backend doesn't care about it */
- if (slot < 0) {
- return;
- }
-
- for (i = 0; i < num_verts; ++i) {
- struct vertex_header *v = header->v[i];
- /* We have to reset the vertex_id because it's used by
- * vbuf to figure out if the vertex had already been
- * emitted. For line/tri strips the first vertex of
- * subsequent primitives would already be emitted,
- * but since we're changing the primitive id on the vertex
- * we want to make sure it's reemitted with the correct
- * data.
- */
- v->vertex_id = UNDEFINED_VERTEX_ID;
- memcpy(&v->data[slot][0], &primid, sizeof(primid));
- memcpy(&v->data[slot][1], &primid, sizeof(primid));
- memcpy(&v->data[slot][2], &primid, sizeof(primid));
- memcpy(&v->data[slot][3], &primid, sizeof(primid));
- }
- ++ia->primid;
-}
-
-
-static void
-ia_point(struct draw_stage *stage,
- struct prim_header *header)
-{
- inject_primid(stage, header, 1);
- stage->next->point(stage->next, header);
-}
-
-static void
-ia_line(struct draw_stage *stage,
- struct prim_header *header)
-{
- inject_primid(stage, header, 2);
- stage->next->line(stage->next, header);
-}
-
-static void
-ia_tri(struct draw_stage *stage,
- struct prim_header *header)
-{
- inject_primid(stage, header, 3);
- stage->next->tri(stage->next, header);
-}
-
-static void
-ia_first_point(struct draw_stage *stage,
- struct prim_header *header)
-{
- struct ia_stage *ia = ia_stage(stage);
-
- if (ia->primid_slot >= 0) {
- stage->point = ia_point;
- } else {
- stage->point = draw_pipe_passthrough_point;
- }
-
- stage->point(stage, header);
-}
-
-static void
-ia_first_line(struct draw_stage *stage,
- struct prim_header *header)
-{
- struct ia_stage *ia = ia_stage(stage);
-
- if (ia->primid_slot >= 0) {
- stage->line = ia_line;
- } else {
- stage->line = draw_pipe_passthrough_line;
- }
-
- stage->line(stage, header);
-}
-
-static void
-ia_first_tri(struct draw_stage *stage,
- struct prim_header *header)
-{
- struct ia_stage *ia = ia_stage(stage);
-
- if (ia->primid_slot >= 0) {
- stage->tri = ia_tri;
- } else {
- stage->tri = draw_pipe_passthrough_tri;
- }
-
- stage->tri(stage, header);
-}
-
-
-static void
-ia_flush(struct draw_stage *stage, unsigned flags)
-{
- stage->point = ia_first_point;
- stage->line = ia_first_line;
- stage->tri = ia_first_tri;
- stage->next->flush(stage->next, flags);
-}
-
-
-static void
-ia_reset_stipple_counter(struct draw_stage *stage)
-{
- stage->next->reset_stipple_counter(stage->next);
-}
-
-
-static void
-ia_destroy(struct draw_stage *stage)
-{
- draw_free_temp_verts(stage);
- FREE(stage);
-}
-
-
-static boolean
-needs_primid(const struct draw_context *draw)
-{
- const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
- const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
- if (fs && fs->info.uses_primid) {
- return !gs || !gs->info.uses_primid;
- }
- return FALSE;
-}
-
-boolean
-draw_ia_stage_required(const struct draw_context *draw, unsigned prim)
-{
- const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
- if (needs_primid(draw)) {
- return TRUE;
- }
-
- if (gs) {
- return FALSE;
- }
-
- switch (prim) {
- case PIPE_PRIM_LINES_ADJACENCY:
- case PIPE_PRIM_LINE_STRIP_ADJACENCY:
- case PIPE_PRIM_TRIANGLES_ADJACENCY:
- case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
- return TRUE;
- default:
- return FALSE;
- }
-}
-
-void
-draw_ia_prepare_outputs(struct draw_context *draw,
- struct draw_stage *stage)
-{
- struct ia_stage *ia = ia_stage(stage);
- if (needs_primid(draw)) {
- ia->primid_slot = draw_alloc_extra_vertex_attrib(
- stage->draw, TGSI_SEMANTIC_PRIMID, 0);
- } else {
- ia->primid_slot = -1;
- }
- ia->primid = 0;
-}
-
-struct draw_stage *
-draw_ia_stage(struct draw_context *draw)
-{
- struct ia_stage *ia = CALLOC_STRUCT(ia_stage);
- if (ia == NULL)
- goto fail;
-
- ia->stage.draw = draw;
- ia->stage.name = "ia";
- ia->stage.next = NULL;
- ia->stage.point = ia_first_point;
- ia->stage.line = ia_first_line;
- ia->stage.tri = ia_first_tri;
- ia->stage.flush = ia_flush;
- ia->stage.reset_stipple_counter = ia_reset_stipple_counter;
- ia->stage.destroy = ia_destroy;
-
- if (!draw_alloc_temp_verts(&ia->stage, 0))
- goto fail;
-
- return &ia->stage;
-
-fail:
- if (ia)
- ia->stage.destroy(&ia->stage);
-
- return NULL;
-}
prim );
}
- /* If we need to decompose the primitives or inject
- * primitive id information then we have to run
- * the pipeline.
- */
- if (draw_ia_stage_required(draw, prim)) {
- return TRUE;
- }
-
/* Don't have to worry about triangles turning into lines/points
* and triggering the pipeline, because we have to trigger the
* pipeline *anyway* if unfilled mode is active.
next = draw->pipeline.clip;
}
- /* Input assembler */
- if (draw_ia_stage_required(draw, draw->pt.prim)) {
- draw->pipeline.ia->next = next;
- next = draw->pipeline.ia;
- }
-
draw->pipeline.first = next;
if (0) {
#include "draw_prim_assembler.h"
+#include "draw_fs.h"
+#include "draw_gs.h"
+
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
const struct draw_prim_info *input_prims;
const struct draw_vertex_info *input_verts;
+
+ boolean needs_primid;
+ int primid_slot;
+ unsigned primid;
+
+ boolean is_strip;
+ boolean is_first_prim;
+ unsigned num_prims;
};
+
+static boolean
+needs_primid(const struct draw_context *draw)
+{
+ const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
+ const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
+ if (fs && fs->info.uses_primid) {
+ return !gs || !gs->info.uses_primid;
+ }
+ return FALSE;
+}
+
boolean
draw_prim_assembler_is_required(const struct draw_context *draw,
const struct draw_prim_info *prim_info,
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return TRUE;
default:
- return FALSE;
+ return needs_primid(draw);
}
}
asmblr->input_verts->vertex_size);
asmblr->output_verts->count += 1;
}
+ ++asmblr->num_prims;
+}
+
+
+static void
+inject_primid(struct draw_assembler *asmblr,
+ unsigned idx,
+ unsigned primid)
+{
+ int slot = asmblr->primid_slot;
+ char *input = (char*)asmblr->input_verts->verts;
+ unsigned input_offset = asmblr->input_verts->stride * idx;
+ struct vertex_header *v = (struct vertex_header*)(input + input_offset);
+
+ /* In case the backend doesn't care about it */
+ if (slot < 0) {
+ return;
+ }
+
+ memcpy(&v->data[slot][0], &primid, sizeof(primid));
+ memcpy(&v->data[slot][1], &primid, sizeof(primid));
+ memcpy(&v->data[slot][2], &primid, sizeof(primid));
+ memcpy(&v->data[slot][3], &primid, sizeof(primid));
}
+
static void
prim_point(struct draw_assembler *asmblr,
unsigned idx)
{
unsigned indices[1];
+ if (asmblr->needs_primid) {
+ inject_primid(asmblr, idx, asmblr->primid++);
+ }
indices[0] = idx;
-
+
copy_verts(asmblr, indices, 1);
}
{
unsigned indices[2];
+ if (asmblr->needs_primid) {
+ if (asmblr->is_strip && asmblr->is_first_prim) {
+ inject_primid(asmblr, i0, asmblr->primid++);
+ inject_primid(asmblr, i1, asmblr->primid++);
+ asmblr->is_first_prim = FALSE;
+ } else if (asmblr->is_strip) {
+ inject_primid(asmblr, i1, asmblr->primid++);
+ } else {
+ inject_primid(asmblr, i0, asmblr->primid);
+ inject_primid(asmblr, i1, asmblr->primid++);
+ }
+ }
indices[0] = i0;
indices[1] = i1;
{
unsigned indices[2];
+ if (asmblr->needs_primid) {
+ if (asmblr->is_strip && asmblr->is_first_prim) {
+ inject_primid(asmblr, i1, asmblr->primid++);
+ inject_primid(asmblr, i2, asmblr->primid++);
+ asmblr->is_first_prim = FALSE;
+ } else if (asmblr->is_strip) {
+ inject_primid(asmblr, i2, asmblr->primid++);
+ } else {
+ inject_primid(asmblr, i1, asmblr->primid);
+ inject_primid(asmblr, i2, asmblr->primid++);
+ }
+ }
+
indices[0] = i1;
indices[1] = i2;
{
unsigned indices[3];
+ if (asmblr->needs_primid) {
+ if (asmblr->is_strip && asmblr->is_first_prim) {
+ inject_primid(asmblr, i0, asmblr->primid++);
+ inject_primid(asmblr, i1, asmblr->primid++);
+ inject_primid(asmblr, i2, asmblr->primid++);
+ asmblr->is_first_prim = FALSE;
+ } else if (asmblr->is_strip) {
+ if (asmblr->num_prims & 1) {
+ inject_primid(asmblr, i1, asmblr->primid++);
+ } else {
+ inject_primid(asmblr, i2, asmblr->primid++);
+ }
+ } else {
+ inject_primid(asmblr, i0, asmblr->primid);
+ inject_primid(asmblr, i1, asmblr->primid);
+ inject_primid(asmblr, i2, asmblr->primid++);
+ }
+ }
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
{
unsigned indices[3];
+ if (asmblr->needs_primid) {
+ if (asmblr->is_strip && asmblr->is_first_prim) {
+ inject_primid(asmblr, i0, asmblr->primid++);
+ inject_primid(asmblr, i2, asmblr->primid++);
+ inject_primid(asmblr, i4, asmblr->primid++);
+ asmblr->is_first_prim = FALSE;
+ } else if (asmblr->is_strip) {
+ if (asmblr->num_prims & 1) {
+ inject_primid(asmblr, i2, asmblr->primid++);
+ } else {
+ inject_primid(asmblr, i4, asmblr->primid++);
+ }
+ } else {
+ inject_primid(asmblr, i0, asmblr->primid);
+ inject_primid(asmblr, i2, asmblr->primid);
+ inject_primid(asmblr, i4, asmblr->primid);
+ asmblr->primid++;
+ }
+ }
indices[0] = i0;
indices[1] = i2;
indices[2] = i4;
copy_verts(asmblr, indices, 3);
}
+void
+draw_prim_assembler_prepare_outputs(struct draw_assembler *ia)
+{
+ struct draw_context *draw = ia->draw;
+ if (needs_primid(draw)) {
+ ia->primid_slot = draw_alloc_extra_vertex_attrib(
+ ia->draw, TGSI_SEMANTIC_PRIMID, 0);
+ } else {
+ ia->primid_slot = -1;
+ }
+ ia->primid = 0;
+}
#define FUNC assembler_run_linear
struct draw_prim_info *output_prims,
struct draw_vertex_info *output_verts)
{
- struct draw_assembler asmblr;
+ struct draw_assembler *asmblr = draw->ia;
unsigned start, i;
unsigned assembled_prim = u_assembled_prim(input_prims->prim);
unsigned max_primitives = u_decomposed_prims_for_vertices(
input_prims->prim, input_prims->count);
unsigned max_verts = u_vertices_per_prim(assembled_prim) * max_primitives;
- asmblr.draw = draw;
- asmblr.output_prims = output_prims;
- asmblr.output_verts = output_verts;
- asmblr.input_prims = input_prims;
- asmblr.input_verts = input_verts;
+ asmblr->output_prims = output_prims;
+ asmblr->output_verts = output_verts;
+ asmblr->input_prims = input_prims;
+ asmblr->input_verts = input_verts;
+ asmblr->is_strip =
+ (input_prims->prim == PIPE_PRIM_TRIANGLE_STRIP ||
+ input_prims->prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) ||
+ (input_prims->prim == PIPE_PRIM_LINE_STRIP ||
+ input_prims->prim == PIPE_PRIM_LINE_STRIP_ADJACENCY);
+ asmblr->needs_primid = needs_primid(asmblr->draw);
+ asmblr->is_first_prim = asmblr->is_strip;
+ asmblr->primid = 0;
+ asmblr->num_prims = 0;
output_prims->linear = TRUE;
output_prims->elts = NULL;
{
unsigned count = input_prims->primitive_lengths[i];
if (input_prims->linear) {
- assembler_run_linear(&asmblr, input_prims, input_verts,
+ assembler_run_linear(asmblr, input_prims, input_verts,
start, count);
} else {
- assembler_run_elts(&asmblr, input_prims, input_verts,
+ assembler_run_elts(asmblr, input_prims, input_verts,
start, count);
}
}
output_prims->primitive_lengths[0] = output_verts->count;
output_prims->count = output_verts->count;
}
+
+struct draw_assembler *
+draw_prim_assembler_create(struct draw_context *draw)
+{
+ struct draw_assembler *ia = CALLOC_STRUCT( draw_assembler );
+
+ ia->draw = draw;
+
+ return ia;
+}
+
+void
+draw_prim_assembler_destroy(struct draw_assembler *ia)
+{
+ FREE(ia);
+}
#include "draw/draw_private.h"
+struct draw_assembler;
+
+struct draw_assembler *
+draw_prim_assembler_create(struct draw_context *draw);
+
+void
+draw_prim_assembler_destroy(struct draw_assembler *ia);
+
boolean
draw_prim_assembler_is_required(const struct draw_context *draw,
const struct draw_prim_info *prim_info,
struct draw_vertex_info *out_vert_info);
+void
+draw_prim_assembler_prepare_outputs(struct draw_assembler *ia);
+
+
#endif
struct tgsi_exec_machine;
struct tgsi_sampler;
struct draw_pt_front_end;
+struct draw_assembler;
/**
struct draw_stage *wide_line;
struct draw_stage *wide_point;
struct draw_stage *rasterize;
- struct draw_stage *ia;
float wide_point_threshold; /**< convert pnts to tris if larger than this */
float wide_line_threshold; /**< convert lines to tris if wider than this */
struct pipe_query_data_pipeline_statistics statistics;
boolean collect_statistics;
+ struct draw_assembler *ia;
+
void *driver_private;
};