diff --git a/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c index 0897daf..4bdf36d 100644 --- a/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c +++ b/src/mesa/drivers/dri/radeon/radeon_buffer_objects.c @@ -199,6 +199,115 @@ radeonMapBuffer(GLcontext * ctx, return obj->Pointer; } +/** + * Called via glMapBufferRange(). + * + * The goal of this extension is to allow apps to accumulate their rendering + * at the same time as they accumulate their buffer object. Without it, + * you'd end up blocking on execution of rendering every time you mapped + * the buffer to put new data in. + * + * We support it in 3 ways: If unsynchronized, then don't bother + * flushing the batchbuffer before mapping the buffer, which can save blocking + * in many cases. If we would still block, and they allow the whole buffer + * to be invalidated, then just allocate a new buffer to replace the old one. + * If not, and we'd block, and they allow the subrange of the buffer to be + * invalidated, then we can make a new little BO, let them write into that, + * and blit it into the real BO at unmap time. + */ +static void * +radeon_bufferobj_map_range(GLcontext * ctx, + GLenum target, GLsizei offset, GLsizeiptr length, + GLbitfield access, struct gl_buffer_object *obj) +{ + radeonContextPtr radeon = RADEON_CONTEXT(ctx); + struct radeon_buffer_object *radeon_obj = get_radeon_buffer_object(obj); + + assert(radeon_obj); + + if (radeon_obj->sys_buffer) { + obj->Pointer = radeon_obj->sys_buffer + offset; + return obj->Pointer; + } + + if (radeon_obj->region) + radeon_bufferobj_cow(radeon, radeon_obj); // implement this? + + /* If the mapping is synchronized with other GL operations, flush + * the batchbuffer so that GEM knows about the buffer access for later + * syncing. + */ + if ((access & GL_MAP_WRITE_BIT) && !(access & GL_MAP_UNSYNCHRONIZED_BIT)) + RadeonFlush(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; + + if (radeon_buffer == NULL) { + obj->Pointer = NULL; + return NULL; + } + + /* If the user doesn't care about existing buffer contents and mapping + * would cause us to block, then throw out the old buffer. + */ + if (!(access & GL_MAP_UNSYNCHRONIZED_BIT) && + (access & GL_MAP_INVALIDATE_BUFFER_BIT) && + drm_radeon_bo_busy(radeon_obj->buffer)) { + drm_radeon_bo_unreference(radeon_obj->buffer); + radeon_obj->buffer = dri_bo_alloc(radeon->bufmgr, "bufferobj", + radeon_obj->Base.Size, 64); + } + + /* sigh . Radeon uses different bufmanager */ + + /* If the user is mapping a range of an active buffer object but + * doesn't require the current contents of that range, make a new + * BO, and we'll copy what they put in there out at unmap or + * FlushRange time. + */ + + /* How to check busy-ness for radeons ? */ + if ((access & GL_MAP_INVALIDATE_RANGE_BIT) && + drm_radeon_bo_busy(radeon_obj->buffer)) { + radeon_obj->range_map_bo = drm_radeon_bo_alloc(radeon->bufmgr, + "range map", + length, 64); + if (!(access & GL_MAP_READ_BIT) && + radeon->RadeonScreen->kernel_exec_fencing) { + drm_radeon_gem_bo_map_gtt(radeon_obj->range_map_bo); + radeon_obj->mapped_gtt = GL_TRUE; + } else { + drm_radeon_bo_map(radeon_obj->range_map_bo, + (access & GL_MAP_WRITE_BIT) != 0); + radeon_obj->mapped_gtt = GL_FALSE; + } + obj->Pointer = radeon_obj->range_map_bo->virtual; + return obj->Pointer; + } + +/* Guess Radeon has its own fencing, + what is equvalent of this kernel_exec_fencing ? */ + + /* Also, does radeon track mapped_to_gtt status for it's BOs ? */ + if (!(access & GL_MAP_READ_BIT) && + radeon->RadeonScreen->kernel_exec_fencing) { + drm_radeon_gem_bo_map_gtt(radeon_obj->buffer); + radeon_obj->mapped_gtt = GL_TRUE; + } else { + drm_radeon_bo_map(radeon_obj->buffer, (access & GL_MAP_WRITE_BIT) != 0); + radeon_obj->mapped_gtt = GL_FALSE; + } + + obj->Pointer = radeon_obj->buffer->virtual + offset; + return obj->Pointer; +} + + /** * Called via glUnmapBufferARB()