Merge remote branch 'origin/master' into pipe-video
[mesa.git] / src / mesa / tnl / t_vertex_sse.c
index 733d462901b09d0d215fb4c381259200eb7e90e1..93189656f74733c4d92d7a2327fc4eef2663c3bf 100644 (file)
  *    Keith Whitwell <keithw@tungstengraphics.com>
  */
 
-#include "glheader.h"
-#include "context.h"
-#include "colormac.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
 #include "t_context.h"
 #include "t_vertex.h"
-#include "simple_list.h"
-#include "enums.h"
 
 #if defined(USE_SSE_ASM)
 
 #include "x86/common_x86_asm.h"
 
 
+/**
+ * Number of bytes to allocate for generated SSE functions
+ */
+#define MAX_SSE_CODE_SIZE 1024
+
+
 #define X    0
 #define Y    1
 #define Z    2
@@ -48,7 +54,7 @@
 struct x86_program {
    struct x86_function func;
 
-   GLcontext *ctx;
+   struct gl_context *ctx;
    GLboolean inputs_safe;
    GLboolean outputs_safe;
    GLboolean have_sse2;
@@ -82,8 +88,8 @@ static void emit_load4f_3( struct x86_program *p,
     * a b c 1
     */
    sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
-   sse_shufps(&p->func, dest, get_identity(p), X,Y,Z,W );
-   sse_shufps(&p->func, dest, dest, Y,Z,X,W );
+   sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+   sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
    sse_movlps(&p->func, dest, arg0);
 }
 
@@ -103,7 +109,7 @@ static void emit_load4f_1( struct x86_program *p,
 {
    /* Pull in low word, then swizzle in identity */
    sse_movss(&p->func, dest, arg0);
-   sse_shufps(&p->func, dest, get_identity(p), X,Y,Z,W );
+   sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
 }
 
 
@@ -124,7 +130,7 @@ static void emit_load3f_3( struct x86_program *p,
        * a b c c 
        */
       sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
-      sse_shufps(&p->func, dest, dest, X,X,X,X);
+      sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
       sse_movlps(&p->func, dest, arg0);
    }
 }
@@ -140,7 +146,8 @@ static void emit_load3f_1( struct x86_program *p,
                           struct x86_reg dest,
                           struct x86_reg arg0 )
 {
-   emit_load4f_1(p, dest, arg0);
+   /* Loading from memory erases the upper bits. */
+   sse_movss(&p->func, dest, arg0);
 }
 
 static void emit_load2f_2( struct x86_program *p, 
@@ -154,7 +161,8 @@ static void emit_load2f_1( struct x86_program *p,
                           struct x86_reg dest,
                           struct x86_reg arg0 )
 {
-   emit_load4f_1(p, dest, arg0);
+   /* Loading from memory erases the upper bits. */
+   sse_movss(&p->func, dest, arg0);
 }
 
 static void emit_load1f_1( struct x86_program *p, 
@@ -218,7 +226,7 @@ static void emit_store3f( struct x86_program *p,
       /* Alternate strategy - emit two, shuffle, emit one.
        */
       sse_movlps(&p->func, dest, arg0);
-      sse_shufps(&p->func, arg0, arg0, Z, Z, Z, Z ); /* NOTE! destructive */
+      sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
       sse_movss(&p->func, x86_make_disp(dest,8), arg0);
    }
 }
@@ -334,7 +342,7 @@ static void update_src_ptr( struct x86_program *p,
  */
 static GLboolean build_vertex_emit( struct x86_program *p )
 {
-   GLcontext *ctx = p->ctx;
+   struct gl_context *ctx = p->ctx;
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
    GLuint j = 0;
@@ -346,10 +354,9 @@ static GLboolean build_vertex_emit( struct x86_program *p )
    struct x86_reg temp = x86_make_reg(file_XMM, 0);
    struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
    struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+   struct x86_reg temp2 = x86_make_reg(file_XMM, 3);
    GLubyte *fixup, *label;
 
-   x86_init_func(&p->func);
-   
    /* Push a few regs?
     */
    x86_push(&p->func, countEBP);
@@ -471,7 +478,7 @@ static GLboolean build_vertex_emit( struct x86_program *p )
       case EMIT_3F_XYW:
         get_src_ptr(p, srcECX, vtxESI, a);
         emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
-        sse_shufps(&p->func, temp, temp, X, Y, W, Z);
+        sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
         emit_store(p, dest, 3, temp);
         update_src_ptr(p, srcECX, vtxESI, a);
         break;
@@ -484,12 +491,12 @@ static GLboolean build_vertex_emit( struct x86_program *p )
         {
            get_src_ptr(p, srcECX, vtxESI, a);
            emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
-           sse_shufps(&p->func, temp, temp, X, X, X, X);
+           sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
            emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
            update_src_ptr(p, srcECX, vtxESI, a);
         }
         else {
-           _mesa_printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+           printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
            return GL_FALSE;
         }
         break;
@@ -502,7 +509,7 @@ static GLboolean build_vertex_emit( struct x86_program *p )
            get_src_ptr(p, srcECX, vtxESI, a);
            emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
            if (a->format == EMIT_3UB_3F_BGR)
-              sse_shufps(&p->func, temp, temp, Z, Y, X, W);
+              sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
            emit_pack_store_4ub(p, dest, temp);
            update_src_ptr(p, srcECX, vtxESI, a);
         }
@@ -517,26 +524,27 @@ static GLboolean build_vertex_emit( struct x86_program *p )
 
            /* Make room for incoming value:
             */
-           sse_shufps(&p->func, temp, temp, W, X, Y, Z);
+           sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
 
            get_src_ptr(p, srcECX, vtxESI, &a[1]);
-           emit_load(p, temp, 1, x86_deref(srcECX), a[1].inputsize);
+           emit_load(p, temp2, 1, x86_deref(srcECX), a[1].inputsize);
+           sse_movss(&p->func, temp, temp2);
            update_src_ptr(p, srcECX, vtxESI, &a[1]);
 
            /* Rearrange and possibly do BGR conversion:
             */
            if (a->format == EMIT_3UB_3F_BGR)
-              sse_shufps(&p->func, temp, temp, W, Z, Y, X);
+              sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
            else
-              sse_shufps(&p->func, temp, temp, Y, Z, W, X);
+              sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
 
            emit_pack_store_4ub(p, dest, temp);
            j++;                /* NOTE: two attrs consumed */
         }
         else {
-           _mesa_printf("Can't emit 3ub\n");
+           printf("Can't emit 3ub\n");
+           return GL_FALSE;    /* add this later */
         }
-        return GL_FALSE;       /* add this later */
         break;
 
       case EMIT_4UB_4F_RGBA:
@@ -548,21 +556,21 @@ static GLboolean build_vertex_emit( struct x86_program *p )
       case EMIT_4UB_4F_BGRA:
         get_src_ptr(p, srcECX, vtxESI, a);
         emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
-        sse_shufps(&p->func, temp, temp, Z, Y, X, W);
+        sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
         emit_pack_store_4ub(p, dest, temp);
         update_src_ptr(p, srcECX, vtxESI, a);
         break;
       case EMIT_4UB_4F_ARGB:
         get_src_ptr(p, srcECX, vtxESI, a);
         emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
-        sse_shufps(&p->func, temp, temp, W, X, Y, Z);
+        sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
         emit_pack_store_4ub(p, dest, temp);
         update_src_ptr(p, srcECX, vtxESI, a);
         break;
       case EMIT_4UB_4F_ABGR:
         get_src_ptr(p, srcECX, vtxESI, a);
         emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
-        sse_shufps(&p->func, temp, temp, W, Z, Y, X);
+        sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
         emit_pack_store_4ub(p, dest, temp);
         update_src_ptr(p, srcECX, vtxESI, a);
         break;
@@ -582,12 +590,12 @@ static GLboolean build_vertex_emit( struct x86_program *p )
            break;
         case GL_UNSIGNED_SHORT:
         default:
-           _mesa_printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+           printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
            return GL_FALSE;
         }
         break;
       default:
-        _mesa_printf("unknown a[%d].format %d\n", j, a->format);
+        printf("unknown a[%d].format %d\n", j, a->format);
         return GL_FALSE;       /* catch any new opcodes */
       }
       
@@ -621,13 +629,16 @@ static GLboolean build_vertex_emit( struct x86_program *p )
    x86_pop(&p->func, countEBP);
    x86_ret(&p->func);
 
+   assert(!vtx->emit);
    vtx->emit = (tnl_emit_func)x86_get_func(&p->func);
+
+   assert( (char *) p->func.csr - (char *) p->func.store <= MAX_SSE_CODE_SIZE );
    return GL_TRUE;
 }
 
 
 
-void _tnl_generate_sse_emit( GLcontext *ctx )
+void _tnl_generate_sse_emit( struct gl_context *ctx )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
    struct x86_program p;   
@@ -641,12 +652,15 @@ void _tnl_generate_sse_emit( GLcontext *ctx )
 
    p.ctx = ctx;
    p.inputs_safe = 0;          /* for now */
-   p.outputs_safe = 1;         /* for now */
+   p.outputs_safe = 0;         /* for now */
    p.have_sse2 = cpu_has_xmm2;
    p.identity = x86_make_reg(file_XMM, 6);
    p.chan0 = x86_make_reg(file_XMM, 7);
 
-   x86_init_func(&p.func);
+   if (!x86_init_func_size(&p.func, MAX_SSE_CODE_SIZE)) {
+      vtx->emit = NULL;
+      return;
+   }
 
    if (build_vertex_emit(&p)) {
       _tnl_register_fastpath( vtx, GL_TRUE );
@@ -662,7 +676,7 @@ void _tnl_generate_sse_emit( GLcontext *ctx )
 
 #else
 
-void _tnl_generate_sse_emit( GLcontext *ctx )
+void _tnl_generate_sse_emit( struct gl_context *ctx )
 {
    /* Dummy version for when USE_SSE_ASM not defined */
 }