Exemplo n.º 1
0
void
vbo_split_prims(struct gl_context *ctx,
                const struct gl_vertex_array *arrays[],
                const struct _mesa_prim *prim,
                GLuint nr_prims,
                const struct _mesa_index_buffer *ib,
                GLuint min_index,
                GLuint max_index,
                vbo_draw_func draw,
                const struct split_limits *limits)
{
   if (ib) {
      if (limits->max_indices == 0) {
         /* Could traverse the indices, re-emitting vertices in turn.
          * But it's hard to see why this case would be needed - for
          * software tnl, it is better to convert to non-indexed
          * rendering after transformation is complete.  Are there any devices
          * with hardware tnl that cannot do indexed rendering?
          *
          * For now, this path is disabled.
          */
         assert(0);
      }
      else if (max_index - min_index >= limits->max_verts) {
         /* The vertex buffers are too large for hardware (or the
          * swtnl module).  Traverse the indices, re-emitting vertices
          * in turn.  Use a vertex cache to preserve some of the
          * sharing from the original index list.
          */
         vbo_split_copy(ctx, arrays, prim, nr_prims, ib, draw, limits);
      }
      else if (ib->count > limits->max_indices) {
         /* The index buffer is too large for hardware.  Try to split
          * on whole-primitive boundaries, otherwise try to split the
          * individual primitives.
          */
         vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
                           min_index, max_index, draw, limits);
      }
      else {
         /* Why were we called? */
         assert(0);
      }
   }
   else {
      if (max_index - min_index >= limits->max_verts) {
         /* The vertex buffer is too large for hardware (or the swtnl
          * module).  Try to split on whole-primitive boundaries,
          * otherwise try to split the individual primitives.
          */
         vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
                           min_index, max_index, draw, limits);
      }
      else {
         /* Why were we called? */
         assert(0);
      }
   }
}
Exemplo n.º 2
0
/* Break large primitives into smaller ones.  If not possible, convert
 * the primitive to indexed and pass to split_elts().
 */
static void split_prims( struct split_context *split) 
{
   GLuint csr = 0;
   GLuint i;

   for (i = 0; i < split->nr_prims; i++) {
      const struct _mesa_prim *prim = &split->prim[i];
      GLuint first, incr;
      GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
      GLuint count;

      /* Always wrap on an even numbered vertex to avoid problems with
       * triangle strips.  
       */
      GLuint available = align(split->limits->max_verts - csr - 1, 2); 
      assert(split->limits->max_verts >= csr);

      if (prim->count < first)
	 continue;
      
      count = prim->count - (prim->count - first) % incr; 


      if ((available < count && !split_inplace) || 
	  (available < first && split_inplace)) {
	 flush_vertex(split);
	 csr = 0;
	 available = align(split->limits->max_verts - csr - 1, 2);
      }
      
      if (available >= count) {
	 struct _mesa_prim *outprim = next_outprim(split);
	 *outprim = *prim;
	 csr += prim->count;
	 available = align(split->limits->max_verts - csr - 1, 2); 
      } 
      else if (split_inplace) {
	 GLuint j, nr;


	 for (j = 0 ; j < count ; ) {
	    GLuint remaining = count - j;
	    struct _mesa_prim *outprim = next_outprim(split);

	    nr = MIN2( available, remaining );
	    
	    nr -= (nr - first) % incr;
	    
	    outprim->mode = prim->mode;
	    outprim->begin = (j == 0 && prim->begin);
	    outprim->end = (nr == remaining && prim->end);
	    outprim->start = prim->start + j;
	    outprim->count = nr;
	    
	    if (nr == remaining) {
	       /* Finished. 
		*/
	       j += nr;		
	       csr += nr;
	       available = align(split->limits->max_verts - csr - 1, 2); 
	    }
	    else {
	       /* Wrapped the primitive: 
		*/
	       j += nr - (first - incr);
	       flush_vertex(split);
	       csr = 0;
	       available = align(split->limits->max_verts - csr - 1, 2); 
	    }
	 }
      }
      else if (split->ib == NULL) {
	 /* XXX: could at least send the first max_verts off from the
	  * inplace buffers.
	  */

	 /* else convert to indexed primitive and pass to split_elts,
	  * which will do the necessary copying and turn it back into a
	  * vertex primitive for rendering...
	  */
	 struct _mesa_index_buffer ib;
	 struct _mesa_prim tmpprim;
	 GLuint *elts = malloc(count * sizeof(GLuint));
	 GLuint j;
	 
	 for (j = 0; j < count; j++)
	    elts[j] = prim->start + j;

	 ib.count = count;
	 ib.type = GL_UNSIGNED_INT;
	 ib.obj = split->ctx->Shared->NullBufferObj;
	 ib.ptr = elts;
	    
	 tmpprim = *prim;
	 tmpprim.indexed = 1;
	 tmpprim.start = 0;
	 tmpprim.count = count;

	 flush_vertex(split);

	 vbo_split_copy(split->ctx,
			split->array,
			&tmpprim, 1, 
			&ib,
			split->draw,
			split->limits);
	    
	 free(elts);
      }
      else {
	 flush_vertex(split);

	 vbo_split_copy(split->ctx,
			split->array,
			prim, 1, 
			split->ib,
			split->draw,
			split->limits);
      }
   }

   flush_vertex(split);
}