/**
* Looks up the array object for the given ID.
*
- * Unlike _mesa_lookup_vao, this function generates a GL_INVALID_OPERATION
+ * While _mesa_lookup_vao doesn't generate an error if the object does not
+ * exist, this function comes in two variants.
+ * If is_ext_dsa is false, this function generates a GL_INVALID_OPERATION
* error if the array object does not exist. It also returns the default
* array object when ctx is a compatibility profile context and id is zero.
+ * If is_ext_dsa is true, 0 is not a valid name. If the name exists but
+ * the object has never been bound, it is initialized.
*/
struct gl_vertex_array_object *
-_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id, const char *caller)
+_mesa_lookup_vao_err(struct gl_context *ctx, GLuint id,
+ bool is_ext_dsa, const char *caller)
{
/* The ARB_direct_state_access specification says:
*
* the name of the vertex array object."
*/
if (id == 0) {
- if (ctx->API == API_OPENGL_CORE) {
+ if (is_ext_dsa || ctx->API == API_OPENGL_CORE) {
_mesa_error(ctx, GL_INVALID_OPERATION,
- "%s(zero is not valid vaobj name in a core profile "
- "context)", caller);
+ "%s(zero is not valid vaobj name%s)",
+ caller,
+ is_ext_dsa ? "" : " in a core profile context");
return NULL;
}
* [compatibility profile: zero or] the name of an existing
* vertex array object."
*/
- if (!vao || !vao->EverBound) {
+ if (!vao || (!is_ext_dsa && !vao->EverBound)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
"%s(non-existent vaobj=%u)", caller, id);
return NULL;
}
+ /* The EXT_direct_state_access specification says:
+ *
+ * "If the vertex array object named by the vaobj parameter has not
+ * been previously bound but has been generated (without subsequent
+ * deletion) by GenVertexArrays, the GL first creates a new state
+ * vector in the same manner as when BindVertexArray creates a new
+ * vertex array object."
+ */
+ if (vao && is_ext_dsa && !vao->EverBound)
+ vao->EverBound = true;
+
_mesa_reference_vao(ctx, &ctx->Array.LastLookedUpVAO, vao);
}
assert(index < ARRAY_SIZE(vao->BufferBinding));
struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
- array->Size = size;
- array->Type = type;
- array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
+ _mesa_set_vertex_format(&array->Format, size, type, GL_RGBA,
+ GL_FALSE, GL_FALSE, GL_FALSE);
array->Stride = 0;
array->Ptr = NULL;
array->RelativeOffset = 0;
- array->Normalized = GL_FALSE;
- array->Integer = GL_FALSE;
- array->Doubles = GL_FALSE;
- array->_ElementSize = size * _mesa_sizeof_type(type);
ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex,
VERT_ATTRIB_MAX - 1);
array->BufferBindingIndex = index;
binding->Offset = 0;
- binding->Stride = array->_ElementSize;
+ binding->Stride = array->Format._ElementSize;
binding->BufferObj = NULL;
binding->_BoundArrays = BITFIELD_BIT(index);
init_array(ctx, vao, VERT_ATTRIB_COLOR_INDEX, 1, GL_FLOAT);
break;
case VERT_ATTRIB_EDGEFLAG:
- init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_BOOL);
+ init_array(ctx, vao, VERT_ATTRIB_EDGEFLAG, 1, GL_UNSIGNED_BYTE);
break;
case VERT_ATTRIB_POINT_SIZE:
init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
const GLbitfield enabled = vao->Enabled;
/* VBO array bits. */
const GLbitfield vbos = vao->VertexAttribBufferMask;
+ const GLbitfield divisor_is_nonzero = vao->NonZeroDivisorMask;
/* Compute and store effectively enabled and mapped vbo arrays */
vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos);
+ vao->_EffEnabledNonZeroDivisor =
+ _mesa_vao_enable_to_vp_inputs(mode, enabled & divisor_is_nonzero);
/* Walk those enabled arrays that have a real vbo attached */
GLbitfield mask = enabled;
while (mask) {
GLbitfield eff_bound_arrays = bound;
const GLubyte *ptr = attrib->Ptr;
- unsigned vertex_end = attrib->_ElementSize;
+ unsigned vertex_end = attrib->Format._ElementSize;
/* Walk other user space arrays and see which are interleaved
* using the same binding parameters.
if (binding->InstanceDivisor != binding2->InstanceDivisor)
continue;
if (ptr <= attrib2->Ptr) {
- if (ptr + binding->Stride < attrib2->Ptr + attrib2->_ElementSize)
+ if (ptr + binding->Stride < attrib2->Ptr +
+ attrib2->Format._ElementSize)
continue;
- unsigned end = attrib2->Ptr + attrib2->_ElementSize - ptr;
+ unsigned end = attrib2->Ptr + attrib2->Format._ElementSize - ptr;
vertex_end = MAX2(vertex_end, end);
} else {
if (attrib2->Ptr + binding->Stride < ptr + vertex_end)
/* Query the original api defined attrib/binding information ... */
const unsigned char *const map =_mesa_vao_attribute_map[mode];
if (vao->Enabled & VERT_BIT(map[attr])) {
- const struct gl_array_attributes *attrib = &vao->VertexAttrib[map[attr]];
+ const struct gl_array_attributes *attrib =
+ &vao->VertexAttrib[map[attr]];
const struct gl_vertex_buffer_binding *binding =
&vao->BufferBinding[attrib->BufferBindingIndex];
/* ... and compare that with the computed attrib/binding */
return true;
}
+
+/**
+ * Map buffer objects used in attribute arrays.
+ */
+void
+_mesa_vao_map_arrays(struct gl_context *ctx, struct gl_vertex_array_object *vao,
+ GLbitfield access)
+{
+ GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
+ while (mask) {
+ /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
+ const gl_vert_attrib attr = ffs(mask) - 1;
+ const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
+ struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
+ mask &= ~binding->_BoundArrays;
+
+ struct gl_buffer_object *bo = binding->BufferObj;
+ assert(_mesa_is_bufferobj(bo));
+ if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
+ continue;
+
+ ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
+ }
+}
+
+
+/**
+ * Map buffer objects used in the vao, attribute arrays and index buffer.
+ */
+void
+_mesa_vao_map(struct gl_context *ctx, struct gl_vertex_array_object *vao,
+ GLbitfield access)
+{
+ struct gl_buffer_object *bo = vao->IndexBufferObj;
+
+ /* map the index buffer, if there is one, and not already mapped */
+ if (_mesa_is_bufferobj(bo) && !_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
+ ctx->Driver.MapBufferRange(ctx, 0, bo->Size, access, bo, MAP_INTERNAL);
+
+ _mesa_vao_map_arrays(ctx, vao, access);
+}
+
+
+/**
+ * Unmap buffer objects used in attribute arrays.
+ */
+void
+_mesa_vao_unmap_arrays(struct gl_context *ctx,
+ struct gl_vertex_array_object *vao)
+{
+ GLbitfield mask = vao->Enabled & vao->VertexAttribBufferMask;
+ while (mask) {
+ /* Do not use u_bit_scan as we can walk multiple attrib arrays at once */
+ const gl_vert_attrib attr = ffs(mask) - 1;
+ const GLubyte bindex = vao->VertexAttrib[attr].BufferBindingIndex;
+ struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
+ mask &= ~binding->_BoundArrays;
+
+ struct gl_buffer_object *bo = binding->BufferObj;
+ assert(_mesa_is_bufferobj(bo));
+ if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
+ continue;
+
+ ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
+ }
+}
+
+
+/**
+ * Unmap buffer objects used in the vao, attribute arrays and index buffer.
+ */
+void
+_mesa_vao_unmap(struct gl_context *ctx, struct gl_vertex_array_object *vao)
+{
+ struct gl_buffer_object *bo = vao->IndexBufferObj;
+
+ /* unmap the index buffer, if there is one, and still mapped */
+ if (_mesa_is_bufferobj(bo) && _mesa_bufferobj_mapped(bo, MAP_INTERNAL))
+ ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
+
+ _mesa_vao_unmap_arrays(ctx, vao);
+}
+
+
/**********************************************************************/
/* API Functions */
/**********************************************************************/
*/
_mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
- ctx->NewState |= _NEW_ARRAY;
_mesa_reference_vao(ctx, &ctx->Array.VAO, newObj);
}
* VertexArrayElementBuffer if <vaobj> is not [compatibility profile:
* zero or] the name of an existing vertex array object."
*/
- vao =_mesa_lookup_vao_err(ctx, vaobj, "glVertexArrayElementBuffer");
+ vao =_mesa_lookup_vao_err(ctx, vaobj, false, "glVertexArrayElementBuffer");
if (!vao)
return;
} else {
bufObj = ctx->Shared->NullBufferObj;
}
- if (bufObj)
+ if (bufObj) {
+ bufObj->UsageHistory |= USAGE_ELEMENT_ARRAY_BUFFER;
_mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
+ }
}
* [compatibility profile: zero or] the name of an existing
* vertex array object."
*/
- vao =_mesa_lookup_vao_err(ctx, vaobj, "glGetVertexArrayiv");
+ vao = _mesa_lookup_vao_err(ctx, vaobj, false, "glGetVertexArrayiv");
if (!vao)
return;