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;
#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
driver->NewFramebuffer = _mesa_new_framebuffer;
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);
#endif
#if FEATURE_ARB_map_buffer_range
SET_MapBufferRange(exec, _mesa_MapBufferRange);
SET_FlushMappedBufferRange(exec, _mesa_FlushMappedBufferRange);
#endif
/* GL_ARB_copy_buffer */
SET_CopyBufferSubData(exec, _mesa_CopyBufferSubData);
}

View File

@@ -40,9 +40,9 @@
#ifdef FEATURE_OES_mapbuffer
#define DEFAULT_ACCESS GL_WRITE_ONLY;
#define DEFAULT_ACCESS GL_MAP_WRITE_BIT
#else
#define DEFAULT_ACCESS GL_READ_WRITE;
#define DEFAULT_ACCESS (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)
#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
* \c glBufferSubDataARB and \c glGetBufferSubDataARB.
@@ -271,7 +289,7 @@ _mesa_initialize_buffer_object( struct gl_buffer_object *obj,
obj->RefCount = 1;
obj->Name = name;
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().
*
@@ -845,7 +900,7 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
if (bufObj->Pointer) {
/* if mapped, unmap it now */
ctx->Driver.UnmapBuffer(ctx, 0, bufObj);
bufObj->Access = DEFAULT_ACCESS;
bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL;
}
@@ -1004,7 +1059,7 @@ _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size,
if (bufObj->Pointer) {
/* Unmap the existing buffer. We'll replace it now. Not an error. */
ctx->Driver.UnmapBuffer(ctx, target, bufObj);
bufObj->Access = DEFAULT_ACCESS;
bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL;
}
@@ -1071,13 +1126,18 @@ _mesa_MapBufferARB(GLenum target, GLenum access)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_buffer_object * bufObj;
GLbitfield accessFlags;
ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL);
switch (access) {
case GL_READ_ONLY_ARB:
accessFlags = GL_MAP_READ_BIT;
break;
case GL_WRITE_ONLY_ARB:
accessFlags = GL_MAP_WRITE_BIT;
break;
case GL_READ_WRITE_ARB:
/* OK */
accessFlags = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
break;
default:
_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)");
}
bufObj->Access = access;
bufObj->AccessFlags = accessFlags;
bufObj->Offset = 0;
bufObj->Length = bufObj->Size;
if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
bufObj->Written = GL_TRUE;
@@ -1146,7 +1209,7 @@ _mesa_UnmapBufferARB(GLenum target)
}
#ifdef VBO_DEBUG
if (bufObj->Access == GL_WRITE_ONLY_ARB) {
if (bufObj->AccessFlags & GL_MAP_WRITE_BIT) {
GLuint i, unchanged = 0;
GLubyte *b = (GLubyte *) bufObj->Pointer;
GLint pos = -1;
@@ -1166,8 +1229,10 @@ _mesa_UnmapBufferARB(GLenum target)
#endif
status = ctx->Driver.UnmapBuffer( ctx, target, bufObj );
bufObj->Access = DEFAULT_ACCESS;
bufObj->AccessFlags = DEFAULT_ACCESS;
bufObj->Pointer = NULL;
bufObj->Offset = 0;
bufObj->Length = 0;
return status;
}
@@ -1198,7 +1263,7 @@ _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params)
*params = bufObj->Usage;
break;
case GL_BUFFER_ACCESS_ARB:
*params = bufObj->Access;
*params = simplified_access_mode(bufObj->AccessFlags);
break;
case GL_BUFFER_MAPPED_ARB:
*params = (bufObj->Pointer != NULL);
@@ -1315,3 +1380,153 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
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,
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
_mesa_buffer_unmap( GLcontext *ctx, GLenum target,
struct gl_buffer_object * bufObj );
@@ -167,4 +177,11 @@ _mesa_CopyBufferSubData(GLenum readTarget, GLenum writeTarget,
GLintptr readOffset, GLintptr writeOffset,
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

View File

@@ -8239,6 +8239,12 @@ _mesa_init_dlist_table(struct _glapi_table *table)
SET_ProgramLocalParameters4fvEXT(table, save_ProgramLocalParameters4fvEXT);
#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 */
SET_CopyBufferSubData(table, _mesa_CopyBufferSubData); /* no dlist save */
}

View File

@@ -1,8 +1,9 @@
/*
* Mesa 3-D graphics library
* Version: 7.3
* Version: 7.6
*
* 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
* 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_half_float_pixel", F(ARB_half_float_pixel) },
{ 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) },
{ OFF, "GL_ARB_multitexture", F(ARB_multitexture) },
{ OFF, "GL_ARB_occlusion_query", F(ARB_occlusion_query) },
@@ -199,6 +201,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
#endif
ctx->Extensions.ARB_half_float_pixel = GL_TRUE;
ctx->Extensions.ARB_imaging = GL_TRUE;
ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
ctx->Extensions.ARB_multitexture = GL_TRUE;
#if FEATURE_ARB_occlusion_query
ctx->Extensions.ARB_occlusion_query = GL_TRUE;

View File

@@ -61,6 +61,7 @@
#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL
#define FEATURE_ARB_fragment_program _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_vertex_buffer_object _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. */
/** 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 */
GLintptr Offset; /**< Mapped offset */
GLsizeiptr Length; /**< Mapped length */
@@ -2443,6 +2443,7 @@ struct gl_extensions
GLboolean ARB_framebuffer_object;
GLboolean ARB_half_float_pixel;
GLboolean ARB_imaging;
GLboolean ARB_map_buffer_range;
GLboolean ARB_multisample;
GLboolean ARB_multitexture;
GLboolean ARB_occlusion_query;