~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.3 2002/12/23 15:29:26 tsi Exp $ */
 
2
/*
 
3
Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
 
4
 
 
5
The Weather Channel (TM) funded Tungsten Graphics to develop the
 
6
initial release of the Radeon 8500 driver under the XFree86 license.
 
7
This notice must be preserved.
 
8
 
 
9
Permission is hereby granted, free of charge, to any person obtaining
 
10
a copy of this software and associated documentation files (the
 
11
"Software"), to deal in the Software without restriction, including
 
12
without limitation the rights to use, copy, modify, merge, publish,
 
13
distribute, sublicense, and/or sell copies of the Software, and to
 
14
permit persons to whom the Software is furnished to do so, subject to
 
15
the following conditions:
 
16
 
 
17
The above copyright notice and this permission notice (including the
 
18
next paragraph) shall be included in all copies or substantial
 
19
portions of the Software.
 
20
 
 
21
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
22
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
23
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
24
IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
 
25
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
26
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
27
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
28
*/
 
29
 
 
30
/*
 
31
 * Authors:
 
32
 *   Keith Whitwell <keith@tungstengraphics.com>
 
33
 */
 
34
 
 
35
#include "glheader.h"
 
36
#include "mtypes.h"
 
37
#include "colormac.h"
 
38
#include "enums.h"
 
39
#include "mem.h"
 
40
#include "mmath.h"
 
41
#include "macros.h"
 
42
#include "image.h"
 
43
 
 
44
#include "swrast_setup/swrast_setup.h"
 
45
#include "swrast/s_fog.h"
 
46
#include "math/m_translate.h"
 
47
#include "tnl/tnl.h"
 
48
#include "tnl/t_context.h"
 
49
#include "tnl/t_pipeline.h"
 
50
 
 
51
#include "r200_context.h"
 
52
#include "r200_ioctl.h"
 
53
#include "r200_state.h"
 
54
#include "r200_swtcl.h"
 
55
#include "r200_tcl.h"
 
56
 
 
57
/***********************************************************************
 
58
 *              Build render functions from dd templates               *
 
59
 ***********************************************************************/
 
60
 
 
61
 
 
62
#define R200_XYZW_BIT           0x01
 
63
#define R200_RGBA_BIT           0x02
 
64
#define R200_SPEC_BIT           0x04
 
65
#define R200_TEX0_BIT           0x08
 
66
#define R200_TEX1_BIT           0x10
 
67
#define R200_PTEX_BIT           0x20
 
68
#define R200_MAX_SETUP  0x40
 
69
 
 
70
static void flush_last_swtcl_prim( r200ContextPtr rmesa  );
 
71
 
 
72
static struct {
 
73
   void                (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
 
74
   interp_func          interp;
 
75
   copy_pv_func         copy_pv;
 
76
   GLboolean           (*check_tex_sizes)( GLcontext *ctx );
 
77
   GLuint               vertex_size;
 
78
   GLuint               vertex_stride_shift;
 
79
   GLuint               vertex_format;
 
80
} setup_tab[R200_MAX_SETUP];
 
81
 
 
82
 
 
83
static int se_vtx_fmt_0[] = {
 
84
   0,
 
85
 
 
86
   (R200_VTX_XY |
 
87
    R200_VTX_Z0 |
 
88
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT)),
 
89
 
 
90
   (R200_VTX_XY |
 
91
    R200_VTX_Z0 |
 
92
    R200_VTX_W0 |
 
93
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
 
94
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
 
95
 
 
96
   (R200_VTX_XY |
 
97
    R200_VTX_Z0 |
 
98
    R200_VTX_W0 |
 
99
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
 
100
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
 
101
 
 
102
   (R200_VTX_XY |
 
103
    R200_VTX_Z0 |
 
104
    R200_VTX_W0 |
 
105
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
 
106
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT)),
 
107
 
 
108
   (R200_VTX_XY |
 
109
    R200_VTX_Z0 |
 
110
    R200_VTX_W0 |
 
111
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) |
 
112
    (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT))
 
113
};
 
114
 
 
115
static int se_vtx_fmt_1[] = {
 
116
   0,
 
117
   0,
 
118
   0,
 
119
   ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT)),
 
120
   ((2 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
 
121
    (2 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
 
122
   ((3 << R200_VTX_TEX0_COMP_CNT_SHIFT) |
 
123
    (3 << R200_VTX_TEX1_COMP_CNT_SHIFT)),
 
124
};
 
125
 
 
126
#define TINY_VERTEX_FORMAT      1
 
127
#define NOTEX_VERTEX_FORMAT     2
 
128
#define TEX0_VERTEX_FORMAT      3
 
129
#define TEX1_VERTEX_FORMAT      4
 
130
#define PROJ_TEX1_VERTEX_FORMAT 5
 
131
#define TEX2_VERTEX_FORMAT 0
 
132
#define TEX3_VERTEX_FORMAT 0
 
133
#define PROJ_TEX3_VERTEX_FORMAT 0
 
134
 
 
135
#define DO_XYZW (IND & R200_XYZW_BIT)
 
136
#define DO_RGBA (IND & R200_RGBA_BIT)
 
137
#define DO_SPEC (IND & R200_SPEC_BIT)
 
138
#define DO_FOG  (IND & R200_SPEC_BIT)
 
139
#define DO_TEX0 (IND & R200_TEX0_BIT)
 
140
#define DO_TEX1 (IND & R200_TEX1_BIT)
 
141
#define DO_TEX2 0
 
142
#define DO_TEX3 0
 
143
#define DO_PTEX (IND & R200_PTEX_BIT)
 
144
 
 
145
#define VERTEX r200Vertex
 
146
#define VERTEX_COLOR r200_color_t
 
147
#define GET_VIEWPORT_MAT() 0
 
148
#define GET_TEXSOURCE(n)  n
 
149
#define GET_VERTEX_FORMAT() R200_CONTEXT(ctx)->swtcl.vertex_format
 
150
#define GET_VERTEX_STORE() R200_CONTEXT(ctx)->swtcl.verts
 
151
#define GET_VERTEX_STRIDE_SHIFT() R200_CONTEXT(ctx)->swtcl.vertex_stride_shift
 
152
#define GET_UBYTE_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteColor
 
153
#define GET_UBYTE_SPEC_COLOR_STORE() &R200_CONTEXT(ctx)->UbyteSecondaryColor
 
154
 
 
155
#define HAVE_HW_VIEWPORT    1
 
156
#define HAVE_HW_DIVIDE      (IND & ~(R200_XYZW_BIT|R200_RGBA_BIT))
 
157
#define HAVE_TINY_VERTICES  1
 
158
#define HAVE_RGBA_COLOR     1
 
159
#define HAVE_NOTEX_VERTICES 1
 
160
#define HAVE_TEX0_VERTICES  1
 
161
#define HAVE_TEX1_VERTICES  1
 
162
#define HAVE_TEX2_VERTICES  0
 
163
#define HAVE_TEX3_VERTICES  0
 
164
#define HAVE_PTEX_VERTICES  1
 
165
 
 
166
#define CHECK_HW_DIVIDE    (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
 
167
                                                    DD_TRI_UNFILLED)))
 
168
 
 
169
#define IMPORT_QUALIFIER
 
170
#define IMPORT_FLOAT_COLORS r200_import_float_colors
 
171
#define IMPORT_FLOAT_SPEC_COLORS r200_import_float_spec_colors
 
172
 
 
173
#define INTERP_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].interp
 
174
#define COPY_PV_VERTEX setup_tab[R200_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
 
175
 
 
176
 
 
177
/***********************************************************************
 
178
 *         Generate  pv-copying and translation functions              *
 
179
 ***********************************************************************/
 
180
 
 
181
#define TAG(x) r200_##x
 
182
#define IND ~0
 
183
#include "tnl_dd/t_dd_vb.c"
 
184
#undef IND
 
185
 
 
186
 
 
187
/***********************************************************************
 
188
 *             Generate vertex emit and interp functions               *
 
189
 ***********************************************************************/
 
190
 
 
191
#define IND (R200_XYZW_BIT|R200_RGBA_BIT)
 
192
#define TAG(x) x##_wg
 
193
#include "tnl_dd/t_dd_vbtmp.h"
 
194
 
 
195
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT)
 
196
#define TAG(x) x##_wgt0
 
197
#include "tnl_dd/t_dd_vbtmp.h"
 
198
 
 
199
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_PTEX_BIT)
 
200
#define TAG(x) x##_wgpt0
 
201
#include "tnl_dd/t_dd_vbtmp.h"
 
202
 
 
203
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT)
 
204
#define TAG(x) x##_wgt0t1
 
205
#include "tnl_dd/t_dd_vbtmp.h"
 
206
 
 
207
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_TEX0_BIT|R200_TEX1_BIT|\
 
208
             R200_PTEX_BIT)
 
209
#define TAG(x) x##_wgpt0t1
 
210
#include "tnl_dd/t_dd_vbtmp.h"
 
211
 
 
212
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT)
 
213
#define TAG(x) x##_wgfs
 
214
#include "tnl_dd/t_dd_vbtmp.h"
 
215
 
 
216
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
 
217
             R200_TEX0_BIT)
 
218
#define TAG(x) x##_wgfst0
 
219
#include "tnl_dd/t_dd_vbtmp.h"
 
220
 
 
221
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
 
222
             R200_TEX0_BIT|R200_PTEX_BIT)
 
223
#define TAG(x) x##_wgfspt0
 
224
#include "tnl_dd/t_dd_vbtmp.h"
 
225
 
 
226
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
 
227
             R200_TEX0_BIT|R200_TEX1_BIT)
 
228
#define TAG(x) x##_wgfst0t1
 
229
#include "tnl_dd/t_dd_vbtmp.h"
 
230
 
 
231
#define IND (R200_XYZW_BIT|R200_RGBA_BIT|R200_SPEC_BIT|\
 
232
             R200_TEX0_BIT|R200_TEX1_BIT|R200_PTEX_BIT)
 
233
#define TAG(x) x##_wgfspt0t1
 
234
#include "tnl_dd/t_dd_vbtmp.h"
 
235
 
 
236
 
 
237
/***********************************************************************
 
238
 *                         Initialization 
 
239
 ***********************************************************************/
 
240
 
 
241
static void init_setup_tab( void )
 
242
{
 
243
   init_wg();
 
244
   init_wgt0();
 
245
   init_wgpt0();
 
246
   init_wgt0t1();
 
247
   init_wgpt0t1();
 
248
   init_wgfs();
 
249
   init_wgfst0();
 
250
   init_wgfspt0();
 
251
   init_wgfst0t1();
 
252
   init_wgfspt0t1();
 
253
}
 
254
 
 
255
 
 
256
 
 
257
void r200PrintSetupFlags(char *msg, GLuint flags )
 
258
{
 
259
   fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
 
260
           msg,
 
261
           (int)flags,
 
262
           (flags & R200_XYZW_BIT)      ? " xyzw," : "",
 
263
           (flags & R200_RGBA_BIT)     ? " rgba," : "",
 
264
           (flags & R200_SPEC_BIT)     ? " spec/fog," : "",
 
265
           (flags & R200_TEX0_BIT)     ? " tex-0," : "",
 
266
           (flags & R200_TEX1_BIT)     ? " tex-1," : "",
 
267
           (flags & R200_PTEX_BIT)     ? " proj-tex," : "");
 
268
}
 
269
 
 
270
 
 
271
 
 
272
static void r200SetVertexFormat( GLcontext *ctx, GLuint ind ) 
 
273
{
 
274
   r200ContextPtr rmesa = R200_CONTEXT( ctx );
 
275
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
276
 
 
277
   rmesa->swtcl.SetupIndex = ind;
 
278
      
 
279
   if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
 
280
      tnl->Driver.Render.Interp = r200_interp_extras;
 
281
      tnl->Driver.Render.CopyPV = r200_copy_pv_extras;
 
282
   }
 
283
   else {
 
284
      tnl->Driver.Render.Interp = setup_tab[ind].interp;
 
285
      tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
 
286
   }
 
287
 
 
288
   if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
 
289
      int i;
 
290
      R200_NEWPRIM(rmesa);
 
291
      i = rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
 
292
      rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
 
293
      rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
 
294
 
 
295
      R200_STATECHANGE( rmesa, vtx );
 
296
      rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = se_vtx_fmt_0[i];
 
297
      rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = se_vtx_fmt_1[i];
 
298
   }
 
299
 
 
300
   {
 
301
      GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
 
302
      GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
 
303
      GLuint needproj;
 
304
 
 
305
      /* HW perspective divide is a win, but tiny vertex formats are a
 
306
       * bigger one.
 
307
       */
 
308
      if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
 
309
          (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
 
310
         needproj = GL_TRUE;
 
311
         vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
 
312
         vte &= ~R200_VTX_W0_FMT;
 
313
         vap |= R200_VAP_FORCE_W_TO_ONE;
 
314
      }
 
315
      else {
 
316
         needproj = GL_FALSE;
 
317
         vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
 
318
         vte |= R200_VTX_W0_FMT;
 
319
         vap &= ~R200_VAP_FORCE_W_TO_ONE;
 
320
      }
 
321
 
 
322
      _tnl_need_projected_coords( ctx, needproj );
 
323
      if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
 
324
         R200_STATECHANGE( rmesa, vte );
 
325
         rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
 
326
      }
 
327
      if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
 
328
         R200_STATECHANGE( rmesa, vap );
 
329
         rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
 
330
      }
 
331
   }
 
332
}
 
333
 
 
334
static void r200RenderStart( GLcontext *ctx )
 
335
{
 
336
   r200ContextPtr rmesa = R200_CONTEXT( ctx );
 
337
 
 
338
   if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) {
 
339
      r200SetVertexFormat( ctx, rmesa->swtcl.SetupIndex | R200_PTEX_BIT);
 
340
   }
 
341
   
 
342
   if (rmesa->dma.flush != 0 && 
 
343
       rmesa->dma.flush != flush_last_swtcl_prim)
 
344
      rmesa->dma.flush( rmesa );
 
345
}
 
346
 
 
347
 
 
348
void r200BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
 
349
                           GLuint newinputs )
 
350
{
 
351
   r200ContextPtr rmesa = R200_CONTEXT( ctx );
 
352
   GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + 
 
353
                 (start << rmesa->swtcl.vertex_stride_shift));
 
354
   GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift;
 
355
 
 
356
   newinputs |= rmesa->swtcl.SetupNewInputs;
 
357
   rmesa->swtcl.SetupNewInputs = 0;
 
358
 
 
359
   if (!newinputs)
 
360
      return;
 
361
 
 
362
   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride );
 
363
}
 
364
 
 
365
 
 
366
void r200ChooseVertexState( GLcontext *ctx )
 
367
{
 
368
   r200ContextPtr rmesa = R200_CONTEXT( ctx );
 
369
   GLuint ind = (R200_XYZW_BIT | R200_RGBA_BIT);
 
370
 
 
371
   if (!rmesa->TclFallback || rmesa->Fallback)
 
372
      return;
 
373
 
 
374
   if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
 
375
      ind |= R200_SPEC_BIT;
 
376
 
 
377
   if (ctx->Texture._ReallyEnabled & TEXTURE1_ANY)
 
378
      ind |= R200_TEX0_BIT|R200_TEX1_BIT;
 
379
   else if (ctx->Texture._ReallyEnabled & TEXTURE0_ANY)
 
380
      ind |= R200_TEX0_BIT;
 
381
 
 
382
   r200SetVertexFormat( ctx, ind );
 
383
}
 
384
 
 
385
 
 
386
/* Flush vertices in the current dma region.
 
387
 */
 
388
static void flush_last_swtcl_prim( r200ContextPtr rmesa  )
 
389
{
 
390
   if (R200_DEBUG & DEBUG_IOCTL)
 
391
      fprintf(stderr, "%s\n", __FUNCTION__);
 
392
 
 
393
   if (rmesa->dma.current.buf) {
 
394
      struct r200_dma_region *current = &rmesa->dma.current;
 
395
      GLuint current_offset = (rmesa->r200Screen->agp_buffer_offset +
 
396
                               current->buf->buf->idx * RADEON_BUFFER_SIZE + 
 
397
                               current->start);
 
398
 
 
399
      assert (!(rmesa->swtcl.hw_primitive & R200_VF_PRIM_WALK_IND));
 
400
 
 
401
      assert (current->start + 
 
402
              rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
 
403
              current->ptr);
 
404
 
 
405
      if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
 
406
         r200EmitVertexAOS( rmesa,
 
407
                              rmesa->swtcl.vertex_size,
 
408
                              current_offset);
 
409
 
 
410
         r200EmitVbufPrim( rmesa,
 
411
                           rmesa->swtcl.hw_primitive,
 
412
                           rmesa->swtcl.numverts);
 
413
      }
 
414
 
 
415
      rmesa->swtcl.numverts = 0;
 
416
      current->start = current->ptr;
 
417
 
 
418
      rmesa->dma.flush = 0;
 
419
   }
 
420
}
 
421
 
 
422
 
 
423
/* Alloc space in the current dma region.
 
424
 */
 
425
static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
 
426
                                              int nverts, int vsize )
 
427
{
 
428
   GLuint bytes = vsize * nverts;
 
429
 
 
430
   if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) 
 
431
      r200RefillCurrentDmaRegion( rmesa );
 
432
 
 
433
   if (!rmesa->dma.flush) {
 
434
      rmesa->dma.flush = flush_last_swtcl_prim;
 
435
   }
 
436
 
 
437
   ASSERT( vsize == rmesa->swtcl.vertex_size * 4 );
 
438
   ASSERT( rmesa->dma.flush == flush_last_swtcl_prim );
 
439
   ASSERT( rmesa->dma.current.start + 
 
440
           rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
 
441
           rmesa->dma.current.ptr );
 
442
 
 
443
 
 
444
   {
 
445
      GLubyte *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
 
446
      rmesa->dma.current.ptr += bytes;
 
447
      rmesa->swtcl.numverts += nverts;
 
448
      return head;
 
449
   }
 
450
 
 
451
}
 
452
 
 
453
 
 
454
 
 
455
 
 
456
void r200_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count )
 
457
{
 
458
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
459
   GLuint vertex_size = rmesa->swtcl.vertex_size * 4;
 
460
   CARD32 *dest = r200AllocDmaLowVerts( rmesa, count-start, vertex_size );
 
461
   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, 
 
462
                                            vertex_size );
 
463
}
 
464
 
 
465
 
 
466
 
 
467
void r200_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
 
468
{
 
469
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
470
 
 
471
   r200AllocDmaRegionVerts( rmesa, 
 
472
                              &rmesa->swtcl.indexed_verts, 
 
473
                              count - start,
 
474
                              rmesa->swtcl.vertex_size * 4, 
 
475
                              64);
 
476
 
 
477
   setup_tab[rmesa->swtcl.SetupIndex].emit( 
 
478
      ctx, start, count, 
 
479
      rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, 
 
480
      rmesa->swtcl.vertex_size * 4 );
 
481
}
 
482
 
 
483
 
 
484
/*
 
485
 * Render unclipped vertex buffers by emitting vertices directly to
 
486
 * dma buffers.  Use strip/fan hardware primitives where possible.
 
487
 * Try to simulate missing primitives with indexed vertices.
 
488
 */
 
489
#define HAVE_POINTS      1
 
490
#define HAVE_LINES       1
 
491
#define HAVE_LINE_STRIPS 1
 
492
#define HAVE_TRIANGLES   1
 
493
#define HAVE_TRI_STRIPS  1
 
494
#define HAVE_TRI_STRIP_1 0
 
495
#define HAVE_TRI_FANS    1
 
496
#define HAVE_QUADS       1
 
497
#define HAVE_QUAD_STRIPS 1
 
498
#define HAVE_POLYGONS    1
 
499
#define HAVE_ELTS        1
 
500
 
 
501
static const GLuint hw_prim[GL_POLYGON+1] = {
 
502
   R200_VF_PRIM_POINTS,
 
503
   R200_VF_PRIM_LINES,
 
504
   0,
 
505
   R200_VF_PRIM_LINE_STRIP,
 
506
   R200_VF_PRIM_TRIANGLES,
 
507
   R200_VF_PRIM_TRIANGLE_STRIP,
 
508
   R200_VF_PRIM_TRIANGLE_FAN,
 
509
   R200_VF_PRIM_QUADS,
 
510
   R200_VF_PRIM_QUAD_STRIP,
 
511
   R200_VF_PRIM_POLYGON
 
512
};
 
513
 
 
514
static __inline void r200DmaPrimitive( r200ContextPtr rmesa, GLenum prim )
 
515
{
 
516
   R200_NEWPRIM( rmesa );
 
517
   rmesa->swtcl.hw_primitive = hw_prim[prim];
 
518
   assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
 
519
}
 
520
 
 
521
static __inline void r200EltPrimitive( r200ContextPtr rmesa, GLenum prim )
 
522
{
 
523
   R200_NEWPRIM( rmesa );
 
524
   rmesa->swtcl.hw_primitive = hw_prim[prim] | R200_VF_PRIM_WALK_IND;
 
525
}
 
526
 
 
527
 
 
528
static void VERT_FALLBACK( GLcontext *ctx,
 
529
                           GLuint start,
 
530
                           GLuint count,
 
531
                           GLuint flags )
 
532
{
 
533
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
534
   tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
 
535
   tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
 
536
   tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
 
537
   R200_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP;
 
538
}
 
539
 
 
540
static void ELT_FALLBACK( GLcontext *ctx,
 
541
                          GLuint start,
 
542
                          GLuint count,
 
543
                          GLuint flags )
 
544
{
 
545
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
546
   tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
 
547
   tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
 
548
   tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
 
549
   R200_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_CLIP;
 
550
}
 
551
 
 
552
 
 
553
#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
 
554
#define ELTS_VARS  GLushort *dest
 
555
#define INIT( prim ) r200DmaPrimitive( rmesa, prim )
 
556
#define ELT_INIT(prim) r200EltPrimitive( rmesa, prim )
 
557
#define NEW_PRIMITIVE()  R200_NEWPRIM( rmesa )
 
558
#define NEW_BUFFER()  r200RefillCurrentDmaRegion( rmesa )
 
559
#define GET_CURRENT_VB_MAX_VERTS() \
 
560
  (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
 
561
#define GET_SUBSEQUENT_VB_MAX_VERTS() \
 
562
  ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
 
563
 
 
564
#define GET_CURRENT_VB_MAX_ELTS() \
 
565
  ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
 
566
#define GET_SUBSEQUENT_VB_MAX_ELTS() \
 
567
  ((R200_CMD_BUF_SZ - 1024) / 2)
 
568
 
 
569
 
 
570
 
 
571
/* How do you extend an existing primitive?
 
572
 */
 
573
#define ALLOC_ELTS(nr)                                                  \
 
574
do {                                                                    \
 
575
   if (rmesa->dma.flush == r200FlushElts &&                             \
 
576
       rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) {                \
 
577
                                                                        \
 
578
      dest = (GLushort *)(rmesa->store.cmd_buf +                        \
 
579
                          rmesa->store.cmd_used);                       \
 
580
      rmesa->store.cmd_used += nr*2;                                    \
 
581
   }                                                                    \
 
582
   else {                                                               \
 
583
      if (rmesa->dma.flush) {                                           \
 
584
         rmesa->dma.flush( rmesa );                                     \
 
585
      }                                                                 \
 
586
                                                                        \
 
587
      r200EmitVertexAOS( rmesa,                                 \
 
588
                           rmesa->swtcl.vertex_size,                    \
 
589
                           (rmesa->r200Screen->agp_buffer_offset +      \
 
590
                            rmesa->swtcl.indexed_verts.buf->buf->idx *  \
 
591
                            RADEON_BUFFER_SIZE +                        \
 
592
                            rmesa->swtcl.indexed_verts.start));         \
 
593
                                                                        \
 
594
      dest = r200AllocEltsOpenEnded( rmesa,                             \
 
595
                                       rmesa->swtcl.hw_primitive,       \
 
596
                                       nr );                            \
 
597
   }                                                                    \
 
598
} while (0)
 
599
 
 
600
#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr )
 
601
 
 
602
#ifdef MESA_BIG_ENDIAN
 
603
/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
 
604
#define EMIT_ELT(offset, x) do {                                \
 
605
        int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
 
606
        GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
 
607
        (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
 
608
#else
 
609
#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
 
610
#endif
 
611
#define EMIT_TWO_ELTS(offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
 
612
#define INCR_ELTS( nr ) dest += nr
 
613
#define RELEASE_ELT_VERTS() \
 
614
  r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
 
615
#define EMIT_VERTS( ctx, j, nr ) \
 
616
  r200_emit_contiguous_verts(ctx, j, (j)+(nr))
 
617
#define EMIT_INDEXED_VERTS( ctx, start, count ) \
 
618
  r200_emit_indexed_verts( ctx, start, count )
 
619
 
 
620
 
 
621
#define TAG(x) r200_dma_##x
 
622
#include "tnl_dd/t_dd_dmatmp.h"
 
623
 
 
624
 
 
625
/**********************************************************************/
 
626
/*                          Render pipeline stage                     */
 
627
/**********************************************************************/
 
628
 
 
629
 
 
630
static GLboolean r200_run_render( GLcontext *ctx,
 
631
                                    struct gl_pipeline_stage *stage )
 
632
{
 
633
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
634
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
635
   struct vertex_buffer *VB = &tnl->vb;
 
636
   GLuint i, length, flags = 0;
 
637
   render_func *tab = TAG(render_tab_verts);
 
638
 
 
639
   if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) 
 
640
      RELEASE_ELT_VERTS();
 
641
        
 
642
   
 
643
 
 
644
   if ((R200_DEBUG & DEBUG_VERTS) ||     /* No debug */
 
645
       VB->ClipOrMask ||                 /* No clipping */
 
646
       rmesa->swtcl.RenderIndex != 0 ||  /* No per-vertex manipulations */
 
647
       ctx->Line.StippleFlag)            /* No stipple -- fix me? */
 
648
      return GL_TRUE;           
 
649
 
 
650
   if (VB->Elts) {
 
651
      tab = TAG(render_tab_elts);
 
652
      if (!rmesa->swtcl.indexed_verts.buf)
 
653
         if (!TAG(emit_elt_verts)(ctx, 0, VB->Count))
 
654
            return GL_TRUE;     /* too many vertices */
 
655
   }
 
656
 
 
657
   tnl->Driver.Render.Start( ctx );
 
658
 
 
659
   for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
 
660
   {
 
661
      flags = VB->Primitive[i];
 
662
      length = VB->PrimitiveLength[i];
 
663
 
 
664
      if (R200_DEBUG & DEBUG_PRIMS)
 
665
         fprintf(stderr, "r200_render.c: prim %s %d..%d\n", 
 
666
                 _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), 
 
667
                 i, i+length);
 
668
 
 
669
      if (length)
 
670
         tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
 
671
   }
 
672
 
 
673
   tnl->Driver.Render.Finish( ctx );
 
674
 
 
675
   return GL_FALSE;             /* finished the pipe */
 
676
}
 
677
 
 
678
 
 
679
 
 
680
static void r200_check_render( GLcontext *ctx,
 
681
                                 struct gl_pipeline_stage *stage )
 
682
{
 
683
   GLuint inputs = VERT_OBJ|VERT_CLIP|VERT_RGBA;
 
684
 
 
685
   if (ctx->RenderMode == GL_RENDER) {
 
686
      if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
 
687
         inputs |= VERT_SPEC_RGB;
 
688
 
 
689
      if (ctx->Texture.Unit[0]._ReallyEnabled)
 
690
         inputs |= VERT_TEX(0);
 
691
 
 
692
      if (ctx->Texture.Unit[1]._ReallyEnabled)
 
693
         inputs |= VERT_TEX(1);
 
694
 
 
695
      if (ctx->Fog.Enabled)
 
696
         inputs |= VERT_FOG_COORD;
 
697
   }
 
698
 
 
699
   stage->inputs = inputs;
 
700
}
 
701
 
 
702
 
 
703
static void dtr( struct gl_pipeline_stage *stage )
 
704
{
 
705
   (void)stage;
 
706
}
 
707
 
 
708
 
 
709
const struct gl_pipeline_stage _r200_render_stage =
 
710
{
 
711
   "r200 render",
 
712
   (_DD_NEW_SEPARATE_SPECULAR |
 
713
    _NEW_TEXTURE|
 
714
    _NEW_FOG|
 
715
    _NEW_RENDERMODE),           /* re-check (new inputs) */
 
716
   0,                           /* re-run (always runs) */
 
717
   GL_TRUE,                     /* active */
 
718
   0, 0,                        /* inputs (set in check_render), outputs */
 
719
   0, 0,                        /* changed_inputs, private */
 
720
   dtr,                         /* destructor */
 
721
   r200_check_render,           /* check - initially set to alloc data */
 
722
   r200_run_render              /* run */
 
723
};
 
724
 
 
725
 
 
726
 
 
727
/**************************************************************************/
 
728
 
 
729
 
 
730
static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
 
731
   R200_VF_PRIM_POINTS,
 
732
   R200_VF_PRIM_LINES,
 
733
   R200_VF_PRIM_LINES,
 
734
   R200_VF_PRIM_LINES,
 
735
   R200_VF_PRIM_TRIANGLES,
 
736
   R200_VF_PRIM_TRIANGLES,
 
737
   R200_VF_PRIM_TRIANGLES,
 
738
   R200_VF_PRIM_TRIANGLES,
 
739
   R200_VF_PRIM_TRIANGLES,
 
740
   R200_VF_PRIM_TRIANGLES
 
741
};
 
742
 
 
743
static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim );
 
744
static void r200RenderPrimitive( GLcontext *ctx, GLenum prim );
 
745
static void r200ResetLineStipple( GLcontext *ctx );
 
746
 
 
747
#undef HAVE_QUADS
 
748
#define HAVE_QUADS 0
 
749
 
 
750
#undef HAVE_QUAD_STRIPS
 
751
#define HAVE_QUAD_STRIPS 0
 
752
 
 
753
/***********************************************************************
 
754
 *                    Emit primitives as inline vertices               *
 
755
 ***********************************************************************/
 
756
 
 
757
#undef LOCAL_VARS
 
758
#define CTX_ARG r200ContextPtr rmesa
 
759
#define CTX_ARG2 rmesa
 
760
#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
 
761
#define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
 
762
#define LOCAL_VARS                                              \
 
763
   r200ContextPtr rmesa = R200_CONTEXT(ctx);            \
 
764
   const GLuint shift = rmesa->swtcl.vertex_stride_shift;       \
 
765
   const char *r200verts = (char *)rmesa->swtcl.verts;
 
766
#define VERT(x) (r200Vertex *)(r200verts + (x << shift))
 
767
#define VERTEX r200Vertex 
 
768
#define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
 
769
#define PRINT_VERTEX(v) r200_print_vertex(rmesa->glCtx, v)
 
770
#undef TAG
 
771
#define TAG(x) r200_##x
 
772
#include "tnl_dd/t_dd_triemit.h"
 
773
 
 
774
 
 
775
/***********************************************************************
 
776
 *          Macros for t_dd_tritmp.h to draw basic primitives          *
 
777
 ***********************************************************************/
 
778
 
 
779
#define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
 
780
#define TRI( a, b, c )     r200_triangle( rmesa, a, b, c )
 
781
#define LINE( a, b )       r200_line( rmesa, a, b )
 
782
#define POINT( a )         r200_point( rmesa, a )
 
783
 
 
784
/***********************************************************************
 
785
 *              Build render functions from dd templates               *
 
786
 ***********************************************************************/
 
787
 
 
788
#define R200_TWOSIDE_BIT        0x01
 
789
#define R200_UNFILLED_BIT       0x02
 
790
#define R200_MAX_TRIFUNC        0x04
 
791
 
 
792
 
 
793
static struct {
 
794
   points_func          points;
 
795
   line_func            line;
 
796
   triangle_func        triangle;
 
797
   quad_func            quad;
 
798
} rast_tab[R200_MAX_TRIFUNC];
 
799
 
 
800
 
 
801
#define DO_FALLBACK  0
 
802
#define DO_UNFILLED (IND & R200_UNFILLED_BIT)
 
803
#define DO_TWOSIDE  (IND & R200_TWOSIDE_BIT)
 
804
#define DO_FLAT      0
 
805
#define DO_OFFSET     0
 
806
#define DO_TRI       1
 
807
#define DO_QUAD      1
 
808
#define DO_LINE      1
 
809
#define DO_POINTS    1
 
810
#define DO_FULL_QUAD 1
 
811
 
 
812
#define HAVE_RGBA   1
 
813
#define HAVE_SPEC   1
 
814
#define HAVE_INDEX  0
 
815
#define HAVE_BACK_COLORS  0
 
816
#define HAVE_HW_FLATSHADE 1
 
817
#define TAB rast_tab
 
818
 
 
819
#define DEPTH_SCALE 1.0
 
820
#define UNFILLED_TRI unfilled_tri
 
821
#define UNFILLED_QUAD unfilled_quad
 
822
#define VERT_X(_v) _v->v.x
 
823
#define VERT_Y(_v) _v->v.y
 
824
#define VERT_Z(_v) _v->v.z
 
825
#define AREA_IS_CCW( a ) (a < 0)
 
826
#define GET_VERTEX(e) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift))
 
827
 
 
828
#define VERT_SET_RGBA( v, c )    v->ui[coloroffset] = LE32_TO_CPU(*(GLuint *)c)
 
829
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
 
830
#define VERT_SAVE_RGBA( idx )    color[idx] = CPU_TO_LE32(v[idx]->ui[coloroffset])
 
831
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = LE32_TO_CPU(color[idx])
 
832
 
 
833
#define VERT_SET_SPEC( v0, c )   if (havespec) {                        \
 
834
                                        v0->v.specular.red   = (c)[0];  \
 
835
                                        v0->v.specular.green = (c)[1];  \
 
836
                                        v0->v.specular.blue  = (c)[2]; }
 
837
#define VERT_COPY_SPEC( v0, v1 ) if (havespec) {                                        \
 
838
                                        v0->v.specular.red   = v1->v.specular.red;      \
 
839
                                        v0->v.specular.green = v1->v.specular.green;    \
 
840
                                        v0->v.specular.blue  = v1->v.specular.blue; }
 
841
#define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = CPU_TO_LE32(v[idx]->ui[5])
 
842
#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = LE32_TO_CPU(spec[idx])
 
843
 
 
844
#undef LOCAL_VARS
 
845
#undef TAG
 
846
#undef INIT
 
847
 
 
848
#define LOCAL_VARS(n)                                                   \
 
849
   r200ContextPtr rmesa = R200_CONTEXT(ctx);                    \
 
850
   GLuint color[n], spec[n];                                            \
 
851
   GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4);        \
 
852
   GLboolean havespec = (rmesa->swtcl.vertex_size > 4);                 \
 
853
   (void) color; (void) spec; (void) coloroffset; (void) havespec;
 
854
 
 
855
/***********************************************************************
 
856
 *                Helpers for rendering unfilled primitives            *
 
857
 ***********************************************************************/
 
858
 
 
859
#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
 
860
#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
 
861
#define TAG(x) x
 
862
#include "tnl_dd/t_dd_unfilled.h"
 
863
#undef IND
 
864
 
 
865
 
 
866
/***********************************************************************
 
867
 *                      Generate GL render functions                   *
 
868
 ***********************************************************************/
 
869
 
 
870
 
 
871
#define IND (0)
 
872
#define TAG(x) x
 
873
#include "tnl_dd/t_dd_tritmp.h"
 
874
 
 
875
#define IND (R200_TWOSIDE_BIT)
 
876
#define TAG(x) x##_twoside
 
877
#include "tnl_dd/t_dd_tritmp.h"
 
878
 
 
879
#define IND (R200_UNFILLED_BIT)
 
880
#define TAG(x) x##_unfilled
 
881
#include "tnl_dd/t_dd_tritmp.h"
 
882
 
 
883
#define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
 
884
#define TAG(x) x##_twoside_unfilled
 
885
#include "tnl_dd/t_dd_tritmp.h"
 
886
 
 
887
 
 
888
static void init_rast_tab( void )
 
889
{
 
890
   init();
 
891
   init_twoside();
 
892
   init_unfilled();
 
893
   init_twoside_unfilled();
 
894
}
 
895
 
 
896
/**********************************************************************/
 
897
/*               Render unclipped begin/end objects                   */
 
898
/**********************************************************************/
 
899
 
 
900
#define VERT(x) (r200Vertex *)(r200verts + (x << shift))
 
901
#define RENDER_POINTS( start, count )           \
 
902
   for ( ; start < count ; start++)             \
 
903
      r200_point( rmesa, VERT(start) )
 
904
#define RENDER_LINE( v0, v1 ) \
 
905
   r200_line( rmesa, VERT(v0), VERT(v1) )
 
906
#define RENDER_TRI( v0, v1, v2 )  \
 
907
   r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
 
908
#define RENDER_QUAD( v0, v1, v2, v3 ) \
 
909
   r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
 
910
#define INIT(x) do {                                    \
 
911
   r200RenderPrimitive( ctx, x );                       \
 
912
} while (0)
 
913
#undef LOCAL_VARS
 
914
#define LOCAL_VARS                                              \
 
915
   r200ContextPtr rmesa = R200_CONTEXT(ctx);            \
 
916
   const GLuint shift = rmesa->swtcl.vertex_stride_shift;               \
 
917
   const char *r200verts = (char *)rmesa->swtcl.verts;          \
 
918
   const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;        \
 
919
   const GLboolean stipple = ctx->Line.StippleFlag;             \
 
920
   (void) elt; (void) stipple;
 
921
#define RESET_STIPPLE   if ( stipple ) r200ResetLineStipple( ctx );
 
922
#define RESET_OCCLUSION
 
923
#define PRESERVE_VB_DEFS
 
924
#define ELT(x) (x)
 
925
#define TAG(x) r200_##x##_verts
 
926
#include "tnl/t_vb_rendertmp.h"
 
927
#undef ELT
 
928
#undef TAG
 
929
#define TAG(x) r200_##x##_elts
 
930
#define ELT(x) elt[x]
 
931
#include "tnl/t_vb_rendertmp.h"
 
932
 
 
933
 
 
934
 
 
935
/**********************************************************************/
 
936
/*                    Choose render functions                         */
 
937
/**********************************************************************/
 
938
 
 
939
void r200ChooseRenderState( GLcontext *ctx )
 
940
{
 
941
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
942
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
943
   GLuint index = 0;
 
944
   GLuint flags = ctx->_TriangleCaps;
 
945
 
 
946
   if (!rmesa->TclFallback || rmesa->Fallback) 
 
947
      return;
 
948
 
 
949
   if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R200_TWOSIDE_BIT;
 
950
   if (flags & DD_TRI_UNFILLED)      index |= R200_UNFILLED_BIT;
 
951
 
 
952
   if (index != rmesa->swtcl.RenderIndex) {
 
953
      tnl->Driver.Render.Points = rast_tab[index].points;
 
954
      tnl->Driver.Render.Line = rast_tab[index].line;
 
955
      tnl->Driver.Render.ClippedLine = rast_tab[index].line;
 
956
      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
 
957
      tnl->Driver.Render.Quad = rast_tab[index].quad;
 
958
 
 
959
      if (index == 0) {
 
960
         tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
 
961
         tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
 
962
         tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
 
963
      } else {
 
964
         tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
 
965
         tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
 
966
         tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
 
967
      }
 
968
 
 
969
      rmesa->swtcl.RenderIndex = index;
 
970
   }
 
971
}
 
972
 
 
973
 
 
974
/**********************************************************************/
 
975
/*                 High level hooks for t_vb_render.c                 */
 
976
/**********************************************************************/
 
977
 
 
978
 
 
979
static void r200RasterPrimitive( GLcontext *ctx, GLuint hwprim )
 
980
{
 
981
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
982
 
 
983
   if (rmesa->swtcl.hw_primitive != hwprim) {
 
984
      R200_NEWPRIM( rmesa );
 
985
      rmesa->swtcl.hw_primitive = hwprim;
 
986
   }
 
987
}
 
988
 
 
989
static void r200RenderPrimitive( GLcontext *ctx, GLenum prim )
 
990
{
 
991
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
992
   rmesa->swtcl.render_primitive = prim;
 
993
   if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) 
 
994
      r200RasterPrimitive( ctx, reduced_hw_prim[prim] );
 
995
}
 
996
 
 
997
static void r200RenderFinish( GLcontext *ctx )
 
998
{
 
999
}
 
1000
 
 
1001
static void r200ResetLineStipple( GLcontext *ctx )
 
1002
{
 
1003
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
1004
   R200_STATECHANGE( rmesa, lin );
 
1005
}
 
1006
 
 
1007
 
 
1008
/**********************************************************************/
 
1009
/*           Transition to/from hardware rasterization.               */
 
1010
/**********************************************************************/
 
1011
 
 
1012
static char *fallbackStrings[] = {
 
1013
   "Texture mode",
 
1014
   "glDrawBuffer(GL_FRONT_AND_BACK)",
 
1015
   "glEnable(GL_STENCIL) without hw stencil buffer",
 
1016
   "glRenderMode(selection or feedback)",
 
1017
   "glBlendEquation",
 
1018
   "glBlendFunc(mode != ADD)"
 
1019
   "R200_NO_RAST"
 
1020
};
 
1021
 
 
1022
 
 
1023
static char *getFallbackString(GLuint bit)
 
1024
{
 
1025
   int i = 0;
 
1026
   while (bit > 1) {
 
1027
      i++;
 
1028
      bit >>= 1;
 
1029
   }
 
1030
   return fallbackStrings[i];
 
1031
}
 
1032
 
 
1033
 
 
1034
void r200Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 
1035
{
 
1036
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
1037
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
1038
   GLuint oldfallback = rmesa->Fallback;
 
1039
 
 
1040
   if (mode) {
 
1041
      rmesa->Fallback |= bit;
 
1042
      if (oldfallback == 0) {
 
1043
         R200_FIREVERTICES( rmesa );
 
1044
         TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
 
1045
         _swsetup_Wakeup( ctx );
 
1046
         _tnl_need_projected_coords( ctx, GL_TRUE );
 
1047
         rmesa->swtcl.RenderIndex = ~0;
 
1048
         if (R200_DEBUG & DEBUG_FALLBACKS) {
 
1049
            fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
 
1050
                    bit, getFallbackString(bit));
 
1051
         }
 
1052
      }
 
1053
   }
 
1054
   else {
 
1055
      rmesa->Fallback &= ~bit;
 
1056
      if (oldfallback == bit) {
 
1057
         _swrast_flush( ctx );
 
1058
         tnl->Driver.Render.Start = r200RenderStart;
 
1059
         tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
 
1060
         tnl->Driver.Render.Finish = r200RenderFinish;
 
1061
         tnl->Driver.Render.BuildVertices = r200BuildVertices;
 
1062
         tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
 
1063
         TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
 
1064
         if (rmesa->TclFallback) {
 
1065
            /* These are already done if rmesa->TclFallback goes to
 
1066
             * zero above. But not if it doesn't (R200_NO_TCL for
 
1067
             * example?)
 
1068
             */
 
1069
            r200ChooseVertexState( ctx );
 
1070
            r200ChooseRenderState( ctx );
 
1071
         }
 
1072
         if (R200_DEBUG & DEBUG_FALLBACKS) {
 
1073
            fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
 
1074
                    bit, getFallbackString(bit));
 
1075
         }
 
1076
      }
 
1077
   }
 
1078
}
 
1079
 
 
1080
 
 
1081
 
 
1082
 
 
1083
/* Cope with depth operations by drawing individual pixels as points??? 
 
1084
 */
 
1085
void
 
1086
r200PointsBitmap( GLcontext *ctx, GLint px, GLint py,
 
1087
                  GLsizei width, GLsizei height,
 
1088
                  const struct gl_pixelstore_attrib *unpack,
 
1089
                  const GLubyte *bitmap )
 
1090
{
 
1091
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
1092
   const GLfloat *rc = ctx->Current.RasterColor; 
 
1093
   GLint row, col;
 
1094
   r200Vertex vert;
 
1095
   GLuint orig_vte;
 
1096
   GLuint h;
 
1097
 
 
1098
 
 
1099
   /* Turn off tcl.  
 
1100
    */
 
1101
   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
 
1102
 
 
1103
   /* Choose tiny vertex format
 
1104
    */
 
1105
   r200SetVertexFormat( ctx, R200_XYZW_BIT | R200_RGBA_BIT );
 
1106
 
 
1107
   /* Ready for point primitives:
 
1108
    */
 
1109
   r200RenderPrimitive( ctx, GL_POINTS );
 
1110
 
 
1111
   /* Turn off the hw viewport transformation:
 
1112
    */
 
1113
   R200_STATECHANGE( rmesa, vte );
 
1114
   orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
 
1115
   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
 
1116
                                           R200_VPORT_Y_SCALE_ENA |
 
1117
                                           R200_VPORT_Z_SCALE_ENA |
 
1118
                                           R200_VPORT_X_OFFSET_ENA |
 
1119
                                           R200_VPORT_Y_OFFSET_ENA |
 
1120
                                           R200_VPORT_Z_OFFSET_ENA); 
 
1121
 
 
1122
   /* Turn off other stuff:  Stipple?, texture?, blending?, etc.
 
1123
    */
 
1124
 
 
1125
 
 
1126
   /* Populate the vertex
 
1127
    *
 
1128
    * Incorporate FOG into RGBA
 
1129
    */
 
1130
   if (ctx->Fog.Enabled) {
 
1131
      const GLfloat *fc = ctx->Fog.Color;
 
1132
      GLfloat color[4];
 
1133
      GLfloat f;
 
1134
 
 
1135
      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
 
1136
         f = _mesa_z_to_fogfactor(ctx, ctx->Current.FogCoord);
 
1137
      else
 
1138
         f = _mesa_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
 
1139
 
 
1140
      color[0] = f * rc[0] + (1.F - f) * fc[0];
 
1141
      color[1] = f * rc[1] + (1.F - f) * fc[1];
 
1142
      color[2] = f * rc[2] + (1.F - f) * fc[2];
 
1143
      color[3] = rc[3];
 
1144
 
 
1145
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   color[0]);
 
1146
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
 
1147
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  color[2]);
 
1148
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
 
1149
   }
 
1150
   else {
 
1151
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   rc[0]);
 
1152
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
 
1153
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  rc[2]);
 
1154
      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
 
1155
   }
 
1156
 
 
1157
 
 
1158
   vert.tv.z = ctx->Current.RasterPos[2];
 
1159
 
 
1160
 
 
1161
   /* Update window height
 
1162
    */
 
1163
   LOCK_HARDWARE( rmesa );
 
1164
   UNLOCK_HARDWARE( rmesa );
 
1165
   h = rmesa->dri.drawable->h + rmesa->dri.drawable->y;
 
1166
   px += rmesa->dri.drawable->x;
 
1167
 
 
1168
   /* Clipping handled by existing mechansims in r200_ioctl.c?
 
1169
    */
 
1170
   for (row=0; row<height; row++) {
 
1171
      const GLubyte *src = (const GLubyte *) 
 
1172
         _mesa_image_address( unpack, bitmap, width, height, 
 
1173
                              GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
 
1174
 
 
1175
      if (unpack->LsbFirst) {
 
1176
         /* Lsb first */
 
1177
         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
 
1178
         for (col=0; col<width; col++) {
 
1179
            if (*src & mask) {
 
1180
               vert.tv.x = px+col;
 
1181
               vert.tv.y = h - (py+row) - 1;
 
1182
               r200_point( rmesa, &vert );
 
1183
            }
 
1184
            src += (mask >> 7);
 
1185
            mask = ((mask << 1) & 0xff) | (mask >> 7);
 
1186
         }
 
1187
 
 
1188
         /* get ready for next row */
 
1189
         if (mask != 1)
 
1190
            src++;
 
1191
      }
 
1192
      else {
 
1193
         /* Msb first */
 
1194
         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
 
1195
         for (col=0; col<width; col++) {
 
1196
            if (*src & mask) {
 
1197
               vert.tv.x = px+col;
 
1198
               vert.tv.y = h - (py+row) - 1;
 
1199
               r200_point( rmesa, &vert );
 
1200
            }
 
1201
            src += mask & 1;
 
1202
            mask = ((mask << 7) & 0xff) | (mask >> 1);
 
1203
         }
 
1204
         /* get ready for next row */
 
1205
         if (mask != 128)
 
1206
            src++;
 
1207
      }
 
1208
   }
 
1209
 
 
1210
   /* Fire outstanding vertices, restore state
 
1211
    */
 
1212
   R200_STATECHANGE( rmesa, vte );
 
1213
   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
 
1214
 
 
1215
   /* Unfallback
 
1216
    */
 
1217
   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
 
1218
 
 
1219
   /* Need to restore vertexformat?
 
1220
    */
 
1221
   if (rmesa->TclFallback)
 
1222
      r200ChooseVertexState( ctx );
 
1223
}
 
1224
 
 
1225
 
 
1226
/**********************************************************************/
 
1227
/*                            Initialization.                         */
 
1228
/**********************************************************************/
 
1229
 
 
1230
void r200InitSwtcl( GLcontext *ctx )
 
1231
{
 
1232
   TNLcontext *tnl = TNL_CONTEXT(ctx);
 
1233
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
1234
   GLuint size = TNL_CONTEXT(ctx)->vb.Size;
 
1235
   static int firsttime = 1;
 
1236
 
 
1237
   if (firsttime) {
 
1238
      init_rast_tab();
 
1239
      init_setup_tab();
 
1240
      firsttime = 0;
 
1241
   }
 
1242
 
 
1243
   tnl->Driver.Render.Start = r200RenderStart;
 
1244
   tnl->Driver.Render.Finish = r200RenderFinish;
 
1245
   tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
 
1246
   tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
 
1247
   tnl->Driver.Render.BuildVertices = r200BuildVertices;
 
1248
 
 
1249
   rmesa->swtcl.verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 );
 
1250
   rmesa->swtcl.RenderIndex = ~0;
 
1251
   rmesa->swtcl.render_primitive = GL_TRIANGLES;
 
1252
   rmesa->swtcl.hw_primitive = 0;
 
1253
}
 
1254
 
 
1255
 
 
1256
void r200DestroySwtcl( GLcontext *ctx )
 
1257
{
 
1258
   r200ContextPtr rmesa = R200_CONTEXT(ctx);
 
1259
 
 
1260
   if (rmesa->swtcl.indexed_verts.buf) 
 
1261
      r200ReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ );
 
1262
 
 
1263
   if (rmesa->swtcl.verts) {
 
1264
      ALIGN_FREE(rmesa->swtcl.verts);
 
1265
      rmesa->swtcl.verts = 0;
 
1266
   }
 
1267
 
 
1268
   if (rmesa->UbyteSecondaryColor.Ptr) {
 
1269
      ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
 
1270
      rmesa->UbyteSecondaryColor.Ptr = 0;
 
1271
   }
 
1272
 
 
1273
   if (rmesa->UbyteColor.Ptr) {
 
1274
      ALIGN_FREE(rmesa->UbyteColor.Ptr);
 
1275
      rmesa->UbyteColor.Ptr = 0;
 
1276
   }
 
1277
}