/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.c,v 1.4 2002/02/22 21:32:59 dawes Exp $ * * GLX Hardware Device Driver for Sun Creator/Creator3D * Copyright (C) 2000, 2001 David S. Miller * * 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 * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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. * * * David S. Miller */ #include "ffb_xmesa.h" #include "ffb_context.h" #include "ffb_vb.h" #include "imports.h" #include "tnl/t_context.h" #include "swrast_setup/swrast_setup.h" #include "math/m_translate.h" #undef VB_DEBUG static void ffb_copy_pv_oneside(GLcontext *ctx, GLuint edst, GLuint esrc) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); ffb_vertex *dst = &fmesa->verts[edst]; ffb_vertex *src = &fmesa->verts[esrc]; #ifdef VB_DEBUG fprintf(stderr, "ffb_copy_pv_oneside: edst(%d) esrc(%d)\n", edst, esrc); #endif dst->color[0].alpha = src->color[0].alpha; dst->color[0].red = src->color[0].red; dst->color[0].green = src->color[0].green; dst->color[0].blue = src->color[0].blue; } static void ffb_copy_pv_twoside(GLcontext *ctx, GLuint edst, GLuint esrc) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); ffb_vertex *dst = &fmesa->verts[edst]; ffb_vertex *src = &fmesa->verts[esrc]; #ifdef VB_DEBUG fprintf(stderr, "ffb_copy_pv_twoside: edst(%d) esrc(%d)\n", edst, esrc); #endif dst->color[0].alpha = src->color[0].alpha; dst->color[0].red = src->color[0].red; dst->color[0].green = src->color[0].green; dst->color[0].blue = src->color[0].blue; dst->color[1].alpha = src->color[1].alpha; dst->color[1].red = src->color[1].red; dst->color[1].green = src->color[1].green; dst->color[1].blue = src->color[1].blue; } #define FFB_VB_RGBA_BIT 0x01 #define FFB_VB_XYZ_BIT 0x02 #define FFB_VB_TWOSIDE_BIT 0x04 #define FFB_VB_MAX 0x08 typedef void (*emit_func)(GLcontext *, GLuint, GLuint); static struct { emit_func emit; interp_func interp; } setup_tab[FFB_VB_MAX]; static void do_import(struct vertex_buffer *VB, struct gl_client_array *to, struct gl_client_array *from) { GLuint count = VB->Count; if (!to->Ptr) { to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 ); to->Type = GL_FLOAT; } /* No need to transform the same value 3000 times. */ if (!from->StrideB) { to->StrideB = 0; count = 1; } else to->StrideB = 4 * sizeof(GLfloat); _math_trans_4f((GLfloat (*)[4]) to->Ptr, from->Ptr, from->StrideB, from->Type, from->Size, 0, count); } static __inline__ void ffbImportColors(ffbContextPtr fmesa, GLcontext *ctx, int index) { struct gl_client_array *to = &fmesa->FloatColor; struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; do_import(VB, to, VB->ColorPtr[index]); VB->ColorPtr[index] = to; } #define IND (FFB_VB_XYZ_BIT) #define TAG(x) x##_w #include "ffb_vbtmp.h" #define IND (FFB_VB_RGBA_BIT) #define TAG(x) x##_g #include "ffb_vbtmp.h" #define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT) #define TAG(x) x##_wg #include "ffb_vbtmp.h" #define IND (FFB_VB_TWOSIDE_BIT) #define TAG(x) x##_t #include "ffb_vbtmp.h" #define IND (FFB_VB_XYZ_BIT | FFB_VB_TWOSIDE_BIT) #define TAG(x) x##_wt #include "ffb_vbtmp.h" #define IND (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT) #define TAG(x) x##_gt #include "ffb_vbtmp.h" #define IND (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT) #define TAG(x) x##_wgt #include "ffb_vbtmp.h" static void init_setup_tab( void ) { init_w(); init_g(); init_wg(); init_t(); init_wt(); init_gt(); init_wgt(); } #ifdef VB_DEBUG static void ffbPrintSetupFlags(char *msg, GLuint flags) { fprintf(stderr, "%s(%x): %s%s%s\n", msg, (int)flags, (flags & FFB_VB_XYZ_BIT) ? " xyz," : "", (flags & FFB_VB_RGBA_BIT) ? " rgba," : "", (flags & FFB_VB_TWOSIDE_BIT) ? " twoside," : ""); } #endif static void ffbDDBuildVertices(GLcontext *ctx, GLuint start, GLuint count, GLuint newinputs) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); newinputs |= fmesa->setupnewinputs; fmesa->setupnewinputs = 0; if (!newinputs) return; if (newinputs & VERT_BIT_CLIP) { setup_tab[fmesa->setupindex].emit(ctx, start, count); } else { GLuint ind = 0; if (newinputs & VERT_BIT_COLOR0) ind |= (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT); ind &= fmesa->setupindex; if (ind) setup_tab[ind].emit(ctx, start, count); } } void ffbChooseVertexState( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); ffbContextPtr fmesa = FFB_CONTEXT(ctx); int ind = FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT; if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ind |= FFB_VB_TWOSIDE_BIT; #ifdef VB_DEBUG ffbPrintSetupFlags("ffb: full setup function", ind); #endif fmesa->setupindex = ind; tnl->Driver.Render.BuildVertices = ffbDDBuildVertices; tnl->Driver.Render.Interp = setup_tab[ind].interp; if (ind & FFB_VB_TWOSIDE_BIT) tnl->Driver.Render.CopyPV = ffb_copy_pv_twoside; else tnl->Driver.Render.CopyPV = ffb_copy_pv_oneside; } void ffbInitVB( GLcontext *ctx ) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); GLuint size = TNL_CONTEXT(ctx)->vb.Size; fmesa->verts = (ffb_vertex *)ALIGN_MALLOC(size * sizeof(ffb_vertex), 32); { static int firsttime = 1; if (firsttime) { init_setup_tab(); firsttime = 0; } } } void ffbFreeVB( GLcontext *ctx ) { ffbContextPtr fmesa = FFB_CONTEXT(ctx); if (fmesa->verts) { ALIGN_FREE(fmesa->verts); fmesa->verts = 0; } }