#include "main/draw_validate.h"
#include "main/dispatch.h"
#include "util/bitscan.h"
+#include "util/u_memory.h"
#include "vbo_noop.h"
#include "vbo_private.h"
*/
static void
vbo_exec_wrap_upgrade_vertex(struct vbo_exec_context *exec,
- GLuint attr, GLuint newSize)
+ GLuint attr, GLuint newSize, GLenum newType)
{
struct gl_context *ctx = exec->ctx;
struct vbo_context *vbo = vbo_context(ctx);
/* Fix up sizes:
*/
exec->vtx.attr[attr].size = newSize;
+ exec->vtx.attr[attr].active_size = newSize;
+ exec->vtx.attr[attr].type = newType;
exec->vtx.vertex_size += newSize - oldSize;
exec->vtx.vertex_size_no_pos = exec->vtx.vertex_size - exec->vtx.attr[0].size;
exec->vtx.max_vert = vbo_compute_max_verts(exec);
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
- vbo_exec_wrap_upgrade_vertex(exec, attr, newSize);
+ vbo_exec_wrap_upgrade_vertex(exec, attr, newSize, newType);
}
else if (newSize < exec->vtx.attr[attr].active_size) {
GLuint i;
*/
for (i = newSize; i <= exec->vtx.attr[attr].size; i++)
exec->vtx.attrptr[attr][i-1] = id[i-1];
- }
-
- exec->vtx.attr[attr].active_size = newSize;
- exec->vtx.attr[attr].type = newType;
- /* Does setting NeedFlush belong here? Necessitates resetting
- * vtxfmt on each flush (otherwise flags won't get reset
- * afterwards).
- */
- if (attr == 0)
- ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+ exec->vtx.attr[attr].active_size = newSize;
+ }
}
\
assert(sz == 1 || sz == 2); \
\
- /* check if attribute size or type is changing */ \
- if (unlikely(exec->vtx.attr[A].active_size != N * sz || \
- exec->vtx.attr[A].type != T)) { \
- vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
- } \
- \
/* store a copy of the attribute in exec except for glVertex */ \
if ((A) != 0) { \
+ /* Check if attribute size or type is changing. */ \
+ if (unlikely(exec->vtx.attr[A].active_size != N * sz || \
+ exec->vtx.attr[A].type != T)) { \
+ vbo_exec_fixup_vertex(ctx, A, N * sz, T); \
+ } \
+ \
C *dest = (C *)exec->vtx.attrptr[A]; \
if (N>0) dest[0] = V0; \
if (N>1) dest[1] = V1; \
if (N>2) dest[2] = V2; \
if (N>3) dest[3] = V3; \
assert(exec->vtx.attr[A].type == T); \
- } \
\
- if ((A) == 0) { \
+ /* we now have accumulated a per-vertex attribute */ \
+ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
+ } else { \
/* This is a glVertex call */ \
+ int size = exec->vtx.attr[0].size; \
+ \
+ /* Check if attribute size or type is changing. */ \
+ if (unlikely(size < N * sz || \
+ exec->vtx.attr[0].type != T)) { \
+ vbo_exec_wrap_upgrade_vertex(exec, 0, N * sz, T); \
+ } \
+ \
uint32_t *dst = (uint32_t *)exec->vtx.buffer_ptr; \
uint32_t *src = (uint32_t *)exec->vtx.vertex; \
unsigned vertex_size_no_pos = exec->vtx.vertex_size_no_pos; \
if (N > 1) *dst++ = V1; \
if (N > 2) *dst++ = V2; \
if (N > 3) *dst++ = V3; \
+ \
+ if (unlikely(N < size)) { \
+ if (N < 2 && size >= 2) *dst++ = V1; \
+ if (N < 3 && size >= 3) *dst++ = V2; \
+ if (N < 4 && size >= 4) *dst++ = V3; \
+ } \
} else { \
/* 64 bits: dst can be unaligned, so copy each 4-byte word */ \
/* separately */ \
if (N > 1) SET_64BIT(dst, V1); \
if (N > 2) SET_64BIT(dst, V2); \
if (N > 3) SET_64BIT(dst, V3); \
+ \
+ if (unlikely(N * 2 < size)) { \
+ if (N < 2 && size >= 4) SET_64BIT(dst, V1); \
+ if (N < 3 && size >= 6) SET_64BIT(dst, V2); \
+ if (N < 4 && size >= 8) SET_64BIT(dst, V3); \
+ } \
} \
\
/* dst now points at the beginning of the next vertex */ \
\
if (unlikely(++exec->vtx.vert_count >= exec->vtx.max_vert)) \
vbo_exec_vtx_wrap(exec); \
- } else { \
- /* we now have accumulated per-vertex attributes */ \
- ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
} \
} while (0)
exec->vtx.prim[i].mode = mode;
exec->vtx.prim[i].begin = 1;
exec->vtx.prim[i].end = 0;
- exec->vtx.prim[i].indexed = 0;
- exec->vtx.prim[i].pad = 0;
exec->vtx.prim[i].start = exec->vtx.vert_count;
exec->vtx.prim[i].count = 0;
- exec->vtx.prim[i].num_instances = 1;
- exec->vtx.prim[i].base_instance = 0;
- exec->vtx.prim[i].is_indirect = 0;
ctx->Driver.CurrentExecPrimitive = mode;
struct _mesa_prim *prev = &exec->vtx.prim[exec->vtx.prim_count - 2];
assert(prev == cur - 1);
- if (vbo_can_merge_prims(prev, cur)) {
- assert(cur->begin);
- assert(cur->end);
- assert(prev->begin);
- assert(prev->end);
- vbo_merge_prims(prev, cur);
+ if (vbo_merge_draws(exec->ctx, false, prev, cur))
exec->vtx.prim_count--; /* drop the last primitive */
- }
}
}
}
-/**
- * Tell the VBO module to use a real OpenGL vertex buffer object to
- * store accumulated immediate-mode vertex data.
- * This replaces the malloced buffer which was created in
- * vb_exec_vtx_init() below.
- */
-void
-vbo_use_buffer_objects(struct gl_context *ctx)
-{
- struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- /* Any buffer name but 0 can be used here since this bufferobj won't
- * go into the bufferobj hashtable.
- */
- GLuint bufName = IMM_BUFFER_NAME;
-
- /* Make sure this func is only used once */
- assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
-
- _mesa_align_free(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
- exec->vtx.buffer_ptr = NULL;
-
- /* Allocate a real buffer object now */
- _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
- exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName);
-
- /* Map the buffer. */
- vbo_exec_vtx_map(exec);
- assert(exec->vtx.buffer_ptr);
-}
-
-
static void
vbo_reset_all_attr(struct vbo_exec_context *exec)
{
void
-vbo_exec_vtx_init(struct vbo_exec_context *exec)
+vbo_exec_vtx_init(struct vbo_exec_context *exec, bool use_buffer_objects)
{
struct gl_context *ctx = exec->ctx;
- /* Allocate a buffer object. Will just reuse this object
- * continuously, unless vbo_use_buffer_objects() is called to enable
- * use of real VBOs.
- */
- _mesa_reference_buffer_object(ctx,
- &exec->vtx.bufferobj,
- ctx->Shared->NullBufferObj);
+ if (use_buffer_objects) {
+ /* Use buffer objects for immediate mode. */
+ struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
- assert(!exec->vtx.buffer_map);
- exec->vtx.buffer_map = _mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
- exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, IMM_BUFFER_NAME);
+
+ /* Map the buffer. */
+ vbo_exec_vtx_map(exec);
+ assert(exec->vtx.buffer_ptr);
+ } else {
+ /* Use allocated memory for immediate mode. */
+ exec->vtx.bufferobj = NULL;
+ exec->vtx.buffer_map =
+ align_malloc(ctx->Const.glBeginEndBufferSize, 64);
+ exec->vtx.buffer_ptr = exec->vtx.buffer_map;
+ }
vbo_exec_vtxfmt_init(exec);
_mesa_noop_vtxfmt_init(ctx, &exec->vtxfmt_noop);
/* True VBOs should already be unmapped
*/
if (exec->vtx.buffer_map) {
- assert(exec->vtx.bufferobj->Name == 0 ||
+ assert(!exec->vtx.bufferobj ||
exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
- if (exec->vtx.bufferobj->Name == 0) {
- _mesa_align_free(exec->vtx.buffer_map);
+ if (!exec->vtx.bufferobj) {
+ align_free(exec->vtx.buffer_map);
exec->vtx.buffer_map = NULL;
exec->vtx.buffer_ptr = NULL;
}
/* Free the vertex buffer. Unmap first if needed.
*/
- if (_mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
+ if (exec->vtx.bufferobj &&
+ _mesa_bufferobj_mapped(exec->vtx.bufferobj, MAP_INTERNAL)) {
ctx->Driver.UnmapBuffer(ctx, exec->vtx.bufferobj, MAP_INTERNAL);
}
_mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);