2 * GLX Hardware Device Driver for Intel i810
3 * Copyright (C) 1999 Keith Whitwell
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
21 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 /* $XFree86: xc/lib/GL/mesa/src/drv/tdfx/tdfx_vb.c,v 1.3 2002/10/30 12:52:01 alanh Exp $ */
33 #include "math/m_translate.h"
34 #include "swrast_setup/swrast_setup.h"
36 #include "tdfx_context.h"
38 #include "tdfx_tris.h"
39 #include "tdfx_state.h"
40 #include "tdfx_render.h"
42 static void copy_pv_rgba4( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
44 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
45 GLubyte
*tdfxverts
= (GLubyte
*)fxMesa
->verts
;
46 GLuint shift
= fxMesa
->vertex_stride_shift
;
47 tdfxVertex
*dst
= (tdfxVertex
*)(tdfxverts
+ (edst
<< shift
));
48 tdfxVertex
*src
= (tdfxVertex
*)(tdfxverts
+ (esrc
<< shift
));
49 dst
->ui
[4] = src
->ui
[4];
52 static void copy_pv_rgba3( GLcontext
*ctx
, GLuint edst
, GLuint esrc
)
54 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
55 GLubyte
*tdfxverts
= (GLubyte
*)fxMesa
->verts
;
56 GLuint shift
= fxMesa
->vertex_stride_shift
;
57 tdfxVertex
*dst
= (tdfxVertex
*)(tdfxverts
+ (edst
<< shift
));
58 tdfxVertex
*src
= (tdfxVertex
*)(tdfxverts
+ (esrc
<< shift
));
59 dst
->ui
[3] = src
->ui
[3];
62 typedef void (*emit_func
)( GLcontext
*, GLuint
, GLuint
, void *, GLuint
);
68 GLboolean (*check_tex_sizes
)( GLcontext
*ctx
);
70 GLuint vertex_stride_shift
;
72 } setup_tab
[TDFX_MAX_SETUP
];
75 static void import_float_colors( GLcontext
*ctx
)
77 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
78 struct gl_client_array
*from
= VB
->ColorPtr
[0];
79 struct gl_client_array
*to
= &TDFX_CONTEXT(ctx
)->UbyteColor
;
80 GLuint count
= VB
->Count
;
83 to
->Ptr
= ALIGN_MALLOC( VB
->Size
* 4 * sizeof(GLubyte
), 32 );
84 to
->Type
= GL_UNSIGNED_BYTE
;
87 /* No need to transform the same value 3000 times.
94 to
->StrideB
= 4 * sizeof(GLubyte
);
96 _math_trans_4ub( (GLubyte (*)[4]) to
->Ptr
,
104 VB
->ColorPtr
[0] = to
;
108 #define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
111 static void interp_extras( GLcontext
*ctx
,
113 GLuint dst
, GLuint out
, GLuint in
,
114 GLboolean force_boundary
)
116 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
118 /*fprintf(stderr, "%s\n", __FUNCTION__);*/
120 if (VB
->ColorPtr
[1]) {
122 GET_COLOR(VB
->ColorPtr
[1], dst
),
123 GET_COLOR(VB
->ColorPtr
[1], out
),
124 GET_COLOR(VB
->ColorPtr
[1], in
) );
128 VB
->EdgeFlag
[dst
] = VB
->EdgeFlag
[out
] || force_boundary
;
131 setup_tab
[TDFX_CONTEXT(ctx
)->SetupIndex
].interp(ctx
, t
, dst
, out
, in
,
135 static void copy_pv_extras( GLcontext
*ctx
, GLuint dst
, GLuint src
)
137 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
139 if (VB
->ColorPtr
[1]) {
140 COPY_CHAN4( GET_COLOR(VB
->ColorPtr
[1], dst
),
141 GET_COLOR(VB
->ColorPtr
[1], src
) );
144 setup_tab
[TDFX_CONTEXT(ctx
)->SetupIndex
].copy_pv(ctx
, dst
, src
);
149 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT)
150 #define TAG(x) x##_wg
151 #include "tdfx_vbtmp.h"
153 /* Special for tdfx: fog requires w
155 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT)
156 #define TAG(x) x##_wg_fog
157 #include "tdfx_vbtmp.h"
159 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT)
160 #define TAG(x) x##_wgt0
161 #include "tdfx_vbtmp.h"
163 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
164 #define TAG(x) x##_wgt0t1
165 #include "tdfx_vbtmp.h"
167 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_PTEX_BIT)
168 #define TAG(x) x##_wgpt0
169 #include "tdfx_vbtmp.h"
171 #define IND (TDFX_XYZ_BIT|TDFX_RGBA_BIT|TDFX_W_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT|\
173 #define TAG(x) x##_wgpt0t1
174 #include "tdfx_vbtmp.h"
176 #define IND (TDFX_RGBA_BIT)
178 #include "tdfx_vbtmp.h"
180 #define IND (TDFX_TEX0_BIT)
181 #define TAG(x) x##_t0
182 #include "tdfx_vbtmp.h"
184 #define IND (TDFX_TEX0_BIT|TDFX_TEX1_BIT)
185 #define TAG(x) x##_t0t1
186 #include "tdfx_vbtmp.h"
188 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT)
189 #define TAG(x) x##_gt0
190 #include "tdfx_vbtmp.h"
192 #define IND (TDFX_RGBA_BIT|TDFX_TEX0_BIT|TDFX_TEX1_BIT)
193 #define TAG(x) x##_gt0t1
194 #include "tdfx_vbtmp.h"
198 static void init_setup_tab( void )
215 void tdfxPrintSetupFlags(char *msg
, GLuint flags
)
217 fprintf(stderr
, "%s(%x): %s%s%s%s%s\n",
220 (flags
& TDFX_XYZ_BIT
) ? " xyz," : "",
221 (flags
& TDFX_W_BIT
) ? " w," : "",
222 (flags
& TDFX_RGBA_BIT
) ? " rgba," : "",
223 (flags
& TDFX_TEX0_BIT
) ? " tex-0," : "",
224 (flags
& TDFX_TEX1_BIT
) ? " tex-1," : "");
229 void tdfxCheckTexSizes( GLcontext
*ctx
)
231 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
232 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
234 if (!setup_tab
[fxMesa
->SetupIndex
].check_tex_sizes(ctx
)) {
235 GLuint ind
= fxMesa
->SetupIndex
|= (TDFX_PTEX_BIT
|TDFX_RGBA_BIT
);
237 /* Tdfx handles projective textures nicely; just have to change
238 * up to the new vertex format.
240 if (setup_tab
[ind
].vertex_format
!= fxMesa
->vertexFormat
) {
242 fxMesa
->dirty
|= TDFX_UPLOAD_VERTEX_LAYOUT
;
243 fxMesa
->vertexFormat
= setup_tab
[ind
].vertex_format
;
244 fxMesa
->vertex_stride_shift
= setup_tab
[ind
].vertex_stride_shift
;
246 /* This is required as we have just changed the vertex
247 * format, so the interp and copy routines must also change.
248 * In the unfilled and twosided cases we are using the
249 * swrast_setup ones anyway, so leave them in place.
251 if (!(ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
252 tnl
->Driver
.Render
.Interp
= setup_tab
[fxMesa
->SetupIndex
].interp
;
253 tnl
->Driver
.Render
.CopyPV
= setup_tab
[fxMesa
->SetupIndex
].copy_pv
;
260 void tdfxBuildVertices( GLcontext
*ctx
, GLuint start
, GLuint count
,
263 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
264 GLubyte
*v
= (fxMesa
->verts
+ (start
<<fxMesa
->vertex_stride_shift
));
265 GLuint stride
= 1<<fxMesa
->vertex_stride_shift
;
267 newinputs
|= fxMesa
->SetupNewInputs
;
268 fxMesa
->SetupNewInputs
= 0;
273 if (newinputs
& VERT_BIT_CLIP
) {
274 setup_tab
[fxMesa
->SetupIndex
].emit( ctx
, start
, count
, v
, stride
);
278 if (newinputs
& VERT_BIT_COLOR0
)
279 ind
|= TDFX_RGBA_BIT
;
281 if (newinputs
& VERT_BIT_TEX0
)
282 ind
|= TDFX_TEX0_BIT
;
284 if (newinputs
& VERT_BIT_TEX1
)
285 ind
|= TDFX_TEX0_BIT
|TDFX_TEX1_BIT
;
287 if (fxMesa
->SetupIndex
& TDFX_PTEX_BIT
)
290 ind
&= fxMesa
->SetupIndex
;
293 setup_tab
[ind
].emit( ctx
, start
, count
, v
, stride
);
299 void tdfxChooseVertexState( GLcontext
*ctx
)
301 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
302 tdfxContextPtr fxMesa
= TDFX_CONTEXT( ctx
);
303 GLuint ind
= TDFX_XYZ_BIT
|TDFX_RGBA_BIT
;
305 if (ctx
->Texture
._EnabledUnits
& 0x2)
307 ind
|= TDFX_W_BIT
|TDFX_TEX1_BIT
|TDFX_TEX0_BIT
;
308 else if (ctx
->Texture
._EnabledUnits
& 0x1)
310 ind
|= TDFX_W_BIT
|TDFX_TEX0_BIT
;
311 else if (ctx
->Fog
.Enabled
)
314 fxMesa
->SetupIndex
= ind
;
316 if (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
)) {
317 tnl
->Driver
.Render
.Interp
= interp_extras
;
318 tnl
->Driver
.Render
.CopyPV
= copy_pv_extras
;
320 tnl
->Driver
.Render
.Interp
= setup_tab
[ind
].interp
;
321 tnl
->Driver
.Render
.CopyPV
= setup_tab
[ind
].copy_pv
;
324 if (setup_tab
[ind
].vertex_format
!= fxMesa
->vertexFormat
) {
326 fxMesa
->dirty
|= TDFX_UPLOAD_VERTEX_LAYOUT
;
327 fxMesa
->vertexFormat
= setup_tab
[ind
].vertex_format
;
328 fxMesa
->vertex_stride_shift
= setup_tab
[ind
].vertex_stride_shift
;
334 void tdfxInitVB( GLcontext
*ctx
)
336 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
337 GLuint size
= TNL_CONTEXT(ctx
)->vb
.Size
;
338 static int firsttime
= 1;
344 fxMesa
->verts
= (GLubyte
*)ALIGN_MALLOC(size
* sizeof(tdfxVertex
), 32);
345 fxMesa
->vertexFormat
= setup_tab
[TDFX_XYZ_BIT
|TDFX_RGBA_BIT
].vertex_format
;
346 fxMesa
->vertex_stride_shift
= setup_tab
[(TDFX_XYZ_BIT
|
347 TDFX_RGBA_BIT
)].vertex_stride_shift
;
348 fxMesa
->SetupIndex
= TDFX_XYZ_BIT
|TDFX_RGBA_BIT
;
352 void tdfxFreeVB( GLcontext
*ctx
)
354 tdfxContextPtr fxMesa
= TDFX_CONTEXT(ctx
);
356 ALIGN_FREE(fxMesa
->verts
);
360 if (fxMesa
->UbyteColor
.Ptr
) {
361 ALIGN_FREE(fxMesa
->UbyteColor
.Ptr
);
362 fxMesa
->UbyteColor
.Ptr
= 0;