aboutsummaryrefslogtreecommitdiff
path: root/src/mesa/tnl/t_vertex.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl/t_vertex.c')
-rw-r--r--src/mesa/tnl/t_vertex.c109
1 files changed, 102 insertions, 7 deletions
diff --git a/src/mesa/tnl/t_vertex.c b/src/mesa/tnl/t_vertex.c
index 900648a..6245f70 100644
--- a/src/mesa/tnl/t_vertex.c
+++ b/src/mesa/tnl/t_vertex.c
@@ -871,6 +871,107 @@ static void generic_emit( GLcontext *ctx,
}
+#define FUSED_EMIT( NAME, COLSZ, HAVE_TEX ) \
+static void NAME( GLcontext *ctx, GLuint start, GLuint end, \
+ void *dest ) \
+{ \
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); \
+ const struct tnl_clipspace_attr *a = vtx->attr; \
+ const GLfloat * const vp = a[0].vp; \
+ const GLubyte *pos_ptr = a[0].inputptr; \
+ const GLubyte *col_ptr = a[1].inputptr; \
+ const GLubyte *tex_ptr = HAVE_TEX ? a[2].inputptr : NULL; \
+ const GLuint pos_stride = a[0].inputstride; \
+ const GLuint col_stride = a[1].inputstride; \
+ const GLuint tex_stride = HAVE_TEX ? a[2].inputstride : 0; \
+ const GLuint pos_off = a[0].vertoffset; \
+ const GLuint col_off = a[1].vertoffset; \
+ const GLuint tex_off = HAVE_TEX ? a[2].vertoffset : 0; \
+ const GLuint stride = vtx->vertex_size; \
+ GLubyte *v = (GLubyte *)dest; \
+ GLuint i; \
+ \
+ end -= start; \
+ \
+ for (i = 0; i < end; i++, v += stride) { \
+ { \
+ const GLfloat *in = (const GLfloat *)pos_ptr; \
+ GLfloat *out = (GLfloat *)(v + pos_off); \
+ \
+ out[0] = vp[0] * in[0] + vp[12]; \
+ out[1] = vp[5] * in[1] + vp[13]; \
+ out[2] = vp[10] * in[2] + vp[14]; \
+ out[3] = in[3]; \
+ pos_ptr += pos_stride; \
+ } \
+ { \
+ const GLfloat *in = (const GLfloat *)col_ptr; \
+ GLchan *c = (GLchan *)(v + col_off); \
+ \
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); \
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); \
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); \
+ if (COLSZ == 4) { \
+ UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]); \
+ } \
+ else \
+ c[3] = CHAN_MAX; \
+ col_ptr += col_stride; \
+ } \
+ if (HAVE_TEX) { \
+ const GLfloat *in = (const GLfloat *)tex_ptr; \
+ GLfloat *out = (GLfloat *)(v + tex_off); \
+ \
+ out[0] = in[0]; \
+ out[1] = in[1]; \
+ out[2] = 0; \
+ out[3] = 1; \
+ tex_ptr += tex_stride; \
+ } \
+ } \
+}
+
+FUSED_EMIT( emit_viewport4_rgba3, 3, 0 )
+FUSED_EMIT( emit_viewport4_rgba4, 4, 0 )
+FUSED_EMIT( emit_viewport4_rgba3_st, 3, 1 )
+FUSED_EMIT( emit_viewport4_rgba4_st, 4, 1 )
+
+#undef FUSED_EMIT
+
+/* Match the installed attribute map plus this flush's input vector
+ * sizes against the fused layouts above; anything else takes
+ * generic_emit.
+ */
+static tnl_emit_func choose_emit_func( struct tnl_clipspace *vtx,
+ struct vertex_buffer *VB )
+{
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint count = vtx->attr_count;
+ GLuint colsz;
+
+ if (count < 2 || count > 3 ||
+ a[0].format != EMIT_4F_VIEWPORT ||
+ VB->AttribPtr[a[0].attrib]->size != 4 ||
+ a[1].attrib != VERT_ATTRIB_COLOR0 ||
+ a[1].format != EMIT_4CHAN_4F_RGBA)
+ return generic_emit;
+
+ colsz = VB->AttribPtr[a[1].attrib]->size;
+ if (colsz != 3 && colsz != 4)
+ return generic_emit;
+
+ if (count == 3) {
+ if (a[2].format != EMIT_4F ||
+ VB->AttribPtr[a[2].attrib]->size != 2)
+ return generic_emit;
+ return (colsz == 4) ? emit_viewport4_rgba4_st
+ : emit_viewport4_rgba3_st;
+ }
+
+ return (colsz == 4) ? emit_viewport4_rgba4 : emit_viewport4_rgba3;
+}
+
+
static void generic_interp( GLcontext *ctx,
GLfloat t,
GLuint edst, GLuint eout, GLuint ein,
@@ -1030,13 +1131,7 @@ static void do_emit( GLcontext *ctx, GLuint start, GLuint end,
a[j].emit = a[j].insert[vptr->size - 1];
}
- vtx->emit = 0;
-
- if (0)
- vtx->emit = _tnl_codegen_emit(ctx);
-
- if (!vtx->emit)
- vtx->emit = generic_emit;
+ vtx->emit = choose_emit_func( vtx, VB );
vtx->emit( ctx, start, end, dest );
}