Fix crash in book/stencil.
authorKeith Whitwell <keith@tungstengraphics.com>
Sat, 13 Jan 2001 05:48:25 +0000 (05:48 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Sat, 13 Jan 2001 05:48:25 +0000 (05:48 +0000)
Allow drivers to perform the perspective divide themselves.  Assembly
to do cliptesting without perspective divide for size-4 vectors.

13 files changed:
src/mesa/main/light.c
src/mesa/main/lines.c
src/mesa/math/m_clip_tmp.h
src/mesa/math/m_xform.c
src/mesa/math/m_xform.h
src/mesa/tnl/t_context.c
src/mesa/tnl/t_context.h
src/mesa/tnl/t_imm_exec.c
src/mesa/tnl/t_vb_cliptmp.h
src/mesa/tnl/t_vb_vertex.c
src/mesa/tnl/tnl.h
src/mesa/x86/x86.c
src/mesa/x86/x86_cliptest.S

index 1eed79bc2a7df41923c64b8f30772070ea19a7d8..bee9f0d807b14a2b8b2fc2969abc402ea0047266 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: light.c,v 1.33 2001/01/04 16:22:18 brianp Exp $ */
+/* $Id: light.c,v 1.34 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -1050,14 +1050,12 @@ static void validate_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
    struct gl_shine_tab *list = ctx->_ShineTabList;
    struct gl_shine_tab *s;
 
-/*     fprintf(stderr, "validate_shine_table %d, shininess %f\n", i, shininess); */
-
    foreach(s, list)
       if ( s->shininess == shininess )
         break;
 
    if (s == list) {
-      GLint i;
+      GLint j;
       GLfloat *m;
 
       foreach(s, list)
@@ -1067,19 +1065,19 @@ static void validate_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
       m = s->tab;
       m[0] = 0.0;
       if (shininess == 0.0) {
-        for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
-           m[i] = 1.0;
+        for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
+           m[j] = 1.0;
       }
       else {
-        for (i = 1 ; i < SHINE_TABLE_SIZE ; i++) {
-            GLdouble t, x = i / (GLfloat) (SHINE_TABLE_SIZE - 1);
+        for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
+            GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
             if (x < 0.005) /* underflow check */
                x = 0.005;
             t = pow(x, shininess);
            if (t > 1e-20)
-              m[i] = t;
+              m[j] = t;
            else
-              m[i] = 0.0;
+              m[j] = 0.0;
         }
         m[SHINE_TABLE_SIZE] = 1.0;
       }
index 730e3f572f91f2de2e666eb12b0d67b34e418207..8a9256c1789bc973dae77b630d5473b183a82cb3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: lines.c,v 1.25 2001/01/08 04:09:41 keithw Exp $ */
+/* $Id: lines.c,v 1.26 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -79,12 +79,14 @@ _mesa_LineStipple( GLint factor, GLushort pattern )
    GET_CURRENT_CONTEXT(ctx);
    ASSERT_OUTSIDE_BEGIN_END(ctx);
 
-   if (ctx->Line.StippleFactor == CLAMP( factor, 1, 256 ) &&
+   factor = CLAMP( factor, 1, 256 );
+
+   if (ctx->Line.StippleFactor == factor &&
        ctx->Line.StipplePattern == pattern)
       return;
 
    FLUSH_VERTICES(ctx, _NEW_LINE);
-   ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
+   ctx->Line.StippleFactor = factor;
    ctx->Line.StipplePattern = pattern;
 
    if (ctx->Driver.LineStipple)
index d977698da5709af621be1260d0c78f9183ac44f2..87571541989971b3f9755a4b992e7db295004f84 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: m_clip_tmp.h,v 1.2 2000/12/26 05:09:31 keithw Exp $ */
+/* $Id: m_clip_tmp.h,v 1.3 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -100,6 +100,59 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec,
    return proj_vec;
 }
 
+
+
+static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec, 
+                                                       GLvector4f *proj_vec, 
+                                                       GLubyte clipMask[],
+                                                       GLubyte *orMask, 
+                                                       GLubyte *andMask )
+{
+   const GLuint stride = clip_vec->stride;
+   const GLfloat *from = (GLfloat *)clip_vec->start;
+   const GLuint count = clip_vec->count;
+   GLuint c = 0;
+   GLubyte tmpAndMask = *andMask;
+   GLubyte tmpOrMask = *orMask;
+   GLuint i;
+   STRIDE_LOOP {
+      const GLfloat cx = from[0];
+      const GLfloat cy = from[1];
+      const GLfloat cz = from[2];
+      const GLfloat cw = from[3];
+#if defined(macintosh)
+      /* on powerpc cliptest is 17% faster in this way. */
+      GLuint mask;
+      mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
+      mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
+      mask |= (((cw < cy) << CLIP_TOP_SHIFT));
+      mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
+      mask |= (((cw < cz) << CLIP_FAR_SHIFT));
+      mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
+#else /* !defined(macintosh)) */
+      GLubyte mask = 0;
+      if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
+      if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
+      if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
+      if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
+      if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
+      if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
+#endif /* defined(macintosh) */
+
+      clipMask[i] = mask;
+      if (mask) {
+        c++;
+        tmpAndMask &= mask;
+        tmpOrMask |= mask;
+      }         
+   }
+
+   *orMask = tmpOrMask;
+   *andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
+   return clip_vec;
+}
+
+
 static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec, 
                                           GLvector4f *proj_vec, 
                                           GLubyte clipMask[],
@@ -132,6 +185,7 @@ static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec,
    return clip_vec;
 }
 
+
 static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec, 
                                           GLvector4f *proj_vec, 
                                           GLubyte clipMask[],
@@ -168,4 +222,8 @@ static void TAG(init_c_cliptest)( void )
    gl_clip_tab[4] = TAG(cliptest_points4);
    gl_clip_tab[3] = TAG(cliptest_points3);
    gl_clip_tab[2] = TAG(cliptest_points2);
+
+   gl_clip_np_tab[4] = TAG(cliptest_np_points4);
+   gl_clip_np_tab[3] = TAG(cliptest_points3);
+   gl_clip_np_tab[2] = TAG(cliptest_points2);
 }
index 77acce922e4758adf647954dac5dd2ea0aa0b309..a51037741fb22bc669efe97102622bed549d2b1e 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: m_xform.c,v 1.6 2001/01/08 04:09:41 keithw Exp $ */
+/* $Id: m_xform.c,v 1.7 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -57,6 +57,7 @@
 #endif
 
 clip_func gl_clip_tab[5];
+clip_func gl_clip_np_tab[5];
 dotprod_func gl_dotprod_tab[2][5];
 vec_copy_func gl_copy_tab[2][0x10];
 normal_func gl_normal_tab[0xf][0x4];
index 4024949257f64e90bde9e86b88b2db785b9613c4..f6b10d6ad369a234545388bdcc532aec296517d8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: m_xform.h,v 1.4 2001/01/05 05:31:42 keithw Exp $ */
+/* $Id: m_xform.h,v 1.5 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -201,6 +201,7 @@ extern dotprod_func  gl_dotprod_tab[2][5];
 extern vec_copy_func gl_copy_tab[2][0x10];
 extern vec_copy_func gl_copy_clean_tab[2][5];
 extern clip_func     gl_clip_tab[5];
+extern clip_func     gl_clip_np_tab[5];
 extern normal_func   gl_normal_tab[0xf][0x4];
 
 /* Use of 3 layers of linked 1-dimensional arrays to reduce
index 93886b71101daf986342a6284a09bf03a879da3b..e0d254edf335eb326d4beb455057acbf119503e6 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_context.c,v 1.9 2001/01/08 21:56:00 keithw Exp $ */
+/* $Id: t_context.c,v 1.10 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -104,6 +104,8 @@ _tnl_CreateContext( GLcontext *ctx )
    _tnl_eval_init( ctx );
    _tnl_install_pipeline( ctx, _tnl_default_pipeline );
 
+
+   tnl->NeedProjCoords = GL_TRUE;
     
    /* Hook our functions into exec and compile dispatch tables.
     */
@@ -195,3 +197,13 @@ _tnl_wakeup_save_exec( GLcontext *ctx )
    ctx->Save->Begin = _tnl_save_Begin;
 }
 
+
+void
+_tnl_need_projected_coords( GLcontext *ctx, GLboolean mode )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   if (tnl->NeedProjCoords != mode) {
+      tnl->NeedProjCoords = mode;
+      _tnl_InvalidateState( ctx, _NEW_PROJECTION );
+   }
+}
index 8e3952a41275a802217dcdaf8b4ed9f02accdc1d..d49c854241850f45a9c6c8627919603d62beeb73 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_context.h,v 1.9 2001/01/05 02:26:49 keithw Exp $ */
+/* $Id: t_context.h,v 1.10 2001/01/13 05:48:26 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -412,6 +412,10 @@ typedef struct {
    GLuint DlistPrimitiveLength;
    GLuint DlistLastPrimitive;
 
+   /* Probably need a better configuration mechanism:
+    */
+   GLboolean NeedProjCoords;
+
    /* Derived state and storage for _tnl_eval_vb:
     */
    struct tnl_eval_store eval;
index e8904dfd1ec8f746db12a8cd70b20e58b4c0e74f..6feff8464fd7e62af94b26ae7ef50a9e88f6aea0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_imm_exec.c,v 1.6 2001/01/08 21:56:00 keithw Exp $ */
+/* $Id: t_imm_exec.c,v 1.7 2001/01/13 05:48:26 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -357,16 +357,21 @@ static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
  */
 void _tnl_run_empty_cassette( GLcontext *ctx, struct immediate *IM )
 {
-   GLuint start = IM->CopyStart;
-
    copy_to_current( ctx, IM, IM->OrFlag ); 
 
-   if (IM->OrFlag & VERT_MATERIAL) 
-      gl_update_material( ctx, IM->Material[start], IM->MaterialMask[start] );
+   if (IM->OrFlag & (VERT_RGBA|VERT_MATERIAL)) {
+      GLuint start = IM->CopyStart;
 
-   if (IM->OrFlag & VERT_RGBA) 
-      if (ctx->Light.ColorMaterialEnabled)
-        gl_update_color_material( ctx, ctx->Current.Color );
+      if (IM->OrFlag & VERT_MATERIAL) 
+        gl_update_material( ctx, IM->Material[start], 
+                            IM->MaterialMask[start] );
+      
+      if (IM->OrFlag & VERT_RGBA) 
+        if (ctx->Light.ColorMaterialEnabled)
+           gl_update_color_material( ctx, ctx->Current.Color );
+
+      gl_validate_all_lighting_tables( ctx );
+   }
 }
 
 
index 5957f4960cca6096a9887ada0f33e15f214a20fe..56f2031c90e0c14a3a3769547f5b341c4158574b 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_vb_cliptmp.h,v 1.5 2001/01/05 02:26:49 keithw Exp $ */
+/* $Id: t_vb_cliptmp.h,v 1.6 2001/01/13 05:48:26 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -115,29 +115,32 @@ do {                                                              \
 } while (0)
 
 
-/* Project if necessary.
- */
 static void TAG(build_proj_verts)( GLcontext *ctx )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
-   GLfloat (*coord)[4] = VB->ClipPtr->data;
-   GLfloat (*proj)[4] = VB->ProjectedClipPtr->data;
-   GLuint last = VB->LastClipped;
-   GLuint i;
-
-   for (i = VB->FirstClipped; i < last; i++) {
-      if (VB->ClipMask[i] == 0) {
-        if (SIZE == 4 && W(i) != 0.0F) {
-           GLfloat wInv = 1.0F / W(i);
-           proj[i][0] = X(i) * wInv;
-           proj[i][1] = Y(i) * wInv;
-           proj[i][2] = Z(i) * wInv;
-           proj[i][3] = wInv;
-        } else {
-           proj[i][0] = X(i);
-           proj[i][1] = Y(i);
-           proj[i][2] = Z(i);
-           proj[i][3] = W(i);
+
+   /* Project if necessary.
+    */
+   if (VB->ProjectedClipPtr) {
+      GLfloat (*coord)[4] = VB->ClipPtr->data;
+      GLfloat (*proj)[4] = VB->ProjectedClipPtr->data;
+      GLuint last = VB->LastClipped;
+      GLuint i;
+
+      for (i = VB->FirstClipped; i < last; i++) {
+        if (VB->ClipMask[i] == 0) {
+           if (SIZE == 4 && W(i) != 0.0F) {
+              GLfloat wInv = 1.0F / W(i);
+              proj[i][0] = X(i) * wInv;
+              proj[i][1] = Y(i) * wInv;
+              proj[i][2] = Z(i) * wInv;
+              proj[i][3] = wInv;
+           } else {
+              proj[i][0] = X(i);
+              proj[i][1] = Y(i);
+              proj[i][2] = Z(i);
+              proj[i][3] = W(i);
+           }
         }
       }
    }
index 7667d423a8be516340eccd92fff57ec8ce70fca3..0c163ee4f313b9ca3910d794716d534f4869f587 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: t_vb_vertex.c,v 1.1 2000/12/26 05:09:33 keithw Exp $ */
+/* $Id: t_vb_vertex.c,v 1.2 2001/01/13 05:48:26 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -134,7 +134,8 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
                                   struct gl_pipeline_stage *stage )
 {
    struct vertex_stage_data *store = (struct vertex_stage_data *)stage->private;
-   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; 
+   TNLcontext *tnl = TNL_CONTEXT(ctx); 
+   struct vertex_buffer *VB = &tnl->vb; 
    
    if (stage->changed_inputs) 
    {
@@ -172,12 +173,36 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
       store->ormask = 0;
       store->andmask = CLIP_ALL_BITS;
 
-      VB->ProjectedClipPtr = 
-        gl_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
-                                        &store->proj,
-                                        store->clipmask,
-                                        &store->ormask,
-                                        &store->andmask );
+      if (tnl->NeedProjCoords) {
+        VB->ProjectedClipPtr = 
+           gl_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+                                           &store->proj,
+                                           store->clipmask,
+                                           &store->ormask,
+                                           &store->andmask );
+
+        /* Drivers expect this to be size 4...
+         */
+        if (VB->ProjectedClipPtr->size < 4) {
+           ASSERT(VB->ProjectedClipPtr == VB->ClipPtr);
+           if (VB->ProjectedClipPtr->flags & VEC_NOT_WRITEABLE) {
+              ASSERT(VB->ProjectedClipPtr == VB->ObjPtr);
+              VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE );
+              VB->ProjectedClipPtr = VB->ClipPtr = VB->ObjPtr;
+           }
+           if (VB->ClipPtr->size == 2) 
+              gl_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+           gl_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+           VB->ClipPtr->size = 4;
+        }
+      } else {
+        VB->ProjectedClipPtr = 0;
+        gl_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+                                           0,
+                                           store->clipmask,
+                                           &store->ormask,
+                                           &store->andmask );
+      }
 
       if (store->andmask) 
         return GL_FALSE;
@@ -203,21 +228,6 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
       if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_OBJ))
         VB->importable_data |= VERT_CLIP;
 
-      /* Drivers expect this to be size 4...
-       */
-      if (VB->ProjectedClipPtr->size < 4) {
-        ASSERT(VB->ProjectedClipPtr == VB->ClipPtr);
-        if (VB->ProjectedClipPtr->flags & VEC_NOT_WRITEABLE) {
-           ASSERT(VB->ProjectedClipPtr == VB->ObjPtr);
-           VB->import_data( ctx, VERT_OBJ, VEC_NOT_WRITEABLE );
-           VB->ProjectedClipPtr = VB->ClipPtr = VB->ObjPtr;
-        }
-        if (VB->ClipPtr->size == 2) 
-           gl_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
-        gl_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
-        VB->ClipPtr->size = 4;
-      }
-
       store->save_eyeptr = VB->EyePtr;
       store->save_clipptr = VB->ClipPtr;
       store->save_projptr = VB->ProjectedClipPtr;
index f95ce0e5037a8db556525352bbab9ddacb694c9e..eb8e9054a9c53cb5f25c296741eba7769529337e 100644 (file)
@@ -59,17 +59,7 @@ _tnl_wakeup_exec( GLcontext *ctx );
 extern void
 _tnl_wakeup_save_exec( GLcontext *ctx );
 
-
-/* Functions to assist driver t&l modules which have to fallback to
- * this module in the middle of a begin/end pair.  Use this instead of
- * glBegin() to identify the primitive as wrapped:
- *
- * Even with this it's difficult to see how the drivers are going to
- * replay any glMaterial commands received in the few vertices before
- * the fallback.
- */
 extern void
-_tnl_fallback_begin( GLcontext *ctx, GLenum mode );
-
+_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag );
 
 #endif
index fd8a22482268aae4061c4f661b44e3c4f9134854..b49965f6b3323a099d02c1ebab8a6d9f04160a18 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: x86.c,v 1.14 2000/12/27 19:57:37 keithw Exp $ */
+/* $Id: x86.c,v 1.15 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -93,6 +93,13 @@ extern GLvector4f * _ASMAPI gl_x86_cliptest_points4( GLvector4f *clip_vec,
                                                     GLubyte *andMask );
 
 
+extern GLvector4f * _ASMAPI gl_x86_cliptest_points4_np( GLvector4f *clip_vec,
+                                                       GLvector4f *proj_vec,
+                                                       GLubyte clipMask[],
+                                                       GLubyte *orMask,
+                                                       GLubyte *andMask );
+
+
 extern void _ASMAPI gl_v16_x86_cliptest_points4( GLfloat *first_vert,
                                                 GLfloat *last_vert,
                                                 GLubyte *or_mask,
@@ -121,6 +128,7 @@ void gl_init_x86_transform_asm( void )
 
    /* XXX this function has been found to cause FP overflow exceptions */
    gl_clip_tab[4] = gl_x86_cliptest_points4;
+   gl_clip_np_tab[4] = gl_x86_cliptest_points4_np;
 
 #ifdef DEBUG
    gl_test_all_transform_functions( "x86" );
index 0258a9b636a99c5f87863da217666d79b4bceaec..8679bcb11e618080c3b42cc512d2b733e923428f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: x86_cliptest.S,v 1.3 2000/12/26 05:09:31 keithw Exp $ */
+/* $Id: x86_cliptest.S,v 1.4 2001/01/13 05:48:25 keithw Exp $ */
 
 /*
  * Mesa 3-D graphics library
@@ -246,3 +246,163 @@ LLBL( ctp4_finish ):
        POP_L( ESI )
 
        RET
+
+
+
+
+
+
+
+ALIGNTEXT16
+GLOBL GLNAME( gl_x86_cliptest_points4_np )
+GLNAME( gl_x86_cliptest_points4_np ):
+
+#ifdef ELFPIC
+#define FRAME_OFFSET 20
+#else
+#define FRAME_OFFSET 16
+#endif
+       PUSH_L( ESI )
+       PUSH_L( EDI )
+       PUSH_L( EBP )
+       PUSH_L( EBX )
+
+#ifdef ELFPIC
+       /* store pointer to clip_table on stack */
+       CALL( LLBL( ctp4_np_get_eip ) )
+       ADD_L( CONST(_GLOBAL_OFFSET_TABLE_), EBX )
+       MOV_L( REGOFF(clip_table@GOT, EBX), EBX )
+       PUSH_L( EBX )
+       JMP( LLBL( ctp4_np_clip_table_ready ) )
+
+LLBL( ctp4_np_get_eip ):
+       /* store eip in ebx */
+       MOV_L( REGIND(ESP), EBX )
+       RET
+
+LLBL( ctp4_np_clip_table_ready ):
+#endif
+
+       MOV_L( ARG_SOURCE, ESI )
+       /* slot */
+
+       MOV_L( ARG_CLIP, EDX )
+       MOV_L( ARG_OR, EBX )
+
+       MOV_L( ARG_AND, EBP )
+       MOV_L( REGOFF(V4F_STRIDE, ESI), EAX )
+
+       MOV_L( REGOFF(V4F_COUNT, ESI), ECX )
+       MOV_L( REGOFF(V4F_START, ESI), ESI )
+
+       MOV_L( EAX, ARG_DEST )          /* put stride in ARG_DEST */
+       ADD_L( EDX, ECX )
+
+       MOV_L( ECX, EDI )               /* put clipmask + count in EDI */
+       CMP_L( ECX, EDX )
+
+       MOV_B( REGIND(EBX), AL )
+       MOV_B( REGIND(EBP), AH )
+
+       JZ( LLBL( ctp4_np_finish ) )
+
+ALIGNTEXT16
+LLBL( ctp4_np_top ):
+
+       MOV_L( SRC(3), EBP )
+       MOV_L( SRC(2), EBX )
+
+       XOR_L( ECX, ECX )
+       ADD_L( EBP, EBP )       /* ebp = abs(S(3))*2 ; carry = sign of S(3) */
+
+       ADC_L( ECX, ECX )
+       ADD_L( EBX, EBX )       /* ebx = abs(S(2))*2 ; carry = sign of S(2) */
+
+       ADC_L( ECX, ECX )
+       CMP_L( EBX, EBP )       /* carry = abs(S(2))*2 > abs(S(3))*2 */
+
+       ADC_L( ECX, ECX )
+       MOV_L( SRC(1), EBX )
+
+       ADD_L( EBX, EBX )       /* ebx = abs(S(1))*2 ; carry = sign of S(1) */
+
+       ADC_L( ECX, ECX )
+       CMP_L( EBX, EBP )       /* carry = abs(S(1))*2 > abs(S(3))*2 */
+
+       ADC_L( ECX, ECX )
+       MOV_L( SRC(0), EBX )
+
+       ADD_L( EBX, EBX )       /* ebx = abs(S(0))*2 ; carry = sign of S(0) */
+
+       ADC_L( ECX, ECX )
+       CMP_L( EBX, EBP )       /* carry = abs(S(0))*2 > abs(S(3))*2 */
+
+       ADC_L( ECX, ECX )
+
+#ifdef ELFPIC
+       MOV_L( REGIND(ESP), EBP )       /* clip_table */
+
+       MOV_B( REGBI(EBP, ECX), CL )
+#else
+       MOV_B( REGOFF(clip_table,ECX), CL )
+#endif
+
+       OR_B( CL, AL )
+       AND_B( CL, AH )
+
+       TEST_B( CL, CL )
+       MOV_B( CL, REGIND(EDX) )
+
+       INC_L( EDX )
+       /* slot */
+
+       ADD_L( ARG_DEST, ESI )
+       CMP_L( EDX, EDI )
+
+       JNZ( LLBL( ctp4_np_top ) )
+
+       MOV_L( ARG_OR, ECX )
+       MOV_L( ARG_AND, EDX )
+
+       MOV_B( AL, REGIND(ECX) )
+       MOV_B( AH, REGIND(EDX) )
+
+LLBL( ctp4_np_finish ):
+
+       MOV_L( ARG_SOURCE, EAX )
+#ifdef ELFPIC
+       POP_L( ESI )                    /* discard ptr to clip_table */
+#endif
+       POP_L( EBX )
+       POP_L( EBP )
+       POP_L( EDI )
+       POP_L( ESI )
+
+       RET
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+       
+
+
+
+
+
+
+
+
+
+       
\ No newline at end of file