Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1900 → Rev 1901

/programs/develop/libraries/Mesa/src/mesa/vbo/descrip.mms
0,0 → 1,62
# Makefile for core library for VMS
# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
# Last revision : 3 October 2007
 
.first
define gl [---.include.gl]
define math [-.math]
define vbo [-.vbo]
define tnl [-.tnl]
define shader [-.shader]
define swrast [-.swrast]
define swrast_setup [-.swrast_setup]
define main [-.main]
define glapi [-.glapi]
 
.include [---]mms-config.
 
##### MACROS #####
 
VPATH = RCS
 
INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang]
LIBDIR = [---.lib]
CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
 
SOURCES =vbo_context.c,vbo_exec.c,vbo_exec_api.c,vbo_exec_array.c,\
vbo_exec_draw.c,vbo_exec_eval.c,vbo_rebase.c,vbo_save.c,\
vbo_save_api.c,vbo_save_draw.c,vbo_save_loopback.c,\
vbo_split.c,vbo_split_copy.c,vbo_split_inplace.c
 
OBJECTS =vbo_context.obj,vbo_exec.obj,vbo_exec_api.obj,vbo_exec_array.obj,\
vbo_exec_draw.obj,vbo_exec_eval.obj,vbo_rebase.obj,vbo_save.obj,\
vbo_save_api.obj,vbo_save_draw.obj,vbo_save_loopback.obj,\
vbo_split.obj,vbo_split_copy.obj,vbo_split_inplace.obj
 
##### RULES #####
 
VERSION=Mesa V3.4
 
##### TARGETS #####
# Make the library
$(LIBDIR)$(GL_LIB) : $(OBJECTS)
@ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
 
clean :
purge
delete *.obj;*
 
vbo_context.obj : vbo_context.c
vbo_exec.obj : vbo_exec.c
vbo_exec_api.obj : vbo_exec_api.c
vbo_exec_array.obj : vbo_exec_array.c
vbo_exec_draw.obj : vbo_exec_draw.c
vbo_exec_eval.obj : vbo_exec_eval.c
vbo_rebase.obj : vbo_rebase.c
vbo_save.obj : vbo_save.c
vbo_save_api.obj : vbo_save_api.c
vbo_save_draw.obj : vbo_save_draw.c
vbo_save_loopback.obj : vbo_save_loopback.c
vbo_split.obj : vbo_split.c
vbo_split_copy.obj : vbo_split_copy.c
vbo_split_inplace.obj : vbo_split_inplace.c
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo.h
0,0 → 1,169
/*
* mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file vbo_context.h
* \brief VBO builder module datatypes and definitions.
* \author Keith Whitwell
*/
 
 
#ifndef _VBO_H
#define _VBO_H
 
#include "main/mtypes.h"
 
struct _mesa_prim {
GLuint mode:8;
GLuint indexed:1;
GLuint begin:1;
GLuint end:1;
GLuint weak:1;
GLuint pad:20;
 
GLuint start;
GLuint count;
GLint basevertex;
GLsizei num_instances;
};
 
/* Would like to call this a "vbo_index_buffer", but this would be
* confusing as the indices are not neccessarily yet in a non-null
* buffer object.
*/
struct _mesa_index_buffer {
GLuint count;
GLenum type;
struct gl_buffer_object *obj;
const void *ptr;
};
 
 
 
GLboolean _vbo_CreateContext( struct gl_context *ctx );
void _vbo_DestroyContext( struct gl_context *ctx );
void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state );
 
 
typedef void (*vbo_draw_func)( struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index );
 
 
 
 
/* Utility function to cope with various constraints on tnl modules or
* hardware. This can be used to split an incoming set of arrays and
* primitives against the following constraints:
* - Maximum number of indices in index buffer.
* - Maximum number of vertices referenced by index buffer.
* - Maximum hardware vertex buffer size.
*/
struct split_limits {
GLuint max_verts;
GLuint max_indices;
GLuint max_vb_size; /* bytes */
};
 
 
void vbo_split_prims( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw,
const struct split_limits *limits );
 
 
/* Helpers for dealing translating away non-zero min_index.
*/
GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] );
GLboolean vbo_any_varyings_in_vbos( const struct gl_client_array *arrays[] );
 
void vbo_rebase_prims( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw );
void
vbo_get_minmax_index(struct gl_context *ctx, const struct _mesa_prim *prim,
const struct _mesa_index_buffer *ib,
GLuint *min_index, GLuint *max_index);
 
void vbo_use_buffer_objects(struct gl_context *ctx);
 
 
void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func);
 
 
void GLAPIENTRY
_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
 
void GLAPIENTRY
_es_Normal3f(GLfloat x, GLfloat y, GLfloat z);
 
void GLAPIENTRY
_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
 
void GLAPIENTRY
_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params);
 
void GLAPIENTRY
_es_Materialf(GLenum face, GLenum pname, GLfloat param);
 
void GLAPIENTRY
_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
 
void GLAPIENTRY
_es_VertexAttrib1f(GLuint indx, GLfloat x);
 
void GLAPIENTRY
_es_VertexAttrib1fv(GLuint indx, const GLfloat* values);
 
void GLAPIENTRY
_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
 
void GLAPIENTRY
_es_VertexAttrib2fv(GLuint indx, const GLfloat* values);
 
void GLAPIENTRY
_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
 
void GLAPIENTRY
_es_VertexAttrib3fv(GLuint indx, const GLfloat* values);
 
void GLAPIENTRY
_es_VertexAttrib4fv(GLuint indx, const GLfloat* values);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_attrib.h
0,0 → 1,107
/*
Copyright (C) Intel Corp. 2006. All Rights Reserved.
Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
develop this 3D driver.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice (including the
next paragraph) shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**********************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef VBO_ATTRIB_H
#define VBO_ATTRIB_H
 
 
/*
* Note: The first attributes match the VERT_ATTRIB_* definitions
* in mtypes.h. However, the tnl module has additional attributes
* for materials, color indexes, edge flags, etc.
*/
/* Although it's nice to use these as bit indexes in a DWORD flag, we
* could manage without if necessary. Another limit currently is the
* number of bits allocated for these numbers in places like vertex
* program instruction formats and register layouts.
*/
enum {
VBO_ATTRIB_POS = 0,
VBO_ATTRIB_WEIGHT = 1,
VBO_ATTRIB_NORMAL = 2,
VBO_ATTRIB_COLOR0 = 3,
VBO_ATTRIB_COLOR1 = 4,
VBO_ATTRIB_FOG = 5,
VBO_ATTRIB_INDEX = 6,
VBO_ATTRIB_EDGEFLAG = 7,
VBO_ATTRIB_TEX0 = 8,
VBO_ATTRIB_TEX1 = 9,
VBO_ATTRIB_TEX2 = 10,
VBO_ATTRIB_TEX3 = 11,
VBO_ATTRIB_TEX4 = 12,
VBO_ATTRIB_TEX5 = 13,
VBO_ATTRIB_TEX6 = 14,
VBO_ATTRIB_TEX7 = 15,
 
VBO_ATTRIB_GENERIC0 = 16, /* Not used? */
VBO_ATTRIB_GENERIC1 = 17,
VBO_ATTRIB_GENERIC2 = 18,
VBO_ATTRIB_GENERIC3 = 19,
VBO_ATTRIB_GENERIC4 = 20,
VBO_ATTRIB_GENERIC5 = 21,
VBO_ATTRIB_GENERIC6 = 22,
VBO_ATTRIB_GENERIC7 = 23,
VBO_ATTRIB_GENERIC8 = 24,
VBO_ATTRIB_GENERIC9 = 25,
VBO_ATTRIB_GENERIC10 = 26,
VBO_ATTRIB_GENERIC11 = 27,
VBO_ATTRIB_GENERIC12 = 28,
VBO_ATTRIB_GENERIC13 = 29,
VBO_ATTRIB_GENERIC14 = 30,
VBO_ATTRIB_GENERIC15 = 31,
 
/* XXX: in the vertex program InputsRead flag, we alias
* materials and generics and use knowledge about the program
* (whether it is a fixed-function emulation) to
* differentiate. Here we must keep them apart instead.
*/
VBO_ATTRIB_MAT_FRONT_AMBIENT = 32,
VBO_ATTRIB_MAT_BACK_AMBIENT = 33,
VBO_ATTRIB_MAT_FRONT_DIFFUSE = 34,
VBO_ATTRIB_MAT_BACK_DIFFUSE = 35,
VBO_ATTRIB_MAT_FRONT_SPECULAR = 36,
VBO_ATTRIB_MAT_BACK_SPECULAR = 37,
VBO_ATTRIB_MAT_FRONT_EMISSION = 38,
VBO_ATTRIB_MAT_BACK_EMISSION = 39,
VBO_ATTRIB_MAT_FRONT_SHININESS = 40,
VBO_ATTRIB_MAT_BACK_SHININESS = 41,
VBO_ATTRIB_MAT_FRONT_INDEXES = 42,
VBO_ATTRIB_MAT_BACK_INDEXES = 43,
 
VBO_ATTRIB_MAX = 44
};
 
#define VBO_ATTRIB_FIRST_MATERIAL VBO_ATTRIB_MAT_FRONT_AMBIENT
#define VBO_ATTRIB_LAST_MATERIAL VBO_ATTRIB_MAT_BACK_INDEXES
 
#define VBO_MAX_COPIED_VERTS 3
 
#endif
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_attrib_tmp.h
0,0 → 1,740
/**************************************************************************
 
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
 
All Rights Reserved.
 
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
 
**************************************************************************/
 
/* float */
#define ATTR1FV( A, V ) ATTR( A, 1, (V)[0], 0, 0, 1 )
#define ATTR2FV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
#define ATTR3FV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
#define ATTR4FV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
 
#define ATTR1F( A, X ) ATTR( A, 1, X, 0, 0, 1 )
#define ATTR2F( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
#define ATTR3F( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
#define ATTR4F( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
 
/* int */
#define ATTR2IV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
#define ATTR3IV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
#define ATTR4IV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
 
#define ATTR1I( A, X ) ATTR( A, 1, X, 0, 0, 1 )
#define ATTR2I( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
#define ATTR3I( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
#define ATTR4I( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
 
 
/* uint */
#define ATTR2UIV( A, V ) ATTR( A, 2, (V)[0], (V)[1], 0, 1 )
#define ATTR3UIV( A, V ) ATTR( A, 3, (V)[0], (V)[1], (V)[2], 1 )
#define ATTR4UIV( A, V ) ATTR( A, 4, (V)[0], (V)[1], (V)[2], (V)[3] )
 
#define ATTR1UI( A, X ) ATTR( A, 1, X, 0, 0, 1 )
#define ATTR2UI( A, X, Y ) ATTR( A, 2, X, Y, 0, 1 )
#define ATTR3UI( A, X, Y, Z ) ATTR( A, 3, X, Y, Z, 1 )
#define ATTR4UI( A, X, Y, Z, W ) ATTR( A, 4, X, Y, Z, W )
 
#define MAT_ATTR( A, N, V ) ATTR( A, N, (V)[0], (V)[1], (V)[2], (V)[3] )
 
 
 
static void GLAPIENTRY
TAG(Vertex2f)(GLfloat x, GLfloat y)
{
GET_CURRENT_CONTEXT(ctx);
ATTR2F(VBO_ATTRIB_POS, x, y);
}
 
static void GLAPIENTRY
TAG(Vertex2fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR2FV(VBO_ATTRIB_POS, v);
}
 
static void GLAPIENTRY
TAG(Vertex3f)(GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3F(VBO_ATTRIB_POS, x, y, z);
}
 
static void GLAPIENTRY
TAG(Vertex3fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3FV(VBO_ATTRIB_POS, v);
}
 
static void GLAPIENTRY
TAG(Vertex4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4F(VBO_ATTRIB_POS, x, y, z, w);
}
 
static void GLAPIENTRY
TAG(Vertex4fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4FV(VBO_ATTRIB_POS, v);
}
 
 
 
static void GLAPIENTRY
TAG(TexCoord1f)(GLfloat x)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1F(VBO_ATTRIB_TEX0, x);
}
 
static void GLAPIENTRY
TAG(TexCoord1fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1FV(VBO_ATTRIB_TEX0, v);
}
 
static void GLAPIENTRY
TAG(TexCoord2f)(GLfloat x, GLfloat y)
{
GET_CURRENT_CONTEXT(ctx);
ATTR2F(VBO_ATTRIB_TEX0, x, y);
}
 
static void GLAPIENTRY
TAG(TexCoord2fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR2FV(VBO_ATTRIB_TEX0, v);
}
 
static void GLAPIENTRY
TAG(TexCoord3f)(GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3F(VBO_ATTRIB_TEX0, x, y, z);
}
 
static void GLAPIENTRY
TAG(TexCoord3fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3FV(VBO_ATTRIB_TEX0, v);
}
 
static void GLAPIENTRY
TAG(TexCoord4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4F(VBO_ATTRIB_TEX0, x, y, z, w);
}
 
static void GLAPIENTRY
TAG(TexCoord4fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4FV(VBO_ATTRIB_TEX0, v);
}
 
 
 
static void GLAPIENTRY
TAG(Normal3f)(GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3F(VBO_ATTRIB_NORMAL, x, y, z);
}
 
static void GLAPIENTRY
TAG(Normal3fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3FV(VBO_ATTRIB_NORMAL, v);
}
 
 
 
static void GLAPIENTRY
TAG(FogCoordfEXT)(GLfloat x)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1F(VBO_ATTRIB_FOG, x);
}
 
 
 
static void GLAPIENTRY
TAG(FogCoordfvEXT)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1FV(VBO_ATTRIB_FOG, v);
}
 
static void GLAPIENTRY
TAG(Color3f)(GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3F(VBO_ATTRIB_COLOR0, x, y, z);
}
 
static void GLAPIENTRY
TAG(Color3fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3FV(VBO_ATTRIB_COLOR0, v);
}
 
static void GLAPIENTRY
TAG(Color4f)(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4F(VBO_ATTRIB_COLOR0, x, y, z, w);
}
 
static void GLAPIENTRY
TAG(Color4fv)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR4FV(VBO_ATTRIB_COLOR0, v);
}
 
 
 
static void GLAPIENTRY
TAG(SecondaryColor3fEXT)(GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3F(VBO_ATTRIB_COLOR1, x, y, z);
}
 
static void GLAPIENTRY
TAG(SecondaryColor3fvEXT)(const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
ATTR3FV(VBO_ATTRIB_COLOR1, v);
}
 
 
 
static void GLAPIENTRY
TAG(EdgeFlag)(GLboolean b)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1F(VBO_ATTRIB_EDGEFLAG, (GLfloat) b);
}
 
 
 
static void GLAPIENTRY
TAG(Indexf)(GLfloat f)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1F(VBO_ATTRIB_INDEX, f);
}
 
static void GLAPIENTRY
TAG(Indexfv)(const GLfloat * f)
{
GET_CURRENT_CONTEXT(ctx);
ATTR1FV(VBO_ATTRIB_INDEX, f);
}
 
 
 
static void GLAPIENTRY
TAG(MultiTexCoord1f)(GLenum target, GLfloat x)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR1F(attr, x);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord1fv)(GLenum target, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR1FV(attr, v);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord2f)(GLenum target, GLfloat x, GLfloat y)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR2F(attr, x, y);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord2fv)(GLenum target, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR2FV(attr, v);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord3f)(GLenum target, GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR3F(attr, x, y, z);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord3fv)(GLenum target, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR3FV(attr, v);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord4f)(GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR4F(attr, x, y, z, w);
}
 
static void GLAPIENTRY
TAG(MultiTexCoord4fv)(GLenum target, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
GLuint attr = (target & 0x7) + VBO_ATTRIB_TEX0;
ATTR4FV(attr, v);
}
 
 
 
static void GLAPIENTRY
TAG(VertexAttrib1fARB)(GLuint index, GLfloat x)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR1F(0, x);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1F(VBO_ATTRIB_GENERIC0 + index, x);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib1fvARB)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR1FV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib2fARB)(GLuint index, GLfloat x, GLfloat y)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2F(0, x, y);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2F(VBO_ATTRIB_GENERIC0 + index, x, y);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib2fvARB)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2FV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib3fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3F(0, x, y, z);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3F(VBO_ATTRIB_GENERIC0 + index, x, y, z);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib3fvARB)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3FV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib4fARB)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4F(0, x, y, z, w);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4F(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttrib4fvARB)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4FV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4FV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
 
 
/* Integer-valued generic attributes.
* XXX: the integers just get converted to floats at this time
*/
static void GLAPIENTRY
TAG(VertexAttribI1i)(GLuint index, GLint x)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR1I(0, x);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1I(VBO_ATTRIB_GENERIC0 + index, x);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI2i)(GLuint index, GLint x, GLint y)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2I(0, x, y);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2I(VBO_ATTRIB_GENERIC0 + index, x, y);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI3i)(GLuint index, GLint x, GLint y, GLint z)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3I(0, x, y, z);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3I(VBO_ATTRIB_GENERIC0 + index, x, y, z);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4I(0, x, y, z, w);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4I(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI2iv)(GLuint index, const GLint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2IV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2IV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI3iv)(GLuint index, const GLint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3IV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3IV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI4iv)(GLuint index, const GLint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4IV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4IV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
 
 
/* Unsigned integer-valued generic attributes.
* XXX: the integers just get converted to floats at this time
*/
static void GLAPIENTRY
TAG(VertexAttribI1ui)(GLuint index, GLuint x)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR1UI(0, x);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR1UI(VBO_ATTRIB_GENERIC0 + index, x);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI2ui)(GLuint index, GLuint x, GLuint y)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2UI(0, x, y);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2UI(VBO_ATTRIB_GENERIC0 + index, x, y);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI3ui)(GLuint index, GLuint x, GLuint y, GLuint z)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3UI(0, x, y, z);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3UI(VBO_ATTRIB_GENERIC0 + index, x, y, z);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4UI(0, x, y, z, w);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4UI(VBO_ATTRIB_GENERIC0 + index, x, y, z, w);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI2uiv)(GLuint index, const GLuint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR2UIV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR2UIV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI3uiv)(GLuint index, const GLuint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR3UIV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR3UIV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
static void GLAPIENTRY
TAG(VertexAttribI4uiv)(GLuint index, const GLuint *v)
{
GET_CURRENT_CONTEXT(ctx);
if (index == 0)
ATTR4UIV(0, v);
else if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR4UIV(VBO_ATTRIB_GENERIC0 + index, v);
else
ERROR();
}
 
 
 
/* In addition to supporting NV_vertex_program, these entrypoints are
* used by the display list and other code specifically because of
* their property of aliasing with other attributes. (See
* vbo_save_loopback.c)
*/
static void GLAPIENTRY
TAG(VertexAttrib1fNV)(GLuint index, GLfloat x)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR1F(index, x);
}
 
static void GLAPIENTRY
TAG(VertexAttrib1fvNV)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR1FV(index, v);
}
 
static void GLAPIENTRY
TAG(VertexAttrib2fNV)(GLuint index, GLfloat x, GLfloat y)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR2F(index, x, y);
}
 
static void GLAPIENTRY
TAG(VertexAttrib2fvNV)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR2FV(index, v);
}
 
static void GLAPIENTRY
TAG(VertexAttrib3fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR3F(index, x, y, z);
}
 
static void GLAPIENTRY
TAG(VertexAttrib3fvNV)(GLuint index,
const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR3FV(index, v);
}
 
static void GLAPIENTRY
TAG(VertexAttrib4fNV)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR4F(index, x, y, z, w);
}
 
static void GLAPIENTRY
TAG(VertexAttrib4fvNV)(GLuint index, const GLfloat * v)
{
GET_CURRENT_CONTEXT(ctx);
if (index < VBO_ATTRIB_MAX)
ATTR4FV(index, v);
}
 
 
 
#define MAT( ATTR, N, face, params ) \
do { \
if (face != GL_BACK) \
MAT_ATTR( ATTR, N, params ); /* front */ \
if (face != GL_FRONT) \
MAT_ATTR( ATTR + 1, N, params ); /* back */ \
} while (0)
 
 
/* Colormaterial conflicts are dealt with later.
*/
static void GLAPIENTRY
TAG(Materialfv)(GLenum face, GLenum pname,
const GLfloat * params)
{
GET_CURRENT_CONTEXT(ctx);
switch (pname) {
case GL_EMISSION:
MAT(VBO_ATTRIB_MAT_FRONT_EMISSION, 4, face, params);
break;
case GL_AMBIENT:
MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
break;
case GL_DIFFUSE:
MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
break;
case GL_SPECULAR:
MAT(VBO_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params);
break;
case GL_SHININESS:
MAT(VBO_ATTRIB_MAT_FRONT_SHININESS, 1, face, params);
break;
case GL_COLOR_INDEXES:
MAT(VBO_ATTRIB_MAT_FRONT_INDEXES, 3, face, params);
break;
case GL_AMBIENT_AND_DIFFUSE:
MAT(VBO_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params);
MAT(VBO_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params);
break;
default:
ERROR();
return;
}
}
 
 
#undef ATTR1FV
#undef ATTR2FV
#undef ATTR3FV
#undef ATTR4FV
 
#undef ATTR1F
#undef ATTR2F
#undef ATTR3F
#undef ATTR4F
 
#undef MAT
#undef MAT_ATTR
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_context.c
0,0 → 1,247
/*
* Mesa 3-D graphics library
* Version: 6.3
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/api_arrayelt.h"
#include "main/bufferobj.h"
#include "math/m_eval.h"
#include "vbo.h"
#include "vbo_context.h"
 
 
 
#define NR_LEGACY_ATTRIBS 16
#define NR_GENERIC_ATTRIBS 16
#define NR_MAT_ATTRIBS 12
 
 
static GLuint check_size( const GLfloat *attr )
{
if (attr[3] != 1.0) return 4;
if (attr[2] != 0.0) return 3;
if (attr[1] != 0.0) return 2;
return 1;
}
 
 
static void init_legacy_currval(struct gl_context *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct gl_client_array *arrays = vbo->legacy_currval;
GLuint i;
 
memset(arrays, 0, sizeof(*arrays) * NR_LEGACY_ATTRIBS);
 
/* Set up a constant (StrideB == 0) array for each current
* attribute:
*/
for (i = 0; i < NR_LEGACY_ATTRIBS; i++) {
struct gl_client_array *cl = &arrays[i];
 
/* Size will have to be determined at runtime:
*/
cl->Size = check_size(ctx->Current.Attrib[i]);
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
cl->Type = GL_FLOAT;
cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[i];
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
}
 
 
static void init_generic_currval(struct gl_context *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct gl_client_array *arrays = vbo->generic_currval;
GLuint i;
 
memset(arrays, 0, sizeof(*arrays) * NR_GENERIC_ATTRIBS);
 
for (i = 0; i < NR_GENERIC_ATTRIBS; i++) {
struct gl_client_array *cl = &arrays[i];
 
/* This will have to be determined at runtime:
*/
cl->Size = 1;
cl->Type = GL_FLOAT;
cl->Format = GL_RGBA;
cl->Ptr = (const void *)ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i];
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
}
 
 
static void init_mat_currval(struct gl_context *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct gl_client_array *arrays = vbo->mat_currval;
GLuint i;
 
ASSERT(NR_MAT_ATTRIBS == MAT_ATTRIB_MAX);
 
memset(arrays, 0, sizeof(*arrays) * NR_MAT_ATTRIBS);
 
/* Set up a constant (StrideB == 0) array for each current
* attribute:
*/
for (i = 0; i < NR_MAT_ATTRIBS; i++) {
struct gl_client_array *cl = &arrays[i];
 
/* Size is fixed for the material attributes, for others will
* be determined at runtime:
*/
switch (i - VERT_ATTRIB_GENERIC0) {
case MAT_ATTRIB_FRONT_SHININESS:
case MAT_ATTRIB_BACK_SHININESS:
cl->Size = 1;
break;
case MAT_ATTRIB_FRONT_INDEXES:
case MAT_ATTRIB_BACK_INDEXES:
cl->Size = 3;
break;
default:
cl->Size = 4;
break;
}
 
cl->Ptr = (const void *)ctx->Light.Material.Attrib[i];
cl->Type = GL_FLOAT;
cl->Format = GL_RGBA;
cl->Stride = 0;
cl->StrideB = 0;
cl->Enabled = 1;
_mesa_reference_buffer_object(ctx, &cl->BufferObj,
ctx->Shared->NullBufferObj);
}
}
 
 
GLboolean _vbo_CreateContext( struct gl_context *ctx )
{
struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
 
ctx->swtnl_im = (void *)vbo;
 
/* Initialize the arrayelt helper
*/
if (!ctx->aelt_context &&
!_ae_create_context( ctx )) {
return GL_FALSE;
}
 
/* TODO: remove these pointers.
*/
vbo->legacy_currval = &vbo->currval[VBO_ATTRIB_POS];
vbo->generic_currval = &vbo->currval[VBO_ATTRIB_GENERIC0];
vbo->mat_currval = &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT];
 
init_legacy_currval( ctx );
init_generic_currval( ctx );
init_mat_currval( ctx );
 
/* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
* of vertex program active.
*/
{
GLuint i;
 
/* When no vertex program, pull in the material attributes in
* the 16..32 generic range.
*/
for (i = 0; i < 16; i++)
vbo->map_vp_none[i] = i;
for (i = 0; i < 12; i++)
vbo->map_vp_none[16+i] = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
for (i = 0; i < 4; i++)
vbo->map_vp_none[28+i] = i;
for (i = 0; i < Elements(vbo->map_vp_arb); i++)
vbo->map_vp_arb[i] = i;
}
 
 
/* Hook our functions into exec and compile dispatch tables. These
* will pretty much be permanently installed, which means that the
* vtxfmt mechanism can be removed now.
*/
vbo_exec_init( ctx );
if (ctx->API == API_OPENGL)
vbo_save_init( ctx );
 
_math_init_eval();
 
return GL_TRUE;
}
 
 
void _vbo_InvalidateState( struct gl_context *ctx, GLuint new_state )
{
_ae_invalidate_state(ctx, new_state);
vbo_exec_invalidate_state(ctx, new_state);
}
 
 
void _vbo_DestroyContext( struct gl_context *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
 
if (ctx->aelt_context) {
_ae_destroy_context( ctx );
ctx->aelt_context = NULL;
}
 
if (vbo) {
GLuint i;
 
for (i = 0; i < VBO_ATTRIB_MAX; i++) {
_mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
}
 
vbo_exec_destroy(ctx);
if (ctx->API == API_OPENGL)
vbo_save_destroy(ctx);
FREE(vbo);
ctx->swtnl_im = NULL;
}
}
 
 
void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
{
struct vbo_context *vbo = vbo_context(ctx);
vbo->draw_prims = func;
}
 
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_context.h
0,0 → 1,112
/*
* mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file vbo_context.h
* \brief VBO builder module datatypes and definitions.
* \author Keith Whitwell
*/
 
 
/**
* \mainpage The VBO builder module
*
* This module hooks into the GL dispatch table and catches all vertex
* building and drawing commands, such as glVertex3f, glBegin and
* glDrawArrays. The module stores all incoming vertex data as arrays
* in GL vertex buffer objects (VBOs), and translates all drawing
* commands into calls to a driver supplied DrawPrimitives() callback.
*
* The module captures both immediate mode and display list drawing,
* and manages the allocation, reference counting and deallocation of
* vertex buffer objects itself.
*
* The DrawPrimitives() callback can be either implemented by the
* driver itself or hooked to the tnl module's _tnl_draw_primitives()
* function for hardware without tnl capablilties or during fallbacks.
*/
 
 
#ifndef _VBO_CONTEXT_H
#define _VBO_CONTEXT_H
 
#include "vbo.h"
#include "vbo_attrib.h"
#include "vbo_exec.h"
#include "vbo_save.h"
 
 
struct vbo_context {
struct gl_client_array currval[VBO_ATTRIB_MAX];
/* These point into the above. TODO: remove.
*/
struct gl_client_array *legacy_currval;
struct gl_client_array *generic_currval;
struct gl_client_array *mat_currval;
 
GLuint map_vp_none[VERT_ATTRIB_MAX];
GLuint map_vp_arb[VERT_ATTRIB_MAX];
 
GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->Current, ctx->Light.Material */
GLfloat CurrentFloatEdgeFlag;
 
 
struct vbo_exec_context exec;
#if FEATURE_dlist
struct vbo_save_context save;
#endif
 
/* Callback into the driver. This must always succeed, the driver
* is responsible for initiating any fallback actions required:
*/
vbo_draw_func draw_prims;
};
 
 
static INLINE struct vbo_context *vbo_context(struct gl_context *ctx)
{
return (struct vbo_context *)(ctx->swtnl_im);
}
 
 
/**
* Return VP_x token to indicate whether we're running fixed-function
* vertex transformation, an NV vertex program or ARB vertex program/shader.
*/
static INLINE enum vp_mode
get_program_mode( struct gl_context *ctx )
{
if (!ctx->VertexProgram._Current)
return VP_NONE;
else if (ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram)
return VP_NONE;
else if (ctx->VertexProgram._Current->IsNVProgram)
return VP_NV;
else
return VP_ARB;
}
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec.c
0,0 → 1,92
/*
* Mesa 3-D graphics library
* Version: 6.3
*
* Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "main/api_arrayelt.h"
#include "main/glheader.h"
#include "main/mtypes.h"
#include "main/vtxfmt.h"
#include "vbo_context.h"
 
 
 
void vbo_exec_init( struct gl_context *ctx )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
exec->ctx = ctx;
 
/* Initialize the arrayelt helper
*/
if (!ctx->aelt_context &&
!_ae_create_context( ctx ))
return;
 
vbo_exec_vtx_init( exec );
vbo_exec_array_init( exec );
 
/* Hook our functions into exec and compile dispatch tables.
*/
_mesa_install_exec_vtxfmt( ctx, &exec->vtxfmt );
 
ctx->Driver.NeedFlush = 0;
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
ctx->Driver.BeginVertices = vbo_exec_BeginVertices;
ctx->Driver.FlushVertices = vbo_exec_FlushVertices;
 
vbo_exec_invalidate_state( ctx, ~0 );
}
 
 
void vbo_exec_destroy( struct gl_context *ctx )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
if (ctx->aelt_context) {
_ae_destroy_context( ctx );
ctx->aelt_context = NULL;
}
 
vbo_exec_vtx_destroy( exec );
vbo_exec_array_destroy( exec );
}
 
 
/**
* Really want to install these callbacks to a central facility to be
* invoked according to the state flags. That will have to wait for a
* mesa rework:
*/
void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
if (new_state & (_NEW_PROGRAM|_NEW_EVAL))
exec->eval.recalculate_maps = 1;
 
_ae_invalidate_state(ctx, new_state);
}
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec.h
0,0 → 1,198
/**************************************************************************
 
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
 
All Rights Reserved.
 
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
 
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
 
#ifndef __VBO_EXEC_H__
#define __VBO_EXEC_H__
 
#include "main/mtypes.h"
#include "vbo.h"
#include "vbo_attrib.h"
 
 
#define VBO_MAX_PRIM 64
 
/* Wierd implementation stuff:
*/
#define VBO_VERT_BUFFER_SIZE (1024*64) /* bytes */
#define VBO_MAX_ATTR_CODEGEN 16
#define ERROR_ATTRIB 16
 
 
/** Current vertex program mode */
enum vp_mode {
VP_NONE, /**< fixed function */
VP_NV, /**< NV vertex program */
VP_ARB /**< ARB vertex program or GLSL vertex shader */
};
 
 
struct vbo_exec_eval1_map {
struct gl_1d_map *map;
GLuint sz;
};
 
struct vbo_exec_eval2_map {
struct gl_2d_map *map;
GLuint sz;
};
 
 
 
struct vbo_exec_copied_vtx {
GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
GLuint nr;
};
 
 
typedef void (*vbo_attrfv_func)( const GLfloat * );
 
 
struct vbo_exec_context
{
struct gl_context *ctx;
GLvertexformat vtxfmt;
 
struct {
struct gl_buffer_object *bufferobj;
 
GLuint vertex_size; /* in dwords */
 
struct _mesa_prim prim[VBO_MAX_PRIM];
GLuint prim_count;
 
GLfloat *buffer_map;
GLfloat *buffer_ptr; /* cursor, points into buffer */
GLuint buffer_used; /* in bytes */
GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current vertex */
 
GLuint vert_count;
GLuint max_vert;
struct vbo_exec_copied_vtx copied;
 
GLubyte attrsz[VBO_ATTRIB_MAX];
GLubyte active_sz[VBO_ATTRIB_MAX];
 
GLfloat *attrptr[VBO_ATTRIB_MAX];
struct gl_client_array arrays[VERT_ATTRIB_MAX];
 
/* According to program mode, the values above plus current
* values are squashed down to the 32 attributes passed to the
* vertex program below:
*/
enum vp_mode program_mode;
GLuint enabled_flags;
const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
} vtx;
 
struct {
GLboolean recalculate_maps;
struct vbo_exec_eval1_map map1[VERT_ATTRIB_MAX];
struct vbo_exec_eval2_map map2[VERT_ATTRIB_MAX];
} eval;
 
struct {
enum vp_mode program_mode;
GLuint enabled_flags;
GLuint array_obj;
 
/* These just mirror the current arrayobj (todo: make arrayobj
* look like this and remove the mirror):
*/
const struct gl_client_array *legacy_array[16];
const struct gl_client_array *generic_array[16];
 
/* Arrays and current values manipulated according to program
* mode, etc. These are the attributes as seen by vertex
* programs:
*/
const struct gl_client_array *inputs[VERT_ATTRIB_MAX];
} array;
 
#ifdef DEBUG
GLint flush_call_depth;
#endif
};
 
 
 
/* External API:
*/
void vbo_exec_init( struct gl_context *ctx );
void vbo_exec_destroy( struct gl_context *ctx );
void vbo_exec_invalidate_state( struct gl_context *ctx, GLuint new_state );
void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap );
 
void vbo_exec_BeginVertices( struct gl_context *ctx );
void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags );
 
 
/* Internal functions:
*/
void vbo_exec_array_init( struct vbo_exec_context *exec );
void vbo_exec_array_destroy( struct vbo_exec_context *exec );
 
 
void vbo_exec_vtx_init( struct vbo_exec_context *exec );
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec );
 
#if FEATURE_beginend
 
void vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap );
void vbo_exec_vtx_map( struct vbo_exec_context *exec );
 
#else /* FEATURE_beginend */
 
static INLINE void
vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
{
}
 
static INLINE void
vbo_exec_vtx_map( struct vbo_exec_context *exec )
{
}
 
#endif /* FEATURE_beginend */
 
void vbo_exec_vtx_wrap( struct vbo_exec_context *exec );
 
void vbo_exec_eval_update( struct vbo_exec_context *exec );
 
void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
GLfloat u, GLfloat v );
 
void vbo_exec_do_EvalCoord1f( struct vbo_exec_context *exec,
GLfloat u);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec_api.c
0,0 → 1,1079
/**************************************************************************
 
Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
 
All Rights Reserved.
 
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
 
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/macros.h"
#include "main/vtxfmt.h"
#include "main/dlist.h"
#include "main/eval.h"
#include "main/state.h"
#include "main/light.h"
#include "main/api_arrayelt.h"
#include "main/api_noop.h"
#include "main/dispatch.h"
 
#include "vbo_context.h"
 
#ifdef ERROR
#undef ERROR
#endif
 
 
/** ID/name for immediate-mode VBO */
#define IMM_BUFFER_NAME 0xaabbccdd
 
 
static void reset_attrfv( struct vbo_exec_context *exec );
 
 
/**
* Close off the last primitive, execute the buffer, restart the
* primitive.
*/
static void vbo_exec_wrap_buffers( struct vbo_exec_context *exec )
{
if (exec->vtx.prim_count == 0) {
exec->vtx.copied.nr = 0;
exec->vtx.vert_count = 0;
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
}
else {
GLuint last_begin = exec->vtx.prim[exec->vtx.prim_count-1].begin;
GLuint last_count;
 
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 -
exec->vtx.prim[i].start);
}
 
last_count = exec->vtx.prim[exec->vtx.prim_count-1].count;
 
/* Execute the buffer and save copied vertices.
*/
if (exec->vtx.vert_count)
vbo_exec_vtx_flush( exec, GL_FALSE );
else {
exec->vtx.prim_count = 0;
exec->vtx.copied.nr = 0;
}
 
/* Emit a glBegin to start the new list.
*/
assert(exec->vtx.prim_count == 0);
 
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;
exec->vtx.prim_count++;
if (exec->vtx.copied.nr == last_count)
exec->vtx.prim[0].begin = last_begin;
}
}
}
 
 
/**
* Deal with buffer wrapping where provoked by the vertex buffer
* filling up, as opposed to upgrade_vertex().
*/
void vbo_exec_vtx_wrap( struct vbo_exec_context *exec )
{
GLfloat *data = exec->vtx.copied.buffer;
GLuint i;
 
/* Run pipeline on current vertices, copy wrapped vertices
* to exec->vtx.copied.
*/
vbo_exec_wrap_buffers( exec );
/* Copy stored stored vertices to start of new list.
*/
assert(exec->vtx.max_vert - exec->vtx.vert_count > exec->vtx.copied.nr);
 
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
memcpy( exec->vtx.buffer_ptr, data,
exec->vtx.vertex_size * sizeof(GLfloat));
exec->vtx.buffer_ptr += exec->vtx.vertex_size;
data += exec->vtx.vertex_size;
exec->vtx.vert_count++;
}
 
exec->vtx.copied.nr = 0;
}
 
 
/**
* Copy the active vertex's values to the ctx->Current fields.
*/
static void vbo_exec_copy_to_current( struct vbo_exec_context *exec )
{
struct gl_context *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]) {
/* Note: the exec->vtx.current[i] pointers point into the
* ctx->Current.Attrib and ctx->Light.Material.Attrib arrays.
*/
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;
ctx->NewState |= _NEW_CURRENT_ATTRIB;
}
}
}
 
/* Colormaterial -- this kindof sucks.
*/
if (ctx->Light.ColorMaterialEnabled &&
exec->vtx.attrsz[VBO_ATTRIB_COLOR0]) {
_mesa_update_color_material(ctx,
ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
}
}
 
 
static void vbo_exec_copy_from_current( struct vbo_exec_context *exec )
{
struct gl_context *ctx = exec->ctx;
struct vbo_context *vbo = vbo_context(ctx);
GLint 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] = 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;
}
}
}
 
 
/**
* Flush existing data, set new attrib size, replay copied vertices.
*/
static void vbo_exec_wrap_upgrade_vertex( struct vbo_exec_context *exec,
GLuint attr,
GLuint newsz )
{
struct gl_context *ctx = exec->ctx;
struct vbo_context *vbo = vbo_context(ctx);
GLint lastcount = exec->vtx.vert_count;
GLfloat *old_attrptr[VBO_ATTRIB_MAX];
GLuint old_vtx_size = exec->vtx.vertex_size;
GLuint oldsz = exec->vtx.attrsz[attr];
GLuint i;
 
/* Run pipeline on current vertices, copy wrapped vertices
* to exec->vtx.copied.
*/
vbo_exec_wrap_buffers( exec );
 
if (unlikely(exec->vtx.copied.nr)) {
/* We're in the middle of a primitive, keep the old vertex
* format around to be able to translate the copied vertices to
* the new format.
*/
memcpy(old_attrptr, exec->vtx.attrptr, sizeof(old_attrptr));
}
 
if (unlikely(oldsz)) {
/* Do a COPY_TO_CURRENT to ensure back-copying works for the
* case when the attribute already exists in the vertex and is
* having its size increased.
*/
vbo_exec_copy_to_current( exec );
}
 
/* Heuristic: Attempt to isolate attributes received outside
* begin/end so that they don't bloat the vertices.
*/
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END &&
!oldsz && lastcount > 8 && exec->vtx.vertex_size) {
vbo_exec_copy_to_current( exec );
reset_attrfv( exec );
}
 
/* Fix up sizes:
*/
exec->vtx.attrsz[attr] = newsz;
exec->vtx.vertex_size += newsz - oldsz;
exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
(exec->vtx.vertex_size * sizeof(GLfloat)));
exec->vtx.vert_count = 0;
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
 
if (unlikely(oldsz)) {
/* Size changed, recalculate all the attrptr[] values
*/
GLfloat *tmp = exec->vtx.vertex;
 
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
if (exec->vtx.attrsz[i]) {
exec->vtx.attrptr[i] = tmp;
tmp += exec->vtx.attrsz[i];
}
else
exec->vtx.attrptr[i] = NULL; /* will not be dereferenced */
}
 
/* Copy from current to repopulate the vertex with correct
* values.
*/
vbo_exec_copy_from_current( exec );
 
} else {
/* Just have to append the new attribute at the end */
exec->vtx.attrptr[attr] = exec->vtx.vertex +
exec->vtx.vertex_size - newsz;
}
 
/* Replay stored vertices to translate them
* to new format here.
*
* -- No need to replay - just copy piecewise
*/
if (unlikely(exec->vtx.copied.nr)) {
GLfloat *data = exec->vtx.copied.buffer;
GLfloat *dest = exec->vtx.buffer_ptr;
GLuint j;
 
assert(exec->vtx.buffer_ptr == exec->vtx.buffer_map);
 
for (i = 0 ; i < exec->vtx.copied.nr ; i++) {
for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
GLuint sz = exec->vtx.attrsz[j];
 
if (sz) {
GLint old_offset = old_attrptr[j] - exec->vtx.vertex;
GLint new_offset = exec->vtx.attrptr[j] - exec->vtx.vertex;
 
if (j == attr) {
if (oldsz) {
GLfloat tmp[4];
COPY_CLEAN_4V(tmp, oldsz, data + old_offset);
COPY_SZ_4V(dest + new_offset, newsz, tmp);
} else {
GLfloat *current = (GLfloat *)vbo->currval[j].Ptr;
COPY_SZ_4V(dest + new_offset, sz, current);
}
}
else {
COPY_SZ_4V(dest + new_offset, sz, data + old_offset);
}
}
}
 
data += old_vtx_size;
dest += exec->vtx.vertex_size;
}
 
exec->vtx.buffer_ptr = dest;
exec->vtx.vert_count += exec->vtx.copied.nr;
exec->vtx.copied.nr = 0;
}
}
 
 
static void vbo_exec_fixup_vertex( struct gl_context *ctx,
GLuint attr, GLuint sz )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
int i;
 
if (sz > exec->vtx.attrsz[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
vbo_exec_wrap_upgrade_vertex( exec, attr, sz );
}
else if (sz < exec->vtx.active_sz[attr]) {
static const GLfloat id[4] = { 0, 0, 0, 1 };
 
/* New size is smaller - just need to fill in some
* zeros. Don't need to flush or wrap.
*/
for (i = sz ; i <= exec->vtx.attrsz[attr] ; i++)
exec->vtx.attrptr[attr][i-1] = id[i-1];
}
 
exec->vtx.active_sz[attr] = sz;
 
/* Does setting NeedFlush belong here? Necessitates resetting
* vtxfmt on each flush (otherwise flags won't get reset
* afterwards).
*/
if (attr == 0)
exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
}
 
 
/*
*/
#define ATTR( A, N, V0, V1, V2, V3 ) \
do { \
struct vbo_exec_context *exec = &vbo_context(ctx)->exec; \
\
if (unlikely(!(exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT))) \
ctx->Driver.BeginVertices( ctx ); \
if (unlikely(exec->vtx.active_sz[A] != N)) \
vbo_exec_fixup_vertex(ctx, A, N); \
\
{ \
GLfloat *dest = 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; \
} \
\
if ((A) == 0) { \
GLuint i; \
\
for (i = 0; i < exec->vtx.vertex_size; i++) \
exec->vtx.buffer_ptr[i] = exec->vtx.vertex[i]; \
\
exec->vtx.buffer_ptr += exec->vtx.vertex_size; \
exec->ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; \
\
if (++exec->vtx.vert_count >= exec->vtx.max_vert) \
vbo_exec_vtx_wrap( exec ); \
} \
} while (0)
 
 
#define ERROR() _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ )
#define TAG(x) vbo_##x
 
#include "vbo_attrib_tmp.h"
 
 
#if FEATURE_beginend
 
 
#if FEATURE_evaluators
 
static void GLAPIENTRY vbo_exec_EvalCoord1f( GLfloat u )
{
GET_CURRENT_CONTEXT( ctx );
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
{
GLint i;
if (exec->eval.recalculate_maps)
vbo_exec_eval_update( exec );
 
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 );
}
}
 
 
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
exec->vtx.vertex_size * sizeof(GLfloat));
 
vbo_exec_do_EvalCoord1f( exec, u );
 
memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
exec->vtx.vertex_size * sizeof(GLfloat));
}
 
static void GLAPIENTRY vbo_exec_EvalCoord2f( GLfloat u, GLfloat v )
{
GET_CURRENT_CONTEXT( ctx );
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
{
GLint i;
if (exec->eval.recalculate_maps)
vbo_exec_eval_update( exec );
 
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->Eval.AutoNormal)
if (exec->vtx.active_sz[VBO_ATTRIB_NORMAL] != 3)
vbo_exec_fixup_vertex( ctx, VBO_ATTRIB_NORMAL, 3 );
}
 
memcpy( exec->vtx.copied.buffer, exec->vtx.vertex,
exec->vtx.vertex_size * sizeof(GLfloat));
 
vbo_exec_do_EvalCoord2f( exec, u, v );
 
memcpy( exec->vtx.vertex, exec->vtx.copied.buffer,
exec->vtx.vertex_size * sizeof(GLfloat));
}
 
static void GLAPIENTRY vbo_exec_EvalCoord1fv( const GLfloat *u )
{
vbo_exec_EvalCoord1f( u[0] );
}
 
static void GLAPIENTRY vbo_exec_EvalCoord2fv( const GLfloat *u )
{
vbo_exec_EvalCoord2f( u[0], u[1] );
}
 
static void GLAPIENTRY vbo_exec_EvalPoint1( GLint i )
{
GET_CURRENT_CONTEXT( ctx );
GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) /
(GLfloat) ctx->Eval.MapGrid1un);
GLfloat u = i * du + ctx->Eval.MapGrid1u1;
 
vbo_exec_EvalCoord1f( u );
}
 
 
static void GLAPIENTRY vbo_exec_EvalPoint2( GLint i, GLint j )
{
GET_CURRENT_CONTEXT( ctx );
GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) /
(GLfloat) ctx->Eval.MapGrid2un);
GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) /
(GLfloat) ctx->Eval.MapGrid2vn);
GLfloat u = i * du + ctx->Eval.MapGrid2u1;
GLfloat v = j * dv + ctx->Eval.MapGrid2v1;
 
vbo_exec_EvalCoord2f( u, v );
}
 
/* use noop eval mesh */
#define vbo_exec_EvalMesh1 _mesa_noop_EvalMesh1
#define vbo_exec_EvalMesh2 _mesa_noop_EvalMesh2
 
#endif /* FEATURE_evaluators */
 
 
/**
* Called via glBegin.
*/
static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT( ctx );
 
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 );
 
CALL_Begin(ctx->Exec, (mode));
return;
}
 
if (!_mesa_valid_to_render(ctx, "glBegin")) {
return;
}
 
/* Heuristic: attempt to isolate attributes occuring outside
* begin/end pairs.
*/
if (exec->vtx.vertex_size && !exec->vtx.attrsz[0])
vbo_exec_FlushVertices_internal( ctx, GL_FALSE );
 
i = exec->vtx.prim_count++;
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].weak = 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;
 
ctx->Driver.CurrentExecPrimitive = mode;
}
else
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
}
 
 
/**
* Called via glEnd.
*/
static void GLAPIENTRY vbo_exec_End( void )
{
GET_CURRENT_CONTEXT( ctx );
 
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 = PRIM_OUTSIDE_BEGIN_END;
 
if (exec->vtx.prim_count == VBO_MAX_PRIM)
vbo_exec_vtx_flush( exec, GL_FALSE );
}
else
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
}
 
 
/**
* Called via glPrimitiveRestartNV()
*/
static void GLAPIENTRY
vbo_exec_PrimitiveRestartNV(void)
{
GLenum curPrim;
GET_CURRENT_CONTEXT( ctx );
 
curPrim = ctx->Driver.CurrentExecPrimitive;
 
if (curPrim == PRIM_OUTSIDE_BEGIN_END) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glPrimitiveRestartNV" );
}
else {
vbo_exec_End();
vbo_exec_Begin(curPrim);
}
}
 
 
 
static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
{
GLvertexformat *vfmt = &exec->vtxfmt;
 
_MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
 
vfmt->Begin = vbo_exec_Begin;
vfmt->End = vbo_exec_End;
vfmt->PrimitiveRestartNV = vbo_exec_PrimitiveRestartNV;
 
_MESA_INIT_DLIST_VTXFMT(vfmt, _mesa_);
_MESA_INIT_EVAL_VTXFMT(vfmt, vbo_exec_);
 
vfmt->Rectf = _mesa_noop_Rectf;
 
/* from attrib_tmp.h:
*/
vfmt->Color3f = vbo_Color3f;
vfmt->Color3fv = vbo_Color3fv;
vfmt->Color4f = vbo_Color4f;
vfmt->Color4fv = vbo_Color4fv;
vfmt->FogCoordfEXT = vbo_FogCoordfEXT;
vfmt->FogCoordfvEXT = vbo_FogCoordfvEXT;
vfmt->MultiTexCoord1fARB = vbo_MultiTexCoord1f;
vfmt->MultiTexCoord1fvARB = vbo_MultiTexCoord1fv;
vfmt->MultiTexCoord2fARB = vbo_MultiTexCoord2f;
vfmt->MultiTexCoord2fvARB = vbo_MultiTexCoord2fv;
vfmt->MultiTexCoord3fARB = vbo_MultiTexCoord3f;
vfmt->MultiTexCoord3fvARB = vbo_MultiTexCoord3fv;
vfmt->MultiTexCoord4fARB = vbo_MultiTexCoord4f;
vfmt->MultiTexCoord4fvARB = vbo_MultiTexCoord4fv;
vfmt->Normal3f = vbo_Normal3f;
vfmt->Normal3fv = vbo_Normal3fv;
vfmt->SecondaryColor3fEXT = vbo_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = vbo_SecondaryColor3fvEXT;
vfmt->TexCoord1f = vbo_TexCoord1f;
vfmt->TexCoord1fv = vbo_TexCoord1fv;
vfmt->TexCoord2f = vbo_TexCoord2f;
vfmt->TexCoord2fv = vbo_TexCoord2fv;
vfmt->TexCoord3f = vbo_TexCoord3f;
vfmt->TexCoord3fv = vbo_TexCoord3fv;
vfmt->TexCoord4f = vbo_TexCoord4f;
vfmt->TexCoord4fv = vbo_TexCoord4fv;
vfmt->Vertex2f = vbo_Vertex2f;
vfmt->Vertex2fv = vbo_Vertex2fv;
vfmt->Vertex3f = vbo_Vertex3f;
vfmt->Vertex3fv = vbo_Vertex3fv;
vfmt->Vertex4f = vbo_Vertex4f;
vfmt->Vertex4fv = vbo_Vertex4fv;
vfmt->VertexAttrib1fARB = vbo_VertexAttrib1fARB;
vfmt->VertexAttrib1fvARB = vbo_VertexAttrib1fvARB;
vfmt->VertexAttrib2fARB = vbo_VertexAttrib2fARB;
vfmt->VertexAttrib2fvARB = vbo_VertexAttrib2fvARB;
vfmt->VertexAttrib3fARB = vbo_VertexAttrib3fARB;
vfmt->VertexAttrib3fvARB = vbo_VertexAttrib3fvARB;
vfmt->VertexAttrib4fARB = vbo_VertexAttrib4fARB;
vfmt->VertexAttrib4fvARB = vbo_VertexAttrib4fvARB;
 
vfmt->VertexAttrib1fNV = vbo_VertexAttrib1fNV;
vfmt->VertexAttrib1fvNV = vbo_VertexAttrib1fvNV;
vfmt->VertexAttrib2fNV = vbo_VertexAttrib2fNV;
vfmt->VertexAttrib2fvNV = vbo_VertexAttrib2fvNV;
vfmt->VertexAttrib3fNV = vbo_VertexAttrib3fNV;
vfmt->VertexAttrib3fvNV = vbo_VertexAttrib3fvNV;
vfmt->VertexAttrib4fNV = vbo_VertexAttrib4fNV;
vfmt->VertexAttrib4fvNV = vbo_VertexAttrib4fvNV;
 
/* integer-valued */
vfmt->VertexAttribI1i = vbo_VertexAttribI1i;
vfmt->VertexAttribI2i = vbo_VertexAttribI2i;
vfmt->VertexAttribI3i = vbo_VertexAttribI3i;
vfmt->VertexAttribI4i = vbo_VertexAttribI4i;
vfmt->VertexAttribI2iv = vbo_VertexAttribI2iv;
vfmt->VertexAttribI3iv = vbo_VertexAttribI3iv;
vfmt->VertexAttribI4iv = vbo_VertexAttribI4iv;
 
/* unsigned integer-valued */
vfmt->VertexAttribI1ui = vbo_VertexAttribI1ui;
vfmt->VertexAttribI2ui = vbo_VertexAttribI2ui;
vfmt->VertexAttribI3ui = vbo_VertexAttribI3ui;
vfmt->VertexAttribI4ui = vbo_VertexAttribI4ui;
vfmt->VertexAttribI2uiv = vbo_VertexAttribI2uiv;
vfmt->VertexAttribI3uiv = vbo_VertexAttribI3uiv;
vfmt->VertexAttribI4uiv = vbo_VertexAttribI4uiv;
 
vfmt->Materialfv = vbo_Materialfv;
 
vfmt->EdgeFlag = vbo_EdgeFlag;
vfmt->Indexf = vbo_Indexf;
vfmt->Indexfv = vbo_Indexfv;
 
}
 
 
#else /* FEATURE_beginend */
 
 
static void vbo_exec_vtxfmt_init( struct vbo_exec_context *exec )
{
/* silence warnings */
(void) vbo_Color3f;
(void) vbo_Color3fv;
(void) vbo_Color4f;
(void) vbo_Color4fv;
(void) vbo_FogCoordfEXT;
(void) vbo_FogCoordfvEXT;
(void) vbo_MultiTexCoord1f;
(void) vbo_MultiTexCoord1fv;
(void) vbo_MultiTexCoord2f;
(void) vbo_MultiTexCoord2fv;
(void) vbo_MultiTexCoord3f;
(void) vbo_MultiTexCoord3fv;
(void) vbo_MultiTexCoord4f;
(void) vbo_MultiTexCoord4fv;
(void) vbo_Normal3f;
(void) vbo_Normal3fv;
(void) vbo_SecondaryColor3fEXT;
(void) vbo_SecondaryColor3fvEXT;
(void) vbo_TexCoord1f;
(void) vbo_TexCoord1fv;
(void) vbo_TexCoord2f;
(void) vbo_TexCoord2fv;
(void) vbo_TexCoord3f;
(void) vbo_TexCoord3fv;
(void) vbo_TexCoord4f;
(void) vbo_TexCoord4fv;
(void) vbo_Vertex2f;
(void) vbo_Vertex2fv;
(void) vbo_Vertex3f;
(void) vbo_Vertex3fv;
(void) vbo_Vertex4f;
(void) vbo_Vertex4fv;
 
(void) vbo_VertexAttrib1fARB;
(void) vbo_VertexAttrib1fvARB;
(void) vbo_VertexAttrib2fARB;
(void) vbo_VertexAttrib2fvARB;
(void) vbo_VertexAttrib3fARB;
(void) vbo_VertexAttrib3fvARB;
(void) vbo_VertexAttrib4fARB;
(void) vbo_VertexAttrib4fvARB;
 
(void) vbo_VertexAttrib1fNV;
(void) vbo_VertexAttrib1fvNV;
(void) vbo_VertexAttrib2fNV;
(void) vbo_VertexAttrib2fvNV;
(void) vbo_VertexAttrib3fNV;
(void) vbo_VertexAttrib3fvNV;
(void) vbo_VertexAttrib4fNV;
(void) vbo_VertexAttrib4fvNV;
 
(void) vbo_Materialfv;
 
(void) vbo_EdgeFlag;
(void) vbo_Indexf;
(void) vbo_Indexfv;
}
 
 
#endif /* FEATURE_beginend */
 
 
/**
* 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;
GLenum target = GL_ARRAY_BUFFER_ARB;
GLenum usage = GL_STREAM_DRAW_ARB;
GLsizei size = VBO_VERT_BUFFER_SIZE;
 
/* Make sure this func is only used once */
assert(exec->vtx.bufferobj == ctx->Shared->NullBufferObj);
if (exec->vtx.buffer_map) {
_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, target);
ctx->Driver.BufferData(ctx, target, size, NULL, usage, exec->vtx.bufferobj);
}
 
 
 
void vbo_exec_vtx_init( struct vbo_exec_context *exec )
{
struct gl_context *ctx = exec->ctx;
struct vbo_context *vbo = vbo_context(ctx);
GLuint i;
 
/* 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);
 
ASSERT(!exec->vtx.buffer_map);
exec->vtx.buffer_map = (GLfloat *)_mesa_align_malloc(VBO_VERT_BUFFER_SIZE, 64);
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
 
vbo_exec_vtxfmt_init( exec );
 
/* Hook our functions into the dispatch table.
*/
_mesa_install_exec_vtxfmt( exec->ctx, &exec->vtxfmt );
 
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
ASSERT(i < Elements(exec->vtx.attrsz));
exec->vtx.attrsz[i] = 0;
ASSERT(i < Elements(exec->vtx.active_sz));
exec->vtx.active_sz[i] = 0;
}
for (i = 0 ; i < VERT_ATTRIB_MAX; i++) {
ASSERT(i < Elements(exec->vtx.inputs));
ASSERT(i < Elements(exec->vtx.arrays));
exec->vtx.inputs[i] = &exec->vtx.arrays[i];
}
{
struct gl_client_array *arrays = exec->vtx.arrays;
unsigned i;
 
memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
 
for (i = 0; i < 16; ++i) {
arrays[i ].BufferObj = NULL;
arrays[i + 16].BufferObj = NULL;
_mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
vbo->legacy_currval[i].BufferObj);
_mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
vbo->generic_currval[i].BufferObj);
}
}
 
exec->vtx.vertex_size = 0;
}
 
 
void vbo_exec_vtx_destroy( struct vbo_exec_context *exec )
{
/* using a real VBO for vertex data */
struct gl_context *ctx = exec->ctx;
unsigned i;
 
/* True VBOs should already be unmapped
*/
if (exec->vtx.buffer_map) {
ASSERT(exec->vtx.bufferobj->Name == 0 ||
exec->vtx.bufferobj->Name == IMM_BUFFER_NAME);
if (exec->vtx.bufferobj->Name == 0) {
_mesa_align_free(exec->vtx.buffer_map);
exec->vtx.buffer_map = NULL;
exec->vtx.buffer_ptr = NULL;
}
}
 
/* Drop any outstanding reference to the vertex buffer
*/
for (i = 0; i < Elements(exec->vtx.arrays); i++) {
_mesa_reference_buffer_object(ctx,
&exec->vtx.arrays[i].BufferObj,
NULL);
}
 
/* Free the vertex buffer. Unmap first if needed.
*/
if (_mesa_bufferobj_mapped(exec->vtx.bufferobj)) {
ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, exec->vtx.bufferobj);
}
_mesa_reference_buffer_object(ctx, &exec->vtx.bufferobj, NULL);
}
 
void vbo_exec_BeginVertices( struct gl_context *ctx )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
if (0) printf("%s\n", __FUNCTION__);
vbo_exec_vtx_map( exec );
 
assert((exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) == 0);
exec->ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
}
 
void vbo_exec_FlushVertices_internal( struct gl_context *ctx, GLboolean unmap )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
if (exec->vtx.vert_count || unmap) {
vbo_exec_vtx_flush( exec, unmap );
}
 
if (exec->vtx.vertex_size) {
vbo_exec_copy_to_current( exec );
reset_attrfv( exec );
}
}
 
 
/**
* \param flags bitmask of FLUSH_STORED_VERTICES, FLUSH_UPDATE_CURRENT
*/
void vbo_exec_FlushVertices( struct gl_context *ctx, GLuint flags )
{
struct vbo_exec_context *exec = &vbo_context(ctx)->exec;
 
#ifdef DEBUG
/* debug check: make sure we don't get called recursively */
exec->flush_call_depth++;
assert(exec->flush_call_depth == 1);
#endif
 
if (0) printf("%s\n", __FUNCTION__);
 
if (exec->ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
if (0) printf("%s - inside begin/end\n", __FUNCTION__);
#ifdef DEBUG
exec->flush_call_depth--;
assert(exec->flush_call_depth == 0);
#endif
return;
}
 
vbo_exec_FlushVertices_internal( ctx, GL_TRUE );
 
/* Need to do this to ensure BeginVertices gets called again:
*/
if (exec->ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
exec->ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
 
exec->ctx->Driver.NeedFlush &= ~flags;
 
#ifdef DEBUG
exec->flush_call_depth--;
assert(exec->flush_call_depth == 0);
#endif
}
 
 
static void reset_attrfv( struct vbo_exec_context *exec )
{
GLuint i;
 
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
exec->vtx.attrsz[i] = 0;
exec->vtx.active_sz[i] = 0;
}
 
exec->vtx.vertex_size = 0;
}
 
void GLAPIENTRY
_es_Color4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a)
{
vbo_Color4f(r, g, b, a);
}
 
 
void GLAPIENTRY
_es_Normal3f(GLfloat x, GLfloat y, GLfloat z)
{
vbo_Normal3f(x, y, z);
}
 
 
void GLAPIENTRY
_es_MultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
{
vbo_MultiTexCoord4f(target, s, t, r, q);
}
 
 
void GLAPIENTRY
_es_Materialfv(GLenum face, GLenum pname, const GLfloat *params)
{
vbo_Materialfv(face, pname, params);
}
 
 
void GLAPIENTRY
_es_Materialf(GLenum face, GLenum pname, GLfloat param)
{
GLfloat p[4];
p[0] = param;
p[1] = p[2] = p[3] = 0.0F;
vbo_Materialfv(face, pname, p);
}
 
 
/**
* A special version of glVertexAttrib4f that does not treat index 0 as
* VBO_ATTRIB_POS.
*/
static void
VertexAttrib4f_nopos(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GET_CURRENT_CONTEXT(ctx);
if (index < MAX_VERTEX_GENERIC_ATTRIBS)
ATTR(VBO_ATTRIB_GENERIC0 + index, 4, x, y, z, w);
else
ERROR();
}
 
void GLAPIENTRY
_es_VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
VertexAttrib4f_nopos(index, x, y, z, w);
}
 
 
void GLAPIENTRY
_es_VertexAttrib1f(GLuint indx, GLfloat x)
{
VertexAttrib4f_nopos(indx, x, 0.0f, 0.0f, 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib1fv(GLuint indx, const GLfloat* values)
{
VertexAttrib4f_nopos(indx, values[0], 0.0f, 0.0f, 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
{
VertexAttrib4f_nopos(indx, x, y, 0.0f, 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib2fv(GLuint indx, const GLfloat* values)
{
VertexAttrib4f_nopos(indx, values[0], values[1], 0.0f, 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
{
VertexAttrib4f_nopos(indx, x, y, z, 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib3fv(GLuint indx, const GLfloat* values)
{
VertexAttrib4f_nopos(indx, values[0], values[1], values[2], 1.0f);
}
 
 
void GLAPIENTRY
_es_VertexAttrib4fv(GLuint indx, const GLfloat* values)
{
VertexAttrib4f_nopos(indx, values[0], values[1], values[2], values[3]);
}
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec_array.c
0,0 → 1,1277
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "main/glheader.h"
#include "main/context.h"
#include "main/state.h"
#include "main/api_validate.h"
#include "main/varray.h"
#include "main/bufferobj.h"
#include "main/enums.h"
#include "main/macros.h"
 
#include "vbo_context.h"
 
 
/**
* Compute min and max elements by scanning the index buffer for
* glDraw[Range]Elements() calls.
* If primitive restart is enabled, we need to ignore restart
* indexes when computing min/max.
*/
void
vbo_get_minmax_index(struct gl_context *ctx,
const struct _mesa_prim *prim,
const struct _mesa_index_buffer *ib,
GLuint *min_index, GLuint *max_index)
{
const GLboolean restart = ctx->Array.PrimitiveRestart;
const GLuint restartIndex = ctx->Array.RestartIndex;
const GLuint count = prim->count;
const void *indices;
GLuint i;
 
if (_mesa_is_bufferobj(ib->obj)) {
const GLvoid *map =
ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
GL_READ_ONLY, ib->obj);
indices = ADD_POINTERS(map, ib->ptr);
} else {
indices = ib->ptr;
}
 
switch (ib->type) {
case GL_UNSIGNED_INT: {
const GLuint *ui_indices = (const GLuint *)indices;
GLuint max_ui = 0;
GLuint min_ui = ~0U;
if (restart) {
for (i = 0; i < count; i++) {
if (ui_indices[i] != restartIndex) {
if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
}
}
}
else {
for (i = 0; i < count; i++) {
if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
}
}
*min_index = min_ui;
*max_index = max_ui;
break;
}
case GL_UNSIGNED_SHORT: {
const GLushort *us_indices = (const GLushort *)indices;
GLuint max_us = 0;
GLuint min_us = ~0U;
if (restart) {
for (i = 0; i < count; i++) {
if (us_indices[i] != restartIndex) {
if (us_indices[i] > max_us) max_us = us_indices[i];
if (us_indices[i] < min_us) min_us = us_indices[i];
}
}
}
else {
for (i = 0; i < count; i++) {
if (us_indices[i] > max_us) max_us = us_indices[i];
if (us_indices[i] < min_us) min_us = us_indices[i];
}
}
*min_index = min_us;
*max_index = max_us;
break;
}
case GL_UNSIGNED_BYTE: {
const GLubyte *ub_indices = (const GLubyte *)indices;
GLuint max_ub = 0;
GLuint min_ub = ~0U;
if (restart) {
for (i = 0; i < count; i++) {
if (ub_indices[i] != restartIndex) {
if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
}
}
}
else {
for (i = 0; i < count; i++) {
if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
}
}
*min_index = min_ub;
*max_index = max_ub;
break;
}
default:
assert(0);
break;
}
 
if (_mesa_is_bufferobj(ib->obj)) {
ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ib->obj);
}
}
 
 
/**
* Check that element 'j' of the array has reasonable data.
* Map VBO if needed.
* For debugging purposes; not normally used.
*/
static void
check_array_data(struct gl_context *ctx, struct gl_client_array *array,
GLuint attrib, GLuint j)
{
if (array->Enabled) {
const void *data = array->Ptr;
if (_mesa_is_bufferobj(array->BufferObj)) {
if (!array->BufferObj->Pointer) {
/* need to map now */
array->BufferObj->Pointer =
ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
GL_READ_ONLY, array->BufferObj);
}
data = ADD_POINTERS(data, array->BufferObj->Pointer);
}
switch (array->Type) {
case GL_FLOAT:
{
GLfloat *f = (GLfloat *) ((GLubyte *) data + array->StrideB * j);
GLint k;
for (k = 0; k < array->Size; k++) {
if (IS_INF_OR_NAN(f[k]) ||
f[k] >= 1.0e20 || f[k] <= -1.0e10) {
printf("Bad array data:\n");
printf(" Element[%u].%u = %f\n", j, k, f[k]);
printf(" Array %u at %p\n", attrib, (void* ) array);
printf(" Type 0x%x, Size %d, Stride %d\n",
array->Type, array->Size, array->Stride);
printf(" Address/offset %p in Buffer Object %u\n",
array->Ptr, array->BufferObj->Name);
f[k] = 1.0; /* XXX replace the bad value! */
}
/*assert(!IS_INF_OR_NAN(f[k]));*/
}
}
break;
default:
;
}
}
}
 
 
/**
* Unmap the buffer object referenced by given array, if mapped.
*/
static void
unmap_array_buffer(struct gl_context *ctx, struct gl_client_array *array)
{
if (array->Enabled &&
_mesa_is_bufferobj(array->BufferObj) &&
_mesa_bufferobj_mapped(array->BufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, array->BufferObj);
}
}
 
 
/**
* Examine the array's data for NaNs, etc.
* For debug purposes; not normally used.
*/
static void
check_draw_elements_data(struct gl_context *ctx, GLsizei count, GLenum elemType,
const void *elements, GLint basevertex)
{
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
const void *elemMap;
GLint i, k;
 
if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
elemMap = ctx->Driver.MapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
GL_READ_ONLY,
ctx->Array.ElementArrayBufferObj);
elements = ADD_POINTERS(elements, elemMap);
}
 
for (i = 0; i < count; i++) {
GLuint j;
 
/* j = element[i] */
switch (elemType) {
case GL_UNSIGNED_BYTE:
j = ((const GLubyte *) elements)[i];
break;
case GL_UNSIGNED_SHORT:
j = ((const GLushort *) elements)[i];
break;
case GL_UNSIGNED_INT:
j = ((const GLuint *) elements)[i];
break;
default:
assert(0);
}
 
/* check element j of each enabled array */
check_array_data(ctx, &arrayObj->Vertex, VERT_ATTRIB_POS, j);
check_array_data(ctx, &arrayObj->Normal, VERT_ATTRIB_NORMAL, j);
check_array_data(ctx, &arrayObj->Color, VERT_ATTRIB_COLOR0, j);
check_array_data(ctx, &arrayObj->SecondaryColor, VERT_ATTRIB_COLOR1, j);
for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
check_array_data(ctx, &arrayObj->TexCoord[k], VERT_ATTRIB_TEX0 + k, j);
}
for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
check_array_data(ctx, &arrayObj->VertexAttrib[k],
VERT_ATTRIB_GENERIC0 + k, j);
}
}
 
if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj)) {
ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
ctx->Array.ElementArrayBufferObj);
}
 
unmap_array_buffer(ctx, &arrayObj->Vertex);
unmap_array_buffer(ctx, &arrayObj->Normal);
unmap_array_buffer(ctx, &arrayObj->Color);
for (k = 0; k < Elements(arrayObj->TexCoord); k++) {
unmap_array_buffer(ctx, &arrayObj->TexCoord[k]);
}
for (k = 0; k < Elements(arrayObj->VertexAttrib); k++) {
unmap_array_buffer(ctx, &arrayObj->VertexAttrib[k]);
}
}
 
 
/**
* Check array data, looking for NaNs, etc.
*/
static void
check_draw_arrays_data(struct gl_context *ctx, GLint start, GLsizei count)
{
/* TO DO */
}
 
 
/**
* Print info/data for glDrawArrays(), for debugging.
*/
static void
print_draw_arrays(struct gl_context *ctx,
GLenum mode, GLint start, GLsizei count)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
int i;
 
printf("vbo_exec_DrawArrays(mode 0x%x, start %d, count %d):\n",
mode, start, count);
 
for (i = 0; i < 32; i++) {
GLuint bufName = exec->array.inputs[i]->BufferObj->Name;
GLint stride = exec->array.inputs[i]->Stride;
printf("attr %2d: size %d stride %d enabled %d "
"ptr %p Bufobj %u\n",
i,
exec->array.inputs[i]->Size,
stride,
/*exec->array.inputs[i]->Enabled,*/
exec->array.legacy_array[i]->Enabled,
exec->array.inputs[i]->Ptr,
bufName);
 
if (bufName) {
struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, bufName);
GLubyte *p = ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
GL_READ_ONLY_ARB, buf);
int offset = (int) (GLintptr) exec->array.inputs[i]->Ptr;
float *f = (float *) (p + offset);
int *k = (int *) f;
int i;
int n = (count * stride) / 4;
if (n > 32)
n = 32;
printf(" Data at offset %d:\n", offset);
for (i = 0; i < n; i++) {
printf(" float[%d] = 0x%08x %f\n", i, k[i], f[i]);
}
ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB, buf);
}
}
}
 
 
/**
* Bind the VBO executor to the current vertex array object prior
* to drawing.
*
* Just translate the arrayobj into a sane layout.
*/
static void
bind_array_obj(struct gl_context *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct gl_array_object *arrayObj = ctx->Array.ArrayObj;
GLuint i;
 
/* TODO: Fix the ArrayObj struct to keep legacy arrays in an array
* rather than as individual named arrays. Then this function can
* go away.
*/
exec->array.legacy_array[VERT_ATTRIB_POS] = &arrayObj->Vertex;
exec->array.legacy_array[VERT_ATTRIB_WEIGHT] = &arrayObj->Weight;
exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &arrayObj->Normal;
exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &arrayObj->Color;
exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &arrayObj->SecondaryColor;
exec->array.legacy_array[VERT_ATTRIB_FOG] = &arrayObj->FogCoord;
exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &arrayObj->Index;
if (arrayObj->PointSize.Enabled) {
/* this aliases COLOR_INDEX */
exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &arrayObj->PointSize;
}
exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &arrayObj->EdgeFlag;
 
for (i = 0; i < Elements(arrayObj->TexCoord); i++)
exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &arrayObj->TexCoord[i];
 
for (i = 0; i < Elements(arrayObj->VertexAttrib); i++) {
assert(i < Elements(exec->array.generic_array));
exec->array.generic_array[i] = &arrayObj->VertexAttrib[i];
}
exec->array.array_obj = arrayObj->Name;
}
 
 
/**
* Set the vbo->exec->inputs[] pointers to point to the enabled
* vertex arrays. This depends on the current vertex program/shader
* being executed because of whether or not generic vertex arrays
* alias the conventional vertex arrays.
* For arrays that aren't enabled, we set the input[attrib] pointer
* to point at a zero-stride current value "array".
*/
static void
recalculate_input_bindings(struct gl_context *ctx)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
const struct gl_client_array **inputs = &exec->array.inputs[0];
GLbitfield const_inputs = 0x0;
GLuint i;
 
exec->array.program_mode = get_program_mode(ctx);
exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled;
 
switch (exec->array.program_mode) {
case VP_NONE:
/* When no vertex program is active (or the vertex program is generated
* from fixed-function state). We put the material values into the
* generic slots. This is the only situation where material values
* are available as per-vertex attributes.
*/
for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
else {
inputs[i] = &vbo->legacy_currval[i];
const_inputs |= 1 << i;
}
}
 
for (i = 0; i < MAT_ATTRIB_MAX; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i];
const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
 
/* Could use just about anything, just to fill in the empty
* slots:
*/
for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
break;
 
case VP_NV:
/* NV_vertex_program - attribute arrays alias and override
* conventional, legacy arrays. No materials, and the generic
* slots are vacant.
*/
for (i = 0; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.generic_array[i]->Enabled)
inputs[i] = exec->array.generic_array[i];
else if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
else {
inputs[i] = &vbo->legacy_currval[i];
const_inputs |= 1 << i;
}
}
 
/* Could use just about anything, just to fill in the empty
* slots:
*/
for (i = VERT_ATTRIB_GENERIC0; i < VERT_ATTRIB_MAX; i++) {
inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0];
const_inputs |= 1 << i;
}
break;
 
case VP_ARB:
/* GL_ARB_vertex_program or GLSL vertex shader - Only the generic[0]
* attribute array aliases and overrides the legacy position array.
*
* Otherwise, legacy attributes available in the legacy slots,
* generic attributes in the generic slots and materials are not
* available as per-vertex attributes.
*/
if (exec->array.generic_array[0]->Enabled)
inputs[0] = exec->array.generic_array[0];
else if (exec->array.legacy_array[0]->Enabled)
inputs[0] = exec->array.legacy_array[0];
else {
inputs[0] = &vbo->legacy_currval[0];
const_inputs |= 1 << 0;
}
 
for (i = 1; i <= VERT_ATTRIB_TEX7; i++) {
if (exec->array.legacy_array[i]->Enabled)
inputs[i] = exec->array.legacy_array[i];
else {
inputs[i] = &vbo->legacy_currval[i];
const_inputs |= 1 << i;
}
}
 
for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) {
if (exec->array.generic_array[i]->Enabled)
inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i];
else {
inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i];
const_inputs |= 1 << (VERT_ATTRIB_GENERIC0 + i);
}
 
}
break;
}
 
_mesa_set_varying_vp_inputs( ctx, ~const_inputs );
}
 
 
/**
* Examine the enabled vertex arrays to set the exec->array.inputs[] values.
* These will point to the arrays to actually use for drawing. Some will
* be user-provided arrays, other will be zero-stride const-valued arrays.
* Note that this might set the _NEW_ARRAY dirty flag so state validation
* must be done after this call.
*/
static void
bind_arrays(struct gl_context *ctx)
{
bind_array_obj(ctx);
recalculate_input_bindings(ctx);
}
 
 
/**
* Helper function called by the other DrawArrays() functions below.
* This is where we handle primitive restart for drawing non-indexed
* arrays. If primitive restart is enabled, it typically means
* splitting one DrawArrays() into two.
*/
static void
vbo_draw_arrays(struct gl_context *ctx, GLenum mode, GLint start,
GLsizei count, GLuint numInstances)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_prim prim[2];
 
bind_arrays(ctx);
 
/* Again... because we may have changed the bitmask of per-vertex varying
* attributes. If we regenerate the fixed-function vertex program now
* we may be able to prune down the number of vertex attributes which we
* need in the shader.
*/
if (ctx->NewState)
_mesa_update_state(ctx);
 
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
prim[0].pad = 0;
prim[0].mode = mode;
prim[0].start = 0; /* filled in below */
prim[0].count = 0; /* filled in below */
prim[0].indexed = 0;
prim[0].basevertex = 0;
prim[0].num_instances = numInstances;
 
/* Implement the primitive restart index */
if (ctx->Array.PrimitiveRestart && ctx->Array.RestartIndex < count) {
GLuint primCount = 0;
 
if (ctx->Array.RestartIndex == start) {
/* special case: RestartIndex at beginning */
if (count > 1) {
prim[0].start = start + 1;
prim[0].count = count - 1;
primCount = 1;
}
}
else if (ctx->Array.RestartIndex == start + count - 1) {
/* special case: RestartIndex at end */
if (count > 1) {
prim[0].start = start;
prim[0].count = count - 1;
primCount = 1;
}
}
else {
/* general case: RestartIndex in middle, split into two prims */
prim[0].start = start;
prim[0].count = ctx->Array.RestartIndex - start;
 
prim[1] = prim[0];
prim[1].start = ctx->Array.RestartIndex + 1;
prim[1].count = count - prim[1].start;
 
primCount = 2;
}
 
if (primCount > 0) {
/* draw one or two prims */
vbo->draw_prims(ctx, exec->array.inputs, prim, primCount, NULL,
GL_TRUE, start, start + count - 1);
}
}
else {
/* no prim restart */
prim[0].start = start;
prim[0].count = count;
 
vbo->draw_prims(ctx, exec->array.inputs, prim, 1, NULL,
GL_TRUE, start, start + count - 1);
}
}
 
 
 
/**
* Called from glDrawArrays when in immediate mode (not display list mode).
*/
static void GLAPIENTRY
vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx, "glDrawArrays(%s, %d, %d)\n",
_mesa_lookup_enum_by_nr(mode), start, count);
 
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
 
FLUSH_CURRENT( ctx, 0 );
 
if (!_mesa_valid_to_render(ctx, "glDrawArrays")) {
return;
}
 
if (0)
check_draw_arrays_data(ctx, start, count);
 
vbo_draw_arrays(ctx, mode, start, count, 1);
 
if (0)
print_draw_arrays(ctx, mode, start, count);
}
 
 
/**
* Called from glDrawArraysInstanced when in immediate mode (not
* display list mode).
*/
static void GLAPIENTRY
vbo_exec_DrawArraysInstanced(GLenum mode, GLint start, GLsizei count,
GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx, "glDrawArraysInstanced(%s, %d, %d, %d)\n",
_mesa_lookup_enum_by_nr(mode), start, count, primcount);
 
if (!_mesa_validate_DrawArraysInstanced(ctx, mode, start, count, primcount))
return;
 
FLUSH_CURRENT( ctx, 0 );
 
if (!_mesa_valid_to_render(ctx, "glDrawArraysInstanced")) {
return;
}
 
if (0)
check_draw_arrays_data(ctx, start, count);
 
vbo_draw_arrays(ctx, mode, start, count, primcount);
 
if (0)
print_draw_arrays(ctx, mode, start, count);
}
 
 
/**
* Map GL_ELEMENT_ARRAY_BUFFER and print contents.
* For debugging.
*/
static void
dump_element_buffer(struct gl_context *ctx, GLenum type)
{
const GLvoid *map = ctx->Driver.MapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER_ARB,
GL_READ_ONLY,
ctx->Array.ElementArrayBufferObj);
switch (type) {
case GL_UNSIGNED_BYTE:
{
const GLubyte *us = (const GLubyte *) map;
GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size; i++) {
printf("%02x ", us[i]);
if (i % 32 == 31)
printf("\n");
}
printf("\n");
}
break;
case GL_UNSIGNED_SHORT:
{
const GLushort *us = (const GLushort *) map;
GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 2; i++) {
printf("%04x ", us[i]);
if (i % 16 == 15)
printf("\n");
}
printf("\n");
}
break;
case GL_UNSIGNED_INT:
{
const GLuint *us = (const GLuint *) map;
GLint i;
for (i = 0; i < ctx->Array.ElementArrayBufferObj->Size / 4; i++) {
printf("%08x ", us[i]);
if (i % 8 == 7)
printf("\n");
}
printf("\n");
}
break;
default:
;
}
 
ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB,
ctx->Array.ElementArrayBufferObj);
}
 
 
/**
* Inner support for both _mesa_DrawElements and _mesa_DrawRangeElements.
* Do the rendering for a glDrawElements or glDrawRangeElements call after
* we've validated buffer bounds, etc.
*/
static void
vbo_validated_drawrangeelements(struct gl_context *ctx, GLenum mode,
GLboolean index_bounds_valid,
GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices,
GLint basevertex, GLint primcount)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
struct _mesa_prim prim[1];
 
FLUSH_CURRENT( ctx, 0 );
 
if (!_mesa_valid_to_render(ctx, "glDraw[Range]Elements")) {
return;
}
 
bind_arrays( ctx );
 
/* check for dirty state again */
if (ctx->NewState)
_mesa_update_state( ctx );
 
ib.count = count;
ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = indices;
 
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
prim[0].pad = 0;
prim[0].mode = mode;
prim[0].start = 0;
prim[0].count = count;
prim[0].indexed = 1;
prim[0].basevertex = basevertex;
prim[0].num_instances = primcount;
 
/* Need to give special consideration to rendering a range of
* indices starting somewhere above zero. Typically the
* application is issuing multiple DrawRangeElements() to draw
* successive primitives layed out linearly in the vertex arrays.
* Unless the vertex arrays are all in a VBO (or locked as with
* CVA), the OpenGL semantics imply that we need to re-read or
* re-upload the vertex data on each draw call.
*
* In the case of hardware tnl, we want to avoid starting the
* upload at zero, as it will mean every draw call uploads an
* increasing amount of not-used vertex data. Worse - in the
* software tnl module, all those vertices might be transformed and
* lit but never rendered.
*
* If we just upload or transform the vertices in start..end,
* however, the indices will be incorrect.
*
* At this level, we don't know exactly what the requirements of
* the backend are going to be, though it will likely boil down to
* either:
*
* 1) Do nothing, everything is in a VBO and is processed once
* only.
*
* 2) Adjust the indices and vertex arrays so that start becomes
* zero.
*
* Rather than doing anything here, I'll provide a helper function
* for the latter case elsewhere.
*/
 
vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib,
index_bounds_valid, start, end );
}
 
 
/**
* Called by glDrawRangeElementsBaseVertex() in immediate mode.
*/
static void GLAPIENTRY
vbo_exec_DrawRangeElementsBaseVertex(GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices,
GLint basevertex)
{
static GLuint warnCount = 0;
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx,
"glDrawRangeElementsBaseVertex(%s, %u, %u, %d, %s, %p, %d)\n",
_mesa_lookup_enum_by_nr(mode), start, end, count,
_mesa_lookup_enum_by_nr(type), indices, basevertex);
 
if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
type, indices, basevertex ))
return;
 
/* NOTE: It's important that 'end' is a reasonable value.
* in _tnl_draw_prims(), we use end to determine how many vertices
* to transform. If it's too large, we can unnecessarily split prims
* or we can read/write out of memory in several different places!
*/
 
/* Catch/fix some potential user errors */
if (type == GL_UNSIGNED_BYTE) {
start = MIN2(start, 0xff);
end = MIN2(end, 0xff);
}
else if (type == GL_UNSIGNED_SHORT) {
start = MIN2(start, 0xffff);
end = MIN2(end, 0xffff);
}
 
if (end >= ctx->Array.ArrayObj->_MaxElement) {
/* the max element is out of bounds of one or more enabled arrays */
warnCount++;
 
if (warnCount < 10) {
_mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, count %d, "
"type 0x%x, indices=%p)\n"
"\tend is out of bounds (max=%u) "
"Element Buffer %u (size %d)\n"
"\tThis should probably be fixed in the application.",
start, end, count, type, indices,
ctx->Array.ArrayObj->_MaxElement - 1,
ctx->Array.ElementArrayBufferObj->Name,
(int) ctx->Array.ElementArrayBufferObj->Size);
}
 
if (0)
dump_element_buffer(ctx, type);
 
if (0)
_mesa_print_arrays(ctx);
 
#ifdef DEBUG
/* 'end' was out of bounds, but now let's check the actual array
* indexes to see if any of them are out of bounds.
*/
{
GLuint max = _mesa_max_buffer_index(ctx, count, type, indices,
ctx->Array.ElementArrayBufferObj);
if (max >= ctx->Array.ArrayObj->_MaxElement) {
if (warnCount < 10) {
_mesa_warning(ctx, "glDraw[Range]Elements(start %u, end %u, "
"count %d, type 0x%x, indices=%p)\n"
"\tindex=%u is out of bounds (max=%u) "
"Element Buffer %u (size %d)\n"
"\tSkipping the glDrawRangeElements() call",
start, end, count, type, indices, max,
ctx->Array.ArrayObj->_MaxElement - 1,
ctx->Array.ElementArrayBufferObj->Name,
(int) ctx->Array.ElementArrayBufferObj->Size);
}
}
/* XXX we could also find the min index and compare to 'start'
* to see if start is correct. But it's more likely to get the
* upper bound wrong.
*/
}
#endif
 
/* Set 'end' to the max possible legal value */
assert(ctx->Array.ArrayObj->_MaxElement >= 1);
end = ctx->Array.ArrayObj->_MaxElement - 1;
}
else if (0) {
printf("glDraw[Range]Elements{,BaseVertex}"
"(start %u, end %u, type 0x%x, count %d) ElemBuf %u, "
"base %d\n",
start, end, type, count,
ctx->Array.ElementArrayBufferObj->Name,
basevertex);
}
 
#if 0
check_draw_elements_data(ctx, count, type, indices);
#else
(void) check_draw_elements_data;
#endif
 
vbo_validated_drawrangeelements(ctx, mode, GL_TRUE, start, end,
count, type, indices, basevertex, 1);
}
 
 
/**
* Called by glDrawRangeElements() in immediate mode.
*/
static void GLAPIENTRY
vbo_exec_DrawRangeElements(GLenum mode, GLuint start, GLuint end,
GLsizei count, GLenum type, const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx,
"glDrawRangeElements(%s, %u, %u, %d, %s, %p)\n",
_mesa_lookup_enum_by_nr(mode), start, end, count,
_mesa_lookup_enum_by_nr(type), indices);
 
vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
indices, 0);
}
 
 
/**
* Called by glDrawElements() in immediate mode.
*/
static void GLAPIENTRY
vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx, "glDrawElements(%s, %u, %s, %p)\n",
_mesa_lookup_enum_by_nr(mode), count,
_mesa_lookup_enum_by_nr(type), indices);
 
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
return;
 
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
count, type, indices, 0, 1);
}
 
 
/**
* Called by glDrawElementsBaseVertex() in immediate mode.
*/
static void GLAPIENTRY
vbo_exec_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx, "glDrawElementsBaseVertex(%s, %d, %s, %p, %d)\n",
_mesa_lookup_enum_by_nr(mode), count,
_mesa_lookup_enum_by_nr(type), indices, basevertex);
 
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices,
basevertex ))
return;
 
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
count, type, indices, basevertex, 1);
}
 
 
/**
* Called by glDrawElementsInstanced() in immediate mode.
*/
static void GLAPIENTRY
vbo_exec_DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
 
if (MESA_VERBOSE & VERBOSE_DRAW)
_mesa_debug(ctx, "glDrawElementsInstanced(%s, %d, %s, %p, %d)\n",
_mesa_lookup_enum_by_nr(mode), count,
_mesa_lookup_enum_by_nr(type), indices, primcount);
 
if (!_mesa_validate_DrawElementsInstanced(ctx, mode, count, type, indices,
primcount))
return;
 
vbo_validated_drawrangeelements(ctx, mode, GL_FALSE, ~0, ~0,
count, type, indices, 0, primcount);
}
 
 
/**
* Inner support for both _mesa_MultiDrawElements() and
* _mesa_MultiDrawRangeElements().
* This does the actual rendering after we've checked array indexes, etc.
*/
static void
vbo_validated_multidrawelements(struct gl_context *ctx, GLenum mode,
const GLsizei *count, GLenum type,
const GLvoid **indices, GLsizei primcount,
const GLint *basevertex)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct _mesa_index_buffer ib;
struct _mesa_prim *prim;
unsigned int index_type_size = 0;
uintptr_t min_index_ptr, max_index_ptr;
GLboolean fallback = GL_FALSE;
int i;
 
if (primcount == 0)
return;
 
FLUSH_CURRENT( ctx, 0 );
 
if (!_mesa_valid_to_render(ctx, "glMultiDrawElements")) {
return;
}
 
prim = calloc(1, primcount * sizeof(*prim));
if (prim == NULL) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glMultiDrawElements");
return;
}
 
/* Decide if we can do this all as one set of primitives sharing the
* same index buffer, or if we have to reset the index pointer per
* primitive.
*/
bind_arrays( ctx );
 
/* check for dirty state again */
if (ctx->NewState)
_mesa_update_state( ctx );
 
switch (type) {
case GL_UNSIGNED_INT:
index_type_size = 4;
break;
case GL_UNSIGNED_SHORT:
index_type_size = 2;
break;
case GL_UNSIGNED_BYTE:
index_type_size = 1;
break;
default:
assert(0);
}
 
min_index_ptr = (uintptr_t)indices[0];
max_index_ptr = 0;
for (i = 0; i < primcount; i++) {
min_index_ptr = MIN2(min_index_ptr, (uintptr_t)indices[i]);
max_index_ptr = MAX2(max_index_ptr, (uintptr_t)indices[i] +
index_type_size * count[i]);
}
 
/* Check if we can handle this thing as a bunch of index offsets from the
* same index pointer. If we can't, then we have to fall back to doing
* a draw_prims per primitive.
* Check that the difference between each prim's indexes is a multiple of
* the index/element size.
*/
if (index_type_size != 1) {
for (i = 0; i < primcount; i++) {
if ((((uintptr_t)indices[i] - min_index_ptr) % index_type_size) != 0) {
fallback = GL_TRUE;
break;
}
}
}
 
/* If the index buffer isn't in a VBO, then treating the application's
* subranges of the index buffer as one large index buffer may lead to
* us reading unmapped memory.
*/
if (!_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
fallback = GL_TRUE;
 
if (!fallback) {
ib.count = (max_index_ptr - min_index_ptr) / index_type_size;
ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = (void *)min_index_ptr;
 
for (i = 0; i < primcount; i++) {
prim[i].begin = (i == 0);
prim[i].end = (i == primcount - 1);
prim[i].weak = 0;
prim[i].pad = 0;
prim[i].mode = mode;
prim[i].start = ((uintptr_t)indices[i] - min_index_ptr) / index_type_size;
prim[i].count = count[i];
prim[i].indexed = 1;
prim[i].num_instances = 1;
if (basevertex != NULL)
prim[i].basevertex = basevertex[i];
else
prim[i].basevertex = 0;
}
 
vbo->draw_prims(ctx, exec->array.inputs, prim, primcount, &ib,
GL_FALSE, ~0, ~0);
} else {
/* render one prim at a time */
for (i = 0; i < primcount; i++) {
ib.count = count[i];
ib.type = type;
ib.obj = ctx->Array.ElementArrayBufferObj;
ib.ptr = indices[i];
 
prim[0].begin = 1;
prim[0].end = 1;
prim[0].weak = 0;
prim[0].pad = 0;
prim[0].mode = mode;
prim[0].start = 0;
prim[0].count = count[i];
prim[0].indexed = 1;
prim[0].num_instances = 1;
if (basevertex != NULL)
prim[0].basevertex = basevertex[i];
else
prim[0].basevertex = 0;
 
vbo->draw_prims(ctx, exec->array.inputs, prim, 1, &ib,
GL_FALSE, ~0, ~0);
}
}
 
free(prim);
}
 
 
static void GLAPIENTRY
vbo_exec_MultiDrawElements(GLenum mode,
const GLsizei *count, GLenum type,
const GLvoid **indices,
GLsizei primcount)
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
 
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
for (i = 0; i < primcount; i++) {
if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
0))
return;
}
 
vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
NULL);
}
 
 
static void GLAPIENTRY
vbo_exec_MultiDrawElementsBaseVertex(GLenum mode,
const GLsizei *count, GLenum type,
const GLvoid **indices,
GLsizei primcount,
const GLsizei *basevertex)
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
 
ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
 
for (i = 0; i < primcount; i++) {
if (!_mesa_validate_DrawElements(ctx, mode, count[i], type, indices[i],
basevertex[i]))
return;
}
 
vbo_validated_multidrawelements(ctx, mode, count, type, indices, primcount,
basevertex);
}
 
 
/**
* Plug in the immediate-mode vertex array drawing commands into the
* givven vbo_exec_context object.
*/
void
vbo_exec_array_init( struct vbo_exec_context *exec )
{
exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays;
exec->vtxfmt.DrawElements = vbo_exec_DrawElements;
exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements;
exec->vtxfmt.MultiDrawElementsEXT = vbo_exec_MultiDrawElements;
exec->vtxfmt.DrawElementsBaseVertex = vbo_exec_DrawElementsBaseVertex;
exec->vtxfmt.DrawRangeElementsBaseVertex = vbo_exec_DrawRangeElementsBaseVertex;
exec->vtxfmt.MultiDrawElementsBaseVertex = vbo_exec_MultiDrawElementsBaseVertex;
exec->vtxfmt.DrawArraysInstanced = vbo_exec_DrawArraysInstanced;
exec->vtxfmt.DrawElementsInstanced = vbo_exec_DrawElementsInstanced;
}
 
 
void
vbo_exec_array_destroy( struct vbo_exec_context *exec )
{
/* nothing to do */
}
 
 
 
/**
* The following functions are only used for OpenGL ES 1/2 support.
* And some aren't even supported (yet) in ES 1/2.
*/
 
 
void GLAPIENTRY
_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count)
{
vbo_exec_DrawArrays(mode, first, count);
}
 
 
void GLAPIENTRY
_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
vbo_exec_DrawElements(mode, count, type, indices);
}
 
 
void GLAPIENTRY
_mesa_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLint basevertex)
{
vbo_exec_DrawElementsBaseVertex(mode, count, type, indices, basevertex);
}
 
 
void GLAPIENTRY
_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count,
GLenum type, const GLvoid *indices)
{
vbo_exec_DrawRangeElements(mode, start, end, count, type, indices);
}
 
 
void GLAPIENTRY
_mesa_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices, GLint basevertex)
{
vbo_exec_DrawRangeElementsBaseVertex(mode, start, end, count, type,
indices, basevertex);
}
 
 
void GLAPIENTRY
_mesa_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
const GLvoid **indices, GLsizei primcount)
{
vbo_exec_MultiDrawElements(mode, count, type, indices, primcount);
}
 
 
void GLAPIENTRY
_mesa_MultiDrawElementsBaseVertex(GLenum mode,
const GLsizei *count, GLenum type,
const GLvoid **indices, GLsizei primcount,
const GLint *basevertex)
{
vbo_exec_MultiDrawElementsBaseVertex(mode, count, type, indices,
primcount, basevertex);
}
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec_draw.c
0,0 → 1,419
/*
* Mesa 3-D graphics library
* Version: 7.2
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/compiler.h"
#include "main/enums.h"
#include "main/state.h"
 
#include "vbo_context.h"
 
 
#if FEATURE_beginend
 
 
static void
vbo_exec_debug_verts( struct vbo_exec_context *exec )
{
GLuint count = exec->vtx.vert_count;
GLuint i;
 
printf("%s: %u vertices %d primitives, %d vertsize\n",
__FUNCTION__,
count,
exec->vtx.prim_count,
exec->vtx.vertex_size);
 
for (i = 0 ; i < exec->vtx.prim_count ; i++) {
struct _mesa_prim *prim = &exec->vtx.prim[i];
printf(" prim %d: %s%s %d..%d %s %s\n",
i,
_mesa_lookup_prim_by_nr(prim->mode),
prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
prim->begin ? "BEGIN" : "(wrap)",
prim->end ? "END" : "(wrap)");
}
}
 
 
/*
* NOTE: Need to have calculated primitives by this point -- do it on the fly.
* NOTE: Old 'parity' issue is gone.
*/
static GLuint
vbo_copy_vertices( struct vbo_exec_context *exec )
{
GLuint nr = exec->vtx.prim[exec->vtx.prim_count-1].count;
GLuint ovf, i;
GLuint sz = exec->vtx.vertex_size;
GLfloat *dst = exec->vtx.copied.buffer;
const GLfloat *src = (exec->vtx.buffer_map +
exec->vtx.prim[exec->vtx.prim_count-1].start *
exec->vtx.vertex_size);
 
 
switch (exec->ctx->Driver.CurrentExecPrimitive) {
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case GL_TRIANGLES:
ovf = nr%3;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case GL_QUADS:
ovf = nr&3;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case GL_LINE_STRIP:
if (nr == 0) {
return 0;
}
else {
memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 1;
}
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0) {
return 0;
}
else if (nr == 1) {
memcpy( dst, src+0, sz * sizeof(GLfloat) );
return 1;
}
else {
memcpy( dst, src+0, sz * sizeof(GLfloat) );
memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) );
return 2;
}
case GL_TRIANGLE_STRIP:
/* no parity issue, but need to make sure the tri is not drawn twice */
if (nr & 1) {
exec->vtx.prim[exec->vtx.prim_count-1].count--;
}
/* fallthrough */
case GL_QUAD_STRIP:
switch (nr) {
case 0:
ovf = 0;
break;
case 1:
ovf = 1;
break;
default:
ovf = 2 + (nr & 1);
break;
}
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) );
return i;
case PRIM_OUTSIDE_BEGIN_END:
return 0;
default:
assert(0);
return 0;
}
}
 
 
 
/* TODO: populate these as the vertex is defined:
*/
static void
vbo_exec_bind_arrays( struct gl_context *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_exec_context *exec = &vbo->exec;
struct gl_client_array *arrays = exec->vtx.arrays;
const GLuint count = exec->vtx.vert_count;
const GLuint *map;
GLuint attr;
GLbitfield varying_inputs = 0x0;
 
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
*/
switch (get_program_mode(exec->ctx)) {
case VP_NONE:
for (attr = 0; attr < 16; attr++) {
exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
}
for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
ASSERT(attr + 16 < Elements(exec->vtx.inputs));
exec->vtx.inputs[attr + 16] = &vbo->mat_currval[attr];
}
map = vbo->map_vp_none;
break;
case VP_NV:
case VP_ARB:
/* The aliasing of attributes for NV vertex programs has already
* occurred. NV vertex programs cannot access material values,
* nor attributes greater than VERT_ATTRIB_TEX7.
*/
for (attr = 0; attr < 16; attr++) {
exec->vtx.inputs[attr] = &vbo->legacy_currval[attr];
ASSERT(attr + 16 < Elements(exec->vtx.inputs));
exec->vtx.inputs[attr + 16] = &vbo->generic_currval[attr];
}
map = vbo->map_vp_arb;
 
/* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
* In that case we effectively need to route the data from
* glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
*/
if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
(ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
exec->vtx.inputs[16] = exec->vtx.inputs[0];
exec->vtx.attrsz[16] = exec->vtx.attrsz[0];
exec->vtx.attrptr[16] = exec->vtx.attrptr[0];
exec->vtx.attrsz[0] = 0;
}
break;
default:
assert(0);
}
 
/* Make all active attributes (including edgeflag) available as
* arrays of floats.
*/
for (attr = 0; attr < VERT_ATTRIB_MAX ; attr++) {
const GLuint src = map[attr];
 
if (exec->vtx.attrsz[src]) {
GLsizeiptr offset = (GLbyte *)exec->vtx.attrptr[src] -
(GLbyte *)exec->vtx.vertex;
 
/* override the default array set above */
ASSERT(attr < Elements(exec->vtx.inputs));
ASSERT(attr < Elements(exec->vtx.arrays)); /* arrays[] */
exec->vtx.inputs[attr] = &arrays[attr];
 
if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
/* a real buffer obj: Ptr is an offset, not a pointer*/
assert(exec->vtx.bufferobj->Pointer); /* buf should be mapped */
assert(offset >= 0);
arrays[attr].Ptr = (GLubyte *)exec->vtx.bufferobj->Offset + offset;
}
else {
/* Ptr into ordinary app memory */
arrays[attr].Ptr = (GLubyte *)exec->vtx.buffer_map + offset;
}
arrays[attr].Size = exec->vtx.attrsz[src];
arrays[attr].StrideB = exec->vtx.vertex_size * sizeof(GLfloat);
arrays[attr].Stride = exec->vtx.vertex_size * sizeof(GLfloat);
arrays[attr].Type = GL_FLOAT;
arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
exec->vtx.bufferobj);
arrays[attr]._MaxElement = count; /* ??? */
 
varying_inputs |= 1 << attr;
}
}
 
_mesa_set_varying_vp_inputs( ctx, varying_inputs );
}
 
 
static void
vbo_exec_vtx_unmap( struct vbo_exec_context *exec )
{
GLenum target = GL_ARRAY_BUFFER_ARB;
 
if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
struct gl_context *ctx = exec->ctx;
if (ctx->Driver.FlushMappedBufferRange) {
GLintptr offset = exec->vtx.buffer_used - exec->vtx.bufferobj->Offset;
GLsizeiptr length = (exec->vtx.buffer_ptr - exec->vtx.buffer_map) * sizeof(float);
 
if (length)
ctx->Driver.FlushMappedBufferRange(ctx, target,
offset, length,
exec->vtx.bufferobj);
}
 
exec->vtx.buffer_used += (exec->vtx.buffer_ptr -
exec->vtx.buffer_map) * sizeof(float);
 
assert(exec->vtx.buffer_used <= VBO_VERT_BUFFER_SIZE);
assert(exec->vtx.buffer_ptr != NULL);
ctx->Driver.UnmapBuffer(ctx, target, exec->vtx.bufferobj);
exec->vtx.buffer_map = NULL;
exec->vtx.buffer_ptr = NULL;
exec->vtx.max_vert = 0;
}
}
 
 
void
vbo_exec_vtx_map( struct vbo_exec_context *exec )
{
struct gl_context *ctx = exec->ctx;
const GLenum target = GL_ARRAY_BUFFER_ARB;
const GLenum access = GL_READ_WRITE_ARB; /* for MapBuffer */
const GLenum accessRange = GL_MAP_WRITE_BIT | /* for MapBufferRange */
GL_MAP_INVALIDATE_RANGE_BIT |
GL_MAP_UNSYNCHRONIZED_BIT |
GL_MAP_FLUSH_EXPLICIT_BIT |
MESA_MAP_NOWAIT_BIT;
const GLenum usage = GL_STREAM_DRAW_ARB;
if (!_mesa_is_bufferobj(exec->vtx.bufferobj))
return;
 
if (exec->vtx.buffer_map != NULL) {
assert(0);
exec->vtx.buffer_map = NULL;
exec->vtx.buffer_ptr = NULL;
}
 
if (VBO_VERT_BUFFER_SIZE > exec->vtx.buffer_used + 1024 &&
ctx->Driver.MapBufferRange) {
exec->vtx.buffer_map =
(GLfloat *)ctx->Driver.MapBufferRange(ctx,
target,
exec->vtx.buffer_used,
(VBO_VERT_BUFFER_SIZE -
exec->vtx.buffer_used),
accessRange,
exec->vtx.bufferobj);
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
}
if (!exec->vtx.buffer_map) {
exec->vtx.buffer_used = 0;
 
ctx->Driver.BufferData(ctx, target,
VBO_VERT_BUFFER_SIZE,
NULL, usage, exec->vtx.bufferobj);
 
 
if (ctx->Driver.MapBufferRange)
exec->vtx.buffer_map =
(GLfloat *)ctx->Driver.MapBufferRange(ctx, target,
0, VBO_VERT_BUFFER_SIZE,
accessRange,
exec->vtx.bufferobj);
if (!exec->vtx.buffer_map)
exec->vtx.buffer_map =
(GLfloat *)ctx->Driver.MapBuffer(ctx, target, access, exec->vtx.bufferobj);
assert(exec->vtx.buffer_map);
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
}
 
if (0)
printf("map %d..\n", exec->vtx.buffer_used);
}
 
 
 
/**
* Execute the buffer and save copied verts.
*/
void
vbo_exec_vtx_flush( struct vbo_exec_context *exec, GLboolean unmap )
{
if (0)
vbo_exec_debug_verts( exec );
 
if (exec->vtx.prim_count &&
exec->vtx.vert_count) {
 
exec->vtx.copied.nr = vbo_copy_vertices( exec );
 
if (exec->vtx.copied.nr != exec->vtx.vert_count) {
struct gl_context *ctx = exec->ctx;
/* Before the update_state() as this may raise _NEW_ARRAY
* from _mesa_set_varying_vp_inputs().
*/
vbo_exec_bind_arrays( ctx );
 
if (ctx->NewState)
_mesa_update_state( ctx );
 
if (_mesa_is_bufferobj(exec->vtx.bufferobj)) {
vbo_exec_vtx_unmap( exec );
}
 
if (0)
printf("%s %d %d\n", __FUNCTION__, exec->vtx.prim_count,
exec->vtx.vert_count);
 
vbo_context(ctx)->draw_prims( ctx,
exec->vtx.inputs,
exec->vtx.prim,
exec->vtx.prim_count,
NULL,
GL_TRUE,
0,
exec->vtx.vert_count - 1);
 
/* If using a real VBO, get new storage -- unless asked not to.
*/
if (_mesa_is_bufferobj(exec->vtx.bufferobj) && !unmap) {
vbo_exec_vtx_map( exec );
}
}
}
 
/* May have to unmap explicitly if we didn't draw:
*/
if (unmap &&
_mesa_is_bufferobj(exec->vtx.bufferobj) &&
exec->vtx.buffer_map) {
vbo_exec_vtx_unmap( exec );
}
 
 
if (unmap || exec->vtx.vertex_size == 0)
exec->vtx.max_vert = 0;
else
exec->vtx.max_vert = ((VBO_VERT_BUFFER_SIZE - exec->vtx.buffer_used) /
(exec->vtx.vertex_size * sizeof(GLfloat)));
 
exec->vtx.buffer_ptr = exec->vtx.buffer_map;
exec->vtx.prim_count = 0;
exec->vtx.vert_count = 0;
}
 
 
#endif /* FEATURE_beginend */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_exec_eval.c
0,0 → 1,263
/*
* Mesa 3-D graphics library
* Version: 6.1
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "math/m_eval.h"
#include "main/dispatch.h"
#include "vbo_exec.h"
 
 
static void clear_active_eval1( struct vbo_exec_context *exec, GLuint attr )
{
assert(attr < Elements(exec->eval.map1));
exec->eval.map1[attr].map = NULL;
}
 
static void clear_active_eval2( struct vbo_exec_context *exec, GLuint attr )
{
assert(attr < Elements(exec->eval.map2));
exec->eval.map2[attr].map = NULL;
}
 
static void set_active_eval1( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
struct gl_1d_map *map )
{
assert(attr < Elements(exec->eval.map1));
if (!exec->eval.map1[attr].map) {
exec->eval.map1[attr].map = map;
exec->eval.map1[attr].sz = dim;
}
}
 
static void set_active_eval2( struct vbo_exec_context *exec, GLuint attr, GLuint dim,
struct gl_2d_map *map )
{
assert(attr < Elements(exec->eval.map2));
if (!exec->eval.map2[attr].map) {
exec->eval.map2[attr].map = map;
exec->eval.map2[attr].sz = dim;
}
}
 
void vbo_exec_eval_update( struct vbo_exec_context *exec )
{
struct gl_context *ctx = exec->ctx;
GLuint attr;
 
/* Vertex program maps have priority over conventional attribs */
 
for (attr = 0; attr < VBO_ATTRIB_FIRST_MATERIAL; attr++) {
clear_active_eval1( exec, attr );
clear_active_eval2( exec, attr );
}
 
if (ctx->Eval.Map1Color4)
set_active_eval1( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 );
if (ctx->Eval.Map2Color4)
set_active_eval2( exec, VBO_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 );
 
if (ctx->Eval.Map1TextureCoord4)
set_active_eval1( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 );
else if (ctx->Eval.Map1TextureCoord3)
set_active_eval1( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 );
else if (ctx->Eval.Map1TextureCoord2)
set_active_eval1( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 );
else if (ctx->Eval.Map1TextureCoord1)
set_active_eval1( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 );
 
if (ctx->Eval.Map2TextureCoord4)
set_active_eval2( exec, VBO_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 );
else if (ctx->Eval.Map2TextureCoord3)
set_active_eval2( exec, VBO_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 );
else if (ctx->Eval.Map2TextureCoord2)
set_active_eval2( exec, VBO_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 );
else if (ctx->Eval.Map2TextureCoord1)
set_active_eval2( exec, VBO_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 );
 
if (ctx->Eval.Map1Normal)
set_active_eval1( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal );
 
if (ctx->Eval.Map2Normal)
set_active_eval2( exec, VBO_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal );
 
if (ctx->Eval.Map1Vertex4)
set_active_eval1( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 );
else if (ctx->Eval.Map1Vertex3)
set_active_eval1( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 );
 
if (ctx->Eval.Map2Vertex4)
set_active_eval2( exec, VBO_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 );
else if (ctx->Eval.Map2Vertex3)
set_active_eval2( exec, VBO_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 );
 
/* _NEW_PROGRAM */
if (ctx->VertexProgram._Enabled) {
/* These are the 16 evaluators which GL_NV_vertex_program defines.
* They alias and override the conventional vertex attributs.
*/
for (attr = 0; attr < 16; attr++) {
/* _NEW_EVAL */
assert(attr < Elements(ctx->Eval.Map1Attrib));
if (ctx->Eval.Map1Attrib[attr])
set_active_eval1( exec, attr, 4, &ctx->EvalMap.Map1Attrib[attr] );
 
assert(attr < Elements(ctx->Eval.Map2Attrib));
if (ctx->Eval.Map2Attrib[attr])
set_active_eval2( exec, attr, 4, &ctx->EvalMap.Map2Attrib[attr] );
}
}
 
exec->eval.recalculate_maps = 0;
}
 
 
 
void vbo_exec_do_EvalCoord1f(struct vbo_exec_context *exec, GLfloat u)
{
GLuint attr;
 
for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
struct gl_1d_map *map = exec->eval.map1[attr].map;
if (map) {
GLfloat uu = (u - map->u1) * map->du;
GLfloat data[4];
 
ASSIGN_4V(data, 0, 0, 0, 1);
 
_math_horner_bezier_curve(map->Points, data, uu,
exec->eval.map1[attr].sz,
map->Order);
 
COPY_SZ_4V( exec->vtx.attrptr[attr],
exec->vtx.attrsz[attr],
data );
}
}
 
/** Vertex -- EvalCoord1f is a noop if this map not enabled:
**/
if (exec->eval.map1[0].map) {
struct gl_1d_map *map = exec->eval.map1[0].map;
GLfloat uu = (u - map->u1) * map->du;
GLfloat vertex[4];
 
ASSIGN_4V(vertex, 0, 0, 0, 1);
 
_math_horner_bezier_curve(map->Points, vertex, uu,
exec->eval.map1[0].sz,
map->Order);
 
if (exec->eval.map1[0].sz == 4)
CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
else
CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
}
}
 
 
 
void vbo_exec_do_EvalCoord2f( struct vbo_exec_context *exec,
GLfloat u, GLfloat v )
{
GLuint attr;
 
for (attr = 1; attr <= VBO_ATTRIB_TEX7; attr++) {
struct gl_2d_map *map = exec->eval.map2[attr].map;
if (map) {
GLfloat uu = (u - map->u1) * map->du;
GLfloat vv = (v - map->v1) * map->dv;
GLfloat data[4];
 
ASSIGN_4V(data, 0, 0, 0, 1);
 
_math_horner_bezier_surf(map->Points,
data,
uu, vv,
exec->eval.map2[attr].sz,
map->Uorder, map->Vorder);
 
COPY_SZ_4V( exec->vtx.attrptr[attr],
exec->vtx.attrsz[attr],
data );
}
}
 
/** Vertex -- EvalCoord2f is a noop if this map not enabled:
**/
if (exec->eval.map2[0].map) {
struct gl_2d_map *map = exec->eval.map2[0].map;
GLfloat uu = (u - map->u1) * map->du;
GLfloat vv = (v - map->v1) * map->dv;
GLfloat vertex[4];
 
ASSIGN_4V(vertex, 0, 0, 0, 1);
 
if (exec->ctx->Eval.AutoNormal) {
GLfloat normal[4];
GLfloat du[4], dv[4];
 
_math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv,
exec->eval.map2[0].sz,
map->Uorder, map->Vorder);
 
if (exec->eval.map2[0].sz == 4) {
du[0] = du[0]*vertex[3] - du[3]*vertex[0];
du[1] = du[1]*vertex[3] - du[3]*vertex[1];
du[2] = du[2]*vertex[3] - du[3]*vertex[2];
dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0];
dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1];
dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2];
}
 
 
CROSS3(normal, du, dv);
NORMALIZE_3FV(normal);
normal[3] = 1.0;
 
COPY_SZ_4V( exec->vtx.attrptr[VBO_ATTRIB_NORMAL],
exec->vtx.attrsz[VBO_ATTRIB_NORMAL],
normal );
 
}
else {
_math_horner_bezier_surf(map->Points, vertex, uu, vv,
exec->eval.map2[0].sz,
map->Uorder, map->Vorder);
}
 
if (exec->vtx.attrsz[0] == 4)
CALL_Vertex4fv(GET_DISPATCH(), ( vertex ));
else
CALL_Vertex3fv(GET_DISPATCH(), ( vertex ));
}
}
 
 
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_rebase.c
0,0 → 1,251
 
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
/* Helper for drivers which find themselves rendering a range of
* indices starting somewhere above zero. Typically the application
* is issuing multiple DrawArrays() or DrawElements() to draw
* successive primitives layed out linearly in the vertex arrays.
* Unless the vertex arrays are all in a VBO, the OpenGL semantics
* imply that we need to re-upload the vertex data on each draw call.
* In that case, we want to avoid starting the upload at zero, as it
* will mean every draw call uploads an increasing amount of not-used
* vertex data. Worse - in the software tnl module, all those
* vertices will be transformed and lit.
*
* If we just upload the new data, however, the indices will be
* incorrect as we tend to upload each set of vertex data to a new
* region.
*
* This file provides a helper to adjust the arrays, primitives and
* indices of a draw call so that it can be re-issued with a min_index
* of zero.
*/
 
#include "main/glheader.h"
#include "main/imports.h"
#include "main/mtypes.h"
 
#include "vbo.h"
 
 
#define REBASE(TYPE) \
static void *rebase_##TYPE( const void *ptr, \
GLuint count, \
TYPE min_index ) \
{ \
const TYPE *in = (TYPE *)ptr; \
TYPE *tmp_indices = malloc(count * sizeof(TYPE)); \
GLuint i; \
\
for (i = 0; i < count; i++) \
tmp_indices[i] = in[i] - min_index; \
\
return (void *)tmp_indices; \
}
 
 
REBASE(GLuint)
REBASE(GLushort)
REBASE(GLubyte)
 
GLboolean vbo_all_varyings_in_vbos( const struct gl_client_array *arrays[] )
{
GLuint i;
for (i = 0; i < VERT_ATTRIB_MAX; i++)
if (arrays[i]->StrideB &&
arrays[i]->BufferObj->Name == 0)
return GL_FALSE;
 
return GL_TRUE;
}
 
GLboolean vbo_any_varyings_in_vbos( const struct gl_client_array *arrays[] )
{
GLuint i;
 
for (i = 0; i < VERT_ATTRIB_MAX; i++)
if (arrays[i]->StrideB &&
arrays[i]->BufferObj->Name != 0)
return GL_TRUE;
 
return GL_FALSE;
}
 
/* Adjust primitives, indices and vertex definitions so that min_index
* becomes zero. There are lots of reasons for wanting to do this, eg:
*
* Software tnl:
* - any time min_index != 0, otherwise unused vertices lower than
* min_index will be transformed.
*
* Hardware tnl:
* - if ib != NULL and min_index != 0, otherwise vertices lower than
* min_index will be uploaded. Requires adjusting index values.
*
* - if ib == NULL and min_index != 0, just for convenience so this doesn't
* have to be handled within the driver.
*
* Hardware tnl with VBO support:
* - as above, but only when vertices are not (all?) in VBO's.
* - can't save time by trying to upload half a vbo - typically it is
* all or nothing.
*/
void vbo_rebase_prims( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw )
{
struct gl_client_array tmp_arrays[VERT_ATTRIB_MAX];
const struct gl_client_array *tmp_array_pointers[VERT_ATTRIB_MAX];
 
struct _mesa_index_buffer tmp_ib;
struct _mesa_prim *tmp_prims = NULL;
void *tmp_indices = NULL;
GLuint i;
 
assert(min_index != 0);
 
if (0)
printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
 
 
/* XXX this path is disabled for now.
* There's rendering corruption in some apps when it's enabled.
*/
if (0 && ib && ctx->Extensions.ARB_draw_elements_base_vertex) {
/* If we can just tell the hardware or the TNL to interpret our
* indices with a different base, do so.
*/
tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
 
for (i = 0; i < nr_prims; i++) {
tmp_prims[i] = prim[i];
tmp_prims[i].basevertex -= min_index;
}
 
prim = tmp_prims;
} else if (ib) {
/* Unfortunately need to adjust each index individually.
*/
GLboolean map_ib = ib->obj->Name && !ib->obj->Pointer;
void *ptr;
 
if (map_ib)
ctx->Driver.MapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER,
GL_READ_ONLY_ARB,
ib->obj);
 
 
ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
 
/* Some users might prefer it if we translated elements to
* GLuints here. Others wouldn't...
*/
switch (ib->type) {
case GL_UNSIGNED_INT:
tmp_indices = rebase_GLuint( ptr, ib->count, min_index );
break;
case GL_UNSIGNED_SHORT:
tmp_indices = rebase_GLushort( ptr, ib->count, min_index );
break;
case GL_UNSIGNED_BYTE:
tmp_indices = rebase_GLubyte( ptr, ib->count, min_index );
break;
}
 
if (map_ib)
ctx->Driver.UnmapBuffer(ctx,
GL_ELEMENT_ARRAY_BUFFER,
ib->obj);
 
tmp_ib.obj = ctx->Shared->NullBufferObj;
tmp_ib.ptr = tmp_indices;
tmp_ib.count = ib->count;
tmp_ib.type = ib->type;
 
ib = &tmp_ib;
}
else {
/* Otherwise the primitives need adjustment.
*/
tmp_prims = (struct _mesa_prim *)malloc(sizeof(*prim) * nr_prims);
 
for (i = 0; i < nr_prims; i++) {
/* If this fails, it could indicate an application error:
*/
assert(prim[i].start >= min_index);
 
tmp_prims[i] = prim[i];
tmp_prims[i].start -= min_index;
}
 
prim = tmp_prims;
}
 
/* Just need to adjust the pointer values on each incoming array.
* This works for VBO and non-vbo rendering and shouldn't pesimize
* VBO-based upload schemes. However this may still not be a fast
* path for hardware tnl for VBO based rendering as most machines
* will be happier if you just specify a starting vertex value in
* each primitive.
*
* For drivers with hardware tnl, you only want to do this if you
* are forced to, eg non-VBO indexed rendering with start != 0.
*/
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
tmp_arrays[i] = *arrays[i];
tmp_arrays[i].Ptr += min_index * tmp_arrays[i].StrideB;
tmp_array_pointers[i] = &tmp_arrays[i];
}
/* Re-issue the draw call.
*/
draw( ctx,
tmp_array_pointers,
prim,
nr_prims,
ib,
GL_TRUE,
0,
max_index - min_index );
if (tmp_indices)
free(tmp_indices);
if (tmp_prims)
free(tmp_prims);
}
 
 
 
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_save.c
0,0 → 1,122
/*
* Mesa 3-D graphics library
* Version: 7.2
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "main/mtypes.h"
#include "main/bufferobj.h"
#include "main/imports.h"
 
#include "vbo_context.h"
 
 
#if FEATURE_dlist
 
 
static void vbo_save_callback_init( struct gl_context *ctx )
{
ctx->Driver.NewList = vbo_save_NewList;
ctx->Driver.EndList = vbo_save_EndList;
ctx->Driver.SaveFlushVertices = vbo_save_SaveFlushVertices;
ctx->Driver.BeginCallList = vbo_save_BeginCallList;
ctx->Driver.EndCallList = vbo_save_EndCallList;
ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
}
 
 
 
void vbo_save_init( struct gl_context *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_save_context *save = &vbo->save;
 
save->ctx = ctx;
 
vbo_save_api_init( save );
vbo_save_callback_init(ctx);
 
{
struct gl_client_array *arrays = save->arrays;
unsigned i;
 
memcpy(arrays, vbo->legacy_currval, 16 * sizeof(arrays[0]));
memcpy(arrays + 16, vbo->generic_currval, 16 * sizeof(arrays[0]));
 
for (i = 0; i < 16; ++i) {
arrays[i ].BufferObj = NULL;
arrays[i + 16].BufferObj = NULL;
_mesa_reference_buffer_object(ctx, &arrays[i ].BufferObj,
vbo->legacy_currval[i].BufferObj);
_mesa_reference_buffer_object(ctx, &arrays[i + 16].BufferObj,
vbo->generic_currval[i].BufferObj);
}
}
 
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
}
 
 
void vbo_save_destroy( struct gl_context *ctx )
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_save_context *save = &vbo->save;
GLuint i;
 
if (save->prim_store) {
if ( --save->prim_store->refcount == 0 ) {
FREE( save->prim_store );
save->prim_store = NULL;
}
if ( --save->vertex_store->refcount == 0 ) {
_mesa_reference_buffer_object(ctx,
&save->vertex_store->bufferobj, NULL);
FREE( save->vertex_store );
save->vertex_store = NULL;
}
}
 
for (i = 0; i < VBO_ATTRIB_MAX; i++) {
_mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL);
}
}
 
 
 
 
/* Note that this can occur during the playback of a display list:
*/
void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
if (fallback)
save->replay_flags |= VBO_SAVE_FALLBACK;
else
save->replay_flags &= ~VBO_SAVE_FALLBACK;
}
 
 
#endif /* FEATURE_dlist */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_save.h
0,0 → 1,199
/**************************************************************************
 
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas.
 
All Rights Reserved.
 
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
 
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
 
#ifndef VBO_SAVE_H
#define VBO_SAVE_H
 
#include "main/mtypes.h"
#include "vbo.h"
#include "vbo_attrib.h"
 
 
struct vbo_save_copied_vtx {
GLfloat buffer[VBO_ATTRIB_MAX * 4 * VBO_MAX_COPIED_VERTS];
GLuint nr;
};
 
 
/* For display lists, this structure holds a run of vertices of the
* same format, and a strictly well-formed set of begin/end pairs,
* starting on the first vertex and ending at the last. Vertex
* copying on buffer breaks is precomputed according to these
* primitives, though there are situations where the copying will need
* correction at execute-time, perhaps by replaying the list as
* immediate mode commands.
*
* On executing this list, the 'current' values may be updated with
* the values of the final vertex, and often no fixup of the start of
* the vertex list is required.
*
* Eval and other commands that don't fit into these vertex lists are
* compiled using the fallback opcode mechanism provided by dlist.c.
*/
struct vbo_save_vertex_list {
GLubyte attrsz[VBO_ATTRIB_MAX];
GLuint vertex_size;
 
/* Copy of the final vertex from node->vertex_store->bufferobj.
* Keep this in regular (non-VBO) memory to avoid repeated
* map/unmap of the VBO when updating GL current data.
*/
GLfloat *current_data;
GLuint current_size;
 
GLuint buffer_offset;
GLuint count;
GLuint wrap_count; /* number of copied vertices at start */
GLboolean dangling_attr_ref; /* current attr implicitly referenced
outside the list */
 
struct _mesa_prim *prim;
GLuint prim_count;
 
struct vbo_save_vertex_store *vertex_store;
struct vbo_save_primitive_store *prim_store;
};
 
/* These buffers should be a reasonable size to support upload to
* hardware. Current vbo implementation will re-upload on any
* changes, so don't make too big or apps which dynamically create
* dlists and use only a few times will suffer.
*
* Consider stategy of uploading regions from the VBO on demand in the
* case of dynamic vbos. Then make the dlist code signal that
* likelyhood as it occurs. No reason we couldn't change usage
* internally even though this probably isn't allowed for client VBOs?
*/
#define VBO_SAVE_BUFFER_SIZE (8*1024) /* dwords */
#define VBO_SAVE_PRIM_SIZE 128
#define VBO_SAVE_PRIM_WEAK 0x40
 
#define VBO_SAVE_FALLBACK 0x10000000
 
/* Storage to be shared among several vertex_lists.
*/
struct vbo_save_vertex_store {
struct gl_buffer_object *bufferobj;
GLfloat *buffer;
GLuint used;
GLuint refcount;
};
 
struct vbo_save_primitive_store {
struct _mesa_prim buffer[VBO_SAVE_PRIM_SIZE];
GLuint used;
GLuint refcount;
};
 
 
struct vbo_save_context {
struct gl_context *ctx;
GLvertexformat vtxfmt;
struct gl_client_array arrays[VBO_ATTRIB_MAX];
const struct gl_client_array *inputs[VBO_ATTRIB_MAX];
 
GLubyte attrsz[VBO_ATTRIB_MAX];
GLubyte active_sz[VBO_ATTRIB_MAX];
GLuint vertex_size;
 
GLfloat *buffer;
GLuint count;
GLuint wrap_count;
GLuint replay_flags;
 
struct _mesa_prim *prim;
GLuint prim_count, prim_max;
 
struct vbo_save_vertex_store *vertex_store;
struct vbo_save_primitive_store *prim_store;
 
GLfloat *buffer_ptr; /* cursor, points into buffer */
GLfloat vertex[VBO_ATTRIB_MAX*4]; /* current values */
GLfloat *attrptr[VBO_ATTRIB_MAX];
GLuint vert_count;
GLuint max_vert;
GLboolean dangling_attr_ref;
GLboolean have_materials;
 
GLuint opcode_vertex_list;
 
struct vbo_save_copied_vtx copied;
GLfloat *current[VBO_ATTRIB_MAX]; /* points into ctx->ListState */
GLubyte *currentsz[VBO_ATTRIB_MAX];
};
 
#if FEATURE_dlist
 
void vbo_save_init( struct gl_context *ctx );
void vbo_save_destroy( struct gl_context *ctx );
void vbo_save_fallback( struct gl_context *ctx, GLboolean fallback );
 
/* save_loopback.c:
*/
void vbo_loopback_vertex_list( struct gl_context *ctx,
const GLfloat *buffer,
const GLubyte *attrsz,
const struct _mesa_prim *prim,
GLuint prim_count,
GLuint wrap_count,
GLuint vertex_size);
 
/* Callbacks:
*/
void vbo_save_EndList( struct gl_context *ctx );
void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode );
void vbo_save_EndCallList( struct gl_context *ctx );
void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *list );
void vbo_save_SaveFlushVertices( struct gl_context *ctx );
GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode );
 
void vbo_save_playback_vertex_list( struct gl_context *ctx, void *data );
 
void vbo_save_api_init( struct vbo_save_context *save );
 
#else /* FEATURE_dlist */
 
static INLINE void
vbo_save_init( struct gl_context *ctx )
{
}
 
static INLINE void
vbo_save_destroy( struct gl_context *ctx )
{
}
 
#endif /* FEATURE_dlist */
 
#endif /* VBO_SAVE_H */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_save_api.c
0,0 → 1,1301
/**************************************************************************
 
Copyright 2002-2008 Tungsten Graphics Inc., Cedar Park, Texas.
 
All Rights Reserved.
 
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
 
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
 
/* Display list compiler attempts to store lists of vertices with the
* same vertex layout. Additionally it attempts to minimize the need
* for execute-time fixup of these vertex lists, allowing them to be
* cached on hardware.
*
* There are still some circumstances where this can be thwarted, for
* example by building a list that consists of one very long primitive
* (eg Begin(Triangles), 1000 vertices, End), and calling that list
* from inside a different begin/end object (Begin(Lines), CallList,
* End).
*
* In that case the code will have to replay the list as individual
* commands through the Exec dispatch table, or fix up the copied
* vertices at execute-time.
*
* The other case where fixup is required is when a vertex attribute
* is introduced in the middle of a primitive. Eg:
* Begin(Lines)
* TexCoord1f() Vertex2f()
* TexCoord1f() Color3f() Vertex2f()
* End()
*
* If the current value of Color isn't known at compile-time, this
* primitive will require fixup.
*
*
* The list compiler currently doesn't attempt to compile lists
* containing EvalCoord or EvalPoint commands. On encountering one of
* these, compilation falls back to opcodes.
*
* This could be improved to fallback only when a mix of EvalCoord and
* Vertex commands are issued within a single primitive.
*/
 
 
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/dlist.h"
#include "main/enums.h"
#include "main/eval.h"
#include "main/macros.h"
#include "main/api_noop.h"
#include "main/api_validate.h"
#include "main/api_arrayelt.h"
#include "main/vtxfmt.h"
#include "main/dispatch.h"
 
#include "vbo_context.h"
 
 
#if FEATURE_dlist
 
 
#ifdef ERROR
#undef ERROR
#endif
 
 
/* An interesting VBO number/name to help with debugging */
#define VBO_BUF_ID 12345
 
 
/*
* NOTE: Old 'parity' issue is gone, but copying can still be
* wrong-footed on replay.
*/
static GLuint _save_copy_vertices( struct gl_context *ctx,
const struct vbo_save_vertex_list *node,
const GLfloat *src_buffer)
{
struct vbo_save_context *save = &vbo_context( ctx )->save;
const struct _mesa_prim *prim = &node->prim[node->prim_count-1];
GLuint nr = prim->count;
GLuint sz = save->vertex_size;
const GLfloat *src = src_buffer + prim->start * sz;
GLfloat *dst = save->copied.buffer;
GLuint ovf, i;
 
if (prim->end)
return 0;
switch( prim->mode )
{
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
return i;
case GL_TRIANGLES:
ovf = nr%3;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
return i;
case GL_QUADS:
ovf = nr&3;
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
return i;
case GL_LINE_STRIP:
if (nr == 0)
return 0;
else {
memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) );
return 1;
}
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0)
return 0;
else if (nr == 1) {
memcpy( dst, src+0, sz*sizeof(GLfloat) );
return 1;
} else {
memcpy( dst, src+0, sz*sizeof(GLfloat) );
memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) );
return 2;
}
case GL_TRIANGLE_STRIP:
case GL_QUAD_STRIP:
switch (nr) {
case 0: ovf = 0; break;
case 1: ovf = 1; break;
default: ovf = 2 + (nr&1); break;
}
for (i = 0 ; i < ovf ; i++)
memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) );
return i;
default:
assert(0);
return 0;
}
}
 
 
static struct vbo_save_vertex_store *alloc_vertex_store( struct gl_context *ctx )
{
struct vbo_save_vertex_store *vertex_store = CALLOC_STRUCT(vbo_save_vertex_store);
 
/* obj->Name needs to be non-zero, but won't ever be examined more
* closely than that. In particular these buffers won't be entered
* into the hash and can never be confused with ones visible to the
* user. Perhaps there could be a special number for internal
* buffers:
*/
vertex_store->bufferobj = ctx->Driver.NewBufferObject(ctx,
VBO_BUF_ID,
GL_ARRAY_BUFFER_ARB);
 
ctx->Driver.BufferData( ctx,
GL_ARRAY_BUFFER_ARB,
VBO_SAVE_BUFFER_SIZE * sizeof(GLfloat),
NULL,
GL_STATIC_DRAW_ARB,
vertex_store->bufferobj);
 
vertex_store->buffer = NULL;
vertex_store->used = 0;
vertex_store->refcount = 1;
 
return vertex_store;
}
 
static void free_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
{
assert(!vertex_store->buffer);
 
if (vertex_store->bufferobj) {
_mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
}
 
FREE( vertex_store );
}
 
static GLfloat *map_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
{
assert(vertex_store->bufferobj);
assert(!vertex_store->buffer);
vertex_store->buffer = (GLfloat *)ctx->Driver.MapBuffer(ctx,
GL_ARRAY_BUFFER_ARB, /* not used */
GL_WRITE_ONLY, /* not used */
vertex_store->bufferobj);
 
assert(vertex_store->buffer);
return vertex_store->buffer + vertex_store->used;
}
 
static void unmap_vertex_store( struct gl_context *ctx, struct vbo_save_vertex_store *vertex_store )
{
ctx->Driver.UnmapBuffer( ctx, GL_ARRAY_BUFFER_ARB, vertex_store->bufferobj );
vertex_store->buffer = NULL;
}
 
 
static struct vbo_save_primitive_store *alloc_prim_store( struct gl_context *ctx )
{
struct vbo_save_primitive_store *store = CALLOC_STRUCT(vbo_save_primitive_store);
(void) ctx;
store->used = 0;
store->refcount = 1;
return store;
}
 
static void _save_reset_counters( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
save->prim = save->prim_store->buffer + save->prim_store->used;
save->buffer = (save->vertex_store->buffer +
save->vertex_store->used);
 
assert(save->buffer == save->buffer_ptr);
 
if (save->vertex_size)
save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
save->vertex_size);
else
save->max_vert = 0;
 
save->vert_count = 0;
save->prim_count = 0;
save->prim_max = VBO_SAVE_PRIM_SIZE - save->prim_store->used;
save->dangling_attr_ref = 0;
}
 
 
/* Insert the active immediate struct onto the display list currently
* being built.
*/
static void _save_compile_vertex_list( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
struct vbo_save_vertex_list *node;
 
/* Allocate space for this structure in the display list currently
* being compiled.
*/
node = (struct vbo_save_vertex_list *)
_mesa_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node));
 
if (!node)
return;
 
/* Duplicate our template, increment refcounts to the storage structs:
*/
memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
node->vertex_size = save->vertex_size;
node->buffer_offset = (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
node->count = save->vert_count;
node->wrap_count = save->copied.nr;
node->dangling_attr_ref = save->dangling_attr_ref;
node->prim = save->prim;
node->prim_count = save->prim_count;
node->vertex_store = save->vertex_store;
node->prim_store = save->prim_store;
 
node->vertex_store->refcount++;
node->prim_store->refcount++;
 
 
node->current_size = node->vertex_size - node->attrsz[0];
node->current_data = NULL;
 
if (node->current_size) {
/* If the malloc fails, we just pull the data out of the VBO
* later instead.
*/
node->current_data = MALLOC( node->current_size * sizeof(GLfloat) );
if (node->current_data) {
const char *buffer = (const char *)save->vertex_store->buffer;
unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
unsigned vertex_offset = 0;
 
if (node->count)
vertex_offset = (node->count-1) * node->vertex_size * sizeof(GLfloat);
 
memcpy( node->current_data,
buffer + node->buffer_offset + vertex_offset + attr_offset,
node->current_size * sizeof(GLfloat) );
}
}
 
 
 
assert(node->attrsz[VBO_ATTRIB_POS] != 0 ||
node->count == 0);
 
if (save->dangling_attr_ref)
ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
 
save->vertex_store->used += save->vertex_size * node->count;
save->prim_store->used += node->prim_count;
 
 
/* Copy duplicated vertices
*/
save->copied.nr = _save_copy_vertices( ctx, node, save->buffer );
 
 
/* Deal with GL_COMPILE_AND_EXECUTE:
*/
if (ctx->ExecuteFlag) {
struct _glapi_table *dispatch = GET_DISPATCH();
 
_glapi_set_dispatch(ctx->Exec);
 
vbo_loopback_vertex_list( ctx,
(const GLfloat *)((const char *)save->vertex_store->buffer +
node->buffer_offset),
node->attrsz,
node->prim,
node->prim_count,
node->wrap_count,
node->vertex_size);
 
_glapi_set_dispatch(dispatch);
}
 
 
/* Decide whether the storage structs are full, or can be used for
* the next vertex lists as well.
*/
if (save->vertex_store->used >
VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {
 
/* Unmap old store:
*/
unmap_vertex_store( ctx, save->vertex_store );
 
/* Release old reference:
*/
save->vertex_store->refcount--;
assert(save->vertex_store->refcount != 0);
save->vertex_store = NULL;
 
/* Allocate and map new store:
*/
save->vertex_store = alloc_vertex_store( ctx );
save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
}
 
if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
save->prim_store->refcount--;
assert(save->prim_store->refcount != 0);
save->prim_store = alloc_prim_store( ctx );
}
 
/* Reset our structures for the next run of vertices:
*/
_save_reset_counters( ctx );
}
 
 
/* TODO -- If no new vertices have been stored, don't bother saving
* it.
*/
static void _save_wrap_buffers( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i = save->prim_count - 1;
GLenum mode;
GLboolean weak;
 
assert(i < (GLint) save->prim_max);
assert(i >= 0);
 
/* Close off in-progress primitive.
*/
save->prim[i].count = (save->vert_count -
save->prim[i].start);
mode = save->prim[i].mode;
weak = save->prim[i].weak;
/* store the copied vertices, and allocate a new list.
*/
_save_compile_vertex_list( ctx );
 
/* Restart interrupted primitive
*/
save->prim[0].mode = mode;
save->prim[0].weak = weak;
save->prim[0].begin = 0;
save->prim[0].end = 0;
save->prim[0].pad = 0;
save->prim[0].start = 0;
save->prim[0].count = 0;
save->prim[0].num_instances = 1;
save->prim_count = 1;
}
 
 
 
/* Called only when buffers are wrapped as the result of filling the
* vertex_store struct.
*/
static void _save_wrap_filled_vertex( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLfloat *data = save->copied.buffer;
GLuint i;
 
/* Emit a glEnd to close off the last vertex list.
*/
_save_wrap_buffers( ctx );
/* Copy stored stored vertices to start of new list.
*/
assert(save->max_vert - save->vert_count > save->copied.nr);
 
for (i = 0 ; i < save->copied.nr ; i++) {
memcpy( save->buffer_ptr, data, save->vertex_size * sizeof(GLfloat));
data += save->vertex_size;
save->buffer_ptr += save->vertex_size;
save->vert_count++;
}
}
 
 
static void _save_copy_to_current( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLuint i;
 
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (save->attrsz[i]) {
save->currentsz[i][0] = save->attrsz[i];
COPY_CLEAN_4V(save->current[i],
save->attrsz[i],
save->attrptr[i]);
}
}
}
 
 
static void _save_copy_from_current( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
 
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
switch (save->attrsz[i]) {
case 4: save->attrptr[i][3] = save->current[i][3];
case 3: save->attrptr[i][2] = save->current[i][2];
case 2: save->attrptr[i][1] = save->current[i][1];
case 1: save->attrptr[i][0] = save->current[i][0];
case 0: break;
}
}
}
 
 
 
 
/* Flush existing data, set new attrib size, replay copied vertices.
*/
static void _save_upgrade_vertex( struct gl_context *ctx,
GLuint attr,
GLuint newsz )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLuint oldsz;
GLuint i;
GLfloat *tmp;
 
/* Store the current run of vertices, and emit a GL_END. Emit a
* BEGIN in the new buffer.
*/
if (save->vert_count)
_save_wrap_buffers( ctx );
else
assert( save->copied.nr == 0 );
 
/* Do a COPY_TO_CURRENT to ensure back-copying works for the case
* when the attribute already exists in the vertex and is having
* its size increased.
*/
_save_copy_to_current( ctx );
 
/* Fix up sizes:
*/
oldsz = save->attrsz[attr];
save->attrsz[attr] = newsz;
 
save->vertex_size += newsz - oldsz;
save->max_vert = ((VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
save->vertex_size);
save->vert_count = 0;
 
/* Recalculate all the attrptr[] values:
*/
for (i = 0, tmp = save->vertex ; i < VBO_ATTRIB_MAX ; i++) {
if (save->attrsz[i]) {
save->attrptr[i] = tmp;
tmp += save->attrsz[i];
}
else
save->attrptr[i] = NULL; /* will not be dereferenced. */
}
 
/* Copy from current to repopulate the vertex with correct values.
*/
_save_copy_from_current( ctx );
 
/* Replay stored vertices to translate them to new format here.
*
* If there are copied vertices and the new (upgraded) attribute
* has not been defined before, this list is somewhat degenerate,
* and will need fixup at runtime.
*/
if (save->copied.nr)
{
GLfloat *data = save->copied.buffer;
GLfloat *dest = save->buffer;
GLuint j;
 
/* Need to note this and fix up at runtime (or loopback):
*/
if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) {
assert(oldsz == 0);
save->dangling_attr_ref = GL_TRUE;
}
 
for (i = 0 ; i < save->copied.nr ; i++) {
for (j = 0 ; j < VBO_ATTRIB_MAX ; j++) {
if (save->attrsz[j]) {
if (j == attr) {
if (oldsz) {
COPY_CLEAN_4V( dest, oldsz, data );
data += oldsz;
dest += newsz;
}
else {
COPY_SZ_4V( dest, newsz, save->current[attr] );
dest += newsz;
}
}
else {
GLint sz = save->attrsz[j];
COPY_SZ_4V( dest, sz, data );
data += sz;
dest += sz;
}
}
}
}
 
save->buffer_ptr = dest;
save->vert_count += save->copied.nr;
}
}
 
static void save_fixup_vertex( struct gl_context *ctx, GLuint attr, GLuint sz )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
if (sz > save->attrsz[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
_save_upgrade_vertex( ctx, attr, sz );
}
else if (sz < save->active_sz[attr]) {
static GLfloat id[4] = { 0, 0, 0, 1 };
GLuint i;
 
/* New size is equal or smaller - just need to fill in some
* zeros.
*/
for (i = sz ; i <= save->attrsz[attr] ; i++)
save->attrptr[attr][i-1] = id[i-1];
}
 
save->active_sz[attr] = sz;
}
 
static void _save_reset_vertex( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLuint i;
 
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
save->attrsz[i] = 0;
save->active_sz[i] = 0;
}
save->vertex_size = 0;
}
 
 
 
#define ERROR() _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ );
 
 
/* Only one size for each attribute may be active at once. Eg. if
* Color3f is installed/active, then Color4f may not be, even if the
* vertex actually contains 4 color coordinates. This is because the
* 3f version won't otherwise set color[3] to 1.0 -- this is the job
* of the chooser function when switching between Color4f and Color3f.
*/
#define ATTR( A, N, V0, V1, V2, V3 ) \
do { \
struct vbo_save_context *save = &vbo_context(ctx)->save; \
\
if (save->active_sz[A] != N) \
save_fixup_vertex(ctx, A, N); \
\
{ \
GLfloat *dest = save->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; \
} \
\
if ((A) == 0) { \
GLuint i; \
\
for (i = 0; i < save->vertex_size; i++) \
save->buffer_ptr[i] = save->vertex[i]; \
\
save->buffer_ptr += save->vertex_size; \
\
if (++save->vert_count >= save->max_vert) \
_save_wrap_filled_vertex( ctx ); \
} \
} while (0)
 
#define TAG(x) _save_##x
 
#include "vbo_attrib_tmp.h"
 
 
 
 
/* Cope with EvalCoord/CallList called within a begin/end object:
* -- Flush current buffer
* -- Fallback to opcodes for the rest of the begin/end object.
*/
static void DO_FALLBACK( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
if (save->vert_count || save->prim_count) {
GLint i = save->prim_count - 1;
 
/* Close off in-progress primitive.
*/
save->prim[i].count = (save->vert_count -
save->prim[i].start);
 
/* Need to replay this display list with loopback,
* unfortunately, otherwise this primitive won't be handled
* properly:
*/
save->dangling_attr_ref = 1;
_save_compile_vertex_list( ctx );
}
 
_save_copy_to_current( ctx );
_save_reset_vertex( ctx );
_save_reset_counters( ctx );
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
ctx->Driver.SaveNeedFlush = 0;
}
 
static void GLAPIENTRY _save_EvalCoord1f( GLfloat u )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalCoord1f(ctx->Save, (u));
}
 
static void GLAPIENTRY _save_EvalCoord1fv( const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalCoord1fv(ctx->Save, (v));
}
 
static void GLAPIENTRY _save_EvalCoord2f( GLfloat u, GLfloat v )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalCoord2f(ctx->Save, (u, v));
}
 
static void GLAPIENTRY _save_EvalCoord2fv( const GLfloat *v )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalCoord2fv(ctx->Save, (v));
}
 
static void GLAPIENTRY _save_EvalPoint1( GLint i )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalPoint1(ctx->Save, (i));
}
 
static void GLAPIENTRY _save_EvalPoint2( GLint i, GLint j )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_EvalPoint2(ctx->Save, (i, j));
}
 
static void GLAPIENTRY _save_CallList( GLuint l )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_CallList(ctx->Save, (l));
}
 
static void GLAPIENTRY _save_CallLists( GLsizei n, GLenum type, const GLvoid *v )
{
GET_CURRENT_CONTEXT(ctx);
DO_FALLBACK(ctx);
CALL_CallLists(ctx->Save, (n, type, v));
}
 
 
 
 
/* This begin is hooked into ... Updating of
* ctx->Driver.CurrentSavePrimitive is already taken care of.
*/
GLboolean vbo_save_NotifyBegin( struct gl_context *ctx, GLenum mode )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
GLuint i = save->prim_count++;
 
assert(i < save->prim_max);
save->prim[i].mode = mode & ~VBO_SAVE_PRIM_WEAK;
save->prim[i].begin = 1;
save->prim[i].end = 0;
save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0;
save->prim[i].pad = 0;
save->prim[i].start = save->vert_count;
save->prim[i].count = 0;
save->prim[i].num_instances = 1;
 
_mesa_install_save_vtxfmt( ctx, &save->vtxfmt );
ctx->Driver.SaveNeedFlush = 1;
return GL_TRUE;
}
 
 
 
static void GLAPIENTRY _save_End( void )
{
GET_CURRENT_CONTEXT( ctx );
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i = save->prim_count - 1;
 
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
save->prim[i].end = 1;
save->prim[i].count = (save->vert_count -
save->prim[i].start);
 
if (i == (GLint) save->prim_max - 1) {
_save_compile_vertex_list( ctx );
assert(save->copied.nr == 0);
}
 
/* Swap out this vertex format while outside begin/end. Any color,
* etc. received between here and the next begin will be compiled
* as opcodes.
*/
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
}
 
 
/* These are all errors as this vtxfmt is only installed inside
* begin/end pairs.
*/
static void GLAPIENTRY _save_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) count; (void) type; (void) indices;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
}
 
 
static void GLAPIENTRY _save_DrawRangeElements(GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) start; (void) end; (void) count; (void) type; (void) indices;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
}
 
static void GLAPIENTRY _save_DrawElementsBaseVertex(GLenum mode,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) count; (void) type; (void) indices; (void)basevertex;
 
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
}
 
static void GLAPIENTRY _save_DrawRangeElementsBaseVertex(GLenum mode,
GLuint start,
GLuint end,
GLsizei count,
GLenum type,
const GLvoid *indices,
GLint basevertex)
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) start; (void) end; (void) count; (void) type;
(void) indices; (void)basevertex;
 
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawRangeElements" );
}
 
static void GLAPIENTRY _save_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) start; (void) count;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
}
 
static void GLAPIENTRY _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
GET_CURRENT_CONTEXT(ctx);
(void) x1; (void) y1; (void) x2; (void) y2;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glRectf" );
}
 
static void GLAPIENTRY _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) i1; (void) i2;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh1" );
}
 
static void GLAPIENTRY _save_EvalMesh2( GLenum mode, GLint i1, GLint i2,
GLint j1, GLint j2 )
{
GET_CURRENT_CONTEXT(ctx);
(void) mode; (void) i1; (void) i2; (void) j1; (void) j2;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "glEvalMesh2" );
}
 
static void GLAPIENTRY _save_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT( ctx );
(void) mode;
_mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive glBegin" );
}
 
 
static void GLAPIENTRY _save_PrimitiveRestartNV( void )
{
GLenum curPrim;
GET_CURRENT_CONTEXT( ctx );
 
curPrim = ctx->Driver.CurrentSavePrimitive;
 
_save_End();
_save_Begin(curPrim);
}
 
 
/* Unlike the functions above, these are to be hooked into the vtxfmt
* maintained in ctx->ListState, active when the list is known or
* suspected to be outside any begin/end primitive.
*/
static void GLAPIENTRY _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
GET_CURRENT_CONTEXT(ctx);
vbo_save_NotifyBegin( ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK );
CALL_Vertex2f(GET_DISPATCH(), ( x1, y1 ));
CALL_Vertex2f(GET_DISPATCH(), ( x2, y1 ));
CALL_Vertex2f(GET_DISPATCH(), ( x2, y2 ));
CALL_Vertex2f(GET_DISPATCH(), ( x1, y2 ));
CALL_End(GET_DISPATCH(), ());
}
 
 
static void GLAPIENTRY _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
 
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
 
_ae_map_vbos( ctx );
 
vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
 
for (i = 0; i < count; i++)
CALL_ArrayElement(GET_DISPATCH(), (start + i));
CALL_End(GET_DISPATCH(), ());
 
_ae_unmap_vbos( ctx );
}
 
/* Could do better by copying the arrays and element list intact and
* then emitting an indexed prim at runtime.
*/
static void GLAPIENTRY _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
 
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices, 0 ))
return;
 
_ae_map_vbos( ctx );
 
if (_mesa_is_bufferobj(ctx->Array.ElementArrayBufferObj))
indices = ADD_POINTERS(ctx->Array.ElementArrayBufferObj->Pointer, indices);
 
vbo_save_NotifyBegin( ctx, mode | VBO_SAVE_PRIM_WEAK );
 
switch (type) {
case GL_UNSIGNED_BYTE:
for (i = 0 ; i < count ; i++)
CALL_ArrayElement(GET_DISPATCH(), ( ((GLubyte *)indices)[i] ));
break;
case GL_UNSIGNED_SHORT:
for (i = 0 ; i < count ; i++)
CALL_ArrayElement(GET_DISPATCH(), ( ((GLushort *)indices)[i] ));
break;
case GL_UNSIGNED_INT:
for (i = 0 ; i < count ; i++)
CALL_ArrayElement(GET_DISPATCH(), ( ((GLuint *)indices)[i] ));
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
break;
}
 
CALL_End(GET_DISPATCH(), ());
 
_ae_unmap_vbos( ctx );
}
 
static void GLAPIENTRY _save_OBE_DrawRangeElements(GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
if (_mesa_validate_DrawRangeElements( ctx, mode,
start, end,
count, type, indices, 0 ))
_save_OBE_DrawElements( mode, count, type, indices );
}
 
 
 
 
 
static void _save_vtxfmt_init( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLvertexformat *vfmt = &save->vtxfmt;
 
_MESA_INIT_ARRAYELT_VTXFMT(vfmt, _ae_);
 
vfmt->Begin = _save_Begin;
vfmt->Color3f = _save_Color3f;
vfmt->Color3fv = _save_Color3fv;
vfmt->Color4f = _save_Color4f;
vfmt->Color4fv = _save_Color4fv;
vfmt->EdgeFlag = _save_EdgeFlag;
vfmt->End = _save_End;
vfmt->PrimitiveRestartNV = _save_PrimitiveRestartNV;
vfmt->FogCoordfEXT = _save_FogCoordfEXT;
vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
vfmt->Indexf = _save_Indexf;
vfmt->Indexfv = _save_Indexfv;
vfmt->Materialfv = _save_Materialfv;
vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
vfmt->Normal3f = _save_Normal3f;
vfmt->Normal3fv = _save_Normal3fv;
vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
vfmt->TexCoord1f = _save_TexCoord1f;
vfmt->TexCoord1fv = _save_TexCoord1fv;
vfmt->TexCoord2f = _save_TexCoord2f;
vfmt->TexCoord2fv = _save_TexCoord2fv;
vfmt->TexCoord3f = _save_TexCoord3f;
vfmt->TexCoord3fv = _save_TexCoord3fv;
vfmt->TexCoord4f = _save_TexCoord4f;
vfmt->TexCoord4fv = _save_TexCoord4fv;
vfmt->Vertex2f = _save_Vertex2f;
vfmt->Vertex2fv = _save_Vertex2fv;
vfmt->Vertex3f = _save_Vertex3f;
vfmt->Vertex3fv = _save_Vertex3fv;
vfmt->Vertex4f = _save_Vertex4f;
vfmt->Vertex4fv = _save_Vertex4fv;
vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
 
vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
/* integer-valued */
vfmt->VertexAttribI1i = _save_VertexAttribI1i;
vfmt->VertexAttribI2i = _save_VertexAttribI2i;
vfmt->VertexAttribI3i = _save_VertexAttribI3i;
vfmt->VertexAttribI4i = _save_VertexAttribI4i;
vfmt->VertexAttribI2iv = _save_VertexAttribI2iv;
vfmt->VertexAttribI3iv = _save_VertexAttribI3iv;
vfmt->VertexAttribI4iv = _save_VertexAttribI4iv;
 
/* unsigned integer-valued */
vfmt->VertexAttribI1ui = _save_VertexAttribI1ui;
vfmt->VertexAttribI2ui = _save_VertexAttribI2ui;
vfmt->VertexAttribI3ui = _save_VertexAttribI3ui;
vfmt->VertexAttribI4ui = _save_VertexAttribI4ui;
vfmt->VertexAttribI2uiv = _save_VertexAttribI2uiv;
vfmt->VertexAttribI3uiv = _save_VertexAttribI3uiv;
vfmt->VertexAttribI4uiv = _save_VertexAttribI4uiv;
 
/* This will all require us to fallback to saving the list as opcodes:
*/
_MESA_INIT_DLIST_VTXFMT(vfmt, _save_); /* inside begin/end */
 
_MESA_INIT_EVAL_VTXFMT(vfmt, _save_);
 
/* These are all errors as we at least know we are in some sort of
* begin/end pair:
*/
vfmt->Begin = _save_Begin;
vfmt->Rectf = _save_Rectf;
vfmt->DrawArrays = _save_DrawArrays;
vfmt->DrawElements = _save_DrawElements;
vfmt->DrawRangeElements = _save_DrawRangeElements;
vfmt->DrawElementsBaseVertex = _save_DrawElementsBaseVertex;
vfmt->DrawRangeElementsBaseVertex = _save_DrawRangeElementsBaseVertex;
/* Loops back into vfmt->DrawElements */
vfmt->MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
vfmt->MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
}
 
 
void vbo_save_SaveFlushVertices( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
/* Noop when we are actually active:
*/
if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM ||
ctx->Driver.CurrentSavePrimitive <= GL_POLYGON)
return;
 
if (save->vert_count ||
save->prim_count)
_save_compile_vertex_list( ctx );
_save_copy_to_current( ctx );
_save_reset_vertex( ctx );
_save_reset_counters( ctx );
ctx->Driver.SaveNeedFlush = 0;
}
 
void vbo_save_NewList( struct gl_context *ctx, GLuint list, GLenum mode )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
(void) list; (void) mode;
 
if (!save->prim_store)
save->prim_store = alloc_prim_store( ctx );
 
if (!save->vertex_store)
save->vertex_store = alloc_vertex_store( ctx );
save->buffer_ptr = map_vertex_store( ctx, save->vertex_store );
_save_reset_vertex( ctx );
_save_reset_counters( ctx );
ctx->Driver.SaveNeedFlush = 0;
}
 
void vbo_save_EndList( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
/* EndList called inside a (saved) Begin/End pair?
*/
if (ctx->Driver.CurrentSavePrimitive != PRIM_OUTSIDE_BEGIN_END) {
 
if (save->prim_count > 0) {
GLint i = save->prim_count - 1;
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
save->prim[i].end = 0;
save->prim[i].count = (save->vert_count -
save->prim[i].start);
}
 
/* Make sure this vertex list gets replayed by the "loopback"
* mechanism:
*/
save->dangling_attr_ref = 1;
vbo_save_SaveFlushVertices( ctx );
 
/* Swap out this vertex format while outside begin/end. Any color,
* etc. received between here and the next begin will be compiled
* as opcodes.
*/
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
}
 
unmap_vertex_store( ctx, save->vertex_store );
 
assert(save->vertex_size == 0);
}
void vbo_save_BeginCallList( struct gl_context *ctx, struct gl_display_list *dlist )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
save->replay_flags |= dlist->Flags;
}
 
void vbo_save_EndCallList( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
if (ctx->ListState.CallDepth == 1) {
/* This is correct: want to keep only the VBO_SAVE_FALLBACK
* flag, if it is set:
*/
save->replay_flags &= VBO_SAVE_FALLBACK;
}
}
 
 
static void vbo_destroy_vertex_list( struct gl_context *ctx, void *data )
{
struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
(void) ctx;
 
if ( --node->vertex_store->refcount == 0 )
free_vertex_store( ctx, node->vertex_store );
 
if ( --node->prim_store->refcount == 0 )
FREE( node->prim_store );
 
if (node->current_data) {
FREE(node->current_data);
node->current_data = NULL;
}
}
 
 
static void vbo_print_vertex_list( struct gl_context *ctx, void *data )
{
struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *)data;
GLuint i;
(void) ctx;
 
printf("VBO-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n",
node->count,
node->prim_count,
node->vertex_size);
 
for (i = 0 ; i < node->prim_count ; i++) {
struct _mesa_prim *prim = &node->prim[i];
_mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n",
i,
_mesa_lookup_prim_by_nr(prim->mode),
prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
(prim->begin) ? "BEGIN" : "(wrap)",
(prim->end) ? "END" : "(wrap)");
}
}
 
 
static void _save_current_init( struct gl_context *ctx )
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
 
for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_GENERIC15; i++) {
const GLuint j = i - VBO_ATTRIB_POS;
ASSERT(j < VERT_ATTRIB_MAX);
save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j];
save->current[i] = ctx->ListState.CurrentAttrib[j];
}
 
for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) {
const GLuint j = i - VBO_ATTRIB_FIRST_MATERIAL;
ASSERT(j < MAT_ATTRIB_MAX);
save->currentsz[i] = &ctx->ListState.ActiveMaterialSize[j];
save->current[i] = ctx->ListState.CurrentMaterial[j];
}
}
 
/**
* Initialize the display list compiler
*/
void vbo_save_api_init( struct vbo_save_context *save )
{
struct gl_context *ctx = save->ctx;
GLuint i;
 
save->opcode_vertex_list =
_mesa_dlist_alloc_opcode( ctx,
sizeof(struct vbo_save_vertex_list),
vbo_save_playback_vertex_list,
vbo_destroy_vertex_list,
vbo_print_vertex_list );
 
ctx->Driver.NotifySaveBegin = vbo_save_NotifyBegin;
 
_save_vtxfmt_init( ctx );
_save_current_init( ctx );
 
/* These will actually get set again when binding/drawing */
for (i = 0; i < VBO_ATTRIB_MAX; i++)
save->inputs[i] = &save->arrays[i];
 
/* Hook our array functions into the outside-begin-end vtxfmt in
* ctx->ListState.
*/
ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf;
ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays;
ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements;
ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements;
/* loops back into _save_OBE_DrawElements */
ctx->ListState.ListVtxfmt.MultiDrawElementsEXT = _mesa_noop_MultiDrawElements;
ctx->ListState.ListVtxfmt.MultiDrawElementsBaseVertex = _mesa_noop_MultiDrawElementsBaseVertex;
_mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt );
}
 
 
#endif /* FEATURE_dlist */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_save_draw.c
0,0 → 1,303
/*
* Mesa 3-D graphics library
* Version: 7.2
*
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/light.h"
#include "main/state.h"
 
#include "vbo_context.h"
 
 
#if FEATURE_dlist
 
 
/**
* After playback, copy everything but the position from the
* last vertex to the saved state
*/
static void
_playback_copy_to_current(struct gl_context *ctx,
const struct vbo_save_vertex_list *node)
{
struct vbo_context *vbo = vbo_context(ctx);
GLfloat vertex[VBO_ATTRIB_MAX * 4];
GLfloat *data;
GLuint i, offset;
 
if (node->current_size == 0)
return;
 
if (node->current_data) {
data = node->current_data;
}
else {
data = vertex;
 
if (node->count)
offset = (node->buffer_offset +
(node->count-1) * node->vertex_size * sizeof(GLfloat));
else
offset = node->buffer_offset;
 
ctx->Driver.GetBufferSubData( ctx, 0, offset,
node->vertex_size * sizeof(GLfloat),
data, node->vertex_store->bufferobj );
 
data += node->attrsz[0]; /* skip vertex position */
}
 
for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
if (node->attrsz[i]) {
GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
GLfloat tmp[4];
 
COPY_CLEAN_4V(tmp,
node->attrsz[i],
data);
if (memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
memcpy(current, tmp, 4 * sizeof(GLfloat));
 
vbo->currval[i].Size = node->attrsz[i];
 
if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
i <= VBO_ATTRIB_LAST_MATERIAL)
ctx->NewState |= _NEW_LIGHT;
 
ctx->NewState |= _NEW_CURRENT_ATTRIB;
}
 
data += node->attrsz[i];
}
}
 
/* Colormaterial -- this kindof sucks.
*/
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material(ctx, ctx->Current.Attrib[VBO_ATTRIB_COLOR0]);
}
 
/* CurrentExecPrimitive
*/
if (node->prim_count) {
const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
if (prim->end)
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
else
ctx->Driver.CurrentExecPrimitive = prim->mode;
}
}
 
 
 
/**
* Treat the vertex storage as a VBO, define vertex arrays pointing
* into it:
*/
static void vbo_bind_vertex_list(struct gl_context *ctx,
const struct vbo_save_vertex_list *node)
{
struct vbo_context *vbo = vbo_context(ctx);
struct vbo_save_context *save = &vbo->save;
struct gl_client_array *arrays = save->arrays;
GLuint buffer_offset = node->buffer_offset;
const GLuint *map;
GLuint attr;
GLubyte node_attrsz[VBO_ATTRIB_MAX]; /* copy of node->attrsz[] */
GLbitfield varying_inputs = 0x0;
 
memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
 
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
*/
switch (get_program_mode(ctx)) {
case VP_NONE:
for (attr = 0; attr < 16; attr++) {
save->inputs[attr] = &vbo->legacy_currval[attr];
}
for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
save->inputs[attr + 16] = &vbo->mat_currval[attr];
}
map = vbo->map_vp_none;
break;
case VP_NV:
case VP_ARB:
/* The aliasing of attributes for NV vertex programs has already
* occurred. NV vertex programs cannot access material values,
* nor attributes greater than VERT_ATTRIB_TEX7.
*/
for (attr = 0; attr < 16; attr++) {
save->inputs[attr] = &vbo->legacy_currval[attr];
save->inputs[attr + 16] = &vbo->generic_currval[attr];
}
map = vbo->map_vp_arb;
 
/* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
* In that case we effectively need to route the data from
* glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
*/
if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
(ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
save->inputs[16] = save->inputs[0];
node_attrsz[16] = node_attrsz[0];
node_attrsz[0] = 0;
}
break;
default:
assert(0);
}
 
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
const GLuint src = map[attr];
 
if (node_attrsz[src]) {
/* override the default array set above */
save->inputs[attr] = &arrays[attr];
 
arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
arrays[attr].Size = node->attrsz[src];
arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
arrays[attr].Type = GL_FLOAT;
arrays[attr].Format = GL_RGBA;
arrays[attr].Enabled = 1;
_mesa_reference_buffer_object(ctx,
&arrays[attr].BufferObj,
node->vertex_store->bufferobj);
arrays[attr]._MaxElement = node->count; /* ??? */
assert(arrays[attr].BufferObj->Name);
 
buffer_offset += node->attrsz[src] * sizeof(GLfloat);
varying_inputs |= 1<<attr;
}
}
 
_mesa_set_varying_vp_inputs( ctx, varying_inputs );
}
 
 
static void
vbo_save_loopback_vertex_list(struct gl_context *ctx,
const struct vbo_save_vertex_list *list)
{
const char *buffer = ctx->Driver.MapBuffer(ctx,
GL_ARRAY_BUFFER_ARB,
GL_READ_ONLY, /* ? */
list->vertex_store->bufferobj);
 
vbo_loopback_vertex_list(ctx,
(const GLfloat *)(buffer + list->buffer_offset),
list->attrsz,
list->prim,
list->prim_count,
list->wrap_count,
list->vertex_size);
 
ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER_ARB,
list->vertex_store->bufferobj);
}
 
 
/**
* Execute the buffer and save copied verts.
* This is called from the display list code when executing
* a drawing command.
*/
void
vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
{
const struct vbo_save_vertex_list *node =
(const struct vbo_save_vertex_list *) data;
struct vbo_save_context *save = &vbo_context(ctx)->save;
 
FLUSH_CURRENT(ctx, 0);
 
if (node->prim_count > 0 && node->count > 0) {
 
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END &&
node->prim[0].begin) {
 
/* Degenerate case: list is called inside begin/end pair and
* includes operations such as glBegin or glDrawArrays.
*/
if (0)
printf("displaylist recursive begin");
 
vbo_save_loopback_vertex_list( ctx, node );
return;
}
else if (save->replay_flags) {
/* Various degnerate cases: translate into immediate mode
* calls rather than trying to execute in place.
*/
vbo_save_loopback_vertex_list( ctx, node );
return;
}
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;
}
 
vbo_bind_vertex_list( ctx, node );
 
/* Again...
*/
if (ctx->NewState)
_mesa_update_state( ctx );
 
vbo_context(ctx)->draw_prims(ctx,
save->inputs,
node->prim,
node->prim_count,
NULL,
GL_TRUE,
0, /* Node is a VBO, so this is ok */
node->count - 1);
}
 
/* Copy to current?
*/
_playback_copy_to_current( ctx, node );
}
 
 
#endif /* FEATURE_dlist */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_save_loopback.c
0,0 → 1,195
/**************************************************************************
*
* Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "main/context.h"
#include "main/glheader.h"
#include "main/enums.h"
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/dispatch.h"
#include "glapi/glapi.h"
 
#include "vbo_context.h"
 
 
#if FEATURE_dlist
 
 
typedef void (*attr_func)( struct gl_context *ctx, GLint target, const GLfloat * );
 
 
/* This file makes heavy use of the aliasing of NV vertex attributes
* with the legacy attributes, and also with ARB and Material
* attributes as currently implemented.
*/
static void VertexAttrib1fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
}
 
static void VertexAttrib2fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
}
 
static void VertexAttrib3fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
}
 
static void VertexAttrib4fvNV(struct gl_context *ctx, GLint target, const GLfloat *v)
{
CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
}
 
static attr_func vert_attrfunc[4] = {
VertexAttrib1fvNV,
VertexAttrib2fvNV,
VertexAttrib3fvNV,
VertexAttrib4fvNV
};
 
struct loopback_attr {
GLint target;
GLint sz;
attr_func func;
};
 
/* Don't emit ends and begins on wrapped primitives. Don't replay
* wrapped vertices. If we get here, it's probably because the
* precalculated wrapping is wrong.
*/
static void loopback_prim( struct gl_context *ctx,
const GLfloat *buffer,
const struct _mesa_prim *prim,
GLuint wrap_count,
GLuint vertex_size,
const struct loopback_attr *la, GLuint nr )
{
GLint start = prim->start;
GLint end = start + prim->count;
const GLfloat *data;
GLint j;
GLuint k;
 
if (0)
printf("loopback prim %s(%s,%s) verts %d..%d\n",
_mesa_lookup_prim_by_nr(prim->mode),
prim->begin ? "begin" : "..",
prim->end ? "end" : "..",
start,
end);
 
if (prim->begin) {
CALL_Begin(GET_DISPATCH(), ( prim->mode ));
}
else {
assert(start == 0);
start += wrap_count;
}
 
data = buffer + start * vertex_size;
 
for (j = start ; j < end ; j++) {
const GLfloat *tmp = data + la[0].sz;
 
for (k = 1 ; k < nr ; k++) {
la[k].func( ctx, la[k].target, tmp );
tmp += la[k].sz;
}
/* Fire the vertex
*/
la[0].func( ctx, VBO_ATTRIB_POS, data );
data = tmp;
}
 
if (prim->end) {
CALL_End(GET_DISPATCH(), ());
}
}
 
/* Primitives generated by DrawArrays/DrawElements/Rectf may be
* caught here. If there is no primitive in progress, execute them
* normally, otherwise need to track and discard the generated
* primitives.
*/
static void loopback_weak_prim( struct gl_context *ctx,
const struct _mesa_prim *prim )
{
/* Use the prim_weak flag to ensure that if this primitive
* wraps, we don't mistake future vertex_lists for part of the
* surrounding primitive.
*
* While this flag is set, we are simply disposing of data
* generated by an operation now known to be a noop.
*/
if (prim->begin)
ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
if (prim->end)
ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
}
 
 
void vbo_loopback_vertex_list( struct gl_context *ctx,
const GLfloat *buffer,
const GLubyte *attrsz,
const struct _mesa_prim *prim,
GLuint prim_count,
GLuint wrap_count,
GLuint vertex_size)
{
struct loopback_attr la[VBO_ATTRIB_MAX];
GLuint i, nr = 0;
 
/* All Legacy, NV, ARB and Material attributes are routed through
* the NV attributes entrypoints:
*/
for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
if (attrsz[i]) {
la[nr].target = i;
la[nr].sz = attrsz[i];
la[nr].func = vert_attrfunc[attrsz[i]-1];
nr++;
}
}
 
for (i = 0 ; i < prim_count ; i++) {
if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
(ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
{
loopback_weak_prim( ctx, &prim[i] );
}
else
{
loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
}
}
}
 
 
#endif /* FEATURE_dlist */
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_split.c
0,0 → 1,169
 
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
/* Deal with hardware and/or swtnl maximums:
* - maximum number of vertices in buffer
* - maximum number of elements (maybe zero)
*
* The maximums may vary with opengl state (eg if a larger hardware
* vertex is required in this state, the maximum number of vertices
* may be smaller than in another state).
*
* We want buffer splitting to be a convenience function for the code
* actually drawing the primitives rather than a system-wide maximum,
* otherwise it is hard to avoid pessimism.
*
* For instance, if a driver has no hardware limits on vertex buffer
* dimensions, it would not ordinarily want to split vbos. But if
* there is an unexpected fallback, eg memory manager fails to upload
* textures, it will want to pass the drawing commands onto swtnl,
* which does have limitations. A convenience function allows swtnl
* to split the drawing and vbos internally without imposing its
* limitations on drivers which want to use it as a fallback path.
*/
 
#include "main/glheader.h"
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/macros.h"
 
#include "vbo_split.h"
#include "vbo.h"
 
/* True if a primitive can be split without copying of vertices, false
* otherwise.
*/
GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr)
{
switch (mode) {
case GL_POINTS:
*first = 1;
*incr = 1;
return GL_TRUE;
case GL_LINES:
*first = 2;
*incr = 2;
return GL_TRUE;
case GL_LINE_STRIP:
*first = 2;
*incr = 1;
return GL_TRUE;
case GL_TRIANGLES:
*first = 3;
*incr = 3;
return GL_TRUE;
case GL_TRIANGLE_STRIP:
*first = 3;
*incr = 1;
return GL_TRUE;
case GL_QUADS:
*first = 4;
*incr = 4;
return GL_TRUE;
case GL_QUAD_STRIP:
*first = 4;
*incr = 2;
return GL_TRUE;
default:
*first = 0;
*incr = 1; /* so that count % incr works */
return GL_FALSE;
}
}
 
 
 
void vbo_split_prims( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw,
const struct split_limits *limits )
{
GLint max_basevertex = prim->basevertex;
GLuint i;
 
for (i = 1; i < nr_prims; i++)
max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
 
/* XXX max_basevertex is computed but not used, why? */
 
if (ib) {
if (limits->max_indices == 0) {
/* Could traverse the indices, re-emitting vertices in turn.
* But it's hard to see why this case would be needed - for
* software tnl, it is better to convert to non-indexed
* rendering after transformation is complete, as is done in
* the t_dd_rendertmp.h templates. Are there any devices
* with hardware tnl that cannot do indexed rendering?
*
* For now, this path is disabled.
*/
assert(0);
}
else if (max_index - min_index >= limits->max_verts) {
/* The vertex buffers are too large for hardware (or the
* swtnl module). Traverse the indices, re-emitting vertices
* in turn. Use a vertex cache to preserve some of the
* sharing from the original index list.
*/
vbo_split_copy(ctx, arrays, prim, nr_prims, ib,
draw, limits );
}
else if (ib->count > limits->max_indices) {
/* The index buffer is too large for hardware. Try to split
* on whole-primitive boundaries, otherwise try to split the
* individual primitives.
*/
vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
min_index, max_index, draw, limits );
}
else {
/* Why were we called? */
assert(0);
}
}
else {
if (max_index - min_index >= limits->max_verts) {
/* The vertex buffer is too large for hardware (or the swtnl
* module). Try to split on whole-primitive boundaries,
* otherwise try to split the individual primitives.
*/
vbo_split_inplace(ctx, arrays, prim, nr_prims, ib,
min_index, max_index, draw, limits );
}
else {
/* Why were we called? */
assert(0);
}
}
}
 
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_split.h
0,0 → 1,72
/*
* mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file vbo_context.h
* \brief VBO builder module datatypes and definitions.
* \author Keith Whitwell
*/
 
 
/**
* \mainpage The VBO splitter
*
* This is the private data used internally to the vbo_split_prims()
* helper function. Nobody outside the vbo_split* files needs to
* include or know about this structure.
*/
 
 
#ifndef _VBO_SPLIT_H
#define _VBO_SPLIT_H
 
#include "vbo.h"
 
 
/* True if a primitive can be split without copying of vertices, false
* otherwise.
*/
GLboolean split_prim_inplace(GLenum mode, GLuint *first, GLuint *incr);
 
void vbo_split_inplace( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw,
const struct split_limits *limits );
 
/* Requires ib != NULL:
*/
void vbo_split_copy( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
vbo_draw_func draw,
const struct split_limits *limits );
 
#endif
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_split_copy.c
0,0 → 1,625
 
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
/* Split indexed primitives with per-vertex copying.
*/
 
#include "main/glheader.h"
#include "main/bufferobj.h"
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
#include "main/mtypes.h"
 
#include "vbo_split.h"
#include "vbo.h"
 
 
#define ELT_TABLE_SIZE 16
 
/**
* Used for vertex-level splitting of indexed buffers. Note that
* non-indexed primitives may be converted to indexed in some cases
* (eg loops, fans) in order to use this splitting path.
*/
struct copy_context {
 
struct gl_context *ctx;
const struct gl_client_array **array;
const struct _mesa_prim *prim;
GLuint nr_prims;
const struct _mesa_index_buffer *ib;
vbo_draw_func draw;
 
const struct split_limits *limits;
 
struct {
GLuint attr;
GLuint size;
const struct gl_client_array *array;
const GLubyte *src_ptr;
 
struct gl_client_array dstarray;
 
} varying[VERT_ATTRIB_MAX];
GLuint nr_varying;
 
const struct gl_client_array *dstarray_ptr[VERT_ATTRIB_MAX];
struct _mesa_index_buffer dstib;
 
GLuint *translated_elt_buf;
const GLuint *srcelt;
 
/** A baby hash table to avoid re-emitting (some) duplicate
* vertices when splitting indexed primitives.
*/
struct {
GLuint in;
GLuint out;
} vert_cache[ELT_TABLE_SIZE];
 
GLuint vertex_size;
GLubyte *dstbuf;
GLubyte *dstptr; /**< dstptr == dstbuf + dstelt_max * vertsize */
GLuint dstbuf_size; /**< in vertices */
GLuint dstbuf_nr; /**< count of emitted vertices, also the largest value
* in dstelt. Our MaxIndex.
*/
 
GLuint *dstelt;
GLuint dstelt_nr;
GLuint dstelt_size;
 
#define MAX_PRIM 32
struct _mesa_prim dstprim[MAX_PRIM];
GLuint dstprim_nr;
 
};
 
 
static GLuint attr_size( const struct gl_client_array *array )
{
return array->Size * _mesa_sizeof_type(array->Type);
}
 
 
/**
* Starts returning true slightly before the buffer fills, to ensure
* that there is sufficient room for any remaining vertices to finish
* off the prim:
*/
static GLboolean
check_flush( struct copy_context *copy )
{
GLenum mode = copy->dstprim[copy->dstprim_nr].mode;
 
if (GL_TRIANGLE_STRIP == mode &&
copy->dstelt_nr & 1) { /* see bug9962 */
return GL_FALSE;
}
 
if (copy->dstbuf_nr + 4 > copy->dstbuf_size)
return GL_TRUE;
 
if (copy->dstelt_nr + 4 > copy->dstelt_size)
return GL_TRUE;
 
return GL_FALSE;
}
 
 
/**
* Dump the parameters/info for a vbo->draw() call.
*/
static void
dump_draw_info(struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index)
{
GLuint i, j;
 
printf("VBO Draw:\n");
for (i = 0; i < nr_prims; i++) {
printf("Prim %u of %u\n", i, nr_prims);
printf(" Prim mode 0x%x\n", prims[i].mode);
printf(" IB: %p\n", (void*) ib);
for (j = 0; j < VERT_ATTRIB_MAX; j++) {
printf(" array %d at %p:\n", j, (void*) arrays[j]);
printf(" enabled %d, ptr %p, size %d, type 0x%x, stride %d\n",
arrays[j]->Enabled, arrays[j]->Ptr,
arrays[j]->Size, arrays[j]->Type, arrays[j]->StrideB);
if (0) {
GLint k = prims[i].start + prims[i].count - 1;
GLfloat *last = (GLfloat *) (arrays[j]->Ptr + arrays[j]->Stride * k);
printf(" last: %f %f %f\n",
last[0], last[1], last[2]);
}
}
}
}
 
 
static void
flush( struct copy_context *copy )
{
GLuint i;
 
/* Set some counters:
*/
copy->dstib.count = copy->dstelt_nr;
 
#if 0
dump_draw_info(copy->ctx,
copy->dstarray_ptr,
copy->dstprim,
copy->dstprim_nr,
&copy->dstib,
0,
copy->dstbuf_nr);
#else
(void) dump_draw_info;
#endif
 
copy->draw( copy->ctx,
copy->dstarray_ptr,
copy->dstprim,
copy->dstprim_nr,
&copy->dstib,
GL_TRUE,
0,
copy->dstbuf_nr - 1 );
 
/* Reset all pointers:
*/
copy->dstprim_nr = 0;
copy->dstelt_nr = 0;
copy->dstbuf_nr = 0;
copy->dstptr = copy->dstbuf;
 
/* Clear the vertex cache:
*/
for (i = 0; i < ELT_TABLE_SIZE; i++)
copy->vert_cache[i].in = ~0;
}
 
 
/**
* Called at begin of each primitive during replay.
*/
static void
begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
 
prim->mode = mode;
prim->begin = begin_flag;
}
 
 
/**
* Use a hashtable to attempt to identify recently-emitted vertices
* and avoid re-emitting them.
*/
static GLuint
elt(struct copy_context *copy, GLuint elt_idx)
{
GLuint elt = copy->srcelt[elt_idx];
GLuint slot = elt & (ELT_TABLE_SIZE-1);
 
/* printf("elt %d\n", elt); */
 
/* Look up the incoming element in the vertex cache. Re-emit if
* necessary.
*/
if (copy->vert_cache[slot].in != elt) {
GLubyte *csr = copy->dstptr;
GLuint i;
 
/* printf(" --> emit to dstelt %d\n", copy->dstbuf_nr); */
 
for (i = 0; i < copy->nr_varying; i++) {
const struct gl_client_array *srcarray = copy->varying[i].array;
const GLubyte *srcptr = copy->varying[i].src_ptr + elt * srcarray->StrideB;
 
memcpy(csr, srcptr, copy->varying[i].size);
csr += copy->varying[i].size;
 
#ifdef NAN_CHECK
if (srcarray->Type == GL_FLOAT) {
GLuint k;
GLfloat *f = (GLfloat *) srcptr;
for (k = 0; k < srcarray->Size; k++) {
assert(!IS_INF_OR_NAN(f[k]));
assert(f[k] <= 1.0e20 && f[k] >= -1.0e20);
}
}
#endif
 
if (0)
{
const GLuint *f = (const GLuint *)srcptr;
GLuint j;
printf(" varying %d: ", i);
for(j = 0; j < copy->varying[i].size / 4; j++)
printf("%x ", f[j]);
printf("\n");
}
}
 
copy->vert_cache[slot].in = elt;
copy->vert_cache[slot].out = copy->dstbuf_nr++;
copy->dstptr += copy->vertex_size;
 
assert(csr == copy->dstptr);
assert(copy->dstptr == (copy->dstbuf +
copy->dstbuf_nr * copy->vertex_size));
}
/* else */
/* printf(" --> reuse vertex\n"); */
/* printf(" --> emit %d\n", copy->vert_cache[slot].out); */
copy->dstelt[copy->dstelt_nr++] = copy->vert_cache[slot].out;
return check_flush(copy);
}
 
 
/**
* Called at end of each primitive during replay.
*/
static void
end( struct copy_context *copy, GLboolean end_flag )
{
struct _mesa_prim *prim = &copy->dstprim[copy->dstprim_nr];
 
/* printf("end (%d)\n", end_flag); */
 
prim->end = end_flag;
prim->count = copy->dstelt_nr - prim->start;
 
if (++copy->dstprim_nr == MAX_PRIM ||
check_flush(copy))
flush(copy);
}
 
 
static void
replay_elts( struct copy_context *copy )
{
GLuint i, j, k;
GLboolean split;
 
for (i = 0; i < copy->nr_prims; i++) {
const struct _mesa_prim *prim = &copy->prim[i];
const GLuint start = prim->start;
GLuint first, incr;
 
switch (prim->mode) {
case GL_LINE_LOOP:
/* Convert to linestrip and emit the final vertex explicitly,
* but only in the resultant strip that requires it.
*/
j = 0;
while (j != prim->count) {
begin(copy, GL_LINE_STRIP, prim->begin && j == 0);
 
for (split = GL_FALSE; j != prim->count && !split; j++)
split = elt(copy, start + j);
 
if (j == prim->count) {
/* Done, emit final line. Split doesn't matter as
* it is always raised a bit early so we can emit
* the last verts if necessary!
*/
if (prim->end)
(void)elt(copy, start + 0);
 
end(copy, prim->end);
}
else {
/* Wrap
*/
assert(split);
end(copy, 0);
j--;
}
}
break;
 
case GL_TRIANGLE_FAN:
case GL_POLYGON:
j = 2;
while (j != prim->count) {
begin(copy, prim->mode, prim->begin && j == 0);
 
split = elt(copy, start+0);
assert(!split);
 
split = elt(copy, start+j-1);
assert(!split);
 
for (; j != prim->count && !split; j++)
split = elt(copy, start+j);
 
end(copy, prim->end && j == prim->count);
 
if (j != prim->count) {
/* Wrapped the primitive, need to repeat some vertices:
*/
j -= 1;
}
}
break;
 
default:
(void)split_prim_inplace(prim->mode, &first, &incr);
j = 0;
while (j != prim->count) {
 
begin(copy, prim->mode, prim->begin && j == 0);
 
split = 0;
for (k = 0; k < first; k++, j++)
split |= elt(copy, start+j);
 
assert(!split);
 
for (; j != prim->count && !split; )
for (k = 0; k < incr; k++, j++)
split |= elt(copy, start+j);
 
end(copy, prim->end && j == prim->count);
 
if (j != prim->count) {
/* Wrapped the primitive, need to repeat some vertices:
*/
assert(j > first - incr);
j -= (first - incr);
}
}
break;
}
}
 
if (copy->dstprim_nr)
flush(copy);
}
 
 
static void
replay_init( struct copy_context *copy )
{
struct gl_context *ctx = copy->ctx;
GLuint i;
GLuint offset;
const GLvoid *srcptr;
 
/* Make a list of varying attributes and their vbo's. Also
* calculate vertex size.
*/
copy->vertex_size = 0;
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
struct gl_buffer_object *vbo = copy->array[i]->BufferObj;
 
if (copy->array[i]->StrideB == 0) {
copy->dstarray_ptr[i] = copy->array[i];
}
else {
GLuint j = copy->nr_varying++;
copy->varying[j].attr = i;
copy->varying[j].array = copy->array[i];
copy->varying[j].size = attr_size(copy->array[i]);
copy->vertex_size += attr_size(copy->array[i]);
if (_mesa_is_bufferobj(vbo) && !_mesa_bufferobj_mapped(vbo))
ctx->Driver.MapBuffer(ctx, GL_ARRAY_BUFFER, GL_READ_ONLY, vbo);
 
copy->varying[j].src_ptr = ADD_POINTERS(vbo->Pointer,
copy->array[i]->Ptr);
 
copy->dstarray_ptr[i] = &copy->varying[j].dstarray;
}
}
 
/* There must always be an index buffer. Currently require the
* caller convert non-indexed prims to indexed. Could alternately
* do it internally.
*/
if (_mesa_is_bufferobj(copy->ib->obj) &&
!_mesa_bufferobj_mapped(copy->ib->obj))
ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, GL_READ_ONLY,
copy->ib->obj);
 
srcptr = (const GLubyte *) ADD_POINTERS(copy->ib->obj->Pointer,
copy->ib->ptr);
 
switch (copy->ib->type) {
case GL_UNSIGNED_BYTE:
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
copy->srcelt = copy->translated_elt_buf;
 
for (i = 0; i < copy->ib->count; i++)
copy->translated_elt_buf[i] = ((const GLubyte *)srcptr)[i];
break;
 
case GL_UNSIGNED_SHORT:
copy->translated_elt_buf = malloc(sizeof(GLuint) * copy->ib->count);
copy->srcelt = copy->translated_elt_buf;
 
for (i = 0; i < copy->ib->count; i++)
copy->translated_elt_buf[i] = ((const GLushort *)srcptr)[i];
break;
 
case GL_UNSIGNED_INT:
copy->translated_elt_buf = NULL;
copy->srcelt = (const GLuint *)srcptr;
break;
}
 
/* Figure out the maximum allowed vertex buffer size:
*/
if (copy->vertex_size * copy->limits->max_verts <= copy->limits->max_vb_size) {
copy->dstbuf_size = copy->limits->max_verts;
}
else {
copy->dstbuf_size = copy->limits->max_vb_size / copy->vertex_size;
}
 
/* Allocate an output vertex buffer:
*
* XXX: This should be a VBO!
*/
copy->dstbuf = malloc(copy->dstbuf_size * copy->vertex_size);
copy->dstptr = copy->dstbuf;
 
/* Setup new vertex arrays to point into the output buffer:
*/
for (offset = 0, i = 0; i < copy->nr_varying; i++) {
const struct gl_client_array *src = copy->varying[i].array;
struct gl_client_array *dst = &copy->varying[i].dstarray;
 
dst->Size = src->Size;
dst->Type = src->Type;
dst->Format = GL_RGBA;
dst->Stride = copy->vertex_size;
dst->StrideB = copy->vertex_size;
dst->Ptr = copy->dstbuf + offset;
dst->Enabled = GL_TRUE;
dst->Normalized = src->Normalized;
dst->BufferObj = ctx->Shared->NullBufferObj;
dst->_MaxElement = copy->dstbuf_size; /* may be less! */
 
offset += copy->varying[i].size;
}
 
/* Allocate an output element list:
*/
copy->dstelt_size = MIN2(65536,
copy->ib->count * 2 + 3);
copy->dstelt_size = MIN2(copy->dstelt_size,
copy->limits->max_indices);
copy->dstelt = malloc(sizeof(GLuint) * copy->dstelt_size);
copy->dstelt_nr = 0;
 
/* Setup the new index buffer to point to the allocated element
* list:
*/
copy->dstib.count = 0; /* duplicates dstelt_nr */
copy->dstib.type = GL_UNSIGNED_INT;
copy->dstib.obj = ctx->Shared->NullBufferObj;
copy->dstib.ptr = copy->dstelt;
}
 
 
/**
* Free up everything allocated during split/replay.
*/
static void
replay_finish( struct copy_context *copy )
{
struct gl_context *ctx = copy->ctx;
GLuint i;
 
/* Free our vertex and index buffers:
*/
free(copy->translated_elt_buf);
free(copy->dstbuf);
free(copy->dstelt);
 
/* Unmap VBO's
*/
for (i = 0; i < copy->nr_varying; i++) {
struct gl_buffer_object *vbo = copy->varying[i].array->BufferObj;
if (_mesa_is_bufferobj(vbo) && _mesa_bufferobj_mapped(vbo))
ctx->Driver.UnmapBuffer(ctx, GL_ARRAY_BUFFER, vbo);
}
 
/* Unmap index buffer:
*/
if (_mesa_is_bufferobj(copy->ib->obj) &&
_mesa_bufferobj_mapped(copy->ib->obj)) {
ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER, copy->ib->obj);
}
}
 
 
/**
* Split VBO into smaller pieces, draw the pieces.
*/
void vbo_split_copy( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
vbo_draw_func draw,
const struct split_limits *limits )
{
struct copy_context copy;
GLuint i, this_nr_prims;
 
for (i = 0; i < nr_prims;) {
/* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
* will rebase the elements to the basevertex, and we'll only
* emit strings of prims with the same basevertex in one draw call.
*/
for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
this_nr_prims++) {
if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
break;
}
 
memset(&copy, 0, sizeof(copy));
 
/* Require indexed primitives:
*/
assert(ib);
 
copy.ctx = ctx;
copy.array = arrays;
copy.prim = &prim[i];
copy.nr_prims = this_nr_prims;
copy.ib = ib;
copy.draw = draw;
copy.limits = limits;
 
/* Clear the vertex cache:
*/
for (i = 0; i < ELT_TABLE_SIZE; i++)
copy.vert_cache[i].in = ~0;
 
replay_init(&copy);
replay_elts(&copy);
replay_finish(&copy);
}
}
/programs/develop/libraries/Mesa/src/mesa/vbo/vbo_split_inplace.c
0,0 → 1,283
 
/*
* Mesa 3-D graphics library
* Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "main/mtypes.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/image.h"
#include "vbo_split.h"
 
 
#define MAX_PRIM 32
 
/* Used for splitting without copying. No attempt is made to handle
* too large indexed vertex buffers: In general you need to copy to do
* that.
*/
struct split_context {
struct gl_context *ctx;
const struct gl_client_array **array;
const struct _mesa_prim *prim;
GLuint nr_prims;
const struct _mesa_index_buffer *ib;
GLuint min_index;
GLuint max_index;
vbo_draw_func draw;
 
const struct split_limits *limits;
GLuint limit;
 
struct _mesa_prim dstprim[MAX_PRIM];
GLuint dstprim_nr;
};
 
 
 
 
static void flush_vertex( struct split_context *split )
{
struct _mesa_index_buffer ib;
GLuint i;
 
if (!split->dstprim_nr)
return;
 
if (split->ib) {
ib = *split->ib;
 
ib.count = split->max_index - split->min_index + 1;
ib.ptr = (const void *)((const char *)ib.ptr +
split->min_index * _mesa_sizeof_type(ib.type));
 
/* Rebase the primitives to save index buffer entries. */
for (i = 0; i < split->dstprim_nr; i++)
split->dstprim[i].start -= split->min_index;
}
 
assert(split->max_index >= split->min_index);
 
split->draw(split->ctx,
split->array,
split->dstprim,
split->dstprim_nr,
split->ib ? &ib : NULL,
!split->ib,
split->min_index,
split->max_index);
 
split->dstprim_nr = 0;
split->min_index = ~0;
split->max_index = 0;
}
 
 
static struct _mesa_prim *next_outprim( struct split_context *split )
{
if (split->dstprim_nr == MAX_PRIM-1) {
flush_vertex(split);
}
 
{
struct _mesa_prim *prim = &split->dstprim[split->dstprim_nr++];
memset(prim, 0, sizeof(*prim));
return prim;
}
}
 
static void update_index_bounds(struct split_context *split,
const struct _mesa_prim *prim)
{
split->min_index = MIN2(split->min_index, prim->start);
split->max_index = MAX2(split->max_index, prim->start + prim->count - 1);
}
 
/* Return the maximum amount of vertices that can be emitted for a
* primitive starting at 'prim->start', depending on the previous
* index bounds.
*/
static GLuint get_max_vertices(struct split_context *split,
const struct _mesa_prim *prim)
{
if ((prim->start > split->min_index &&
prim->start - split->min_index >= split->limit) ||
(prim->start < split->max_index &&
split->max_index - prim->start >= split->limit))
/* "prim" starts too far away from the old range. */
return 0;
 
return MIN2(split->min_index, prim->start) + split->limit - prim->start;
}
 
/* Break large primitives into smaller ones. If not possible, convert
* the primitive to indexed and pass to split_elts().
*/
static void split_prims( struct split_context *split)
{
GLuint i;
 
for (i = 0; i < split->nr_prims; i++) {
const struct _mesa_prim *prim = &split->prim[i];
GLuint first, incr;
GLboolean split_inplace = split_prim_inplace(prim->mode, &first, &incr);
GLuint available = get_max_vertices(split, prim);
GLuint count = prim->count - (prim->count - first) % incr;
 
if (prim->count < first)
continue;
 
if ((available < count && !split_inplace) ||
(available < first && split_inplace)) {
flush_vertex(split);
available = get_max_vertices(split, prim);
}
if (available >= count) {
struct _mesa_prim *outprim = next_outprim(split);
 
*outprim = *prim;
update_index_bounds(split, outprim);
}
else if (split_inplace) {
GLuint j, nr;
 
for (j = 0 ; j < count ; ) {
GLuint remaining = count - j;
struct _mesa_prim *outprim = next_outprim(split);
 
nr = MIN2( available, remaining );
nr -= (nr - first) % incr;
outprim->mode = prim->mode;
outprim->begin = (j == 0 && prim->begin);
outprim->end = (nr == remaining && prim->end);
outprim->start = prim->start + j;
outprim->count = nr;
 
update_index_bounds(split, outprim);
 
if (nr == remaining) {
/* Finished.
*/
j += nr;
}
else {
/* Wrapped the primitive:
*/
j += nr - (first - incr);
flush_vertex(split);
available = get_max_vertices(split, prim);
}
}
}
else if (split->ib == NULL) {
/* XXX: could at least send the first max_verts off from the
* inplace buffers.
*/
 
/* else convert to indexed primitive and pass to split_elts,
* which will do the necessary copying and turn it back into a
* vertex primitive for rendering...
*/
struct _mesa_index_buffer ib;
struct _mesa_prim tmpprim;
GLuint *elts = malloc(count * sizeof(GLuint));
GLuint j;
for (j = 0; j < count; j++)
elts[j] = prim->start + j;
 
ib.count = count;
ib.type = GL_UNSIGNED_INT;
ib.obj = split->ctx->Shared->NullBufferObj;
ib.ptr = elts;
tmpprim = *prim;
tmpprim.indexed = 1;
tmpprim.start = 0;
tmpprim.count = count;
 
flush_vertex(split);
 
vbo_split_copy(split->ctx,
split->array,
&tmpprim, 1,
&ib,
split->draw,
split->limits);
free(elts);
}
else {
flush_vertex(split);
 
vbo_split_copy(split->ctx,
split->array,
prim, 1,
split->ib,
split->draw,
split->limits);
}
}
 
flush_vertex(split);
}
 
 
void vbo_split_inplace( struct gl_context *ctx,
const struct gl_client_array *arrays[],
const struct _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLuint min_index,
GLuint max_index,
vbo_draw_func draw,
const struct split_limits *limits )
{
struct split_context split;
 
memset(&split, 0, sizeof(split));
 
split.ctx = ctx;
split.array = arrays;
split.prim = prim;
split.nr_prims = nr_prims;
split.ib = ib;
 
/* Empty interval, makes calculations simpler. */
split.min_index = ~0;
split.max_index = 0;
 
split.draw = draw;
split.limits = limits;
split.limit = ib ? limits->max_indices : limits->max_verts;
 
split_prims( &split );
}
 
 
/programs/develop/libraries/Mesa/src/mesa/vbo/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property