Merge vtx-0-2-branch
This commit is contained in:
301
src/mesa/tnl/t_save_loopback.c
Normal file
301
src/mesa/tnl/t_save_loopback.c
Normal file
@@ -0,0 +1,301 @@
|
||||
|
||||
/*
|
||||
* Mesa 3-D graphics library
|
||||
* Version: 5.1
|
||||
*
|
||||
* Copyright (C) 1999-2003 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 "context.h"
|
||||
#include "enums.h"
|
||||
#include "glapi.h"
|
||||
#include "imports.h"
|
||||
#include "macros.h"
|
||||
#include "mtypes.h"
|
||||
#include "t_context.h"
|
||||
#include "t_save_api.h"
|
||||
|
||||
/* If someone compiles a display list like:
|
||||
* glBegin(Triangles)
|
||||
* glVertex()
|
||||
* ... lots of vertices ...
|
||||
* glEnd()
|
||||
*
|
||||
* or:
|
||||
* glDrawArrays(...)
|
||||
*
|
||||
* and then tries to execute it like this:
|
||||
*
|
||||
* glBegin(Lines)
|
||||
* glCallList()
|
||||
* glEnd()
|
||||
*
|
||||
* it will wind up in here, as the vertex copying used when wrapping
|
||||
* buffers in list compilation (Triangles) won't be right for how the
|
||||
* list is being executed (as Lines).
|
||||
*
|
||||
* This could be avoided by not compiling as vertex_lists until after
|
||||
* the first glEnd() has been seen. However, that would miss an
|
||||
* important category of display lists, for the sake of a degenerate
|
||||
* usage.
|
||||
*
|
||||
* Further, replaying degenerately-called lists in this fashion is
|
||||
* probably still faster than the replay using opcodes.
|
||||
*/
|
||||
|
||||
typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
|
||||
|
||||
|
||||
/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */
|
||||
static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->VertexAttrib1fvNV(target, v);
|
||||
}
|
||||
|
||||
static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->VertexAttrib2fvNV(target, v);
|
||||
}
|
||||
|
||||
static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->VertexAttrib3fvNV(target, v);
|
||||
}
|
||||
|
||||
static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->VertexAttrib4fvNV(target, v);
|
||||
}
|
||||
|
||||
static attr_func vert_attrfunc[4] = {
|
||||
VertexAttrib1fvNV,
|
||||
VertexAttrib2fvNV,
|
||||
VertexAttrib3fvNV,
|
||||
VertexAttrib4fvNV
|
||||
};
|
||||
|
||||
|
||||
static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v )
|
||||
{
|
||||
switch (target) {
|
||||
case _TNL_ATTRIB_MAT_FRONT_SHININESS:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_SHININESS, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_SHININESS:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_SHININESS, v );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v )
|
||||
{
|
||||
switch (target) {
|
||||
case _TNL_ATTRIB_MAT_FRONT_INDEXES:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_COLOR_INDEXES, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_INDEXES:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_COLOR_INDEXES, v );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v )
|
||||
{
|
||||
switch (target) {
|
||||
case _TNL_ATTRIB_MAT_FRONT_EMISSION:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_EMISSION, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_EMISSION:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_EMISSION, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_FRONT_AMBIENT:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_AMBIENT, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_AMBIENT:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_AMBIENT, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_FRONT_DIFFUSE:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_DIFFUSE, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_DIFFUSE:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_DIFFUSE, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_FRONT_SPECULAR:
|
||||
ctx->Exec->Materialfv( GL_FRONT, GL_SPECULAR, v );
|
||||
break;
|
||||
case _TNL_ATTRIB_MAT_BACK_SPECULAR:
|
||||
ctx->Exec->Materialfv( GL_BACK, GL_SPECULAR, v );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static attr_func mat_attrfunc[4] = {
|
||||
mat_attr1fv,
|
||||
0,
|
||||
mat_attr3fv,
|
||||
mat_attr4fv
|
||||
};
|
||||
|
||||
|
||||
static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->Indexf(v[0]);
|
||||
}
|
||||
|
||||
static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v)
|
||||
{
|
||||
ctx->Exec->EdgeFlag((v[0] == 1.0));
|
||||
}
|
||||
|
||||
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 the
|
||||
* precalculated wrapping is wrong.
|
||||
*/
|
||||
static void loopback_prim( GLcontext *ctx,
|
||||
struct tnl_vertex_list *list, GLuint i,
|
||||
struct loopback_attr *la, GLuint nr )
|
||||
{
|
||||
struct tnl_prim *prim = &list->prim[i];
|
||||
GLint begin = prim->start;
|
||||
GLint end = begin + prim->count;
|
||||
GLfloat *data;
|
||||
GLint j, k;
|
||||
|
||||
if (prim->mode & PRIM_BEGIN) {
|
||||
glBegin( prim->mode & PRIM_MODE_MASK );
|
||||
} else {
|
||||
assert(i == 0);
|
||||
assert(begin == 0);
|
||||
begin += list->wrap_count;
|
||||
}
|
||||
|
||||
data = list->buffer + begin * list->vertex_size;
|
||||
|
||||
for (j = begin ; j < end ; j++) {
|
||||
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, VERT_ATTRIB_POS, data );
|
||||
data = tmp;
|
||||
}
|
||||
|
||||
if (prim->mode & PRIM_END) {
|
||||
glEnd();
|
||||
}
|
||||
else {
|
||||
assert (i == list->prim_count-1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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( GLcontext *ctx,
|
||||
struct tnl_vertex_list *list, GLuint i,
|
||||
struct loopback_attr *la, GLuint nr )
|
||||
{
|
||||
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
|
||||
loopback_prim( ctx, list, i, la, nr );
|
||||
else {
|
||||
struct tnl_prim *prim = &list->prim[i];
|
||||
|
||||
/* 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->mode & PRIM_BEGIN)
|
||||
ctx->Driver.CurrentExecPrimitive |= PRIM_WEAK;
|
||||
if (prim->mode & PRIM_END)
|
||||
ctx->Driver.CurrentExecPrimitive &= ~PRIM_WEAK;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list )
|
||||
{
|
||||
struct loopback_attr la[_TNL_ATTRIB_MAX];
|
||||
GLuint i, nr = 0;
|
||||
|
||||
for (i = 0 ; i <= _TNL_ATTRIB_TEX7 ; i++) {
|
||||
if (list->attrsz[i]) {
|
||||
la[nr].target = i;
|
||||
la[nr].sz = list->attrsz[i];
|
||||
la[nr].func = vert_attrfunc[list->attrsz[i]-1];
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ;
|
||||
i <= _TNL_ATTRIB_MAT_BACK_INDEXES ;
|
||||
i++) {
|
||||
if (list->attrsz[i]) {
|
||||
la[nr].target = i;
|
||||
la[nr].sz = list->attrsz[i];
|
||||
la[nr].func = mat_attrfunc[list->attrsz[i]-1];
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
|
||||
if (list->attrsz[_TNL_ATTRIB_EDGEFLAG]) {
|
||||
la[nr].target = _TNL_ATTRIB_EDGEFLAG;
|
||||
la[nr].sz = list->attrsz[_TNL_ATTRIB_EDGEFLAG];
|
||||
la[nr].func = edgeflag_attr1fv;
|
||||
nr++;
|
||||
}
|
||||
|
||||
if (list->attrsz[_TNL_ATTRIB_INDEX]) {
|
||||
la[nr].target = _TNL_ATTRIB_INDEX;
|
||||
la[nr].sz = list->attrsz[_TNL_ATTRIB_INDEX];
|
||||
la[nr].func = index_attr1fv;
|
||||
nr++;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < list->prim_count ; i++) {
|
||||
if (list->prim[i].mode & PRIM_WEAK)
|
||||
loopback_weak_prim( ctx, list, i, la, nr );
|
||||
else
|
||||
loopback_prim( ctx, list, i, la, nr );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user