| /* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vtxfmt.c,v 1.1 2002/02/22 21:32:59 dawes Exp $ |
| * |
| * GLX Hardware Device Driver for Sun Creator/Creator3D |
| * Copyright (C) 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 <davem@redhat.com> |
| */ |
| |
| #include "glheader.h" |
| #include "api_noop.h" |
| #include "context.h" |
| #include "light.h" |
| #include "macros.h" |
| #include "imports.h" |
| #include "mtypes.h" |
| #include "simple_list.h" |
| #include "vtxfmt.h" |
| #include "ffb_xmesa.h" |
| #include "ffb_context.h" |
| #include "ffb_vb.h" |
| #include "tnl/tnl.h" |
| #include "tnl/t_context.h" |
| |
| #include "ffb_vtxfmt.h" |
| |
| #define TNL_VERTEX ffbTnlVertex |
| |
| #define INTERP_RGBA(t, out, a, b) \ |
| do { \ |
| GLint i; \ |
| for ( i = 0 ; i < 4 ; i++ ) { \ |
| GLfloat fa = a[i]; \ |
| GLfloat fb = b[i]; \ |
| out[i] = LINTERP( t, fa, fb ); \ |
| } \ |
| } while (0) |
| |
| /* Color functions: */ |
| |
| static INLINE void ffb_recalc_base_color(GLcontext *ctx) |
| { |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); |
| struct gl_light *light; |
| |
| COPY_3V(fmesa->vtx_state.light.base_color, ctx->Light._BaseColor[0]); |
| foreach (light, &ctx->Light.EnabledList) { |
| ACC_3V(fmesa->vtx_state.light.base_color, |
| light->_MatAmbient[0]); |
| } |
| |
| fmesa->vtx_state.light.base_alpha = ctx->Light._BaseAlpha[0]; |
| } |
| |
| #define GET_CURRENT \ |
| GET_CURRENT_CONTEXT(ctx); \ |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx) |
| |
| #define CURRENT_COLOR(COMP) fmesa->vtx_state.current.color[COMP] |
| #define CURRENT_SPECULAR(COMP) fmesa->vtx_state.current.specular[COMP] |
| #define COLOR_IS_FLOAT |
| #define RECALC_BASE_COLOR(ctx) ffb_recalc_base_color(ctx) |
| |
| #define TAG(x) ffb_##x |
| #include "tnl_dd/t_dd_imm_capi.h" |
| |
| /* Normal functions: */ |
| |
| struct ffb_norm_tab { |
| void (*normal3f_multi)(GLfloat x, GLfloat y, GLfloat z); |
| void (*normal3fv_multi)(const GLfloat *v); |
| void (*normal3f_single)(GLfloat x, GLfloat y, GLfloat z); |
| void (*normal3fv_single)(const GLfloat *v); |
| }; |
| |
| static struct ffb_norm_tab norm_tab[0x4]; |
| |
| #define HAVE_HW_LIGHTING 0 |
| #define GET_CURRENT_VERTEX \ |
| GET_CURRENT_CONTEXT(ctx); \ |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ |
| ffbTnlVertexPtr v = fmesa->imm.v0 |
| |
| #define CURRENT_NORMAL fmesa->vtx_state.current.normal |
| #define BASE_COLOR fmesa->vtx_state.light.base_color |
| #define BASE_ALPHA fmesa->vtx_state.light.base_alpha |
| #define VERT_COLOR( COMP ) v->color[COMP] |
| #define VERT_COLOR_IS_FLOAT |
| |
| #define IND (0) |
| #define TAG(x) ffb_##x |
| #define PRESERVE_NORMAL_DEFS |
| #include "tnl_dd/t_dd_imm_napi.h" |
| |
| #define IND (NORM_RESCALE) |
| #define TAG(x) ffb_##x##_rescale |
| #define PRESERVE_NORMAL_DEFS |
| #include "tnl_dd/t_dd_imm_napi.h" |
| |
| #define IND (NORM_NORMALIZE) |
| #define TAG(x) ffb_##x##_normalize |
| #include "tnl_dd/t_dd_imm_napi.h" |
| |
| static void ffb_init_norm_funcs(void) |
| { |
| ffb_init_norm(); |
| ffb_init_norm_rescale(); |
| ffb_init_norm_normalize(); |
| } |
| |
| static void choose_normals(void) |
| { |
| GET_CURRENT_CONTEXT(ctx); |
| GLuint index; |
| |
| if (ctx->Light.Enabled) { |
| if (ctx->Transform.Normalize) { |
| index = NORM_NORMALIZE; |
| } else if (!ctx->Transform.RescaleNormals && |
| ctx->_ModelViewInvScale != 1.0) { |
| index = NORM_RESCALE; |
| } else { |
| index = 0; |
| } |
| |
| if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) { |
| SET_Normal3f(ctx->Exec, norm_tab[index].normal3f_single); |
| SET_Normal3fv(ctx->Exec, norm_tab[index].normal3fv_single); |
| } else { |
| SET_Normal3f(ctx->Exec, norm_tab[index].normal3f_multi); |
| SET_Normal3fv(ctx->Exec, norm_tab[index].normal3fv_multi); |
| } |
| } else { |
| SET_Normal3f(ctx->Exec, _mesa_noop_Normal3f); |
| SET_Normal3fv(ctx->Exec, _mesa_noop_Normal3fv); |
| } |
| } |
| |
| static void ffb_choose_Normal3f(GLfloat x, GLfloat y, GLfloat z) |
| { |
| choose_normals(); |
| CALL_Normal3f(GET_DISPATCH(), (x, y, z)); |
| } |
| |
| static void ffb_choose_Normal3fv(const GLfloat *v) |
| { |
| choose_normals(); |
| CALL_Normal3fv(GET_DISPATCH(), (v)); |
| } |
| |
| /* Vertex functions: */ |
| |
| #define GET_CURRENT_VERTEX \ |
| GET_CURRENT_CONTEXT(ctx); \ |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); \ |
| ffbTnlVertexPtr v = fmesa->imm.v0 |
| |
| #define CURRENT_VERTEX v->obj |
| #define SAVE_VERTEX fmesa->imm.save_vertex(ctx, v) |
| |
| #define TAG(x) ffb_##x |
| #include "tnl_dd/t_dd_imm_vapi.h" |
| |
| struct ffb_vert_tab { |
| void (*save_vertex)(GLcontext *ctx, ffbTnlVertexPtr v); |
| void (*interpolate_vertex)(GLfloat t, |
| ffbTnlVertex *O, |
| const ffbTnlVertex *I, |
| const ffbTnlVertex *J); |
| }; |
| |
| static struct ffb_vert_tab vert_tab[0xf]; |
| |
| #define VTX_NORMAL 0x0 |
| #define VTX_RGBA 0x1 |
| |
| #define LOCAL_VARS \ |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx) |
| |
| #define CURRENT_COLOR fmesa->vtx_state.current.color |
| #define COLOR_IS_FLOAT |
| #define FLUSH_VERTEX fmesa->imm.flush_vertex( ctx, v ); |
| |
| #define IND (VTX_NORMAL) |
| #define TAG(x) ffb_##x##_NORMAL |
| #define PRESERVE_VERTEX_DEFS |
| #include "tnl_dd/t_dd_imm_vertex.h" |
| |
| #define IND (VTX_RGBA) |
| #define TAG(x) ffb_##x##_RGBA |
| #include "tnl_dd/t_dd_imm_vertex.h" |
| |
| static void ffb_init_vert_funcs( void ) |
| { |
| ffb_init_vert_NORMAL(); |
| ffb_init_vert_RGBA(); |
| } |
| |
| #define LOCAL_VARS \ |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx) |
| |
| #define GET_INTERP_FUNC \ |
| ffb_interp_func interp = fmesa->imm.interp |
| |
| #define FLUSH_VERTEX fmesa->imm.flush_vertex |
| #define IMM_VERTEX( V ) fmesa->imm.V |
| #define IMM_VERTICES( n ) fmesa->imm.vertices[n] |
| |
| #define EMIT_VERTEX_USES_HWREGS |
| |
| /* XXX Implement me XXX */ |
| #define EMIT_VERTEX_TRI(VTX0, VTX1, VTX2) \ |
| do { } while (0) |
| #define EMIT_VERTEX_LINE(VTX0, VTX1) \ |
| do { } while (0) |
| #define EMIT_VERTEX_POINT(VTX0) \ |
| do { } while (0) |
| |
| #define TAG(x) ffb_##x |
| #include "tnl_dd/t_dd_imm_primtmp.h" |
| |
| /* Bzzt: Material changes are lost on fallback. */ |
| static void ffb_Materialfv(GLenum face, GLenum pname, |
| const GLfloat *params) |
| { |
| GET_CURRENT_CONTEXT(ctx); |
| |
| _mesa_noop_Materialfv( face, pname, params ); |
| ffb_recalc_base_color( ctx ); |
| } |
| |
| /* Fallback functions: */ |
| |
| static void ffb_do_fallback(GLcontext *ctx) |
| { |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); |
| struct ffb_current_state *current = &fmesa->vtx_state.current; |
| |
| /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks |
| * and revive internal state that depended on those callbacks: |
| */ |
| _tnl_wakeup_exec(ctx); |
| |
| /* Replay enough vertices that the current primitive is continued |
| * correctly: |
| */ |
| if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END ) |
| CALL_Begin(GET_DISPATCH(), (fmesa->imm.prim)); |
| |
| if (ctx->Light.Enabled) { |
| /* Catch ColorMaterial */ |
| CALL_Color4fv(GET_DISPATCH(), (ctx->Current.Color)); |
| CALL_Normal3fv(GET_DISPATCH(), (current->normal)); |
| } else { |
| CALL_Color4fv(GET_DISPATCH(), (current->color)); |
| } |
| } |
| |
| #define PRE_LOOPBACK( FUNC ) do { \ |
| GET_CURRENT_CONTEXT(ctx); \ |
| ffb_do_fallback( ctx ); \ |
| } while (0) |
| |
| #define TAG(x) ffb_fallback_##x |
| #include "vtxfmt_tmp.h" |
| |
| static void ffb_Begin(GLenum prim) |
| { |
| GET_CURRENT_CONTEXT(ctx); |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); |
| |
| if (prim > GL_POLYGON) { |
| _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); |
| return; |
| } |
| |
| if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END) { |
| _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); |
| return; |
| } |
| |
| ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES | |
| FLUSH_UPDATE_CURRENT); |
| |
| fmesa->imm.prim = prim; |
| fmesa->imm.v0 = &fmesa->imm.vertices[0]; |
| fmesa->imm.save_vertex = ffb_save_vertex_RGBA; |
| fmesa->imm.flush_vertex = ffb_flush_tab[prim]; |
| |
| /* XXX Lock hardware, update FBC, PPC, DRAWOP, etc. XXX */ |
| } |
| |
| static void ffb_End(void) |
| { |
| GET_CURRENT_CONTEXT(ctx); |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); |
| |
| if (fmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END) { |
| _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); |
| return; |
| } |
| |
| fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; |
| |
| ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES | |
| FLUSH_UPDATE_CURRENT); |
| |
| /* XXX Unlock hardware, etc. */ |
| } |
| |
| void ffbInitTnlModule(GLcontext *ctx) |
| { |
| ffbContextPtr fmesa = FFB_CONTEXT(ctx); |
| GLvertexformat *vfmt = &(fmesa->imm.vtxfmt); |
| |
| /* Work in progress... */ |
| return; |
| |
| ffb_init_norm_funcs(); |
| ffb_init_vert_funcs(); |
| |
| /* start by initializing to no-op functions */ |
| _mesa_noop_vtxfmt_init(vfmt); |
| |
| /* Handled fully in supported states: */ |
| vfmt->ArrayElement = NULL; /* FIXME: ... */ |
| vfmt->Color3f = ffb_choose_Color3f; |
| vfmt->Color3fv = ffb_choose_Color3fv; |
| vfmt->Color3ub = ffb_choose_Color3ub; |
| vfmt->Color3ubv = ffb_choose_Color3ubv; |
| vfmt->Color4f = ffb_choose_Color4f; |
| vfmt->Color4fv = ffb_choose_Color4fv; |
| vfmt->Color4ub = ffb_choose_Color4ub; |
| vfmt->Color4ubv = ffb_choose_Color4ubv; |
| vfmt->FogCoordfvEXT = ffb_FogCoordfvEXT; |
| vfmt->FogCoordfEXT = ffb_FogCoordfEXT; |
| vfmt->Materialfv = ffb_Materialfv; |
| vfmt->MultiTexCoord1fARB = ffb_fallback_MultiTexCoord1fARB; |
| vfmt->MultiTexCoord1fvARB = ffb_fallback_MultiTexCoord1fvARB; |
| vfmt->MultiTexCoord2fARB = ffb_fallback_MultiTexCoord2fARB; |
| vfmt->MultiTexCoord2fvARB = ffb_fallback_MultiTexCoord2fvARB; |
| vfmt->MultiTexCoord3fARB = ffb_fallback_MultiTexCoord3fARB; |
| vfmt->MultiTexCoord3fvARB = ffb_fallback_MultiTexCoord3fvARB; |
| vfmt->MultiTexCoord4fARB = ffb_fallback_MultiTexCoord4fARB; |
| vfmt->MultiTexCoord4fvARB = ffb_fallback_MultiTexCoord4fvARB; |
| vfmt->Normal3f = ffb_choose_Normal3f; |
| vfmt->Normal3fv = ffb_choose_Normal3fv; |
| vfmt->SecondaryColor3ubEXT = ffb_SecondaryColor3ubEXT; |
| vfmt->SecondaryColor3ubvEXT = ffb_SecondaryColor3ubvEXT; |
| vfmt->SecondaryColor3fEXT = ffb_SecondaryColor3fEXT; |
| vfmt->SecondaryColor3fvEXT = ffb_SecondaryColor3fvEXT; |
| vfmt->TexCoord1f = ffb_fallback_TexCoord1f; |
| vfmt->TexCoord1fv = ffb_fallback_TexCoord1fv; |
| vfmt->TexCoord2f = ffb_fallback_TexCoord2f; |
| vfmt->TexCoord2fv = ffb_fallback_TexCoord2fv; |
| vfmt->TexCoord3f = ffb_fallback_TexCoord3f; |
| vfmt->TexCoord3fv = ffb_fallback_TexCoord3fv; |
| vfmt->TexCoord4f = ffb_fallback_TexCoord4f; |
| vfmt->TexCoord4fv = ffb_fallback_TexCoord4fv; |
| |
| vfmt->Vertex2f = ffb_Vertex2f; |
| vfmt->Vertex2fv = ffb_Vertex2fv; |
| vfmt->Vertex3f = ffb_Vertex3f; |
| vfmt->Vertex3fv = ffb_Vertex3fv; |
| vfmt->Vertex4f = ffb_Vertex4f; |
| vfmt->Vertex4fv = ffb_Vertex4fv; |
| |
| vfmt->Begin = ffb_Begin; |
| vfmt->End = ffb_End; |
| |
| vfmt->DrawArrays = NULL; |
| vfmt->DrawElements = NULL; |
| |
| /* Active but unsupported -- fallback if we receive these: |
| * |
| * All of these fallbacks can be fixed with additional code, except |
| * CallList, unless we build a play_immediate_noop() command which |
| * turns an immediate back into glBegin/glEnd commands... |
| */ |
| vfmt->CallList = ffb_fallback_CallList; |
| vfmt->EvalCoord1f = ffb_fallback_EvalCoord1f; |
| vfmt->EvalCoord1fv = ffb_fallback_EvalCoord1fv; |
| vfmt->EvalCoord2f = ffb_fallback_EvalCoord2f; |
| vfmt->EvalCoord2fv = ffb_fallback_EvalCoord2fv; |
| vfmt->EvalMesh1 = ffb_fallback_EvalMesh1; |
| vfmt->EvalMesh2 = ffb_fallback_EvalMesh2; |
| vfmt->EvalPoint1 = ffb_fallback_EvalPoint1; |
| vfmt->EvalPoint2 = ffb_fallback_EvalPoint2; |
| |
| vfmt->prefer_float_colors = GL_TRUE; |
| |
| fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END; |
| |
| /* THIS IS A HACK! */ |
| _mesa_install_exec_vtxfmt( ctx, vfmt ); |
| } |