/**************************************************************************
-Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
+Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
All Rights Reserved.
* 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/bufferobj.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/vtxfmt.h"
+#if FEATURE_dlist
+#include "main/dlist.h"
+#endif
+#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 );
GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
GLuint last_count;
- if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
GLint i = exec->vtx.prim_count - 1;
assert(i >= 0);
exec->vtx.prim[i].count = (exec->vtx.vert_count -
*/
assert(exec->vtx.prim_count == 0);
- if (exec->ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
exec->vtx.prim[0].mode = exec->ctx->Driver.CurrentExecPrimitive;
exec->vtx.prim[0].start = 0;
exec->vtx.prim[0].count = 0;
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(current,
- exec->vtx.attrsz[i],
- exec->vtx.attrptr[i]);
+ GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
+ GLfloat tmp[4];
+
+ COPY_CLEAN_4V(tmp,
+ exec->vtx.attrsz[i],
+ exec->vtx.attrptr[i]);
+
+ if (memcmp(current, tmp, sizeof(tmp)) != 0)
+ {
+ memcpy(current, tmp, sizeof(tmp));
- /* 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).
- */
- if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
- i <= VBO_ATTRIB_MAT_BACK_INDEXES)
- ctx->NewState |= _NEW_LIGHT;
+ /* 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).
+ */
+ if (i >= VBO_ATTRIB_MAT_FRONT_AMBIENT &&
+ i <= VBO_ATTRIB_MAT_BACK_INDEXES)
+ ctx->NewState |= _NEW_LIGHT;
+
+ ctx->NewState |= _NEW_CURRENT_ATTRIB;
+ }
}
}
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 );
}
+/**
+ * Check if programs/shaders are enabled and valid at glBegin time.
+ */
+GLboolean
+vbo_validate_shaders(GLcontext *ctx)
+{
+ if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
+ (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+ return GL_FALSE;
+ }
+ if (ctx->Shader.CurrentProgram && !ctx->Shader.CurrentProgram->LinkStatus) {
+ return GL_FALSE;
+ }
+ return GL_TRUE;
+}
+
+
/* Build a list of primitives on the fly. Keep
* ctx->Driver.CurrentExecPrimitive uptodate as well.
*/
{
GET_CURRENT_CONTEXT( ctx );
- if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
+ if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
int i;
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,
- "glBegin (invalid vertex/fragment program)");
- return;
- }
-
CALL_Begin(ctx->Exec, (mode));
return;
}
+ if (!vbo_validate_shaders(ctx)) {
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glBegin (invalid vertex/fragment program)");
+ return;
+ }
+
/* Heuristic: attempt to isolate attributes occuring outside
* begin/end pairs.
*/
{
GET_CURRENT_CONTEXT( ctx );
- if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
int idx = exec->vtx.vert_count;
int i = exec->vtx.prim_count - 1;
exec->vtx.prim[i].end = 1;
exec->vtx.prim[i].count = idx - exec->vtx.prim[i].start;
- ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+ ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
if (exec->vtx.prim_count == VBO_MAX_PRIM)
vbo_exec_vtx_flush( exec );
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
vfmt->Begin = vbo_exec_Begin;
+#if FEATURE_dlist
vfmt->CallList = _mesa_CallList;
vfmt->CallLists = _mesa_CallLists;
+#endif
vfmt->End = vbo_exec_End;
vfmt->EvalCoord1f = vbo_exec_EvalCoord1f;
vfmt->EvalCoord1fv = vbo_exec_EvalCoord1fv;
}
+/**
+ * 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)
+{
+ 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);
+ }
+
+ /* 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);
+
+ /* 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;
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);
+ _mesa_reference_buffer_object(ctx,
+ &exec->vtx.bufferobj,
+ ctx->Array.NullBufferObj);
+ ASSERT(!exec->vtx.buffer_map);
+ exec->vtx.buffer_map = ALIGN_MALLOC(VBO_VERT_BUFFER_SIZE * sizeof(GLfloat), 64);
vbo_exec_vtxfmt_init( exec );
/* Hook our functions into the dispatch table.
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;
+ if (exec->vtx.bufferobj->Name) {
+ /* using a real VBO for vertex data */
+ GLcontext *ctx = exec->ctx;
+ _mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
+ }
+ else {
+ /* just using malloc'd space for vertex data */
+ if (exec->vtx.buffer_map) {
+ ALIGN_FREE(exec->vtx.buffer_map);
+ exec->vtx.buffer_map = NULL;
+ }
}
}
exec->vtx.vertex_size = 0;
}
+
+void GLAPIENTRY
+_vbo_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
+{
+ vbo_Color4f(r, g, b, a);
+}
+
+
+void GLAPIENTRY
+_vbo_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+ vbo_Normal3f(x, y, z);
+}
+
+
+void GLAPIENTRY
+_vbo_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
+{
+ vbo_MultiTexCoord4f(target, s, t, r, q);
+}
+
+void GLAPIENTRY
+_vbo_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
+{
+ vbo_Materialfv(face, pname, params);
+}
+
+
+void GLAPIENTRY
+_vbo_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ vbo_VertexAttrib4fARB(index, x, y, z, w);
+}