* Keith Whitwell <keith@tungstengraphics.com>
*/
-#include "glheader.h"
-#include "context.h"
-#include "macros.h"
-#include "vtxfmt.h"
-#include "dlist.h"
-#include "state.h"
-#include "light.h"
-#include "api_arrayelt.h"
-#include "api_noop.h"
-#include "dispatch.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/vtxfmt.h"
+#include "main/dlist.h"
+#include "main/state.h"
+#include "main/light.h"
+#include "main/api_arrayelt.h"
+#include "main/api_noop.h"
+#include "glapi/dispatch.h"
#include "vbo_context.h"
+#ifdef ERROR
+#undef ERROR
+#endif
+
+
static void reset_attrfv( struct vbo_exec_context *exec );
static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
{
GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
GLuint i;
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (exec->vtx.attrsz[i]) {
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+
/* Note: the exec->vtx.current[i] pointers point into the
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
- COPY_CLEAN_4V(exec->vtx.current[i],
+ COPY_CLEAN_4V(current,
exec->vtx.attrsz[i],
exec->vtx.attrptr[i]);
+
+ /* Given that we explicitly state size here, there is no need
+ * for the COPY_CLEAN above, could just copy 16 bytes and be
+ * done. The only problem is when Mesa accesses ctx->Current
+ * directly.
+ */
+ vbo->currval[i].Size = exec->vtx.attrsz[i];
+
/* This triggers rather too much recalculation of Mesa state
* that doesn't get used (eg light positions).
*/
}
}
- /* color index is special (it's not a float[4] so COPY_CLEAN_4V above
- * will trash adjacent memory!)
- */
- if (exec->vtx.attrsz[VBO_ATTRIB_INDEX]) {
- ctx->Current.Index = exec->vtx.attrptr[VBO_ATTRIB_INDEX][0];
- }
-
- /* Edgeflag requires additional treatment:
- */
- if (exec->vtx.attrsz[VBO_ATTRIB_EDGEFLAG]) {
- ctx->Current.EdgeFlag = (exec->vtx.CurrentFloatEdgeFlag == 1.0);
- }
-
/* Colormaterial -- this kindof sucks.
*/
if (ctx->Light.ColorMaterialEnabled &&
static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
{
GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
GLint i;
- /* Edgeflag requires additional treatment:
- */
- exec->vtx.CurrentFloatEdgeFlag =
- (GLfloat)ctx->Current.EdgeFlag;
-
- for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++)
+ for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
+ const GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
switch (exec->vtx.attrsz[i]) {
- case 4: exec->vtx.attrptr[i][3] = exec->vtx.current[i][3];
- case 3: exec->vtx.attrptr[i][2] = exec->vtx.current[i][2];
- case 2: exec->vtx.attrptr[i][1] = exec->vtx.current[i][1];
- case 1: exec->vtx.attrptr[i][0] = exec->vtx.current[i][0];
+ case 4: exec->vtx.attrptr[i][3] = current[3];
+ case 3: exec->vtx.attrptr[i][2] = current[2];
+ case 2: exec->vtx.attrptr[i][1] = current[1];
+ case 1: exec->vtx.attrptr[i][0] = current[0];
break;
}
+ }
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
GLuint newsz )
{
GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
GLint lastcount = exec->vtx.vert_count;
GLfloat *tmp;
GLuint oldsz;
data += oldsz;
dest += newsz;
} else {
- COPY_SZ_4V( dest, newsz, exec->vtx.current[j] );
+ const GLfloat *current = (const GLfloat *)vbo->currval[j].Ptr;
+ COPY_SZ_4V( dest, newsz, current );
dest += newsz;
}
}
if (exec->eval.recalculate_maps)
vbo_exec_eval_update( exec );
- for (i = 0 ; i <= VBO_ATTRIB_INDEX ; i++) {
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map1[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map1[i].sz)
vbo_exec_fixup_vertex( ctx, i, exec->eval.map1[i].sz );
if (exec->eval.recalculate_maps)
vbo_exec_eval_update( exec );
- for (i = 0 ; i <= VBO_ATTRIB_INDEX ; i++) {
+ for (i = 0; i <= VBO_ATTRIB_TEX7; i++) {
if (exec->eval.map2[i].map)
if (exec->vtx.active_sz[i] != exec->eval.map2[i].sz)
vbo_exec_fixup_vertex( ctx, i, exec->eval.map2[i].sz );
if (ctx->NewState) {
_mesa_update_state( ctx );
+ /* XXX also need to check if shader enabled, but invalid */
if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
(ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
_mesa_error(ctx, GL_INVALID_OPERATION,
}
-static void vbo_exec_current_init( struct vbo_exec_context *exec )
+/**
+ * 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(GLcontext *ctx)
{
- GLcontext *ctx = exec->ctx;
- GLint i;
-
- /* setup the pointers for the typical 16 vertex attributes */
- for (i = 0; i < VBO_ATTRIB_FIRST_MATERIAL; i++)
- exec->vtx.current[i] = ctx->Current.Attrib[i];
+ 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 = 0xaabbccdd;
+ GLenum target = GL_ARRAY_BUFFER_ARB;
+ GLenum access = GL_READ_WRITE_ARB;
+ GLenum usage = GL_STREAM_DRAW_ARB;
+ GLsizei size = VBO_VERT_BUFFER_SIZE * sizeof(GLfloat);
+
+ /* Make sure this func is only used once */
+ assert(exec->vtx.bufferobj == ctx->Array.NullBufferObj);
+ if (exec->vtx.buffer_map) {
+ _mesa_align_free(exec->vtx.buffer_map);
+ }
- /* setup pointers for the 12 material attributes */
- for (i = 0; i < MAT_ATTRIB_MAX; i++)
- exec->vtx.current[VBO_ATTRIB_FIRST_MATERIAL + i] =
- ctx->Light.Material.Attrib[i];
+ /* Allocate a real buffer object now */
+ exec->vtx.bufferobj = ctx->Driver.NewBufferObject(ctx, bufName, target);
+ ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
- exec->vtx.current[VBO_ATTRIB_INDEX] = &ctx->Current.Index;
- exec->vtx.current[VBO_ATTRIB_EDGEFLAG] = &exec->vtx.CurrentFloatEdgeFlag;
+ /* and map it */
+ exec->vtx.buffer_map
+ = ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
}
+
+
void vbo_exec_vtx_init( struct vbo_exec_context *exec )
{
GLcontext *ctx = exec->ctx;
+ struct vbo_context *vbo = vbo_context(ctx);
GLuint i;
/* Allocate a buffer object. Will just reuse this object
- * continuously.
+ * continuously, unless vbo_use_buffer_objects() is called to enable
+ * use of real VBOs.
*/
exec->vtx.bufferobj = ctx->Array.NullBufferObj;
exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
- vbo_exec_current_init( exec );
vbo_exec_vtxfmt_init( exec );
/* Hook our functions into the dispatch table.
exec->vtx.active_sz[i] = 0;
exec->vtx.inputs[i] = &exec->vtx.arrays[i];
}
-
+
+ {
+ struct gl_client_array *arrays = exec->vtx.arrays;
+ memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
+ memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
+ }
+
exec->vtx.vertex_size = 0;
}
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
{
- if (exec->vtx.buffer_map) {
- ALIGN_FREE(exec->vtx.buffer_map);
- exec->vtx.buffer_map = NULL;
+ GLcontext *ctx = exec->ctx;
+ if (exec->vtx.bufferobj->Name) {
+ ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, exec->vtx.bufferobj);
+ ctx->Driver.DeleteBuffer(ctx, exec->vtx.bufferobj);
+ exec->vtx.bufferobj = NULL;
+ }
+ else {
+ if (exec->vtx.buffer_map) {
+ ALIGN_FREE(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ }
}
}