Пример #1
0
static GLboolean
vbo_maybe_split(struct gl_context *ctx, const struct gl_client_array **arrays,
	    const struct _mesa_prim *prims, GLuint nr_prims,
	    const struct _mesa_index_buffer *ib,
	    GLuint min_index, GLuint max_index)
{
	struct nouveau_context *nctx = to_nouveau_context(ctx);
	struct nouveau_render_state *render = to_render_state(ctx);
	struct nouveau_bufctx *bufctx = nctx->hw.bufctx;
	unsigned pushbuf_avail = PUSHBUF_DWORDS - 2 * (bufctx->relocs +
						       render->attr_count),
		vert_avail = get_max_vertices(ctx, NULL, pushbuf_avail),
		idx_avail = get_max_vertices(ctx, ib, pushbuf_avail);
	int stride;

	/* Try to keep client buffers smaller than the scratch BOs. */
	if (render->mode == VBO &&
	    (stride = get_max_client_stride(ctx, arrays)))
		    vert_avail = MIN2(vert_avail,
				      NOUVEAU_SCRATCH_SIZE / stride);

	if (max_index - min_index > vert_avail ||
	    (ib && ib->count > idx_avail)) {
		struct split_limits limits = {
			.max_verts = vert_avail,
			.max_indices = idx_avail,
			.max_vb_size = ~0,
		};

		vbo_split_prims(ctx, arrays, prims, nr_prims, ib, min_index,
				max_index, TAG(vbo_render_prims), &limits);
		return GL_TRUE;
	}

	return GL_FALSE;
}

/* VBO rendering path. */

static GLboolean
check_update_array(struct nouveau_array *a, unsigned offset,
		   struct nouveau_bo *bo, int *pdelta)
{
	int delta = *pdelta;
	GLboolean dirty;

	if (a->bo == bo) {
		if (delta < 0)
			delta = ((int)offset - (int)a->offset) / a->stride;

		dirty = (delta < 0 ||
			 offset != (a->offset + delta * a->stride));
	} else {
		dirty = GL_TRUE;
	}

	*pdelta = (dirty ? 0 : delta);
	return dirty;
}
Пример #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 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 available = get_max_vertices(split, prim);
      GLuint count = prim->count - (prim->count - first) % incr;

      if (prim->count < first)
	 continue;

      if ((available < count && !split_inplace) ||
	  (available < first && split_inplace)) {
	 flush_vertex(split);
	 available = get_max_vertices(split, prim);
      }
      
      if (available >= count) {
	 struct _mesa_prim *outprim = next_outprim(split);

	 *outprim = *prim;
	 update_index_bounds(split, outprim);
      }
      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;
            outprim->num_instances = prim->num_instances;
            outprim->base_instance = prim->base_instance;

	    update_index_bounds(split, outprim);

	    if (nr == remaining) {
	       /* Finished. 
		*/
	       j += nr;
	    }
	    else {
	       /* Wrapped the primitive: 
		*/
	       j += nr - (first - incr);
	       flush_vertex(split);
	       available = get_max_vertices(split, prim);
	    }
	 }
      }
      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;
         tmpprim.num_instances = 1;
         tmpprim.base_instance = 0;

	 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);
}