X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi915%2Fintel_buffer_objects.c;h=e6760964909e72124f2f582d2c4646e5e56b34da;hb=ca4d1def392249209a5980fadb1678ffba95b381;hp=77b074d278b83c4ab5370d1615447ddab42809bd;hpb=279f0bce47be8f11d2ba2561179af166fe6c37bf;p=mesa.git diff --git a/src/mesa/drivers/dri/i915/intel_buffer_objects.c b/src/mesa/drivers/dri/i915/intel_buffer_objects.c index 77b074d278b..e6760964909 100644 --- a/src/mesa/drivers/dri/i915/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/i915/intel_buffer_objects.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE 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. @@ -40,7 +40,8 @@ #include "intel_regions.h" static GLboolean -intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj); +intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj, + gl_map_buffer_index index); /** Allocates a new drm_intel_bo to store the data for the buffer object. */ static void @@ -67,11 +68,11 @@ release_buffer(struct intel_buffer_object *intel_obj) * internal structure where somehow shared. */ static struct gl_buffer_object * -intel_bufferobj_alloc(struct gl_context * ctx, GLuint name, GLenum target) +intel_bufferobj_alloc(struct gl_context * ctx, GLuint name) { struct intel_buffer_object *obj = CALLOC_STRUCT(intel_buffer_object); - _mesa_initialize_buffer_object(ctx, &obj->Base, name, target); + _mesa_initialize_buffer_object(ctx, &obj->Base, name); obj->buffer = NULL; @@ -93,13 +94,12 @@ intel_bufferobj_free(struct gl_context * ctx, struct gl_buffer_object *obj) * to the spec, but Mesa doesn't do UnmapBuffer for us at context destroy * (though it does if you call glDeleteBuffers) */ - if (obj->Pointer) - intel_bufferobj_unmap(ctx, obj); + _mesa_buffer_unmap_all_mappings(ctx, obj); - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); drm_intel_bo_unreference(intel_obj->buffer); - free(intel_obj); + _mesa_delete_buffer_object(ctx, obj); } @@ -116,20 +116,24 @@ intel_bufferobj_data(struct gl_context * ctx, GLenum target, GLsizeiptrARB size, const GLvoid * data, - GLenum usage, struct gl_buffer_object *obj) + GLenum usage, + GLbitfield storageFlags, + struct gl_buffer_object *obj) { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); intel_obj->Base.Size = size; intel_obj->Base.Usage = usage; + intel_obj->Base.StorageFlags = storageFlags; - assert(!obj->Pointer); /* Mesa should have unmapped it */ + assert(!obj->Mappings[MAP_USER].Pointer); /* Mesa should have unmapped it */ + assert(!obj->Mappings[MAP_INTERNAL].Pointer); if (intel_obj->buffer != NULL) release_buffer(intel_obj); - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; if (size != 0) { @@ -137,7 +141,8 @@ intel_bufferobj_data(struct gl_context * ctx, * contents anyway. */ if (target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER) { - intel_obj->sys_buffer = malloc(size); + intel_obj->sys_buffer = + _mesa_align_malloc(size, ctx->Const.MinMapBufferAlignment); if (intel_obj->sys_buffer != NULL) { if (data != NULL) memcpy(intel_obj->sys_buffer, data, size); @@ -188,7 +193,7 @@ intel_bufferobj_subdata(struct gl_context * ctx, return; } - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; } @@ -269,7 +274,8 @@ intel_bufferobj_get_subdata(struct gl_context * ctx, static void * intel_bufferobj_map_range(struct gl_context * ctx, GLintptr offset, GLsizeiptr length, - GLbitfield access, struct gl_buffer_object *obj) + GLbitfield access, struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); @@ -279,9 +285,9 @@ intel_bufferobj_map_range(struct gl_context * ctx, /* _mesa_MapBufferRange (GL entrypoint) sets these, but the vbo module also * internally uses our functions directly. */ - obj->Offset = offset; - obj->Length = length; - obj->AccessFlags = access; + obj->Mappings[index].Offset = offset; + obj->Mappings[index].Length = length; + obj->Mappings[index].AccessFlags = access; if (intel_obj->sys_buffer) { const bool read_only = @@ -291,16 +297,16 @@ intel_bufferobj_map_range(struct gl_context * ctx, release_buffer(intel_obj); if (!intel_obj->buffer || intel_obj->source) { - obj->Pointer = intel_obj->sys_buffer + offset; - return obj->Pointer; + obj->Mappings[index].Pointer = intel_obj->sys_buffer + offset; + return obj->Mappings[index].Pointer; } - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; } if (intel_obj->buffer == NULL) { - obj->Pointer = NULL; + obj->Mappings[index].Pointer = NULL; return NULL; } @@ -336,22 +342,32 @@ intel_bufferobj_map_range(struct gl_context * ctx, */ if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && drm_intel_bo_busy(intel_obj->buffer)) { + /* Ensure that the base alignment of the allocation meets the alignment + * guarantees the driver has advertised to the application. + */ + const unsigned alignment = ctx->Const.MinMapBufferAlignment; + const unsigned extra = (uintptr_t) offset % alignment; + if (access & GL_MAP_FLUSH_EXPLICIT_BIT) { - intel_obj->range_map_buffer = malloc(length); - obj->Pointer = intel_obj->range_map_buffer; + intel_obj->range_map_buffer[index] = + _mesa_align_malloc(length + extra, alignment); + obj->Mappings[index].Pointer = + intel_obj->range_map_buffer[index] + extra; } else { - intel_obj->range_map_bo = drm_intel_bo_alloc(intel->bufmgr, - "range map", - length, 64); + intel_obj->range_map_bo[index] = drm_intel_bo_alloc(intel->bufmgr, + "range map", + length + extra, + alignment); if (!(access & GL_MAP_READ_BIT)) { - drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo); + drm_intel_gem_bo_map_gtt(intel_obj->range_map_bo[index]); } else { - drm_intel_bo_map(intel_obj->range_map_bo, + drm_intel_bo_map(intel_obj->range_map_bo[index], (access & GL_MAP_WRITE_BIT) != 0); } - obj->Pointer = intel_obj->range_map_bo->virtual; + obj->Mappings[index].Pointer = + intel_obj->range_map_bo[index]->virtual + extra; } - return obj->Pointer; + return obj->Mappings[index].Pointer; } if (access & GL_MAP_UNSYNCHRONIZED_BIT) @@ -362,8 +378,8 @@ intel_bufferobj_map_range(struct gl_context * ctx, drm_intel_bo_map(intel_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0); } - obj->Pointer = intel_obj->buffer->virtual + offset; - return obj->Pointer; + obj->Mappings[index].Pointer = intel_obj->buffer->virtual + offset; + return obj->Mappings[index].Pointer; } /* Ideally we'd use a BO to avoid taking up cache space for the temporary @@ -374,7 +390,8 @@ intel_bufferobj_map_range(struct gl_context * ctx, static void intel_bufferobj_flush_mapped_range(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj) + struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); @@ -383,7 +400,7 @@ intel_bufferobj_flush_mapped_range(struct gl_context *ctx, /* Unless we're in the range map using a temporary system buffer, * there's no work to do. */ - if (intel_obj->range_map_buffer == NULL) + if (intel_obj->range_map_buffer[index] == NULL) return; if (length == 0) @@ -391,10 +408,15 @@ intel_bufferobj_flush_mapped_range(struct gl_context *ctx, temp_bo = drm_intel_bo_alloc(intel->bufmgr, "range map flush", length, 64); - drm_intel_bo_subdata(temp_bo, 0, length, intel_obj->range_map_buffer); + /* Use obj->Pointer instead of intel_obj->range_map_buffer because the + * former points to the actual mapping while the latter may be offset to + * meet alignment guarantees. + */ + drm_intel_bo_subdata(temp_bo, 0, length, obj->Mappings[index].Pointer); intel_emit_linear_blit(intel, - intel_obj->buffer, obj->Offset + offset, + intel_obj->buffer, + obj->Mappings[index].Offset + offset, temp_bo, 0, length); @@ -406,31 +428,35 @@ intel_bufferobj_flush_mapped_range(struct gl_context *ctx, * Called via glUnmapBuffer(). */ static GLboolean -intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj) +intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj, + gl_map_buffer_index index) { struct intel_context *intel = intel_context(ctx); struct intel_buffer_object *intel_obj = intel_buffer_object(obj); assert(intel_obj); - assert(obj->Pointer); + assert(obj->Mappings[index].Pointer); if (intel_obj->sys_buffer != NULL) { /* always keep the mapping around. */ - } else if (intel_obj->range_map_buffer != NULL) { + } else if (intel_obj->range_map_buffer[index] != NULL) { /* Since we've emitted some blits to buffers that will (likely) be used * in rendering operations in other cache domains in this batch, emit a * flush. Once again, we wish for a domain tracker in libdrm to cover * usage inside of a batchbuffer. */ intel_batchbuffer_emit_mi_flush(intel); - free(intel_obj->range_map_buffer); - intel_obj->range_map_buffer = NULL; - } else if (intel_obj->range_map_bo != NULL) { - drm_intel_bo_unmap(intel_obj->range_map_bo); + _mesa_align_free(intel_obj->range_map_buffer[index]); + intel_obj->range_map_buffer[index] = NULL; + } else if (intel_obj->range_map_bo[index] != NULL) { + const unsigned extra = obj->Mappings[index].Pointer - + intel_obj->range_map_bo[index]->virtual; + + drm_intel_bo_unmap(intel_obj->range_map_bo[index]); intel_emit_linear_blit(intel, - intel_obj->buffer, obj->Offset, - intel_obj->range_map_bo, 0, - obj->Length); + intel_obj->buffer, obj->Mappings[index].Offset, + intel_obj->range_map_bo[index], extra, + obj->Mappings[index].Length); /* Since we've emitted some blits to buffers that will (likely) be used * in rendering operations in other cache domains in this batch, emit a @@ -439,22 +465,21 @@ intel_bufferobj_unmap(struct gl_context * ctx, struct gl_buffer_object *obj) */ intel_batchbuffer_emit_mi_flush(intel); - drm_intel_bo_unreference(intel_obj->range_map_bo); - intel_obj->range_map_bo = NULL; + drm_intel_bo_unreference(intel_obj->range_map_bo[index]); + intel_obj->range_map_bo[index] = NULL; } else if (intel_obj->buffer != NULL) { drm_intel_bo_unmap(intel_obj->buffer); } - obj->Pointer = NULL; - obj->Offset = 0; - obj->Length = 0; + obj->Mappings[index].Pointer = NULL; + obj->Mappings[index].Offset = 0; + obj->Mappings[index].Length = 0; return true; } drm_intel_bo * intel_bufferobj_buffer(struct intel_context *intel, - struct intel_buffer_object *intel_obj, - GLuint flag) + struct intel_buffer_object *intel_obj) { if (intel_obj->source) release_buffer(intel_obj); @@ -465,7 +490,7 @@ intel_bufferobj_buffer(struct intel_context *intel, 0, intel_obj->Base.Size, intel_obj->sys_buffer); - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; intel_obj->offset = 0; } @@ -550,62 +575,6 @@ void intel_upload_data(struct intel_context *intel, intel->upload.offset = base + size; } -void *intel_upload_map(struct intel_context *intel, GLuint size, GLuint align) -{ - GLuint base, delta; - char *ptr; - - base = (intel->upload.offset + align - 1) / align * align; - if (intel->upload.bo == NULL || base + size > intel->upload.bo->size) { - wrap_buffers(intel, size); - base = 0; - } - - delta = base - intel->upload.offset; - if (intel->upload.buffer_len && - intel->upload.buffer_len + delta + size > sizeof(intel->upload.buffer)) - { - drm_intel_bo_subdata(intel->upload.bo, - intel->upload.buffer_offset, - intel->upload.buffer_len, - intel->upload.buffer); - intel->upload.buffer_len = 0; - } - - if (size <= sizeof(intel->upload.buffer)) { - if (intel->upload.buffer_len == 0) - intel->upload.buffer_offset = base; - else - intel->upload.buffer_len += delta; - - ptr = intel->upload.buffer + intel->upload.buffer_len; - intel->upload.buffer_len += size; - } else - ptr = malloc(size); - - return ptr; -} - -void intel_upload_unmap(struct intel_context *intel, - const void *ptr, GLuint size, GLuint align, - drm_intel_bo **return_bo, - GLuint *return_offset) -{ - GLuint base; - - base = (intel->upload.offset + align - 1) / align * align; - if (size > sizeof(intel->upload.buffer)) { - drm_intel_bo_subdata(intel->upload.bo, base, size, ptr); - free((void*)ptr); - } - - drm_intel_bo_reference(intel->upload.bo); - *return_bo = intel->upload.bo; - *return_offset = base; - - intel->upload.offset = base + size; -} - drm_intel_bo * intel_bufferobj_source(struct intel_context *intel, struct intel_buffer_object *intel_obj, @@ -647,29 +616,31 @@ intel_bufferobj_copy_subdata(struct gl_context *ctx, char *ptr = intel_bufferobj_map_range(ctx, 0, dst->Size, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, - dst); + dst, MAP_INTERNAL); memmove(ptr + write_offset, ptr + read_offset, size); - intel_bufferobj_unmap(ctx, dst); + intel_bufferobj_unmap(ctx, dst, MAP_INTERNAL); } else { const char *src_ptr; char *dst_ptr; src_ptr = intel_bufferobj_map_range(ctx, 0, src->Size, - GL_MAP_READ_BIT, src); + GL_MAP_READ_BIT, src, + MAP_INTERNAL); dst_ptr = intel_bufferobj_map_range(ctx, 0, dst->Size, - GL_MAP_WRITE_BIT, dst); + GL_MAP_WRITE_BIT, dst, + MAP_INTERNAL); memcpy(dst_ptr + write_offset, src_ptr + read_offset, size); - intel_bufferobj_unmap(ctx, src); - intel_bufferobj_unmap(ctx, dst); + intel_bufferobj_unmap(ctx, src, MAP_INTERNAL); + intel_bufferobj_unmap(ctx, dst, MAP_INTERNAL); } return; } /* Otherwise, we have real BOs, so blit them. */ - dst_bo = intel_bufferobj_buffer(intel, intel_dst, INTEL_WRITE_PART); + dst_bo = intel_bufferobj_buffer(intel, intel_dst); src_bo = intel_bufferobj_source(intel, intel_src, 64, &src_offset); intel_emit_linear_blit(intel, @@ -706,14 +677,14 @@ intel_buffer_object_purgeable(struct gl_context * ctx, return intel_buffer_purgeable(intel_obj->buffer); if (option == GL_RELEASED_APPLE) { - free(intel_obj->sys_buffer); + _mesa_align_free(intel_obj->sys_buffer); intel_obj->sys_buffer = NULL; return GL_RELEASED_APPLE; } else { /* XXX Create the buffer and madvise(MADV_DONTNEED)? */ struct intel_context *intel = intel_context(ctx); - drm_intel_bo *bo = intel_bufferobj_buffer(intel, intel_obj, INTEL_READ); + drm_intel_bo *bo = intel_bufferobj_buffer(intel, intel_obj); return intel_buffer_purgeable(bo); }