diff options
author | Marek Olšák <[email protected]> | 2014-02-06 19:24:23 +0100 |
---|---|---|
committer | Marek Olšák <[email protected]> | 2014-02-25 16:07:33 +0100 |
commit | dca350201e00c7cf1cfb009158f4abf27fbc96d2 (patch) | |
tree | 8e331dfaa4ab2b623ee559f14fb1f678be6ba5df /src/mesa/main | |
parent | 86e68b0f1f7f5ff58b38653978acaa736ae3d01c (diff) |
mesa: allow buffers to be mapped multiple times
OpenGL allows a buffer to be mapped only once, but we also map buffers
internally, e.g. in the software primitive restart fallback, for PBOs,
vbo_get_minmax_index, etc. This has always been a problem, but it will
be a bigger problem with persistent buffer mappings, which will prevent
all Mesa functions from mapping buffers for internal purposes.
This adds a driver interface to core Mesa which supports multiple buffer
mappings and allows 2 mappings: one for the GL user and one for Mesa.
Note that Gallium supports an unlimited number of buffer and texture
mappings, so it's not really an issue for Gallium.
v2: fix unmapping in xm_dd.c, remove the GL errors there
v3: fix the intel driver (by Fredrik)
Reviewed-by: Fredrik Höglund <[email protected]>
Diffstat (limited to 'src/mesa/main')
-rw-r--r-- | src/mesa/main/api_arrayelt.c | 14 | ||||
-rw-r--r-- | src/mesa/main/api_validate.c | 5 | ||||
-rw-r--r-- | src/mesa/main/bufferobj.c | 215 | ||||
-rw-r--r-- | src/mesa/main/bufferobj.h | 15 | ||||
-rw-r--r-- | src/mesa/main/dd.h | 9 | ||||
-rw-r--r-- | src/mesa/main/dlist.c | 5 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 28 | ||||
-rw-r--r-- | src/mesa/main/pbo.c | 18 | ||||
-rw-r--r-- | src/mesa/main/shared.c | 6 | ||||
-rw-r--r-- | src/mesa/main/texgetimage.c | 10 |
10 files changed, 173 insertions, 152 deletions
diff --git a/src/mesa/main/api_arrayelt.c b/src/mesa/main/api_arrayelt.c index 29a57c8e51d..05cbc0f1f40 100644 --- a/src/mesa/main/api_arrayelt.c +++ b/src/mesa/main/api_arrayelt.c @@ -1458,7 +1458,8 @@ _ae_destroy_context(struct gl_context *ctx) static void check_vbo(AEcontext *actx, struct gl_buffer_object *vbo) { - if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo)) { + if (_mesa_is_bufferobj(vbo) && + !_mesa_bufferobj_mapped(vbo, MAP_INTERNAL)) { GLuint i; for (i = 0; i < actx->nr_vbos; i++) if (actx->vbo[i] == vbo) @@ -1633,7 +1634,8 @@ _ae_map_vbos(struct gl_context *ctx) ctx->Driver.MapBufferRange(ctx, 0, actx->vbo[i]->Size, GL_MAP_READ_BIT, - actx->vbo[i]); + actx->vbo[i], + MAP_INTERNAL); if (actx->nr_vbos) actx->mapped_vbos = GL_TRUE; @@ -1655,7 +1657,7 @@ _ae_unmap_vbos(struct gl_context *ctx) assert (!actx->NewState); for (i = 0; i < actx->nr_vbos; i++) - ctx->Driver.UnmapBuffer(ctx, actx->vbo[i]); + ctx->Driver.UnmapBuffer(ctx, actx->vbo[i], MAP_INTERNAL); actx->mapped_vbos = GL_FALSE; } @@ -1701,7 +1703,8 @@ _ae_ArrayElement(GLint elt) /* emit generic attribute elements */ for (at = actx->attribs; at->func; at++) { const GLubyte *src - = ADD_POINTERS(at->array->BufferObj->Pointer, at->array->Ptr) + = ADD_POINTERS(at->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + at->array->Ptr) + elt * at->array->StrideB; at->func(at->index, src); } @@ -1709,7 +1712,8 @@ _ae_ArrayElement(GLint elt) /* emit conventional arrays elements */ for (aa = actx->arrays; aa->offset != -1 ; aa++) { const GLubyte *src - = ADD_POINTERS(aa->array->BufferObj->Pointer, aa->array->Ptr) + = ADD_POINTERS(aa->array->BufferObj->Mappings[MAP_INTERNAL].Pointer, + aa->array->Ptr) + elt * aa->array->StrideB; CALL_by_offset(disp, (array_func), aa->offset, ((const void *) src)); } diff --git a/src/mesa/main/api_validate.c b/src/mesa/main/api_validate.c index ce007e26598..f3fd1a47569 100644 --- a/src/mesa/main/api_validate.c +++ b/src/mesa/main/api_validate.c @@ -69,7 +69,8 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, if (_mesa_is_bufferobj(elementBuf)) { /* elements are in a user-defined buffer object. need to map it */ map = ctx->Driver.MapBufferRange(ctx, 0, elementBuf->Size, - GL_MAP_READ_BIT, elementBuf); + GL_MAP_READ_BIT, elementBuf, + MAP_INTERNAL); /* Actual address is the sum of pointers */ indices = (const GLvoid *) ADD_POINTERS(map, (const GLubyte *) indices); } @@ -92,7 +93,7 @@ _mesa_max_buffer_index(struct gl_context *ctx, GLuint count, GLenum type, } if (map) { - ctx->Driver.UnmapBuffer(ctx, elementBuf); + ctx->Driver.UnmapBuffer(ctx, elementBuf, MAP_INTERNAL); } return max; diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 3079127ce6c..237b49cb1c7 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -207,11 +207,12 @@ static bool bufferobj_range_mapped(const struct gl_buffer_object *obj, GLintptr offset, GLsizeiptr size) { - if (_mesa_bufferobj_mapped(obj)) { + if (_mesa_bufferobj_mapped(obj, MAP_USER)) { const GLintptr end = offset + size; - const GLintptr mapEnd = obj->Offset + obj->Length; + const GLintptr mapEnd = obj->Mappings[MAP_USER].Offset + + obj->Mappings[MAP_USER].Length; - if (!(end <= obj->Offset || offset >= mapEnd)) { + if (!(end <= obj->Mappings[MAP_USER].Offset || offset >= mapEnd)) { return true; } } @@ -269,7 +270,7 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, return NULL; } - if (bufObj->AccessFlags & GL_MAP_PERSISTENT_BIT) + if (bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) return bufObj; if (mappedRange) { @@ -279,7 +280,7 @@ buffer_object_subdata_range_good(struct gl_context * ctx, GLenum target, } } else { - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); return NULL; } @@ -503,7 +504,6 @@ _mesa_initialize_buffer_object( struct gl_context *ctx, obj->RefCount = 1; obj->Name = name; obj->Usage = GL_STATIC_DRAW_ARB; - obj->AccessFlags = 0; } @@ -675,33 +675,11 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, GLsizeiptr i; GLubyte *dest; - if (_mesa_bufferobj_mapped(bufObj)) { - GLubyte *data = malloc(size); - GLubyte *dataStart = data; - if (data == NULL) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); - return; - } - - if (clearValue == NULL) { - /* Clear with zeros, per the spec */ - memset(data, 0, size); - } - else { - for (i = 0; i < size/clearValueSize; ++i) { - memcpy(data, clearValue, clearValueSize); - data += clearValueSize; - } - } - ctx->Driver.BufferSubData(ctx, offset, size, dataStart, bufObj); - return; - } - ASSERT(ctx->Driver.MapBufferRange); dest = ctx->Driver.MapBufferRange(ctx, offset, size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT, - bufObj); + bufObj, MAP_INTERNAL); if (!dest) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearBuffer[Sub]Data"); @@ -711,7 +689,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, if (clearValue == NULL) { /* Clear with zeros, per the spec */ memset(dest, 0, size); - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); return; } @@ -720,7 +698,7 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, dest += clearValueSize; } - ctx->Driver.UnmapBuffer(ctx, bufObj); + ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_INTERNAL); } @@ -731,16 +709,17 @@ _mesa_buffer_clear_subdata(struct gl_context *ctx, static void * _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *bufObj ) + struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; - assert(!_mesa_bufferobj_mapped(bufObj)); + assert(!_mesa_bufferobj_mapped(bufObj, index)); /* Just return a direct pointer to the data */ - bufObj->Pointer = bufObj->Data + offset; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[index].Pointer = bufObj->Data + offset; + bufObj->Mappings[index].Length = length; + bufObj->Mappings[index].Offset = offset; + bufObj->Mappings[index].AccessFlags = access; + return bufObj->Mappings[index].Pointer; } @@ -751,7 +730,8 @@ _mesa_buffer_map_range( struct gl_context *ctx, GLintptr offset, static void _mesa_buffer_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) { (void) ctx; (void) offset; @@ -769,14 +749,15 @@ _mesa_buffer_flush_mapped_range( struct gl_context *ctx, * \sa glUnmapBufferARB, dd_function_table::UnmapBuffer */ static GLboolean -_mesa_buffer_unmap( struct gl_context *ctx, struct gl_buffer_object *bufObj ) +_mesa_buffer_unmap(struct gl_context *ctx, struct gl_buffer_object *bufObj, + gl_map_buffer_index index) { (void) ctx; /* XXX we might assert here that bufObj->Pointer is non-null */ - bufObj->Pointer = NULL; - bufObj->Length = 0; - bufObj->Offset = 0; - bufObj->AccessFlags = 0x0; + bufObj->Mappings[index].Pointer = NULL; + bufObj->Mappings[index].Length = 0; + bufObj->Mappings[index].Offset = 0; + bufObj->Mappings[index].AccessFlags = 0x0; return GL_TRUE; } @@ -794,14 +775,11 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, { GLubyte *srcPtr, *dstPtr; - /* the buffers should not be mapped */ - assert(!_mesa_bufferobj_mapped(src)); - assert(!_mesa_bufferobj_mapped(dst)); - if (src == dst) { srcPtr = dstPtr = ctx->Driver.MapBufferRange(ctx, 0, src->Size, GL_MAP_READ_BIT | - GL_MAP_WRITE_BIT, src); + GL_MAP_WRITE_BIT, src, + MAP_INTERNAL); if (!srcPtr) return; @@ -810,10 +788,12 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, dstPtr += writeOffset; } else { srcPtr = ctx->Driver.MapBufferRange(ctx, readOffset, size, - GL_MAP_READ_BIT, src); + GL_MAP_READ_BIT, src, + MAP_INTERNAL); dstPtr = ctx->Driver.MapBufferRange(ctx, writeOffset, size, (GL_MAP_WRITE_BIT | - GL_MAP_INVALIDATE_RANGE_BIT), dst); + GL_MAP_INVALIDATE_RANGE_BIT), dst, + MAP_INTERNAL); } /* Note: the src and dst regions will never overlap. Trying to do so @@ -822,9 +802,9 @@ _mesa_copy_buffer_subdata(struct gl_context *ctx, if (srcPtr && dstPtr) memcpy(dstPtr, srcPtr, size); - ctx->Driver.UnmapBuffer(ctx, src); + ctx->Driver.UnmapBuffer(ctx, src, MAP_INTERNAL); if (dst != src) - ctx->Driver.UnmapBuffer(ctx, dst); + ctx->Driver.UnmapBuffer(ctx, dst, MAP_INTERNAL); } @@ -1039,6 +1019,21 @@ _mesa_init_buffer_object_functions(struct dd_function_table *driver) } +void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj) +{ + int i; + + for (i = 0; i < MAP_COUNT; i++) { + if (_mesa_bufferobj_mapped(bufObj, i)) { + ctx->Driver.UnmapBuffer(ctx, bufObj, i); + ASSERT(bufObj->Mappings[i].Pointer == NULL); + bufObj->Mappings[i].AccessFlags = 0; + } + } +} + /**********************************************************************/ /* API Functions */ @@ -1085,12 +1080,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) ASSERT(bufObj->Name == ids[i] || bufObj == &DummyBufferObject); - if (_mesa_bufferobj_mapped(bufObj)) { - /* if mapped, unmap it now */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - bufObj->Pointer = NULL; - } + _mesa_buffer_unmap_all_mappings(ctx, bufObj); /* unbind any vertex pointers bound to this buffer */ for (j = 0; j < Elements(vao->VertexBinding); j++) { @@ -1278,12 +1268,8 @@ _mesa_BufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, return; } - if (_mesa_bufferobj_mapped(bufObj)) { - /* Unmap the existing buffer. We'll replace it now. Not an error. */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - } + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); @@ -1355,12 +1341,8 @@ _mesa_BufferData(GLenum target, GLsizeiptrARB size, return; } - if (_mesa_bufferobj_mapped(bufObj)) { - /* Unmap the existing buffer. We'll replace it now. Not an error. */ - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - } + /* Unmap the existing buffer. We'll replace it now. Not an error. */ + _mesa_buffer_unmap_all_mappings(ctx, bufObj); FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT); @@ -1594,7 +1576,7 @@ _mesa_MapBuffer(GLenum target, GLenum access) return NULL; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); return NULL; } @@ -1606,7 +1588,8 @@ _mesa_MapBuffer(GLenum target, GLenum access) } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj); + map = ctx->Driver.MapBufferRange(ctx, 0, bufObj->Size, accessFlags, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); return NULL; @@ -1616,10 +1599,10 @@ _mesa_MapBuffer(GLenum target, GLenum access) * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == bufObj->Size); - ASSERT(bufObj->Offset == 0); - bufObj->AccessFlags = accessFlags; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == bufObj->Size); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + bufObj->Mappings[MAP_USER].AccessFlags = accessFlags; } if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) @@ -1647,7 +1630,7 @@ _mesa_MapBuffer(GLenum target, GLenum access) } #endif - return bufObj->Pointer; + return bufObj->Mappings[MAP_USER].Pointer; } @@ -1663,7 +1646,7 @@ _mesa_UnmapBuffer(GLenum target) if (!bufObj) return GL_FALSE; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); return GL_FALSE; } @@ -1704,11 +1687,11 @@ _mesa_UnmapBuffer(GLenum target) } #endif - status = ctx->Driver.UnmapBuffer( ctx, bufObj ); - bufObj->AccessFlags = 0; - ASSERT(bufObj->Pointer == NULL); - ASSERT(bufObj->Offset == 0); - ASSERT(bufObj->Length == 0); + status = ctx->Driver.UnmapBuffer(ctx, bufObj, MAP_USER); + bufObj->Mappings[MAP_USER].AccessFlags = 0; + ASSERT(bufObj->Mappings[MAP_USER].Pointer == NULL); + ASSERT(bufObj->Mappings[MAP_USER].Offset == 0); + ASSERT(bufObj->Mappings[MAP_USER].Length == 0); return status; } @@ -1733,25 +1716,26 @@ _mesa_GetBufferParameteriv(GLenum target, GLenum pname, GLint *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Offset; + *params = (GLint) bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = (GLint) bufObj->Length; + *params = (GLint) bufObj->Mappings[MAP_USER].Length; return; case GL_BUFFER_IMMUTABLE_STORAGE: if (!ctx->Extensions.ARB_buffer_storage) @@ -1797,25 +1781,26 @@ _mesa_GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 *params) *params = bufObj->Usage; return; case GL_BUFFER_ACCESS_ARB: - *params = simplified_access_mode(ctx, bufObj->AccessFlags); + *params = simplified_access_mode(ctx, + bufObj->Mappings[MAP_USER].AccessFlags); return; case GL_BUFFER_ACCESS_FLAGS: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->AccessFlags; + *params = bufObj->Mappings[MAP_USER].AccessFlags; return; case GL_BUFFER_MAPPED_ARB: - *params = _mesa_bufferobj_mapped(bufObj); + *params = _mesa_bufferobj_mapped(bufObj, MAP_USER); return; case GL_BUFFER_MAP_OFFSET: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Offset; + *params = bufObj->Mappings[MAP_USER].Offset; return; case GL_BUFFER_MAP_LENGTH: if (!ctx->Extensions.ARB_map_buffer_range) goto invalid_pname; - *params = bufObj->Length; + *params = bufObj->Mappings[MAP_USER].Length; return; case GL_BUFFER_IMMUTABLE_STORAGE: if (!ctx->Extensions.ARB_buffer_storage) @@ -1853,7 +1838,7 @@ _mesa_GetBufferPointerv(GLenum target, GLenum pname, GLvoid **params) if (!bufObj) return; - *params = bufObj->Pointer; + *params = bufObj->Mappings[MAP_USER].Pointer; } @@ -2061,7 +2046,7 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, return NULL; } - if (_mesa_bufferobj_mapped(bufObj)) { + if (_mesa_bufferobj_mapped(bufObj, MAP_USER)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferRange(buffer already mapped)"); return NULL; @@ -2076,15 +2061,16 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, /* Mapping zero bytes should return a non-null pointer. */ if (!length) { static long dummy = 0; - bufObj->Pointer = &dummy; - bufObj->Length = length; - bufObj->Offset = offset; - bufObj->AccessFlags = access; - return bufObj->Pointer; + bufObj->Mappings[MAP_USER].Pointer = &dummy; + bufObj->Mappings[MAP_USER].Length = length; + bufObj->Mappings[MAP_USER].Offset = offset; + bufObj->Mappings[MAP_USER].AccessFlags = access; + return bufObj->Mappings[MAP_USER].Pointer; } ASSERT(ctx->Driver.MapBufferRange); - map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj); + map = ctx->Driver.MapBufferRange(ctx, offset, length, access, bufObj, + MAP_USER); if (!map) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(map failed)"); } @@ -2093,10 +2079,10 @@ _mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, * This is important because other modules (like VBO) might call * the driver function directly. */ - ASSERT(bufObj->Pointer == map); - ASSERT(bufObj->Length == length); - ASSERT(bufObj->Offset == offset); - ASSERT(bufObj->AccessFlags == access); + ASSERT(bufObj->Mappings[MAP_USER].Pointer == map); + ASSERT(bufObj->Mappings[MAP_USER].Length == length); + ASSERT(bufObj->Mappings[MAP_USER].Offset == offset); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags == access); } return map; @@ -2135,30 +2121,33 @@ _mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) if (!bufObj) return; - if (!_mesa_bufferobj_mapped(bufObj)) { + if (!_mesa_bufferobj_mapped(bufObj, MAP_USER)) { /* buffer is not mapped */ _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(buffer is not mapped)"); return; } - if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { + if ((bufObj->Mappings[MAP_USER].AccessFlags & + GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glFlushMappedBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)"); return; } - if (offset + length > bufObj->Length) { + if (offset + length > bufObj->Mappings[MAP_USER].Length) { _mesa_error(ctx, GL_INVALID_VALUE, "glFlushMappedBufferRange(offset %ld + length %ld > mapped length %ld)", - (long)offset, (long)length, (long)bufObj->Length); + (long)offset, (long)length, + (long)bufObj->Mappings[MAP_USER].Length); return; } - ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT); + ASSERT(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_WRITE_BIT); if (ctx->Driver.FlushMappedBufferRange) - ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj); + ctx->Driver.FlushMappedBufferRange(ctx, offset, length, bufObj, + MAP_USER); } @@ -2812,7 +2801,7 @@ _mesa_InvalidateBufferSubData(GLuint buffer, GLintptr offset, * currently mapped by MapBufferRange, unless it was mapped * with MAP_PERSISTENT_BIT set in the MapBufferRange access flags." */ - if (!(bufObj->AccessFlags & GL_MAP_PERSISTENT_BIT) && + if (!(bufObj->Mappings[MAP_USER].AccessFlags & GL_MAP_PERSISTENT_BIT) && bufferobj_range_mapped(bufObj, offset, length)) { _mesa_error(ctx, GL_INVALID_OPERATION, "glInvalidateBufferSubData(intersection with mapped " diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index 253a386c271..9814552eb96 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -37,19 +37,21 @@ */ -/** Is the given buffer object currently mapped? */ +/** Is the given buffer object currently mapped by the GL user? */ static inline GLboolean -_mesa_bufferobj_mapped(const struct gl_buffer_object *obj) +_mesa_bufferobj_mapped(const struct gl_buffer_object *obj, + gl_map_buffer_index index) { - return obj->Pointer != NULL; + return obj->Mappings[index].Pointer != NULL; } /** Can we not use this buffer while mapped? */ static inline GLboolean _mesa_check_disallowed_mapping(const struct gl_buffer_object *obj) { - return _mesa_bufferobj_mapped(obj) && - !(obj->AccessFlags & GL_MAP_PERSISTENT_BIT); + return _mesa_bufferobj_mapped(obj, MAP_USER) && + !(obj->Mappings[MAP_USER].AccessFlags & + GL_MAP_PERSISTENT_BIT); } /** @@ -109,6 +111,9 @@ _mesa_total_buffer_object_memory(struct gl_context *ctx); extern void _mesa_init_buffer_object_functions(struct dd_function_table *driver); +extern void +_mesa_buffer_unmap_all_mappings(struct gl_context *ctx, + struct gl_buffer_object *bufObj); /* * API functions diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h index f1ba6000d02..9715241355d 100644 --- a/src/mesa/main/dd.h +++ b/src/mesa/main/dd.h @@ -605,14 +605,17 @@ struct dd_function_table { */ void * (*MapBufferRange)( struct gl_context *ctx, GLintptr offset, GLsizeiptr length, GLbitfield access, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); void (*FlushMappedBufferRange)(struct gl_context *ctx, GLintptr offset, GLsizeiptr length, - struct gl_buffer_object *obj); + struct gl_buffer_object *obj, + gl_map_buffer_index index); GLboolean (*UnmapBuffer)( struct gl_context *ctx, - struct gl_buffer_object *obj ); + struct gl_buffer_object *obj, + gl_map_buffer_index index); /*@}*/ /** diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 08943c9f9b0..0f4c89b8d20 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -914,7 +914,8 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, map = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, - GL_MAP_READ_BIT, unpack->BufferObj); + GL_MAP_READ_BIT, unpack->BufferObj, + MAP_INTERNAL); if (!map) { /* unable to map src buffer! */ _mesa_error(ctx, GL_INVALID_OPERATION, "unable to map PBO"); @@ -928,7 +929,7 @@ unpack_image(struct gl_context *ctx, GLuint dimensions, image = _mesa_unpack_image(dimensions, width, height, depth, format, type, src, unpack); - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); if (!image) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "display list construction"); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 5c39ac91238..7246b1e0556 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1439,6 +1439,25 @@ struct gl_viewport_attrib }; +typedef enum { + MAP_USER, + MAP_INTERNAL, + + MAP_COUNT +} gl_map_buffer_index; + + +/** + * Fields describing a mapped buffer range. + */ +struct gl_buffer_mapping { + GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ + GLvoid *Pointer; /**< User-space address of mapping */ + GLintptr Offset; /**< Mapped offset */ + GLsizeiptr Length; /**< Mapped length */ +}; + + /** * GL_ARB_vertex/pixel_buffer_object buffer object */ @@ -1452,17 +1471,12 @@ struct gl_buffer_object GLbitfield StorageFlags; /**< GL_MAP_PERSISTENT_BIT, etc. */ GLsizeiptrARB Size; /**< Size of buffer storage in bytes */ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ - /** Fields describing a mapped buffer */ - /*@{*/ - GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */ - GLvoid *Pointer; /**< User-space address of mapping */ - GLintptr Offset; /**< Mapped offset */ - GLsizeiptr Length; /**< Mapped length */ - /*@}*/ GLboolean DeletePending; /**< true if buffer object is removed from the hash */ GLboolean Written; /**< Ever written to? (for debugging) */ GLboolean Purgeable; /**< Is the buffer purgeable under memory pressure? */ GLboolean Immutable; /**< GL_ARB_buffer_storage */ + + struct gl_buffer_mapping Mappings[MAP_COUNT]; }; diff --git a/src/mesa/main/pbo.c b/src/mesa/main/pbo.c index 4a394041778..a0d61a6436b 100644 --- a/src/mesa/main/pbo.c +++ b/src/mesa/main/pbo.c @@ -149,7 +149,8 @@ _mesa_map_pbo_source(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -221,7 +222,7 @@ _mesa_unmap_pbo_source(struct gl_context *ctx, { ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } @@ -246,7 +247,8 @@ _mesa_map_pbo_dest(struct gl_context *ctx, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, pack->BufferObj->Size, GL_MAP_WRITE_BIT, - pack->BufferObj); + pack->BufferObj, + MAP_INTERNAL); if (!buf) return NULL; @@ -317,7 +319,7 @@ _mesa_unmap_pbo_dest(struct gl_context *ctx, { ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ if (_mesa_is_bufferobj(pack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, pack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); } } @@ -351,7 +353,8 @@ _mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, unpack->BufferObj->Size, GL_MAP_READ_BIT, - unpack->BufferObj); + unpack->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -393,7 +396,8 @@ _mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, packing->BufferObj->Size, GL_MAP_READ_BIT, - packing->BufferObj); + packing->BufferObj, + MAP_INTERNAL); if (!buf) { _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, dimensions); @@ -413,6 +417,6 @@ _mesa_unmap_teximage_pbo(struct gl_context *ctx, const struct gl_pixelstore_attrib *unpack) { if (_mesa_is_bufferobj(unpack->BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj); + ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); } } diff --git a/src/mesa/main/shared.c b/src/mesa/main/shared.c index c11c7f9e9eb..6a49348ce51 100644 --- a/src/mesa/main/shared.c +++ b/src/mesa/main/shared.c @@ -186,10 +186,8 @@ delete_bufferobj_cb(GLuint id, void *data, void *userData) { struct gl_buffer_object *bufObj = (struct gl_buffer_object *) data; struct gl_context *ctx = (struct gl_context *) userData; - if (_mesa_bufferobj_mapped(bufObj)) { - ctx->Driver.UnmapBuffer(ctx, bufObj); - bufObj->Pointer = NULL; - } + + _mesa_buffer_unmap_all_mappings(ctx, bufObj); _mesa_reference_buffer_object(ctx, &bufObj, NULL); } diff --git a/src/mesa/main/texgetimage.c b/src/mesa/main/texgetimage.c index b21aa2cf25f..fedd814e932 100644 --- a/src/mesa/main/texgetimage.c +++ b/src/mesa/main/texgetimage.c @@ -635,7 +635,8 @@ _mesa_get_teximage(struct gl_context *ctx, */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)"); @@ -664,7 +665,7 @@ _mesa_get_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } @@ -689,7 +690,8 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, /* pack texture image into a PBO */ GLubyte *buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, ctx->Pack.BufferObj->Size, - GL_MAP_WRITE_BIT, ctx->Pack.BufferObj); + GL_MAP_WRITE_BIT, ctx->Pack.BufferObj, + MAP_INTERNAL); if (!buf) { /* out of memory or other unexpected error */ _mesa_error(ctx, GL_OUT_OF_MEMORY, @@ -731,7 +733,7 @@ _mesa_get_compressed_teximage(struct gl_context *ctx, } if (_mesa_is_bufferobj(ctx->Pack.BufferObj)) { - ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj); + ctx->Driver.UnmapBuffer(ctx, ctx->Pack.BufferObj, MAP_INTERNAL); } } |