static void vbo_bind_vertices(struct gl_context *ctx, const struct gl_client_array **arrays, int base, unsigned min_index, unsigned max_index, int *pdelta) { struct nouveau_render_state *render = to_render_state(ctx); struct nouveau_pushbuf *push = context_push(ctx); struct nouveau_bo *bo[NUM_VERTEX_ATTRS]; unsigned offset[NUM_VERTEX_ATTRS]; GLboolean dirty = GL_FALSE; int i, j, attr; RENDER_LOCALS(ctx); *pdelta = -1; FOR_EACH_BOUND_ATTR(render, i, attr) { const struct gl_client_array *array = arrays[attr]; struct gl_buffer_object *obj = array->BufferObj; struct nouveau_array *a = &render->attrs[attr]; unsigned delta = (base + min_index) * array->StrideB; bo[i] = NULL; if (nouveau_bufferobj_hw(obj)) { /* Array in a buffer obj. */ nouveau_bo_ref(to_nouveau_bufferobj(obj)->bo, &bo[i]); offset[i] = delta + (intptr_t)array->Ptr; } else { int n = max_index - min_index + 1; char *sp = (char *)ADD_POINTERS( nouveau_bufferobj_sys(obj), array->Ptr) + delta; char *dp = nouveau_get_scratch(ctx, n * a->stride, &bo[i], &offset[i]); /* Array in client memory, move it to a * scratch buffer obj. */ for (j = 0; j < n; j++) memcpy(dp + j * a->stride, sp + j * array->StrideB, a->stride); } dirty |= check_update_array(a, offset[i], bo[i], pdelta); } *pdelta -= min_index; if (dirty) { /* Buffers changed, update the attribute binding. */ FOR_EACH_BOUND_ATTR(render, i, attr) { struct nouveau_array *a = &render->attrs[attr]; nouveau_bo_ref(NULL, &a->bo); a->offset = offset[i]; a->bo = bo[i]; } TAG(render_release_vertices)(ctx); TAG(render_bind_vertices)(ctx); } else {
static GLboolean nouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); int ret; obj->Size = size; obj->Usage = usage; /* Free previous storage */ nouveau_bo_ref(NULL, &nbo->bo); FREE(nbo->sys); if (target == GL_ELEMENT_ARRAY_BUFFER_ARB || (size < 512 && usage == GL_DYNAMIC_DRAW_ARB) || context_chipset(ctx) < 0x10) { /* Heuristic: keep it in system ram */ nbo->sys = MALLOC(size); } else { /* Get a hardware BO */ ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, size, &nbo->bo); assert(!ret); } if (data) memcpy(get_bufferobj_map(obj, NOUVEAU_BO_WR), data, size); return GL_TRUE; }
static GLboolean nouveau_bufferobj_data(GLcontext *ctx, GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); int ret; obj->Size = size; obj->Usage = usage; nouveau_bo_ref(NULL, &nbo->bo); ret = nouveau_bo_new(context_dev(ctx), NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, size, &nbo->bo); assert(!ret); if (data) { nouveau_bo_map(nbo->bo, NOUVEAU_BO_WR); memcpy(nbo->bo->map, data, size); nouveau_bo_unmap(nbo->bo); } return GL_TRUE; }
static void * nouveau_bufferobj_map_range(GLcontext *ctx, GLenum target, GLintptr offset, GLsizeiptr length, GLenum access, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); uint32_t flags = 0; assert(!obj->Pointer); if (!nbo->bo) return NULL; if (access == GL_READ_ONLY_ARB || access == GL_READ_WRITE_ARB) flags |= NOUVEAU_BO_RD; if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) flags |= NOUVEAU_BO_WR; nouveau_bo_map_range(nbo->bo, offset, length, flags); obj->Pointer = nbo->bo->map; obj->Offset = offset; obj->Length = length; obj->AccessFlags = access; return obj->Pointer; }
static void nouveau_bufferobj_del(GLcontext *ctx, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); nouveau_bo_ref(NULL, &nbo->bo); FREE(nbo); }
static void nouveau_bufferobj_get_subdata(GLcontext *ctx, GLenum target, GLintptrARB offset, GLsizeiptrARB size, GLvoid *data, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); nouveau_bo_map(nbo->bo, NOUVEAU_BO_RD); memcpy(data, nbo->bo->map + offset, size); nouveau_bo_unmap(nbo->bo); }
static inline char * get_bufferobj_map(struct gl_buffer_object *obj, unsigned flags) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); void *map = NULL; if (nbo->sys) { map = nbo->sys; } else if (nbo->bo) { nouveau_bo_map(nbo->bo, flags); map = nbo->bo->map; nouveau_bo_unmap(nbo->bo); } return map; }
static GLboolean nouveau_bufferobj_unmap(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); assert(obj->Pointer); nouveau_bo_unmap(nbo->bo); obj->Pointer = NULL; obj->Offset = 0; obj->Length = 0; obj->AccessFlags = 0; return GL_TRUE; }
void nouveau_init_array(struct nouveau_array *a, int attr, int stride, int fields, int type, struct gl_buffer_object *obj, const void *ptr, GLboolean map) { a->attr = attr; a->stride = stride; a->fields = fields; a->type = type; a->buf = NULL; if (obj) { if (nouveau_bufferobj_hw(obj)) { struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); nouveau_bo_ref(nbo->bo, &a->bo); a->offset = (intptr_t)ptr; if (map) { nouveau_bo_map(a->bo, NOUVEAU_BO_RD); a->buf = a->bo->map + a->offset; } } else { nouveau_bo_ref(NULL, &a->bo); a->offset = 0; if (map) a->buf = ADD_POINTERS( nouveau_bufferobj_sys(obj), ptr); } } if (a->buf) get_array_extract(a, &a->extract_u, &a->extract_f); }