Commit 72bd2b60 authored by Jakob Bornecrantz's avatar Jakob Bornecrantz Committed by Brian Paul

st/mesa: Implement primitive restart in software

parent d3561bd0
......@@ -75,6 +75,7 @@ struct st_context
struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
struct draw_stage *rastpos_stage; /**< For glRasterPos */
GLboolean sw_primitive_restart;
/* On old libGL's for linux we need to invalidate the drawables
......
......@@ -582,6 +582,118 @@ check_uniforms(struct gl_context *ctx)
}
}
/** Helper code for primitive restart fallback */
#define DO_DRAW(pipe, cur_start, cur_count) \
do { \
info.start = cur_start; \
info.count = cur_count; \
if (u_trim_pipe_prim(info.mode, &info.count)) \
pipe->draw_vbo(pipe, &info); \
} while(0)
/** More helper code for primitive restart fallback */
#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 */ \
DO_DRAW(pipe, cur_start, cur_count); \
} \
/* begin new prim at next elt */ \
cur_start = i + 1; \
cur_count = 0; \
} \
else { \
cur_count++; \
} \
} \
if (cur_count > 0) { \
DO_DRAW(pipe, cur_start, cur_count); \
} \
} while (0)
static void
handle_fallback_primitive_restart(struct pipe_context *pipe,
struct pipe_index_buffer *ibuffer,
struct pipe_draw_info *orig_info)
{
const unsigned start = orig_info->start;
const unsigned count = orig_info->count;
const unsigned end = start + count;
struct pipe_draw_info info = *orig_info;
struct pipe_transfer *transfer;
unsigned instance, i, cur_start, cur_count;
void *ptr;
info.primitive_restart = FALSE;
/* split the draw_arrays calls into two */
if (!info.indexed) {
#if 0
/* handled by VBO */
if (info.restart_index >= info.min_index) {
info.count = MIN(info.restart_index-1, info.max_index) - info.start + 1;
if (u_trim_pipe_prim(info.mode, &info.count))
pipe->draw_vbo(pipe, &info);
}
if (info.restart_index <= info.max_index) {
info.start = MAX(info.min_index, info.restart_index + 1);
info.count = info.max_index - info.start + 1;
if (u_trim_pipe_prim(info.mode, &info.count))
pipe->draw_vbo(pipe, &info);
}
#endif
if (u_trim_pipe_prim(info.mode, &info.count))
pipe->draw_vbo(pipe, &info);
return;
}
/* info.indexed == TRUE */
assert(ibuffer);
assert(ibuffer->buffer);
ptr = pipe_buffer_map(pipe, ibuffer->buffer, PIPE_TRANSFER_READ, &transfer);
if (!ptr)
return;
ptr = ADD_POINTERS(ptr, ibuffer->offset);
/* Need to loop over instances as well to preserve draw order */
for (instance = 0; instance < orig_info->instance_count; instance++) {
info.start_instance = instance + orig_info->start_instance;
info.instance_count = 1;
cur_start = start;
cur_count = 0;
switch (ibuffer->index_size) {
case 1:
{
const ubyte *elt_ub = (const ubyte *)ptr;
PRIM_RESTART_LOOP(elt_ub);
}
break;
case 2:
{
const ushort *elt_us = (const ushort *)ptr;
PRIM_RESTART_LOOP(elt_us);
}
break;
case 4:
{
const uint *elt_ui = (const uint *)ptr;
PRIM_RESTART_LOOP(elt_ui);
}
break;
default:
assert(0 && "bad index_size in handle_fallback_primitive_restart()");
}
}
pipe_buffer_unmap(pipe, transfer);
}
/**
* Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to
......@@ -794,7 +906,22 @@ st_draw_vbo(struct gl_context *ctx,
info.max_index = info.start + info.count - 1;
}
if (u_trim_pipe_prim(info.mode, &info.count))
if (info.primitive_restart) {
/*
* Handle primitive restart for drivers that doesn't support it.
*
* The VBO module handles restart inside of draw_arrays for us,
* but we should still remove the primitive_restart flag on the
* info struct, the fallback function does this for us. Just
* remove the flag for all drivers in this case as well.
*/
if (st->sw_primitive_restart || !info.indexed)
handle_fallback_primitive_restart(pipe, &ibuffer, &info);
else
/* don't trim, restarts might be inside index list */
pipe->draw_vbo(pipe, &info);
}
else if (u_trim_pipe_prim(info.mode, &info.count))
pipe->draw_vbo(pipe, &info);
}
......
......@@ -555,8 +555,9 @@ void st_init_extensions(struct st_context *st)
#endif
}
if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) {
ctx->Extensions.NV_primitive_restart = GL_TRUE;
ctx->Extensions.NV_primitive_restart = GL_TRUE;
if (!screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) {
st->sw_primitive_restart = GL_TRUE;
}
if (screen->get_param(screen, PIPE_CAP_DEPTH_CLAMP)) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment