mesa/st: introduce PIPE_CAP_NO_CLIP_ON_COPY_TEX
[mesa.git] / src / mesa / tnl / t_vertex.c
index a6728c318fe3171be817885335216c0fc87a8d5b..0d29403a8462a6cb5cf1554b2e059215cbb09421 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003 Tungsten Graphics, inc.
+ * Copyright 2003 VMware, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
- * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * VMWARE AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
  * USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  * Authors:
- *    Keith Whitwell <keithw@tungstengraphics.com>
+ *    Keith Whitwell <keithw@vmware.com>
  */
 
-#include "glheader.h"
-#include "context.h"
-#include "colormac.h"
-
+#include <stdio.h>
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/execmem.h"
+#include "util/u_memory.h"
+#include "swrast/s_chan.h"
 #include "t_context.h"
 #include "t_vertex.h"
 
@@ -83,12 +85,22 @@ void _tnl_register_fastpath( struct tnl_clipspace *vtx,
    struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath);
    GLuint i;
 
+   if (fastpath == NULL) {
+      _mesa_error_no_memory(__func__);
+      return;
+   }
+
    fastpath->vertex_size = vtx->vertex_size;
    fastpath->attr_count = vtx->attr_count;
    fastpath->match_strides = match_strides;
    fastpath->func = vtx->emit;
-   fastpath->attr = (struct tnl_attr_type *)
-      _mesa_malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
+   fastpath->attr = malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
+
+   if (fastpath->attr == NULL) {
+      free(fastpath);
+      _mesa_error_no_memory(__func__);
+      return;
+   }
 
    for (i = 0; i < vtx->attr_count; i++) {
       fastpath->attr[i].format = vtx->attr[i].format;
@@ -106,7 +118,7 @@ void _tnl_register_fastpath( struct tnl_clipspace *vtx,
 /***********************************************************************
  * Build codegen functions or return generic ones:
  */
-static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest)
+static void choose_emit_func( struct gl_context *ctx, GLuint count, GLubyte *dest)
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
@@ -150,15 +162,17 @@ static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest)
 
 
 
-static void choose_interp_func( GLcontext *ctx,
+static void choose_interp_func( struct gl_context *ctx,
                                GLfloat t,
                                GLuint edst, GLuint eout, GLuint ein,
                                GLboolean force_boundary )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
+                         ctx->Polygon.BackMode != GL_FILL);
+   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
 
-   if (vtx->need_extras && 
-       (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+   if (vtx->need_extras && (twosided || unfilled)) {
       vtx->interp = _tnl_generic_interp_extras;
    } else {
       vtx->interp = _tnl_generic_interp;
@@ -168,12 +182,15 @@ static void choose_interp_func( GLcontext *ctx,
 }
 
 
-static void choose_copy_pv_func(  GLcontext *ctx, GLuint edst, GLuint esrc )
+static void choose_copy_pv_func(  struct gl_context *ctx, GLuint edst, GLuint esrc )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
+                         ctx->Polygon.BackMode != GL_FILL);
 
-   if (vtx->need_extras && 
-       (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
+
+   if (vtx->need_extras && (twosided || unfilled)) {
       vtx->copy_pv = _tnl_generic_copy_pv_extras;
    } else {
       vtx->copy_pv = _tnl_generic_copy_pv;
@@ -190,7 +207,7 @@ static void choose_copy_pv_func(  GLcontext *ctx, GLuint edst, GLuint esrc )
 
 /* Interpolate between two vertices to produce a third:
  */
-void _tnl_interp( GLcontext *ctx,
+void _tnl_interp( struct gl_context *ctx,
                  GLfloat t,
                  GLuint edst, GLuint eout, GLuint ein,
                  GLboolean force_boundary )
@@ -201,7 +218,7 @@ void _tnl_interp( GLcontext *ctx,
 
 /* Copy colors from one vertex to another:
  */
-void _tnl_copy_pv(  GLcontext *ctx, GLuint edst, GLuint esrc )
+void _tnl_copy_pv(  struct gl_context *ctx, GLuint edst, GLuint esrc )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
    vtx->copy_pv( ctx, edst, esrc );
@@ -212,7 +229,7 @@ void _tnl_copy_pv(  GLcontext *ctx, GLuint edst, GLuint esrc )
  * reverse any viewport transformation, swizzling or other conversions
  * which may have been applied:
  */
-void _tnl_get_attr( GLcontext *ctx, const void *vin,
+void _tnl_get_attr( struct gl_context *ctx, const void *vin,
                              GLenum attr, GLfloat *dest )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
@@ -231,19 +248,19 @@ void _tnl_get_attr( GLcontext *ctx, const void *vin,
     */
    if (attr == _TNL_ATTRIB_POINTSIZE) {
       /* If the hardware vertex doesn't have point size then use size from
-       * GLcontext.  XXX this will be wrong if drawing attenuated points!
+       * struct gl_context.  XXX this will be wrong if drawing attenuated points!
        */
       dest[0] = ctx->Point.Size;
    }
    else {
-      _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
+      memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
    }
 }
 
 
 /* Complementary operation to the above.
  */
-void _tnl_set_attr( GLcontext *ctx, void *vout,
+void _tnl_set_attr( struct gl_context *ctx, void *vout,
                    GLenum attr, const GLfloat *src )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
@@ -260,16 +277,17 @@ void _tnl_set_attr( GLcontext *ctx, void *vout,
 }
 
 
-void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
+void *_tnl_get_vertex( struct gl_context *ctx, GLuint nr )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
 
    return vtx->vertex_buf + nr * vtx->vertex_size;
 }
 
-void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
+void _tnl_invalidate_vertex_state( struct gl_context *ctx, GLuint new_state )
 {
-   if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
+   /* if two-sided lighting changes or filled/unfilled polygon state changes */
+   if (new_state & (_NEW_LIGHT | _NEW_POLYGON) ) {
       struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
       vtx->new_inputs = ~0;
       vtx->interp = choose_interp_func;
@@ -285,7 +303,7 @@ static void invalidate_funcs( struct tnl_clipspace *vtx )
    vtx->new_inputs = ~0;
 }
 
-GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
+GLuint _tnl_install_attrs( struct gl_context *ctx, const struct tnl_attr_map *map,
                           GLuint nr, const GLfloat *vp, 
                           GLuint unpacked_size )
 {
@@ -307,8 +325,8 @@ GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
       const GLuint format = map[i].format;
       if (format == EMIT_PAD) {
         if (DBG)
-           _mesa_printf("%d: pad %d, offset %d\n", i,  
-                        map[i].offset, offset);  
+           printf("%d: pad %d, offset %d\n", i,  
+                  map[i].offset, offset);  
 
         offset += map[i].offset;
 
@@ -338,9 +356,9 @@ GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
 
         
         if (DBG)
-           _mesa_printf("%d: %s, vp %p, offset %d\n", i,  
-                        _tnl_format_info[format].name, (void *)vp,
-                        vtx->attr[j].vertoffset);   
+           printf("%d: %s, vp %p, offset %d\n", i,  
+                  _tnl_format_info[format].name, (void *)vp,
+                  vtx->attr[j].vertoffset);   
 
         offset += _tnl_format_info[format].attrsize;
         j++;
@@ -360,7 +378,7 @@ GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
 
 
 
-void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
+void _tnl_invalidate_vertices( struct gl_context *ctx, GLuint newinputs )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
    vtx->new_inputs |= newinputs;
@@ -370,13 +388,29 @@ void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
 /* This event has broader use beyond this file - will move elsewhere
  * and probably invoke a driver callback.
  */
-void _tnl_notify_pipeline_output_change( GLcontext *ctx )
+void _tnl_notify_pipeline_output_change( struct gl_context *ctx )
 {
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
    invalidate_funcs(vtx);
 }
 
-static void update_input_ptrs( GLcontext *ctx, GLuint start )
+
+static void adjust_input_ptrs( struct gl_context *ctx, GLint diff)
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+   struct tnl_clipspace_attr *a = vtx->attr;
+   const GLuint count = vtx->attr_count;
+   GLuint j;
+
+   diff -= 1;
+   for (j=0; j<count; ++j) {
+           register GLvector4f *vptr = VB->AttribPtr[a->attrib];
+          (a++)->inputptr += diff*vptr->stride;
+   }
+}
+
+static void update_input_ptrs( struct gl_context *ctx, GLuint start )
 {
    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
@@ -408,7 +442,7 @@ static void update_input_ptrs( GLcontext *ctx, GLuint start )
 }
 
 
-void _tnl_build_vertices( GLcontext *ctx,
+void _tnl_build_vertices( struct gl_context *ctx,
                          GLuint start,
                          GLuint end,
                          GLuint newinputs )
@@ -423,7 +457,7 @@ void _tnl_build_vertices( GLcontext *ctx,
 /* Emit VB vertices start..end to dest.  Note that VB vertex at
  * postion start will be emitted to dest at position zero.
  */
-void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
+void *_tnl_emit_vertices_to_buffer( struct gl_context *ctx,
                                    GLuint start,
                                    GLuint end,
                                    void *dest )
@@ -431,15 +465,42 @@ void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
    struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
 
    update_input_ptrs(ctx, start);
-
    /* Note: dest should not be adjusted for non-zero 'start' values:
     */
    vtx->emit( ctx, end - start, (GLubyte*) dest );     
    return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
 }
 
+/* Emit indexed VB vertices start..end to dest.  Note that VB vertex at
+ * postion start will be emitted to dest at position zero.
+ */
+
+void *_tnl_emit_indexed_vertices_to_buffer( struct gl_context *ctx,
+                                           const GLuint *elts,
+                                           GLuint start,
+                                           GLuint end,
+                                           void *dest )
+{
+   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+   GLuint oldIndex;
+   GLubyte *cdest = dest;
+
+   update_input_ptrs(ctx, oldIndex = elts[start++]);
+   vtx->emit( ctx, 1, cdest );
+   cdest += vtx->vertex_size;
+
+   for (; start < end; ++start) {
+      adjust_input_ptrs(ctx, elts[start] - oldIndex);
+      oldIndex = elts[start];
+      vtx->emit( ctx, 1, cdest);
+      cdest += vtx->vertex_size;
+   }
+
+   return (void *) cdest;
+}
+
 
-void _tnl_init_vertices( GLcontext *ctx, 
+void _tnl_init_vertices( struct gl_context *ctx, 
                        GLuint vb_size,
                        GLuint max_vertex_size )
 {
@@ -451,7 +512,7 @@ void _tnl_init_vertices( GLcontext *ctx,
    if (max_vertex_size > vtx->max_vertex_size) {
       _tnl_free_vertices( ctx );
       vtx->max_vertex_size = max_vertex_size;
-      vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 );
+      vtx->vertex_buf = align_calloc(vb_size * max_vertex_size, 32 );
       invalidate_funcs(vtx);
    }
 
@@ -484,35 +545,36 @@ void _tnl_init_vertices( GLcontext *ctx,
    vtx->codegen_emit = NULL;
 
 #ifdef USE_SSE_ASM
-   if (!_mesa_getenv("MESA_NO_CODEGEN"))
+   if (!getenv("MESA_NO_CODEGEN"))
       vtx->codegen_emit = _tnl_generate_sse_emit;
 #endif
 }
 
 
-void _tnl_free_vertices( GLcontext *ctx )
+void _tnl_free_vertices( struct gl_context *ctx )
 {
-   struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
-   struct tnl_clipspace_fastpath *fp, *tmp;
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   if (tnl) {
+      struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+      struct tnl_clipspace_fastpath *fp, *tmp;
 
-   if (vtx->vertex_buf) {
-      ALIGN_FREE(vtx->vertex_buf);
+      align_free(vtx->vertex_buf);
       vtx->vertex_buf = NULL;
+
+      for (fp = vtx->fastpath ; fp ; fp = tmp) {
+         tmp = fp->next;
+         free(fp->attr);
+
+         /* KW: At the moment, fp->func is constrained to be allocated by
+          * _mesa_exec_alloc(), as the hardwired fastpaths in
+          * t_vertex_generic.c are handled specially.  It would be nice
+          * to unify them, but this probably won't change until this
+          * module gets another overhaul.
+          */
+         _mesa_exec_free((void *) fp->func);
+         free(fp);
+      }
+
+      vtx->fastpath = NULL;
    }
-   
-   for (fp = vtx->fastpath ; fp ; fp = tmp) {
-      tmp = fp->next;
-      FREE(fp->attr);
-
-      /* KW: At the moment, fp->func is constrained to be allocated by
-       * _mesa_exec_alloc(), as the hardwired fastpaths in
-       * t_vertex_generic.c are handled specially.  It would be nice
-       * to unify them, but this probably won't change until this
-       * module gets another overhaul.
-       */
-      _mesa_exec_free((void *) fp->func);
-      FREE(fp);
-   }
-   
-   vtx->fastpath = NULL;
 }