X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fnouveau%2Fnouveau_bufferobj.c;h=afccf353960d02222119ab944c145f667852ed2b;hb=da9e6fdfe27065b8ede8b2fe30c8cccc3b573245;hp=fc14060c04922d2aa9bed5e2b44e18e381958b36;hpb=5e4a0f42f243cd5fbc8718660d78705e8c70808f;p=mesa.git diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c index fc14060c049..afccf353960 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c @@ -1,616 +1,182 @@ -#include "bufferobj.h" -#include "enums.h" - +/* + * Copyright (C) 2009 Francisco Jerez. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * 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 NONINFRINGEMENT. + * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS 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. + * + */ + +#include "nouveau_driver.h" #include "nouveau_bufferobj.h" -#include "nouveau_buffers.h" #include "nouveau_context.h" -#include "nouveau_drm.h" -#include "nouveau_object.h" -#include "nouveau_msg.h" - -#define NOUVEAU_MEM_FREE(mem) do { \ - nouveau_mem_free(ctx, (mem)); \ - (mem) = NULL; \ -} while(0) - -#define DEBUG(fmt,args...) do { \ - if (NOUVEAU_DEBUG & DEBUG_BUFFEROBJ) { \ - fprintf(stderr, "%s: "fmt, __func__, ##args); \ - } \ -} while(0) - -static GLboolean -nouveau_bo_download_from_screen(GLcontext *ctx, GLuint offset, GLuint size, - struct gl_buffer_object *bo) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_mem *in_mem; - - DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size); - - /* If there's a permanent backing store, blit directly into it */ - if (nbo->cpu_mem) { - if (nbo->cpu_mem != nbo->gpu_mem) { - DEBUG("..cpu_mem\n"); - nouveau_memformat_flat_emit(ctx, nbo->cpu_mem, - nbo->gpu_mem, - offset, offset, size); - } - } else { - DEBUG("..sys_mem\n"); - in_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP, size, 0); - if (in_mem) { - DEBUG("....via GART\n"); - /* otherwise, try blitting to faster memory and - * copying from there - */ - nouveau_memformat_flat_emit(ctx, in_mem, nbo->gpu_mem, - 0, offset, size); - nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, - NvSubMemFormat); - _mesa_memcpy(nbo->cpu_mem_sys + offset, - in_mem->map, size); - NOUVEAU_MEM_FREE(in_mem); - } else { - DEBUG("....direct VRAM copy\n"); - /* worst case, copy directly from vram */ - _mesa_memcpy(nbo->cpu_mem_sys + offset, - nbo->gpu_mem + offset, - size); - } - } - - return GL_TRUE; -} - -static GLboolean -nouveau_bo_upload_to_screen(GLcontext *ctx, GLuint offset, GLuint size, - struct gl_buffer_object *bo) -{ - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_mem *out_mem; - DEBUG("bo=%p, offset=%d, size=%d\n", bo, offset, size); +#include "main/bufferobj.h" - if (nbo->cpu_mem) { - if (nbo->cpu_mem != nbo->gpu_mem) { - DEBUG("..cpu_mem\n"); - nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, - nbo->cpu_mem, - offset, offset, size); - } - } else { - out_mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_AGP | - NOUVEAU_MEM_MAPPED, - size, 0); - if (out_mem) { - DEBUG("....via GART\n"); - _mesa_memcpy(out_mem->map, - nbo->cpu_mem_sys + offset, size); - nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, out_mem, - offset, 0, size); - nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, - NvSubMemFormat); - NOUVEAU_MEM_FREE(out_mem); - } else { - DEBUG("....direct VRAM copy\n"); - _mesa_memcpy(nbo->gpu_mem->map + offset, - nbo->cpu_mem_sys + offset, - size); - } - } - - return GL_TRUE; -} - -GLboolean -nouveau_bo_move_in(GLcontext *ctx, struct gl_buffer_object *bo) +static inline char * +get_bufferobj_map(struct gl_context *ctx, struct gl_buffer_object *obj, + unsigned flags) { - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - - DEBUG("bo=%p\n", bo); - - if (bo->OnCard) - return GL_TRUE; - assert(nbo->gpu_mem_flags); + struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); + void *map = NULL; - nbo->gpu_mem = nouveau_mem_alloc(ctx, nbo->gpu_mem_flags | - NOUVEAU_MEM_MAPPED, - bo->Size, 0); - assert(nbo->gpu_mem); - - if (nbo->cpu_mem_flags) { - if ((nbo->cpu_mem_flags|NOUVEAU_MEM_MAPPED) != nbo->gpu_mem->type) { - DEBUG("..need cpu_mem buffer\n"); - - nbo->cpu_mem = nouveau_mem_alloc(ctx, - nbo->cpu_mem_flags | - NOUVEAU_MEM_MAPPED, - bo->Size, 0); - - if (nbo->cpu_mem) { - DEBUG("....alloc ok, kill sys_mem buffer\n"); - _mesa_memcpy(nbo->cpu_mem->map, - nbo->cpu_mem_sys, bo->Size); - FREE(nbo->cpu_mem_sys); - } - } else { - DEBUG("..cpu direct access to GPU buffer\n"); - nbo->cpu_mem = nbo->gpu_mem; - } + if (nbo->sys) { + map = nbo->sys; + } else if (nbo->bo) { + nouveau_bo_map(nbo->bo, flags, context_client(ctx)); + map = nbo->bo->map; } - nouveau_bo_upload_to_screen(ctx, 0, bo->Size, bo); - bo->OnCard = GL_TRUE; - return GL_TRUE; + return map; } -GLboolean -nouveau_bo_move_out(GLcontext *ctx, struct gl_buffer_object *bo) +static struct gl_buffer_object * +nouveau_bufferobj_new(struct gl_context *ctx, GLuint buffer) { - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - GLuint nr_dirty; + struct nouveau_bufferobj *nbo; - DEBUG("bo=%p\n", bo); - if (!bo->OnCard) - return GL_TRUE; + nbo = CALLOC_STRUCT(nouveau_bufferobj); + if (!nbo) + return NULL; - nr_dirty = nouveau_bo_download_dirty(ctx, bo); - if (nbo->cpu_mem) { - if (nr_dirty && nbo->cpu_mem != nbo->gpu_mem) - nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, - NvSubMemFormat); - DEBUG("..destroy cpu_mem buffer\n"); - nbo->cpu_mem_sys = malloc(bo->Size); - assert(nbo->cpu_mem_sys); - _mesa_memcpy(nbo->cpu_mem_sys, nbo->cpu_mem->map, bo->Size); - if (nbo->cpu_mem == nbo->gpu_mem) - nbo->cpu_mem = NULL; - else - NOUVEAU_MEM_FREE(nbo->cpu_mem); - } - NOUVEAU_MEM_FREE(nbo->gpu_mem); + _mesa_initialize_buffer_object(ctx, &nbo->base, buffer); - bo->OnCard = GL_FALSE; - return GL_TRUE; + return &nbo->base; } static void -nouveau_bo_choose_storage_method(GLcontext *ctx, GLenum usage, - struct gl_buffer_object *bo) +nouveau_bufferobj_del(struct gl_context *ctx, struct gl_buffer_object *obj) { - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - GLuint gpu_type = 0; - GLuint cpu_type = 0; + struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); - switch (usage) { - /* Client source, changes often, used by GL many times */ - case GL_DYNAMIC_DRAW_ARB: - gpu_type = NOUVEAU_MEM_AGP | NOUVEAU_MEM_FB_ACCEPTABLE; - cpu_type = NOUVEAU_MEM_AGP; - break; - /* GL source, changes often, client reads many times */ - case GL_DYNAMIC_READ_ARB: - /* Client source, specified once, used by GL many times */ - case GL_STATIC_DRAW_ARB: - /* GL source, specified once, client reads many times */ - case GL_STATIC_READ_ARB: - /* Client source, specified once, used by GL a few times */ - case GL_STREAM_DRAW_ARB: - /* GL source, specified once, client reads a few times */ - case GL_STREAM_READ_ARB: - /* GL source, changes often, used by GL many times*/ - case GL_DYNAMIC_COPY_ARB: - /* GL source, specified once, used by GL many times */ - case GL_STATIC_COPY_ARB: - /* GL source, specified once, used by GL a few times */ - case GL_STREAM_COPY_ARB: - gpu_type = NOUVEAU_MEM_FB; - break; - default: - assert(0); - } - - nbo->gpu_mem_flags = gpu_type; - nbo->cpu_mem_flags = cpu_type; - nbo->usage = usage; -} - -void -nouveau_bo_init_storage(GLcontext *ctx, GLuint valid_gpu_access, - GLsizeiptrARB size, - const GLvoid *data, - GLenum usage, - struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - - DEBUG("bo=%p\n", bo); - - /* Free up previous buffers if we can't reuse them */ - if (nbo->usage != usage || - (nbo->gpu_mem && (nbo->gpu_mem->size != size))) { - if (nbo->cpu_mem_sys) - FREE(nbo->cpu_mem_sys); - if (nbo->cpu_mem) { - if (nbo->cpu_mem != nbo->gpu_mem) - NOUVEAU_MEM_FREE(nbo->cpu_mem); - else - nbo->cpu_mem = NULL; - } - if (nbo->gpu_mem) - NOUVEAU_MEM_FREE(nbo->gpu_mem); - - bo->OnCard = GL_FALSE; - nbo->cpu_mem_sys = calloc(1, size); - } - - nouveau_bo_choose_storage_method(ctx, usage, bo); - /* Force off flags that may not be ok for a given buffer */ - nbo->gpu_mem_flags &= valid_gpu_access; - - bo->Usage = usage; - bo->Size = size; - - if (data) { - GLvoid *map = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, bo); - _mesa_memcpy(map, data, size); - nouveau_bo_dirty_all(ctx, GL_FALSE, bo); - nouveau_bo_unmap(ctx, bo); - } + nouveau_bo_ref(NULL, &nbo->bo); + free(nbo->sys); + free(nbo); } -void * -nouveau_bo_map(GLcontext *ctx, GLenum access, struct gl_buffer_object *bo) +static GLboolean +nouveau_bufferobj_data(struct gl_context *ctx, GLenum target, GLsizeiptrARB size, + const GLvoid *data, GLenum usage, GLbitfield storageFlags, + struct gl_buffer_object *obj) { - nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - - DEBUG("bo=%p, access=%s\n", bo, _mesa_lookup_enum_by_nr(access)); + struct nouveau_bufferobj *nbo = to_nouveau_bufferobj(obj); + int ret; - if (bo->OnCard && - (access == GL_READ_ONLY_ARB || access == GL_READ_WRITE_ARB)) { - GLuint nr_dirty; + obj->Size = size; + obj->Usage = usage; + obj->StorageFlags = storageFlags; - DEBUG("..on card\n"); - nr_dirty = nouveau_bo_download_dirty(ctx, bo); + /* Free previous storage */ + nouveau_bo_ref(NULL, &nbo->bo); + free(nbo->sys); + nbo->sys = NULL; - /* nouveau_bo_download_dirty won't wait unless it needs to - * free a temp buffer, which isn't the case if cpu_mem is - * present. - */ - if (nr_dirty && nbo->cpu_mem && nbo->cpu_mem != nbo->gpu_mem) - nouveau_notifier_wait_nop(ctx, nmesa->syncNotifier, - NvSubMemFormat); - } + 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); - if (nbo->cpu_mem) { - DEBUG("..access via cpu_mem\n"); - return nbo->cpu_mem->map; } else { - DEBUG("..access via cpu_mem_sys\n"); - return nbo->cpu_mem_sys; - } -} - -void -nouveau_bo_unmap(GLcontext *ctx, struct gl_buffer_object *bo) -{ - DEBUG("unmap bo=%p\n", bo); -} - -uint32_t -nouveau_bo_gpu_ref(GLcontext *ctx, struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - - assert(nbo->mapped == GL_FALSE); - - DEBUG("gpu_ref\n"); - - if (!bo->OnCard) { - nouveau_bo_move_in(ctx, bo); - bo->OnCard = GL_TRUE; - } - nouveau_bo_upload_dirty(ctx, bo); - - return nouveau_mem_gpu_offset_get(ctx, nbo->gpu_mem); -} - -void -nouveau_bo_dirty_linear(GLcontext *ctx, GLboolean on_card, - uint32_t offset, uint32_t size, - struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_bufferobj_dirty *dirty; - uint32_t start = offset; - uint32_t end = offset + size; - int i; - - if (nbo->cpu_mem == nbo->gpu_mem) - return; - - dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty; - - DEBUG("on_card=%d, offset=%d, size=%d, bo=%p\n", - on_card, offset, size, bo); - - for (i=0; inr_dirty; i++) { - nouveau_bufferobj_region *r = &dirty->dirty[i]; - - /* already dirty */ - if (start >= r->start && end <= r->end) { - DEBUG("..already dirty\n"); - return; - } - - /* add to the end of a region */ - if (start >= r->start && start <= r->end) { - if (end > r->end) { - DEBUG("..extend end of region\n"); - r->end = end; - return; - } - } - - /* add to the start of a region */ - if (start < r->start && end >= r->end) { - DEBUG("..extend start of region\n"); - r->start = start; - /* .. and to the end */ - if (end > r->end) { - DEBUG("....and end\n"); - r->end = end; - } - return; - } - } - - /* new region */ - DEBUG("..new dirty\n"); - dirty->nr_dirty++; - dirty->dirty = realloc(dirty->dirty, - sizeof(nouveau_bufferobj_region) * - dirty->nr_dirty); - dirty->dirty[dirty->nr_dirty - 1].start = start; - dirty->dirty[dirty->nr_dirty - 1].end = end; -} - -void -nouveau_bo_dirty_all(GLcontext *ctx, GLboolean on_card, - struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_bufferobj_dirty *dirty; - - dirty = on_card ? &nbo->gpu_dirty : &nbo->cpu_dirty; - - DEBUG("dirty all\n"); - if (dirty->nr_dirty) { - FREE(dirty->dirty); - dirty->dirty = NULL; - dirty->nr_dirty = 0; - } - - nouveau_bo_dirty_linear(ctx, on_card, 0, bo->Size, bo); -} - -GLuint -nouveau_bo_upload_dirty(GLcontext *ctx, struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_bufferobj_dirty *dirty = &nbo->cpu_dirty; - GLuint nr_dirty; - int i; - - nr_dirty = dirty->nr_dirty; - if (!nr_dirty) { - DEBUG("clean\n"); - return nr_dirty; - } - - for (i=0; idirty[i]; - - DEBUG("dirty %d: o=0x%08x, s=0x%08x\n", - i, r->start, r->end - r->start); - nouveau_bo_upload_to_screen(ctx, - r->start, r->end - r->start, bo); - } - - FREE(dirty->dirty); - dirty->dirty = NULL; - dirty->nr_dirty = 0; - - return nr_dirty; -} - -GLuint -nouveau_bo_download_dirty(GLcontext *ctx, struct gl_buffer_object *bo) -{ - nouveau_buffer_object *nbo = (nouveau_buffer_object *)bo; - nouveau_bufferobj_dirty *dirty = &nbo->gpu_dirty; - GLuint nr_dirty; - int i; - - nr_dirty = dirty->nr_dirty; - if (nr_dirty) { - DEBUG("clean\n"); - return nr_dirty; - } - - for (i=0; idirty[i]; - - DEBUG("dirty %d: o=0x%08x, s=0x%08x\n", - i, r->start, r->end - r->start); - nouveau_bo_download_from_screen(ctx, - r->start, - r->end - r->start, bo); + /* Get a hardware BO */ + ret = nouveau_bo_new(context_dev(ctx), + NOUVEAU_BO_GART | NOUVEAU_BO_MAP, + ctx->Const.MinMapBufferAlignment, + size, NULL, &nbo->bo); + assert(!ret); } - FREE(dirty->dirty); - dirty->dirty = NULL; - dirty->nr_dirty = 0; + if (data) + memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR), data, size); - return nr_dirty; + return GL_TRUE; } static void -nouveauBindBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) -{ -} - -static struct gl_buffer_object * -nouveauNewBufferObject(GLcontext *ctx, GLuint buffer, GLenum target) +nouveau_bufferobj_subdata(struct gl_context *ctx, GLintptrARB offset, + GLsizeiptrARB size, const GLvoid *data, + struct gl_buffer_object *obj) { - nouveau_buffer_object *nbo; - - nbo = CALLOC_STRUCT(nouveau_buffer_object_t); - if (nbo) - _mesa_initialize_buffer_object(&nbo->mesa, buffer, target); - DEBUG("bo=%p\n", nbo); - - return nbo ? &nbo->mesa : NULL; + memcpy(get_bufferobj_map(ctx, obj, NOUVEAU_BO_WR) + offset, data, size); } static void -nouveauDeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj) +nouveau_bufferobj_get_subdata(struct gl_context *ctx, GLintptrARB offset, + GLsizeiptrARB size, GLvoid *data, + struct gl_buffer_object *obj) { - nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj; - - if (nbo->gpu_dirty.nr_dirty) - FREE(nbo->gpu_dirty.dirty); - if (nbo->cpu_dirty.nr_dirty) - FREE(nbo->cpu_dirty.dirty); - if (nbo->cpu_mem) nouveau_mem_free(ctx, nbo->cpu_mem); - if (nbo->gpu_mem) nouveau_mem_free(ctx, nbo->gpu_mem); - - _mesa_delete_buffer_object(ctx, obj); + memcpy(data, get_bufferobj_map(ctx, obj, NOUVEAU_BO_RD) + offset, size); } -static void -nouveauBufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size, - const GLvoid *data, GLenum usage, - struct gl_buffer_object *obj) +static void * +nouveau_bufferobj_map_range(struct gl_context *ctx, GLintptr offset, + GLsizeiptr length, GLbitfield access, + struct gl_buffer_object *obj, + gl_map_buffer_index index) { - GLuint gpu_flags; + unsigned flags = 0; + char *map; - DEBUG("target=%s, size=%d, data=%p, usage=%s, obj=%p\n", - _mesa_lookup_enum_by_nr(target), - (GLuint)size, data, - _mesa_lookup_enum_by_nr(usage), - obj); + assert(!obj->Mappings[index].Pointer); - switch (target) { - case GL_ELEMENT_ARRAY_BUFFER_ARB: - gpu_flags = 0; - break; - default: - gpu_flags = NOUVEAU_BO_VRAM_OK | NOUVEAU_BO_GART_OK; - break; + if (!(access & GL_MAP_UNSYNCHRONIZED_BIT)) { + if (access & GL_MAP_READ_BIT) + flags |= NOUVEAU_BO_RD; + if (access & GL_MAP_WRITE_BIT) + flags |= NOUVEAU_BO_WR; } - nouveau_bo_init_storage(ctx, gpu_flags, size, data, usage, obj); -} - -static void -nouveauBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset, - GLsizeiptrARB size, const GLvoid *data, - struct gl_buffer_object *obj) -{ - GLvoid *out; - DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n", - _mesa_lookup_enum_by_nr(target), - (GLuint)offset, (GLuint)size, data, obj); - - out = nouveau_bo_map(ctx, GL_WRITE_ONLY_ARB, obj); - _mesa_memcpy(out + offset, data, size); - nouveau_bo_dirty_linear(ctx, GL_FALSE, offset, size, obj); - nouveau_bo_unmap(ctx, obj); -} - -static void -nouveauGetBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset, - GLsizeiptrARB size, GLvoid *data, - struct gl_buffer_object *obj) -{ - const GLvoid *in; - - DEBUG("target=%s, offset=0x%x, size=%d, data=%p, obj=%p\n", - _mesa_lookup_enum_by_nr(target), - (GLuint)offset, (GLuint)size, data, obj); - - in = nouveau_bo_map(ctx, GL_READ_ONLY_ARB, obj); - _mesa_memcpy(data, in + offset, size); - nouveau_bo_unmap(ctx, obj); -} - -static void * -nouveauMapBuffer(GLcontext *ctx, GLenum target, GLenum access, - struct gl_buffer_object *obj) -{ - DEBUG("target=%s, access=%s, obj=%p\n", - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(access), - obj - ); - - /* Already mapped.. */ - if (obj->Pointer) + map = get_bufferobj_map(ctx, obj, flags); + if (!map) return NULL; - /* Have to pass READ_WRITE here, nouveau_bo_map will only ensure that - * the cpu_mem buffer is up-to-date if we ask for read access. - * - * However, even if the client only asks for write access, we're still - * forced to reupload the entire buffer. So, we need the cpu_mem buffer - * to have the correct data all the time. - */ - obj->Pointer = nouveau_bo_map(ctx, GL_READ_WRITE_ARB, obj); + obj->Mappings[index].Pointer = map + offset; + obj->Mappings[index].Offset = offset; + obj->Mappings[index].Length = length; + obj->Mappings[index].AccessFlags = access; - /* The GL spec says that a client attempting to write to a bufferobj - * mapped READ_ONLY object may have unpredictable results, possibly - * even program termination. - * - * We're going to use this, and only mark the buffer as dirtied if - * the client asks for write access. - */ - if (target != GL_READ_ONLY_ARB) { - /* We have no way of knowing what was modified by the client, - * so the entire buffer gets dirtied. */ - nouveau_bo_dirty_all(ctx, GL_FALSE, obj); - } - - return obj->Pointer; + return obj->Mappings[index].Pointer; } static GLboolean -nouveauUnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj) +nouveau_bufferobj_unmap(struct gl_context *ctx, struct gl_buffer_object *obj, + gl_map_buffer_index index) { - DEBUG("target=%s, obj=%p\n", _mesa_lookup_enum_by_nr(target), obj); + assert(obj->Mappings[index].Pointer); - assert(obj->Pointer); + obj->Mappings[index].Pointer = NULL; + obj->Mappings[index].Offset = 0; + obj->Mappings[index].Length = 0; + obj->Mappings[index].AccessFlags = 0; - nouveau_bo_unmap(ctx, obj); - obj->Pointer = NULL; return GL_TRUE; } - + void -nouveauInitBufferObjects(GLcontext *ctx) +nouveau_bufferobj_functions_init(struct dd_function_table *functions) { - ctx->Driver.BindBuffer = nouveauBindBuffer; - ctx->Driver.NewBufferObject = nouveauNewBufferObject; - ctx->Driver.DeleteBuffer = nouveauDeleteBuffer; - ctx->Driver.BufferData = nouveauBufferData; - ctx->Driver.BufferSubData = nouveauBufferSubData; - ctx->Driver.GetBufferSubData = nouveauGetBufferSubData; - ctx->Driver.MapBuffer = nouveauMapBuffer; - ctx->Driver.UnmapBuffer = nouveauUnmapBuffer; + functions->NewBufferObject = nouveau_bufferobj_new; + functions->DeleteBuffer = nouveau_bufferobj_del; + functions->BufferData = nouveau_bufferobj_data; + functions->BufferSubData = nouveau_bufferobj_subdata; + functions->GetBufferSubData = nouveau_bufferobj_get_subdata; + functions->MapBufferRange = nouveau_bufferobj_map_range; + functions->UnmapBuffer = nouveau_bufferobj_unmap; } -