Start beginning of pixel shader generator..
[mesa.git] / src / mesa / drivers / dri / r300 / r300_render.c
1 /**************************************************************************
2
3 Copyright (C) 2004 Nicolai Haehnle.
4
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Nicolai Haehnle <prefect_@gmx.net>
31 */
32
33 #include "glheader.h"
34 #include "state.h"
35 #include "imports.h"
36 #include "enums.h"
37 #include "macros.h"
38 #include "context.h"
39 #include "dd.h"
40 #include "simple_list.h"
41
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
46 #include "tnl/tnl.h"
47
48 #include "radeon_reg.h"
49 #include "radeon_macros.h"
50 #include "radeon_ioctl.h"
51 #include "radeon_state.h"
52 #include "r300_context.h"
53 #include "r300_ioctl.h"
54 #include "r300_state.h"
55 #include "r300_reg.h"
56 #include "r300_program.h"
57 #include "r300_tex.h"
58
59 #include "r300_emit.h"
60
61 /**********************************************************************
62 * Hardware rasterization
63 *
64 * When we fell back to software TCL, we still try to use the
65 * rasterization hardware for rendering.
66 **********************************************************************/
67
68 static int r300_get_primitive_type(r300ContextPtr rmesa,
69 GLcontext *ctx,
70 int start,
71 int end,
72 int prim)
73 {
74 TNLcontext *tnl = TNL_CONTEXT(ctx);
75 struct vertex_buffer *VB = &tnl->vb;
76 GLuint i;
77 int type=-1, min_vertices=0;
78 char *name="UNKNOWN";
79
80 if(end<=start)return -1; /* do we need to watch for this ? */
81
82 switch (prim & PRIM_MODE_MASK) {
83 case GL_POINTS:
84 name="P";
85 type=R300_VAP_VF_CNTL__PRIM_POINTS;
86 min_vertices=1;
87 break;
88 case GL_LINES:
89 name="L";
90 type=R300_VAP_VF_CNTL__PRIM_LINES;
91 min_vertices=2;
92 break;
93 case GL_LINE_STRIP:
94 name="LS";
95 type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
96 min_vertices=2;
97 break;
98 case GL_LINE_LOOP:
99 name="LL";
100 min_vertices=2;
101 return -1;
102 break;
103 case GL_TRIANGLES:
104 name="T";
105 type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
106 min_vertices=3;
107 break;
108 case GL_TRIANGLE_STRIP:
109 name="TS";
110 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
111 min_vertices=3;
112 break;
113 case GL_TRIANGLE_FAN:
114 name="TF";
115 type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
116 min_vertices=3;
117 break;
118 case GL_QUADS:
119 name="Q";
120 type=R300_VAP_VF_CNTL__PRIM_QUADS;
121 min_vertices=4;
122 break;
123 case GL_QUAD_STRIP:
124 name="QS";
125 type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
126 min_vertices=4;
127 break;
128 case GL_POLYGON:
129 name="P";
130 type=R300_VAP_VF_CNTL__PRIM_POLYGON;
131 min_vertices=3;
132 break;
133 default:
134 fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
135 __FILE__, __FUNCTION__,
136 prim & PRIM_MODE_MASK);
137 return -1;
138 break;
139 }
140 #if 0
141 fprintf(stderr, "[%d-%d]%s ", start, end, name);
142 #endif
143 if(start+min_vertices>end){
144 static int warn_once=1;
145 if(warn_once){
146 fprintf(stderr, "%s:%s ***WARN_ONCE*** Not enough vertices to draw primitive %02x - help me !\n",
147 __FILE__, __FUNCTION__,
148 prim & PRIM_MODE_MASK);
149 warn_once=0;
150 }
151 return -1;
152 }
153 return type;
154 }
155
156 /* This function compiles GL context into state registers that
157 describe data routing inside of R300 pipeline.
158
159 In particular, it programs input_route, output_vtx_fmt, texture
160 unit configuration and gb_output_vtx_fmt
161
162 This function encompasses setup_AOS() from r300_lib.c
163 */
164
165
166
167
168 /* Immediate implementation - vertex data is sent via command stream */
169
170 static GLfloat default_vector[4]={0.0, 0.0, 0.0, 1.0};
171
172 #define output_vector(v, i) \
173 { \
174 int _i; \
175 for(_i=0;_i<v->size;_i++){ \
176 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
177 } \
178 for(_i=v->size;_i<4;_i++){ \
179 efloat(default_vector[_i]); \
180 } \
181 }
182
183 /* Immediate implementation - vertex data is sent via command stream */
184
185 static void r300_render_immediate_primitive(r300ContextPtr rmesa,
186 GLcontext *ctx,
187 int start,
188 int end,
189 int prim)
190 {
191 TNLcontext *tnl = TNL_CONTEXT(ctx);
192 struct vertex_buffer *VB = &tnl->vb;
193 GLuint i, render_inputs;
194 int k, type;
195 LOCAL_VARS
196
197 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
198
199 #if 0
200 fprintf(stderr,"ObjPtr: size=%d stride=%d\n",
201 VB->ObjPtr->size, VB->ObjPtr->stride);
202 fprintf(stderr,"ColorPtr[0]: size=%d stride=%d\n",
203 VB->ColorPtr[0]->size, VB->ColorPtr[0]->stride);
204 fprintf(stderr,"TexCoordPtr[0]: size=%d stride=%d\n",
205 VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride);
206 #endif
207
208 if(type<0)return;
209
210 if(!VB->ObjPtr){
211 WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
212 return;
213 }
214 /* A packet cannot have more than 16383 data words.. */
215 if(((end-start)*4*rmesa->state.aos_count)>16380){
216 WARN_ONCE("Too many vertices to paint. Fix me !\n");
217 return;
218 }
219
220 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
221
222 if(rmesa->state.aos_count==0){
223 WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n");
224 return;
225 }
226
227 render_inputs = rmesa->state.render_inputs;
228
229 if(!render_inputs){
230 WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
231 return;
232 }
233
234 start_immediate_packet(end-start, type, 4*rmesa->state.aos_count);
235
236 for(i=start;i<end;i++){
237 #if 0
238 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
239 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
240 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
241 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
242 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
243
244 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
245 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
246 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
247 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
248 );
249 #endif
250
251
252 /* coordinates */
253 if(render_inputs & _TNL_BIT_POS)
254 output_vector(VB->ObjPtr, i);
255 if(render_inputs & _TNL_BIT_NORMAL)
256 output_vector(VB->NormalPtr, i);
257
258 /* color components */
259 if(render_inputs & _TNL_BIT_COLOR0)
260 output_vector(VB->ColorPtr[0], i);
261 if(render_inputs & _TNL_BIT_COLOR1)
262 output_vector(VB->SecondaryColorPtr[0], i);
263
264 if(render_inputs & _TNL_BIT_FOG)
265 output_vector(VB->FogCoordPtr, i);
266
267 /* texture coordinates */
268 for(k=0;k < ctx->Const.MaxTextureUnits;k++)
269 if(render_inputs & (_TNL_BIT_TEX0<<k))
270 output_vector(VB->TexCoordPtr[k], i);
271
272 if(render_inputs & _TNL_BIT_INDEX)
273 output_vector(VB->IndexPtr[0], i);
274 if(render_inputs & _TNL_BIT_POINTSIZE)
275 output_vector(VB->PointSizePtr, i);
276 }
277
278 }
279
280
281 static GLboolean r300_run_immediate_render(GLcontext *ctx,
282 struct tnl_pipeline_stage *stage)
283 {
284 r300ContextPtr rmesa = R300_CONTEXT(ctx);
285 TNLcontext *tnl = TNL_CONTEXT(ctx);
286 struct vertex_buffer *VB = &tnl->vb;
287 GLuint i;
288 /* Only do 2d textures */
289 struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D;
290 r300TexObjPtr t=to->DriverData;
291 LOCAL_VARS
292
293
294 /* Update texture state - needs to be done only when actually changed..
295 All the time for now.. */
296
297
298 if (RADEON_DEBUG == DEBUG_PRIMS)
299 fprintf(stderr, "%s\n", __FUNCTION__);
300
301 #if 1 /* we need this, somehow */
302 /* Flush state - make sure command buffer is nice and large */
303 r300Flush(ctx);
304 /* Make sure we have enough space */
305 #else
306 /* Count is very imprecize, but should be good upper bound */
307 r300EnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size + 4+2+30
308 +VB->PrimitiveCount*(1+8)+VB->Count*4*rmesa->state.texture.tc_count+4, __FUNCTION__);
309 #endif
310
311 /* needed before starting 3d operation .. */
312 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
313 e32(0x0000000a);
314
315 reg_start(0x4f18,0);
316 e32(0x00000003);
317
318
319 #if 0 /* looks like the Z offset issue got fixed */
320 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
321 | R300_VPORT_X_OFFSET_ENA
322 | R300_VPORT_Y_SCALE_ENA
323 | R300_VPORT_Y_OFFSET_ENA
324 | R300_VTX_W0_FMT;
325 R300_STATECHANGE(rmesa, vte);
326 #endif
327
328
329
330 /* Magic register - note it is right after 20b0 */
331
332
333 if(rmesa->state.texture.tc_count>0){
334 reg_start(0x20b4,0);
335 e32(0x0000000c);
336
337 }
338
339 r300EmitState(rmesa);
340
341 #if 0
342 reg_start(R300_RB3D_COLORMASK, 0);
343 e32(0xf);
344
345 vsf_start_fragment(0x406, 4);
346 efloat(0.0);
347 efloat(0.0);
348 efloat(0.0);
349 efloat(1.0);
350
351 vsf_start_fragment(0x400, 4);
352 efloat(0.0);
353 efloat(0.0);
354 efloat(0.0);
355 efloat(1.0);
356 #endif
357
358 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
359 r300EmitLOAD_VBPNTR(rmesa, 0);
360
361 for(i=0; i < VB->PrimitiveCount; i++){
362 GLuint prim = VB->Primitive[i].mode;
363 GLuint start = VB->Primitive[i].start;
364 GLuint length = VB->Primitive[i].count;
365 r300_render_immediate_primitive(rmesa, ctx, start, start + length, prim);
366 }
367
368 /* This sequence is required after any 3d drawing packet
369 I suspect it work arounds a bug (or deficiency) in hardware */
370
371 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
372 e32(0x0000000a);
373
374 reg_start(0x4f18,0);
375 e32(0x00000003);
376
377 return GL_FALSE;
378 }
379
380
381 /* vertex buffer implementation */
382
383 /* We use the start part of GART texture buffer for vertices */
384
385
386 static void upload_vertex_buffer(r300ContextPtr rmesa, GLcontext *ctx)
387 {
388 TNLcontext *tnl = TNL_CONTEXT(ctx);
389 struct vertex_buffer *VB = &tnl->vb;
390 int idx=0;
391 int i,j,k;
392 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
393
394 /* A hack - we don't want to overwrite vertex buffers, so we
395 just use AGP space for them.. Fix me ! */
396 static int offset=0;
397 if(offset>2*1024*1024){
398 //fprintf(stderr, "Wrapping agp vertex buffer offset\n");
399 offset=0;
400 }
401 /* Not the most efficient implementation, but, for now, I just want something that
402 works */
403 /* to do - make single memcpy per column (is it possible ?) */
404 /* to do - use dirty flags to avoid redundant copies */
405 #define UPLOAD_VECTOR(v)\
406 { \
407 /* Is the data dirty ? */ \
408 if (v->flags & ((1<<v->size)-1)) { \
409 /* fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); */ \
410 if(v->size*4==v->stride){\
411 /* fast path */ \
412 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
413 } else { \
414 for(i=0;i<VB->Count;i++){ \
415 /* copy one vertex at a time*/ \
416 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
417 } \
418 } \
419 /* v->flags &= ~((1<<v->size)-1);*/ \
420 } \
421 rmesa->state.aos[idx].offset=rsp->gartTextures.handle+offset; \
422 offset+=v->size*4*VB->Count; \
423 idx++; \
424 }
425
426 UPLOAD_VECTOR(VB->ObjPtr);
427 UPLOAD_VECTOR(VB->ColorPtr[0]);
428 /* texture coordinates */
429 for(k=0;k < ctx->Const.MaxTextureUnits;k++)
430 if(ctx->Texture.Unit[k].Enabled)
431 UPLOAD_VECTOR(VB->TexCoordPtr[k]);
432
433 if(idx>=R300_MAX_AOS_ARRAYS){
434 fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
435 exit(-1);
436 }
437 }
438
439 static void r300_render_vb_primitive(r300ContextPtr rmesa,
440 GLcontext *ctx,
441 int start,
442 int end,
443 int prim)
444 {
445 int type;
446 LOCAL_VARS
447
448 if(end<=start)return; /* do we need to watch for this ? */
449
450 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
451 if(type<0)return;
452
453 fire_AOS(PASS_PREFIX end-start, type);
454 }
455
456 static GLboolean r300_run_vb_render(GLcontext *ctx,
457 struct tnl_pipeline_stage *stage)
458 {
459 r300ContextPtr rmesa = R300_CONTEXT(ctx);
460 TNLcontext *tnl = TNL_CONTEXT(ctx);
461 struct vertex_buffer *VB = &tnl->vb;
462 int i, j;
463 LOCAL_VARS
464
465 if (RADEON_DEBUG == DEBUG_PRIMS)
466 fprintf(stderr, "%s\n", __FUNCTION__);
467
468
469 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
470 e32(0x0000000a);
471
472 reg_start(0x4f18,0);
473 e32(0x00000003);
474
475 r300_setup_routing(ctx, GL_FALSE);
476
477 r300EmitState(rmesa);
478
479 /* setup array of structures data */
480 LOCK_HARDWARE(&(rmesa->radeon));
481
482 upload_vertex_buffer(rmesa, ctx);
483 //fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
484
485 for(i=0; i < VB->PrimitiveCount; i++){
486 GLuint prim = VB->Primitive[i].mode;
487 GLuint start = VB->Primitive[i].start;
488 GLuint length = VB->Primitive[i].count;
489
490 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. */
491 r300EmitLOAD_VBPNTR(rmesa, start);
492
493 r300_render_vb_primitive(rmesa, ctx, start, start + length, prim);
494 }
495
496 /* This sequence is required after any 3d drawing packet
497 I suspect it works around a bug (or deficiency) in hardware */
498
499 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
500 e32(0x0000000a);
501
502 reg_start(0x4f18,0);
503 e32(0x00000003);
504
505 end_3d(PASS_PREFIX_VOID);
506
507 /* Flush state - we are done drawing.. */
508 r300FlushCmdBufLocked(ctx, __FUNCTION__);
509 radeonWaitForIdleLocked(&(rmesa->radeon));
510
511 UNLOCK_HARDWARE(&(rmesa->radeon));
512 return GL_FALSE;
513 }
514
515
516 /**
517 * Called by the pipeline manager to render a batch of primitives.
518 * We can return true to pass on to the next stage (i.e. software
519 * rasterization) or false to indicate that the pipeline has finished
520 * after we render something.
521 */
522 static GLboolean r300_run_render(GLcontext *ctx,
523 struct tnl_pipeline_stage *stage)
524 {
525 r300ContextPtr rmesa = R300_CONTEXT(ctx);
526 TNLcontext *tnl = TNL_CONTEXT(ctx);
527 struct vertex_buffer *VB = &tnl->vb;
528 GLuint i;
529
530 if (RADEON_DEBUG == DEBUG_PRIMS)
531 fprintf(stderr, "%s\n", __FUNCTION__);
532
533
534 #if 1
535
536 #if 1
537 return r300_run_immediate_render(ctx, stage);
538 #else
539 return r300_run_vb_render(ctx, stage);
540 #endif
541 #else
542 return GL_TRUE;
543 #endif
544
545 #if 0
546 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
547 TNLcontext *tnl = TNL_CONTEXT(ctx);
548 struct vertex_buffer *VB = &tnl->vb;
549 GLuint i;
550
551 /* Don't handle clipping or indexed vertices or vertex manipulations.
552 */
553 if (mmesa->RenderIndex != 0 ||
554 !mga_validate_render( ctx, VB )) {
555 return GL_TRUE;
556 }
557
558 tnl->Driver.Render.Start( ctx );
559 mmesa->SetupNewInputs = ~0;
560
561 for (i = 0 ; i < VB->PrimitiveCount ; i++)
562 {
563 GLuint prim = VB->Primitive[i].mode;
564 GLuint start = VB->Primitive[i].start;
565 GLuint length = VB->Primitive[i].count;
566
567 if (!length)
568 continue;
569
570 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
571 prim);
572 }
573
574 tnl->Driver.Render.Finish( ctx );
575
576 return GL_FALSE; /* finished the pipe */
577 #endif
578 }
579
580
581 /**
582 * Called by the pipeline manager once before rendering.
583 * We check the GL state here to
584 * a) decide whether we can do the current state in hardware and
585 * b) update hardware registers
586 */
587 #define FALLBACK_IF(expr) \
588 do { \
589 if (expr) { \
590 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
591 fprintf(stderr, "%s: fallback:%s\n", \
592 __FUNCTION__, #expr); \
593 stage->active = GL_FALSE; \
594 return; \
595 } \
596 } while(0)
597
598 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
599 {
600 r300ContextPtr r300 = R300_CONTEXT(ctx);
601 int i;
602
603 if (RADEON_DEBUG & DEBUG_STATE)
604 fprintf(stderr, "%s\n", __FUNCTION__);
605
606 /* We only support rendering in hardware for now */
607 if (ctx->RenderMode != GL_RENDER) {
608 stage->active = GL_FALSE;
609 return;
610 }
611
612 #if 0 // selecting VERT_BIT_NORMAL still doesnt give us normals but why?
613 stage->inputs |= VERT_BIT_POS;
614 stage->inputs |= VERT_BIT_NORMAL;
615 stage->inputs |= VERT_BIT_COLOR0;
616 #endif
617
618 // I failed to figure out how dither works in hardware,
619 // let's just ignore it for now
620 //FALLBACK_IF(ctx->Color.DitherFlag);
621
622 /* I'm almost certain I forgot something here */
623 #if 0 /* This should work now.. */
624 FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
625 FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
626 #endif
627 FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
628 FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
629 FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
630 FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
631 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
632 FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
633 FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
634 FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
635 //FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
636 //if(ctx->Polygon.OffsetFill)WARN_ONCE("Polygon.OffsetFill not implemented, ignoring\n");
637 FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
638 FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
639 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
640 FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
641
642 /* One step at a time - let one texture pass.. */
643 for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
644 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
645
646 /* let r300_run_render do its job */
647 #if 0
648 stage->active = GL_FALSE;
649 #endif
650 }
651
652
653 static void dtr(struct tnl_pipeline_stage *stage)
654 {
655 (void)stage;
656 }
657
658 const struct tnl_pipeline_stage _r300_render_stage = {
659 "r300 hw rasterize",
660 _NEW_ALL, /* re-check (always re-check for now) */
661 0, /* re-run (always runs) */
662 GL_TRUE, /* active */
663 0, 0, /* inputs (set in check_render), outputs */
664 0, 0, /* changed_inputs, private */
665 dtr, /* destructor */
666 r300_check_render, /* check */
667 r300_run_render /* run */
668 };