mesa: implement GL_ARB_map_buffer_range

Only enabled for software drivers at this point.

Note that the gl_buffer_object::Access enum field has been replaced by
a gl_buffer_object::AccessFlags bitfield.  The new field is a mask of
the GL_MAP_x_BIT flags which is a superset of the old GL_READ_ONLY,
GL_WRITE_ONLY and GL_READ_WRITE modes.  When we query GL_BUFFER_ACCESS_ARB
we translate the bitfield into the conventional enum values.
This commit is contained in:
Brian Paul
2009-06-08 17:02:36 -06:00
parent 75cb3c3b7a
commit e75b283b45
8 changed files with 265 additions and 13 deletions

View File

@@ -213,6 +213,11 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
driver->UnmapBuffer = _mesa_buffer_unmap; driver->UnmapBuffer = _mesa_buffer_unmap;
#endif #endif
#if FEATURE_ARB_map_buffer_range
driver->MapBufferRange = _mesa_buffer_map_range;
driver->FlushMappedBufferRange = _mesa_buffer_flush_mapped_range;
#endif
#if FEATURE_EXT_framebuffer_object #if FEATURE_EXT_framebuffer_object
driver->NewFramebuffer = _mesa_new_framebuffer; driver->NewFramebuffer = _mesa_new_framebuffer;
driver->NewRenderbuffer = _mesa_new_soft_renderbuffer; driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;

View File

@@ -895,7 +895,11 @@ _mesa_init_exec_table(struct _glapi_table *exec)
SET_RenderbufferStorageMultisample(exec, _mesa_RenderbufferStorageMultisample); SET_RenderbufferStorageMultisample(exec, _mesa_RenderbufferStorageMultisample);
#endif #endif
#if FEATURE_ARB_map_buffer_range
SET_MapBufferRange(exec, _mesa_MapBufferRange);
SET_FlushMappedBufferRange(exec, _mesa_FlushMappedBufferRange);
#endif
/* GL_ARB_copy_buffer */ /* GL_ARB_copy_buffer */
SET_CopyBufferSubData(exec, _mesa_CopyBufferSubData); SET_CopyBufferSubData(exec, _mesa_CopyBufferSubData);
} }

View File

@@ -40,9 +40,9 @@
#ifdef FEATURE_OES_mapbuffer #ifdef FEATURE_OES_mapbuffer
#define DEFAULT_ACCESS GL_WRITE_ONLY; #define DEFAULT_ACCESS GL_MAP_WRITE_BIT
#else #else
#define DEFAULT_ACCESS GL_READ_WRITE; #define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
#endif #endif
@@ -95,6 +95,24 @@ get_buffer(GLcontext *ctx, GLenum target)
} }
/**
* Convert a GLbitfield describing the mapped buffer access flags
* into one of GL_READ_WRITE, GL_READ_ONLY, or GL_WRITE_ONLY.
*/
static GLenum
simplified_access_mode(GLbitfield access)
{
const GLbitfield rwFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
if ((access & rwFlags) == rwFlags)
return GL_READ_WRITE;
if ((access & GL_MAP_READ_BIT) == GL_MAP_READ_BIT)
return GL_READ_ONLY;
if ((access & GL_MAP_WRITE_BIT) == GL_MAP_WRITE_BIT)
return GL_WRITE_ONLY;
return GL_READ_WRITE; /* this should never happen, but no big deal */
}
/** /**
* Tests the subdata range parameters and sets the GL error code for * Tests the subdata range parameters and sets the GL error code for
* \c glBufferSubDataARB and \c glGetBufferSubDataARB. * \c glBufferSubDataARB and \c glGetBufferSubDataARB.
@@ -271,7 +289,7 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
obj->RefCount = 1; obj->RefCount = 1;
obj->Name = name; obj->Name = name;
obj->Usage = GL_STATIC_DRAW_ARB; obj->Usage = GL_STATIC_DRAW_ARB;
obj->Access = DEFAULT_ACCESS; obj->AccessFlags = DEFAULT_ACCESS;
} }
@@ -409,6 +427,43 @@ _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
} }
/**
* Default fallback for \c dd_function_table::MapBufferRange().
* Called via glMapBufferRange().
*/
void *
_mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset,
GLsizeiptr length, GLbitfield access,
struct gl_buffer_object *bufObj )
{
(void) ctx;
(void) target;
(void) access;
(void) length;
assert(!bufObj->Pointer);
/* Just return a direct pointer to the data */
return bufObj->Data + offset;
}
/**
* Default fallback for \c dd_function_table::FlushMappedBufferRange().
* Called via glFlushMappedBufferRange().
*/
void
_mesa_buffer_flush_mapped_range( GLcontext *ctx, GLenum target,
GLintptr offset, GLsizeiptr length,
struct gl_buffer_object *obj )
{
(void) ctx;
(void) target;
(void) offset;
(void) length;
(void) obj;
/* no-op */
}
/** /**
* Default callback for \c dd_function_table::MapBuffer(). * Default callback for \c dd_function_table::MapBuffer().
* *
@@ -845,7 +900,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
if (bufObj->Pointer) { if (bufObj->Pointer) {
/* if mapped, unmap it now */ /* if mapped, unmap it now */
ctx->Driver.UnmapBuffer(ctx, 0, bufObj); ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
bufObj->Access = DEFAULT_ACCESS; bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL; bufObj->Pointer = NULL;
} }
@@ -1004,7 +1059,7 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
if (bufObj->Pointer) { if (bufObj->Pointer) {
/* Unmap the existing buffer. We'll replace it now. Not an error. */ /* Unmap the existing buffer. We'll replace it now. Not an error. */
ctx->Driver.UnmapBuffer(ctx, target, bufObj); ctx->Driver.UnmapBuffer(ctx, target, bufObj);
bufObj->Access = DEFAULT_ACCESS; bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL; bufObj->Pointer = NULL;
} }
@@ -1071,13 +1126,18 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
{ {
GET_CURRENT_CONTEXT(ctx); GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object * bufObj; struct gl_buffer_object * bufObj;
GLbitfield accessFlags;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
switch (access) { switch (access) {
case GL_READ_ONLY_ARB: case GL_READ_ONLY_ARB:
accessFlags = GL_MAP_READ_BIT;
break;
case GL_WRITE_ONLY_ARB: case GL_WRITE_ONLY_ARB:
accessFlags = GL_MAP_WRITE_BIT;
break;
case GL_READ_WRITE_ARB: case GL_READ_WRITE_ARB:
/* OK */ accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
break; break;
default: default:
_mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)");
@@ -1104,7 +1164,10 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)");
} }
bufObj->Access = access; bufObj->AccessFlags = accessFlags;
bufObj->Offset = 0;
bufObj->Length = bufObj->Size;
if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB) if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
bufObj->Written = GL_TRUE; bufObj->Written = GL_TRUE;
@@ -1146,7 +1209,7 @@ _mesa_UnmapBufferARB(GLenum target)
} }
#ifdef VBO_DEBUG #ifdef VBO_DEBUG
if (bufObj->Access == GL_WRITE_ONLY_ARB) { if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
GLuint i, unchanged = 0; GLuint i, unchanged = 0;
GLubyte *b = (GLubyte *) bufObj->Pointer; GLubyte *b = (GLubyte *) bufObj->Pointer;
GLint pos = -1; GLint pos = -1;
@@ -1166,8 +1229,10 @@ _mesa_UnmapBufferARB(GLenum target)
#endif #endif
status = ctx->Driver.UnmapBuffer( ctx, target, bufObj ); status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
bufObj->Access = DEFAULT_ACCESS; bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL; bufObj->Pointer = NULL;
bufObj->Offset = 0;
bufObj->Length = 0;
return status; return status;
} }
@@ -1198,7 +1263,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
*params = bufObj->Usage; *params = bufObj->Usage;
break; break;
case GL_BUFFER_ACCESS_ARB: case GL_BUFFER_ACCESS_ARB:
*params = bufObj->Access; *params = simplified_access_mode(bufObj->AccessFlags);
break; break;
case GL_BUFFER_MAPPED_ARB: case GL_BUFFER_MAPPED_ARB:
*params = (bufObj->Pointer != NULL); *params = (bufObj->Pointer != NULL);
@@ -1315,3 +1380,153 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size); ctx->Driver.CopyBufferSubData(ctx, src, dst, readOffset, writeOffset, size);
} }
/**
* See GL_ARB_map_buffer_range spec
*/
void * GLAPIENTRY
_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(extension not supported)");
return NULL;
}
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(offset = %ld)", offset);
return NULL;
}
if (length < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(length = %ld)", length);
return NULL;
}
if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(access indicates neither read or write)");
return NULL;
}
if (access & GL_MAP_READ_BIT) {
if ((access & GL_MAP_INVALIDATE_RANGE_BIT) ||
(access & GL_MAP_INVALIDATE_BUFFER_BIT) ||
(access & GL_MAP_UNSYNCHRONIZED_BIT)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(invalid access flags)");
return NULL;
}
}
if ((access & GL_MAP_FLUSH_EXPLICIT_BIT) &&
((access & GL_MAP_WRITE_BIT) == 0)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(invalid access flags)");
return NULL;
}
bufObj = get_buffer(ctx, target);
if (!bufObj || bufObj->Name == 0) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glMapBufferRange(target = 0x%x)", target);
return NULL;
}
if (offset + length > bufObj->Size) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(offset + length > size)");
return NULL;
}
if (bufObj->Pointer) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(buffer already mapped)");
return NULL;
}
ASSERT(ctx->Driver.MapBufferRange);
bufObj->Pointer = ctx->Driver.MapBufferRange(ctx, target, offset, length,
access, bufObj);
bufObj->Offset = offset;
bufObj->Length = length;
bufObj->AccessFlags = access;
return bufObj->Pointer;
}
/**
* See GL_ARB_map_buffer_range spec
*/
void GLAPIENTRY
_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object *bufObj;
ASSERT_OUTSIDE_BEGIN_END(ctx);
if (!ctx->Extensions.ARB_map_buffer_range) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(extension not supported)");
return;
}
if (offset < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(offset = %ld)", offset);
return;
}
if (length < 0) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(length = %ld)", length);
return;
}
bufObj = get_buffer(ctx, target);
if (!bufObj) {
_mesa_error(ctx, GL_INVALID_ENUM,
"glMapBufferRange(target = 0x%x)", target);
return;
}
if (bufObj->Name == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(current buffer is 0)");
return;
}
if (!bufObj->Pointer) {
/* buffer is not mapped */
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(buffer is not mapped)");
return;
}
if ((bufObj->AccessFlags & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"glMapBufferRange(GL_MAP_FLUSH_EXPLICIT_BIT not set)");
return;
}
if (offset + length > bufObj->Length) {
_mesa_error(ctx, GL_INVALID_VALUE,
"glMapBufferRange(offset %ld + length %ld > mapped length %ld)",
offset, length, bufObj->Length);
return;
}
ASSERT(bufObj->AccessFlags & GL_MAP_WRITE_BIT);
if (ctx->Driver.FlushMappedBufferRange)
ctx->Driver.FlushMappedBufferRange(ctx, target, offset, length, bufObj);
}

View File

@@ -79,6 +79,16 @@ extern void *
_mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object * bufObj ); struct gl_buffer_object * bufObj );
extern void *
_mesa_buffer_map_range( GLcontext *ctx, GLenum target, GLintptr offset,
GLsizeiptr length, GLbitfield access,
struct gl_buffer_object *bufObj );
extern void
_mesa_buffer_flush_mapped_range( GLcontext *ctx, GLenum target,
GLintptr offset, GLsizeiptr length,
struct gl_buffer_object *obj );
extern GLboolean extern GLboolean
_mesa_buffer_unmap( GLcontext *ctx, GLenum target, _mesa_buffer_unmap( GLcontext *ctx, GLenum target,
struct gl_buffer_object * bufObj ); struct gl_buffer_object * bufObj );
@@ -167,4 +177,11 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset, GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size); GLsizeiptr size);
extern void * GLAPIENTRY
_mesa_MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length,
GLbitfield access);
extern void GLAPIENTRY
_mesa_FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
#endif #endif

View File

@@ -8239,6 +8239,12 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_ProgramLocalParameters4fvEXT(table, save_ProgramLocalParameters4fvEXT); SET_ProgramLocalParameters4fvEXT(table, save_ProgramLocalParameters4fvEXT);
#endif #endif
/* ARB 50. GL_ARB_map_buffer_range */
#if FEATURE_ARB_map_buffer_range
SET_MapBufferRange(table, _mesa_MapBufferRange); /* no dlist save */
SET_FlushMappedBufferRange(table, _mesa_FlushMappedBufferRange); /* no dl */
#endif
/* ARB 59. GL_ARB_copy_buffer */ /* ARB 59. GL_ARB_copy_buffer */
SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */ SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */
} }

View File

@@ -1,8 +1,9 @@
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 7.3 * Version: 7.6
* *
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved. * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@@ -53,6 +54,7 @@ static const struct {
{ OFF, "GL_ARB_framebuffer_object", F(ARB_framebuffer_object) }, { OFF, "GL_ARB_framebuffer_object", F(ARB_framebuffer_object) },
{ OFF, "GL_ARB_half_float_pixel", F(ARB_half_float_pixel) }, { OFF, "GL_ARB_half_float_pixel", F(ARB_half_float_pixel) },
{ OFF, "GL_ARB_imaging", F(ARB_imaging) }, { OFF, "GL_ARB_imaging", F(ARB_imaging) },
{ OFF, "GL_ARB_map_buffer_range", F(ARB_map_buffer_range) },
{ ON, "GL_ARB_multisample", F(ARB_multisample) }, { ON, "GL_ARB_multisample", F(ARB_multisample) },
{ OFF, "GL_ARB_multitexture", F(ARB_multitexture) }, { OFF, "GL_ARB_multitexture", F(ARB_multitexture) },
{ OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) }, { OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) },
@@ -199,6 +201,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
#endif #endif
ctx->Extensions.ARB_half_float_pixel = GL_TRUE; ctx->Extensions.ARB_half_float_pixel = GL_TRUE;
ctx->Extensions.ARB_imaging = GL_TRUE; ctx->Extensions.ARB_imaging = GL_TRUE;
ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
ctx->Extensions.ARB_multitexture = GL_TRUE; ctx->Extensions.ARB_multitexture = GL_TRUE;
#if FEATURE_ARB_occlusion_query #if FEATURE_ARB_occlusion_query
ctx->Extensions.ARB_occlusion_query = GL_TRUE; ctx->Extensions.ARB_occlusion_query = GL_TRUE;

View File

@@ -61,6 +61,7 @@
#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL #define FEATURE_ARB_occlusion_query _HAVE_FULL_GL
#define FEATURE_ARB_fragment_program _HAVE_FULL_GL #define FEATURE_ARB_fragment_program _HAVE_FULL_GL
#define FEATURE_ARB_framebuffer_object _HAVE_FULL_GL #define FEATURE_ARB_framebuffer_object _HAVE_FULL_GL
#define FEATURE_ARB_map_buffer_range _HAVE_FULL_GL
#define FEATURE_ARB_pixel_buffer_object _HAVE_FULL_GL #define FEATURE_ARB_pixel_buffer_object _HAVE_FULL_GL
#define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL #define FEATURE_ARB_vertex_buffer_object _HAVE_FULL_GL
#define FEATURE_ARB_vertex_program _HAVE_FULL_GL #define FEATURE_ARB_vertex_program _HAVE_FULL_GL

View File

@@ -1503,7 +1503,7 @@ struct gl_buffer_object
GLubyte *Data; /**< Location of storage either in RAM or VRAM. */ GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
/** Fields describing a mapped buffer */ /** Fields describing a mapped buffer */
/*@{*/ /*@{*/
GLenum Access; /**< GL_READ_ONLY_ARB, GL_WRITE_ONLY_ARB, etc. */ GLbitfield AccessFlags; /**< Mask of GL_MAP_x_BIT flags */
GLvoid *Pointer; /**< User-space address of mapping */ GLvoid *Pointer; /**< User-space address of mapping */
GLintptr Offset; /**< Mapped offset */ GLintptr Offset; /**< Mapped offset */
GLsizeiptr Length; /**< Mapped length */ GLsizeiptr Length; /**< Mapped length */
@@ -2443,6 +2443,7 @@ struct gl_extensions
GLboolean ARB_framebuffer_object; GLboolean ARB_framebuffer_object;
GLboolean ARB_half_float_pixel; GLboolean ARB_half_float_pixel;
GLboolean ARB_imaging; GLboolean ARB_imaging;
GLboolean ARB_map_buffer_range;
GLboolean ARB_multisample; GLboolean ARB_multisample;
GLboolean ARB_multitexture; GLboolean ARB_multitexture;
GLboolean ARB_occlusion_query; GLboolean ARB_occlusion_query;