#include "glheader.h"
#include "hash.h"
#include "image.h"
-#include "util/imports.h"
+
#include "context.h"
#include "bufferobj.h"
#include "arrayobj.h"
#include "util/bitscan.h"
#include "util/u_atomic.h"
#include "util/u_math.h"
+#include "util/u_memory.h"
const GLubyte
* to any buffer objects (VBOs).
* This is done just prior to array object destruction.
*/
-static void
-unbind_array_object_vbos(struct gl_context *ctx, struct gl_vertex_array_object *obj)
+void
+_mesa_unbind_array_object_vbos(struct gl_context *ctx,
+ struct gl_vertex_array_object *obj)
{
GLuint i;
struct gl_vertex_array_object *
_mesa_new_vao(struct gl_context *ctx, GLuint name)
{
- struct gl_vertex_array_object *obj = CALLOC_STRUCT(gl_vertex_array_object);
+ struct gl_vertex_array_object *obj = MALLOC_STRUCT(gl_vertex_array_object);
if (obj)
_mesa_initialize_vao(ctx, obj, name);
return obj;
void
_mesa_delete_vao(struct gl_context *ctx, struct gl_vertex_array_object *obj)
{
- unbind_array_object_vbos(ctx, obj);
+ _mesa_unbind_array_object_vbos(ctx, obj);
_mesa_reference_buffer_object(ctx, &obj->IndexBufferObj, NULL);
free(obj->Label);
free(obj);
}
-/**
- * Initialize attributes of a vertex array within a vertex array object.
- * \param vao the container vertex array object
- * \param index which array in the VAO to initialize
- * \param size number of components (1, 2, 3 or 4) per attribute
- * \param type datatype of the attribute (GL_FLOAT, GL_INT, etc).
- */
-static void
-init_array(struct gl_context *ctx,
- struct gl_vertex_array_object *vao,
- gl_vert_attrib index, GLint size, GLint type)
-{
- assert(index < ARRAY_SIZE(vao->VertexAttrib));
- struct gl_array_attributes *array = &vao->VertexAttrib[index];
- assert(index < ARRAY_SIZE(vao->BufferBinding));
- struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[index];
-
- _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;
- ASSERT_BITFIELD_SIZE(struct gl_array_attributes, BufferBindingIndex,
- VERT_ATTRIB_MAX - 1);
- array->BufferBindingIndex = index;
-
- binding->Offset = 0;
- binding->Stride = array->Format._ElementSize;
- binding->BufferObj = NULL;
- binding->_BoundArrays = BITFIELD_BIT(index);
-
- /* Vertex array buffers */
- _mesa_reference_buffer_object(ctx, &binding->BufferObj,
- ctx->Shared->NullBufferObj);
-}
-
-
/**
* Initialize a gl_vertex_array_object's arrays.
*/
struct gl_vertex_array_object *vao,
GLuint name)
{
- GLuint i;
-
+ memcpy(vao, &ctx->Array.DefaultVAOState, sizeof(*vao));
vao->Name = name;
-
- vao->RefCount = 1;
- vao->SharedAndImmutable = false;
-
- /* Init the individual arrays */
- for (i = 0; i < ARRAY_SIZE(vao->VertexAttrib); i++) {
- switch (i) {
- case VERT_ATTRIB_NORMAL:
- init_array(ctx, vao, VERT_ATTRIB_NORMAL, 3, GL_FLOAT);
- break;
- case VERT_ATTRIB_COLOR1:
- init_array(ctx, vao, VERT_ATTRIB_COLOR1, 3, GL_FLOAT);
- break;
- case VERT_ATTRIB_FOG:
- init_array(ctx, vao, VERT_ATTRIB_FOG, 1, GL_FLOAT);
- break;
- case VERT_ATTRIB_COLOR_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_UNSIGNED_BYTE);
- break;
- case VERT_ATTRIB_POINT_SIZE:
- init_array(ctx, vao, VERT_ATTRIB_POINT_SIZE, 1, GL_FLOAT);
- break;
- default:
- init_array(ctx, vao, i, 4, GL_FLOAT);
- break;
- }
- }
-
- vao->_AttributeMapMode = ATTRIBUTE_MAP_MODE_IDENTITY;
-
- _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj,
- ctx->Shared->NullBufferObj);
}
GLsizeiptr* min, GLsizeiptr* max)
{
/* The function is meant to work on VBO bindings */
- assert(_mesa_is_bufferobj(binding->BufferObj));
+ assert(binding->BufferObj);
/* Start with an inverted range of relative offsets. */
GLuint min_offset = ~(GLuint)0;
vao->_EffEnabledVBO = _mesa_vao_enable_to_vp_inputs(mode, enabled & vbos);
vao->_EffEnabledNonZeroDivisor =
_mesa_vao_enable_to_vp_inputs(mode, enabled & divisor_is_nonzero);
+
+ /* Fast path when the VAO is updated too often. */
+ if (vao->IsDynamic)
+ return;
+
+ /* More than 4 updates turn the VAO to dynamic. */
+ if (ctx->Const.AllowDynamicVAOFastPath && ++vao->NumUpdates > 4) {
+ vao->IsDynamic = true;
+ return;
+ }
+
/* Walk those enabled arrays that have a real vbo attached */
GLbitfield mask = enabled;
while (mask) {
struct gl_vertex_buffer_binding *binding = &vao->BufferBinding[bindex];
/* The scan goes different for user space arrays than vbos */
- if (_mesa_is_bufferobj(binding->BufferObj)) {
+ if (binding->BufferObj) {
/* The bound arrays. */
const GLbitfield bound = enabled & binding->_BoundArrays;
}
/* User space buffer object */
- assert(!_mesa_is_bufferobj(binding2->BufferObj));
+ assert(!binding2->BufferObj);
eff_bound_arrays |= VERT_BIT(j);
}
assert(binding->Stride == binding2->Stride);
assert(binding->InstanceDivisor == binding2->InstanceDivisor);
assert(binding->BufferObj == binding2->BufferObj);
- if (_mesa_is_bufferobj(binding->BufferObj)) {
+ if (binding->BufferObj) {
assert(attrib->_EffRelativeOffset <= MaxRelativeOffset);
assert(binding->Offset + attrib->RelativeOffset ==
binding2->_EffOffset + attrib->_EffRelativeOffset);
&vao->BufferBinding[attrib_array->BufferBindingIndex];
/* We have already masked out vao->VertexAttribBufferMask */
- assert(!_mesa_is_bufferobj(buffer_binding->BufferObj));
+ assert(!buffer_binding->BufferObj);
/* Bail out once we find the first non vbo with a non zero stride */
if (buffer_binding->Stride != 0)
&vao->BufferBinding[attrib_array->BufferBindingIndex];
/* We have already masked with vao->VertexAttribBufferMask */
- assert(_mesa_is_bufferobj(buffer_binding->BufferObj));
+ assert(buffer_binding->BufferObj);
/* Bail out once we find the first disallowed mapping */
if (_mesa_check_disallowed_mapping(buffer_binding->BufferObj))
mask &= ~binding->_BoundArrays;
struct gl_buffer_object *bo = binding->BufferObj;
- assert(_mesa_is_bufferobj(bo));
+ assert(bo);
if (_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
continue;
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))
+ if (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);
mask &= ~binding->_BoundArrays;
struct gl_buffer_object *bo = binding->BufferObj;
- assert(_mesa_is_bufferobj(bo));
+ assert(bo);
if (!_mesa_bufferobj_mapped(bo, MAP_INTERNAL))
continue;
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))
+ if (bo && _mesa_bufferobj_mapped(bo, MAP_INTERNAL))
ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
_mesa_vao_unmap_arrays(ctx, vao);
if (ctx->Array._DrawVAO == obj)
_mesa_set_draw_vao(ctx, ctx->Array._EmptyVAO, 0);
- /* Unreference the array object.
+ /* Unreference the array object.
* If refcount hits zero, the object will be deleted.
*/
_mesa_reference_vao(ctx, &obj, NULL);
} else {
bufObj = _mesa_lookup_bufferobj(ctx, buffer);
}
- } else {
- bufObj = ctx->Shared->NullBufferObj;
- }
- if (bufObj) {
+ if (!bufObj)
+ return;
+
bufObj->UsageHistory |= USAGE_ELEMENT_ARRAY_BUFFER;
- _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
+ } else {
+ bufObj = NULL;
}
+
+ _mesa_reference_buffer_object(ctx, &vao->IndexBufferObj, bufObj);
}
return;
}
- param[0] = vao->IndexBufferObj->Name;
+ param[0] = vao->IndexBufferObj ? vao->IndexBufferObj->Name : 0;
}