i965: Add support for GL_FIXED vertex attributes.
authorEric Anholt <eric@anholt.net>
Wed, 8 Jun 2011 20:44:00 +0000 (13:44 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 10 Jun 2011 20:17:10 +0000 (13:17 -0700)
This sadly requires work in the VS to rescale them, because the
hardware doesn't support this format natively.

Fixes arb_es2_compatibility-fixed-type and gtf/fixed_data_type.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/drivers/dri/i965/brw_draw_upload.c
src/mesa/drivers/dri/i965/brw_vs.c
src/mesa/drivers/dri/i965/brw_vs.h
src/mesa/drivers/dri/i965/brw_vs_emit.c

index 3cc3372048664788ac4809be295f3ae0d0df62a6..c6e5395106959a823e8a290a9c8356f81b65c958 100644 (file)
@@ -207,6 +207,10 @@ static GLuint get_surface_type( GLenum type, GLuint size,
       case GL_UNSIGNED_INT: return uint_types_scale[size];
       case GL_UNSIGNED_SHORT: return ushort_types_scale[size];
       case GL_UNSIGNED_BYTE: return ubyte_types_scale[size];
+      /* This produces GL_FIXED inputs as values between INT32_MIN and
+       * INT32_MAX, which will be scaled down by 1/65536 by the VS.
+       */
+      case GL_FIXED: return int_types_scale[size];
       default: assert(0); return 0;
       }
    }
@@ -225,6 +229,7 @@ static GLuint get_size( GLenum type )
    case GL_UNSIGNED_INT: return sizeof(GLuint);
    case GL_UNSIGNED_SHORT: return sizeof(GLushort);
    case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
+   case GL_FIXED: return sizeof(GLuint);
    default: assert(0); return 0;
    }
 }
index d6a539955317c3c0b5243ffee23716b4bb64afad..80d5e78ed0bcbeefeb75ec8ba6db3c57dd163beb 100644 (file)
@@ -145,6 +145,14 @@ static void brw_upload_vs_prog(struct brw_context *brw)
       }
    }
 
+   /* BRW_NEW_VERTICES */
+   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      if (vp->program.Base.InputsRead & (1 << i) &&
+         brw->vb.inputs[i].glarray->Type == GL_FIXED) {
+        key.gl_fixed_input_size[i] = brw->vb.inputs[i].glarray->Size;
+      }
+   }
+
    /* Make an early check for the key.
     */
    drm_intel_bo_unreference(brw->vs.prog_bo);
@@ -164,7 +172,8 @@ const struct brw_tracked_state brw_vs_prog = {
    .dirty = {
       .mesa  = (_NEW_TRANSFORM | _NEW_POLYGON | _NEW_POINT | _NEW_LIGHT |
                _NEW_BUFFERS),
-      .brw   = BRW_NEW_VERTEX_PROGRAM,
+      .brw   = (BRW_NEW_VERTEX_PROGRAM |
+               BRW_NEW_VERTICES),
       .cache = 0
    },
    .prepare = brw_upload_vs_prog
index 7ca84a54b01b1fd0d5ffad69bb1484a12b8aaa2a..432994a8534cf26a15b4a3f27e15f0a633f16a69 100644 (file)
 
 struct brw_vs_prog_key {
    GLuint program_string_id;
+   /**
+    * Number of channels of the vertex attribute that need GL_FIXED rescaling
+    */
+   uint8_t gl_fixed_input_size[VERT_ATTRIB_MAX];
    GLuint nr_userclip:4;
    GLuint copy_edgeflag:1;
    GLuint point_coord_replace:8;
index 7d5eb353eee938f70af89fe1bb9058ccd2298865..b6c9e5a1ceb610496d803f4e6184951d646ad3f5 100644 (file)
@@ -1878,6 +1878,26 @@ get_predicate(const struct prog_instruction *inst)
    }
 }
 
+static void
+brw_vs_rescale_gl_fixed(struct brw_vs_compile *c)
+{
+   struct brw_compile *p = &c->func;
+   int i;
+
+   for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+      if (!(c->prog_data.inputs_read & (1 << i)))
+        continue;
+
+      if (c->key.gl_fixed_input_size[i] != 0) {
+        struct brw_reg reg = c->regs[PROGRAM_INPUT][i];
+
+        brw_MUL(p,
+                brw_writemask(reg, (1 << c->key.gl_fixed_input_size[i]) - 1),
+                reg, brw_imm_f(1.0 / 65536.0));
+      }
+   }
+}
+
 /* Emit the vertex program instructions here.
  */
 void brw_vs_emit(struct brw_vs_compile *c )
@@ -1937,6 +1957,8 @@ void brw_vs_emit(struct brw_vs_compile *c )
     */
    brw_vs_alloc_regs(c);
 
+   brw_vs_rescale_gl_fixed(c);
+
    if (c->needs_stack)
       brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack));