i965: Fix can_cut_index_handle_restart_index() for byte/short types.
authorKenneth Graunke <kenneth@whitecape.org>
Sat, 25 May 2013 17:17:32 +0000 (10:17 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 29 May 2013 21:22:08 +0000 (14:22 -0700)
Pre-Haswell hardware doesn't support an arbitrary restart index, and
instead compares the index buffer value against 0xFF for byte-size
buffers, 0xFFFF for short-size buffers, or 0xFFFFFFFF for unsigned
integer buffers.

OpenGL allows the restart index to be an arbitrary unsigned integer.
When comparing against byte/short types, the index buffer value should
be promoted to a full 32-bit integer before doing the comparison.  The
restart index is /not/ supposed to be masked to byte/short size.

This means that with certain restart indexes, the comparison should
always fail.  For example, a restart index of 0xF000FFFF should never
match any byte/short index buffer values due to the extra high bits.

We must not enable hardware primitive restart in such a case.  For now,
fall back to software primitive restart as it's the simplest fix.  In
the future, we could detect restart indexes that will never match and
skip both hardware and software primitive restart.

NOTE: This is a candidate for stable branches.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_primitive_restart.c

index 85c5147c89007fc12813189ba702512ace3e1061..e9265388fc94f0ae408951c3619267acd2725d51 100644 (file)
@@ -43,17 +43,23 @@ static bool
 can_cut_index_handle_restart_index(struct gl_context *ctx,
                                    const struct _mesa_index_buffer *ib)
 {
+   /* The FixedIndex variant means 0xFF, 0xFFFF, or 0xFFFFFFFF based on
+    * the index buffer type, which corresponds exactly to the hardware.
+    */
+   if (ctx->Array.PrimitiveRestartFixedIndex)
+      return true;
+
    bool cut_index_will_work;
 
    switch (ib->type) {
    case GL_UNSIGNED_BYTE:
-      cut_index_will_work = (ctx->Array._RestartIndex & 0xff) == 0xff;
+      cut_index_will_work = ctx->Array.RestartIndex == 0xff;
       break;
    case GL_UNSIGNED_SHORT:
-      cut_index_will_work = (ctx->Array._RestartIndex & 0xffff) == 0xffff;
+      cut_index_will_work = ctx->Array.RestartIndex == 0xffff;
       break;
    case GL_UNSIGNED_INT:
-      cut_index_will_work = ctx->Array._RestartIndex == 0xffffffff;
+      cut_index_will_work = ctx->Array.RestartIndex == 0xffffffff;
       break;
    default:
       cut_index_will_work = false;