summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/draw/draw_pt.c86
-rw-r--r--src/gallium/docs/source/context.rst9
-rw-r--r--src/gallium/drivers/llvmpipe/lp_screen.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_screen.c2
-rw-r--r--src/gallium/include/pipe/p_defines.h1
-rw-r--r--src/gallium/include/pipe/p_state.h6
6 files changed, 105 insertions, 1 deletions
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index f44bf2507c..4078b2a07d 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -287,6 +287,84 @@ draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
}
+/** Helper code for below */
+#define PRIM_RESTART_LOOP(elements) \
+ do { \
+ for (i = start; i < end; i++) { \
+ if (elements[i] == info->restart_index) { \
+ if (cur_count > 0) { \
+ /* draw elts up to prev pos */ \
+ draw_pt_arrays(draw, prim, cur_start, cur_count); \
+ } \
+ /* begin new prim at next elt */ \
+ cur_start = i + 1; \
+ cur_count = 0; \
+ } \
+ else { \
+ cur_count++; \
+ } \
+ } \
+ if (cur_count > 0) { \
+ draw_pt_arrays(draw, prim, cur_start, cur_count); \
+ } \
+ } while (0)
+
+
+/**
+ * For drawing prims with primitive restart enabled.
+ * Scan for restart indexes and draw the runs of elements/vertices between
+ * the restarts.
+ */
+static void
+draw_pt_arrays_restart(struct draw_context *draw,
+ const struct pipe_draw_info *info)
+{
+ const unsigned prim = info->mode;
+ const unsigned start = info->start;
+ const unsigned count = info->count;
+ const unsigned end = start + count;
+ unsigned i, cur_start, cur_count;
+
+ assert(info->primitive_restart);
+
+ if (draw->pt.user.elts) {
+ /* indexed prims (draw_elements) */
+ cur_start = start;
+ cur_count = 0;
+
+ switch (draw->pt.user.eltSize) {
+ case 1:
+ {
+ const ubyte *elt_ub = (const ubyte *) draw->pt.user.elts;
+ PRIM_RESTART_LOOP(elt_ub);
+ }
+ break;
+ case 2:
+ {
+ const ushort *elt_us = (const ushort *) draw->pt.user.elts;
+ PRIM_RESTART_LOOP(elt_us);
+ }
+ break;
+ case 4:
+ {
+ const uint *elt_ui = (const uint *) draw->pt.user.elts;
+ PRIM_RESTART_LOOP(elt_ui);
+ }
+ break;
+ default:
+ assert(0 && "bad eltSize in draw_arrays()");
+ }
+ }
+ else {
+ /* Non-indexed prims (draw_arrays).
+ * Primitive restart should have been handled in the state tracker.
+ */
+ draw_pt_arrays(draw, prim, start, count);
+ }
+}
+
+
+
/**
* Non-instanced drawing.
* \sa draw_arrays_instanced
@@ -395,6 +473,12 @@ draw_vbo(struct draw_context *draw,
for (instance = 0; instance < info->instance_count; instance++) {
draw->instance_id = instance + info->start_instance;
- draw_pt_arrays(draw, info->mode, info->start, info->count);
+
+ if (info->primitive_restart) {
+ draw_pt_arrays_restart(draw, info);
+ }
+ else {
+ draw_pt_arrays(draw, info->mode, info->start, info->count);
+ }
}
}
diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst
index 5342fc25dc..e09a1304c4 100644
--- a/src/gallium/docs/source/context.rst
+++ b/src/gallium/docs/source/context.rst
@@ -156,6 +156,15 @@ If there is an index buffer bound, and ``indexed`` field is true, all vertex
indices will be looked up in the index buffer. ``min_index``, ``max_index``,
and ``index_bias`` apply after index lookup.
+When drawing indexed primitives, the primitive restart index can be
+used to draw disjoint primitive strips. For example, several separate
+line strips can be drawn by designating a special index value as the
+restart index. The ``primitive_restart`` flag enables/disables this
+feature. The ``restart_index`` field specifies the restart index value.
+
+When primitive restart is in use, array indexes are compared to the
+restart index before adding the index_bias offset.
+
If a given vertex element has ``instance_divisor`` set to 0, it is said
it contains per-vertex data and effective vertex attribute address needs
to be recalculated for every index.
diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c
index 96633d9365..ad0ea75b3a 100644
--- a/src/gallium/drivers/llvmpipe/lp_screen.c
+++ b/src/gallium/drivers/llvmpipe/lp_screen.c
@@ -158,6 +158,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
return 0;
+ case PIPE_CAP_PRIMITIVE_RESTART:
+ return 1;
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 1;
case PIPE_CAP_DEPTH_CLAMP:
diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c
index 37557d1194..a2bfa1bd8d 100644
--- a/src/gallium/drivers/softpipe/sp_screen.c
+++ b/src/gallium/drivers/softpipe/sp_screen.c
@@ -112,6 +112,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1;
case PIPE_CAP_STREAM_OUTPUT:
return 1;
+ case PIPE_CAP_PRIMITIVE_RESTART:
+ return 1;
case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE:
return 0;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index b6894c09e8..53f7b601ad 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -452,6 +452,7 @@ enum pipe_cap {
PIPE_CAP_BLEND_EQUATION_SEPARATE,
PIPE_CAP_SM3, /*< Shader Model, supported */
PIPE_CAP_STREAM_OUTPUT,
+ PIPE_CAP_PRIMITIVE_RESTART,
/** Maximum texture image units accessible from vertex and fragment shaders
* combined */
PIPE_CAP_MAX_COMBINED_SAMPLERS,
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index 9a2b31da50..fc6dba346d 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -457,6 +457,12 @@ struct pipe_draw_info
int index_bias; /**< a bias to be added to each index */
unsigned min_index; /**< the min index */
unsigned max_index; /**< the max index */
+
+ /**
+ * Primitive restart enable/index (only applies to indexed drawing)
+ */
+ boolean primitive_restart;
+ unsigned restart_index;
};