Changed parts of r300_setup_routing to use WARN_ONCE.
[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;
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 fprintf(stderr, "FIXME: Dont know how to handle GL_ARB_vertex_buffer_object "
212 "correctly\n");
213 return;
214 }
215 /* A packet cannot have more than 16383 data words.. */
216 if(((end-start)*4*rmesa->state.aos_count)>16380){
217 fprintf(stderr, "%s:%s: Too many vertices to paint. Fix me !\n");
218 return;
219 }
220
221 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
222
223 start_immediate_packet(end-start, type, 4*rmesa->state.aos_count);
224
225 for(i=start;i<end;i++){
226 #if 0
227 fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
228 VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
229 VEC_ELT(VB->ObjPtr, GLfloat, i)[1],
230 VEC_ELT(VB->ObjPtr, GLfloat, i)[2],
231 VEC_ELT(VB->ObjPtr, GLfloat, i)[3],
232
233 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[0],
234 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[1],
235 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[2],
236 VEC_ELT(VB->ColorPtr[0], GLfloat, i)[3]
237 );
238 #endif
239
240
241 /* coordinates */
242 if(tnl->render_inputs & _TNL_BIT_POS)
243 output_vector(VB->ObjPtr, i);
244 if(tnl->render_inputs & _TNL_BIT_NORMAL)
245 output_vector(VB->NormalPtr, i);
246
247 /* color components */
248 if(tnl->render_inputs & _TNL_BIT_COLOR0)
249 output_vector(VB->ColorPtr[0], i);
250 if(tnl->render_inputs & _TNL_BIT_COLOR1)
251 output_vector(VB->SecondaryColorPtr[0], i);
252
253 if(tnl->render_inputs & _TNL_BIT_FOG)
254 output_vector(VB->FogCoordPtr, i);
255
256 /* texture coordinates */
257 for(k=0;k < ctx->Const.MaxTextureUnits;k++)
258 if(tnl->render_inputs & (_TNL_BIT_TEX0<<k))
259 output_vector(VB->TexCoordPtr[k], i);
260
261 if(tnl->render_inputs & _TNL_BIT_INDEX)
262 output_vector(VB->IndexPtr[0], i);
263 if(tnl->render_inputs & _TNL_BIT_POINTSIZE)
264 output_vector(VB->PointSizePtr, i);
265 }
266
267 }
268
269
270 static GLboolean r300_run_immediate_render(GLcontext *ctx,
271 struct tnl_pipeline_stage *stage)
272 {
273 r300ContextPtr rmesa = R300_CONTEXT(ctx);
274 TNLcontext *tnl = TNL_CONTEXT(ctx);
275 struct vertex_buffer *VB = &tnl->vb;
276 GLuint i;
277 /* Only do 2d textures */
278 struct gl_texture_object *to=ctx->Texture.Unit[0].Current2D;
279 r300TexObjPtr t=to->DriverData;
280 LOCAL_VARS
281
282
283 /* Update texture state - needs to be done only when actually changed..
284 All the time for now.. */
285
286
287 if (RADEON_DEBUG == DEBUG_PRIMS)
288 fprintf(stderr, "%s\n", __FUNCTION__);
289
290 #if 1 /* we need this, somehow */
291 /* Flush state - make sure command buffer is nice and large */
292 r300Flush(ctx);
293 /* Make sure we have enough space */
294 #else 0
295 /* Count is very imprecize, but should be good upper bound */
296 r300EnsureCmdBufSpace(rmesa, rmesa->hw.max_state_size + 4+2+30
297 +VB->PrimitiveCount*(1+8)+VB->Count*4*rmesa->state.texture.tc_count+4, __FUNCTION__);
298 #endif
299
300 /* needed before starting 3d operation .. */
301 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
302 e32(0x0000000a);
303
304 reg_start(0x4f18,0);
305 e32(0x00000003);
306
307
308 #if 0 /* looks like the Z offset issue got fixed */
309 rmesa->hw.vte.cmd[1] = R300_VPORT_X_SCALE_ENA
310 | R300_VPORT_X_OFFSET_ENA
311 | R300_VPORT_Y_SCALE_ENA
312 | R300_VPORT_Y_OFFSET_ENA
313 | R300_VTX_W0_FMT;
314 R300_STATECHANGE(rmesa, vte);
315 #endif
316
317
318
319 /* Magic register - note it is right after 20b0 */
320
321
322 if(rmesa->state.texture.tc_count>0){
323 reg_start(0x20b4,0);
324 e32(0x0000000c);
325
326 }
327
328 r300EmitState(rmesa);
329
330 #if 0
331 reg_start(R300_RB3D_COLORMASK, 0);
332 e32(0xf);
333
334 vsf_start_fragment(0x406, 4);
335 efloat(0.0);
336 efloat(0.0);
337 efloat(0.0);
338 efloat(1.0);
339
340 vsf_start_fragment(0x400, 4);
341 efloat(0.0);
342 efloat(0.0);
343 efloat(0.0);
344 efloat(1.0);
345 #endif
346
347 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
348 r300EmitLOAD_VBPNTR(rmesa, 0);
349
350 for(i=0; i < VB->PrimitiveCount; i++){
351 GLuint prim = VB->Primitive[i].mode;
352 GLuint start = VB->Primitive[i].start;
353 GLuint length = VB->Primitive[i].count;
354 r300_render_immediate_primitive(rmesa, ctx, start, start + length, prim);
355 }
356
357 /* This sequence is required after any 3d drawing packet
358 I suspect it work arounds a bug (or deficiency) in hardware */
359
360 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
361 e32(0x0000000a);
362
363 reg_start(0x4f18,0);
364 e32(0x00000003);
365
366 return GL_FALSE;
367 }
368
369
370 /* vertex buffer implementation */
371
372 /* We use the start part of GART texture buffer for vertices */
373
374
375 static void upload_vertex_buffer(r300ContextPtr rmesa, GLcontext *ctx)
376 {
377 TNLcontext *tnl = TNL_CONTEXT(ctx);
378 struct vertex_buffer *VB = &tnl->vb;
379 int idx=0;
380 int i,j,k;
381 radeonScreenPtr rsp=rmesa->radeon.radeonScreen;
382
383 /* A hack - we don't want to overwrite vertex buffers, so we
384 just use AGP space for them.. Fix me ! */
385 static int offset=0;
386 if(offset>2*1024*1024){
387 //fprintf(stderr, "Wrapping agp vertex buffer offset\n");
388 offset=0;
389 }
390 /* Not the most efficient implementation, but, for now, I just want something that
391 works */
392 /* to do - make single memcpy per column (is it possible ?) */
393 /* to do - use dirty flags to avoid redundant copies */
394 #define UPLOAD_VECTOR(v)\
395 { \
396 /* Is the data dirty ? */ \
397 if (v->flags & ((1<<v->size)-1)) { \
398 /* fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); */ \
399 if(v->size*4==v->stride){\
400 /* fast path */ \
401 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
402 } else { \
403 for(i=0;i<VB->Count;i++){ \
404 /* copy one vertex at a time*/ \
405 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
406 } \
407 } \
408 /* v->flags &= ~((1<<v->size)-1);*/ \
409 } \
410 rmesa->state.aos[idx].offset=rsp->gartTextures.handle+offset; \
411 offset+=v->size*4*VB->Count; \
412 idx++; \
413 }
414
415 UPLOAD_VECTOR(VB->ObjPtr);
416 UPLOAD_VECTOR(VB->ColorPtr[0]);
417 /* texture coordinates */
418 for(k=0;k < ctx->Const.MaxTextureUnits;k++)
419 if(ctx->Texture.Unit[k].Enabled)
420 UPLOAD_VECTOR(VB->TexCoordPtr[k]);
421
422 if(idx>=R300_MAX_AOS_ARRAYS){
423 fprintf(stderr, "Aieee ! Maximum AOS arrays count exceeded.. \n");
424 exit(-1);
425 }
426 }
427
428 static void r300_render_vb_primitive(r300ContextPtr rmesa,
429 GLcontext *ctx,
430 int start,
431 int end,
432 int prim)
433 {
434 int type;
435 LOCAL_VARS
436
437 if(end<=start)return; /* do we need to watch for this ? */
438
439 type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
440 if(type<0)return;
441
442 fire_AOS(PASS_PREFIX end-start, type);
443 }
444
445 static GLboolean r300_run_vb_render(GLcontext *ctx,
446 struct tnl_pipeline_stage *stage)
447 {
448 r300ContextPtr rmesa = R300_CONTEXT(ctx);
449 TNLcontext *tnl = TNL_CONTEXT(ctx);
450 struct vertex_buffer *VB = &tnl->vb;
451 int i, j;
452 LOCAL_VARS
453
454 if (RADEON_DEBUG == DEBUG_PRIMS)
455 fprintf(stderr, "%s\n", __FUNCTION__);
456
457
458 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
459 e32(0x0000000a);
460
461 reg_start(0x4f18,0);
462 e32(0x00000003);
463
464 r300_setup_routing(ctx, GL_FALSE);
465
466 r300EmitState(rmesa);
467
468 /* setup array of structures data */
469 LOCK_HARDWARE(&(rmesa->radeon));
470
471 upload_vertex_buffer(rmesa, ctx);
472 //fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
473
474 for(i=0; i < VB->PrimitiveCount; i++){
475 GLuint prim = VB->Primitive[i].mode;
476 GLuint start = VB->Primitive[i].start;
477 GLuint length = VB->Primitive[i].count;
478
479 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. */
480 r300EmitLOAD_VBPNTR(rmesa, start);
481
482 r300_render_vb_primitive(rmesa, ctx, start, start + length, prim);
483 }
484
485 /* This sequence is required after any 3d drawing packet
486 I suspect it works around a bug (or deficiency) in hardware */
487
488 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
489 e32(0x0000000a);
490
491 reg_start(0x4f18,0);
492 e32(0x00000003);
493
494 end_3d(PASS_PREFIX_VOID);
495
496 /* Flush state - we are done drawing.. */
497 r300FlushCmdBufLocked(ctx, __FUNCTION__);
498 radeonWaitForIdleLocked(&(rmesa->radeon));
499
500 UNLOCK_HARDWARE(&(rmesa->radeon));
501 return GL_FALSE;
502 }
503
504
505 /**
506 * Called by the pipeline manager to render a batch of primitives.
507 * We can return true to pass on to the next stage (i.e. software
508 * rasterization) or false to indicate that the pipeline has finished
509 * after we render something.
510 */
511 static GLboolean r300_run_render(GLcontext *ctx,
512 struct tnl_pipeline_stage *stage)
513 {
514 r300ContextPtr rmesa = R300_CONTEXT(ctx);
515 TNLcontext *tnl = TNL_CONTEXT(ctx);
516 struct vertex_buffer *VB = &tnl->vb;
517 GLuint i;
518
519 if (RADEON_DEBUG == DEBUG_PRIMS)
520 fprintf(stderr, "%s\n", __FUNCTION__);
521
522
523 #if 1
524
525 #if 1
526 return r300_run_immediate_render(ctx, stage);
527 #else
528 return r300_run_vb_render(ctx, stage);
529 #endif
530 #else
531 return GL_TRUE;
532 #endif
533
534 #if 0
535 mgaContextPtr mmesa = MGA_CONTEXT(ctx);
536 TNLcontext *tnl = TNL_CONTEXT(ctx);
537 struct vertex_buffer *VB = &tnl->vb;
538 GLuint i;
539
540 /* Don't handle clipping or indexed vertices or vertex manipulations.
541 */
542 if (mmesa->RenderIndex != 0 ||
543 !mga_validate_render( ctx, VB )) {
544 return GL_TRUE;
545 }
546
547 tnl->Driver.Render.Start( ctx );
548 mmesa->SetupNewInputs = ~0;
549
550 for (i = 0 ; i < VB->PrimitiveCount ; i++)
551 {
552 GLuint prim = VB->Primitive[i].mode;
553 GLuint start = VB->Primitive[i].start;
554 GLuint length = VB->Primitive[i].count;
555
556 if (!length)
557 continue;
558
559 mga_render_tab_verts[prim & PRIM_MODE_MASK]( ctx, start, start + length,
560 prim);
561 }
562
563 tnl->Driver.Render.Finish( ctx );
564
565 return GL_FALSE; /* finished the pipe */
566 #endif
567 }
568
569
570 /**
571 * Called by the pipeline manager once before rendering.
572 * We check the GL state here to
573 * a) decide whether we can do the current state in hardware and
574 * b) update hardware registers
575 */
576 #define FALLBACK_IF(expr) \
577 do { \
578 if (expr) { \
579 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
580 fprintf(stderr, "%s: fallback:%s\n", \
581 __FUNCTION__, #expr); \
582 stage->active = GL_FALSE; \
583 return; \
584 } \
585 } while(0)
586
587 static void r300_check_render(GLcontext *ctx, struct tnl_pipeline_stage *stage)
588 {
589 r300ContextPtr r300 = R300_CONTEXT(ctx);
590 int i;
591
592 if (RADEON_DEBUG & DEBUG_STATE)
593 fprintf(stderr, "%s\n", __FUNCTION__);
594
595 /* We only support rendering in hardware for now */
596 if (ctx->RenderMode != GL_RENDER) {
597 stage->active = GL_FALSE;
598 return;
599 }
600
601 #if 0 // selecting VERT_BIT_NORMAL still doesnt give us normals but why?
602 stage->inputs |= VERT_BIT_POS;
603 stage->inputs |= VERT_BIT_NORMAL;
604 stage->inputs |= VERT_BIT_COLOR0;
605 #endif
606
607 // I failed to figure out how dither works in hardware,
608 // let's just ignore it for now
609 //FALLBACK_IF(ctx->Color.DitherFlag);
610
611 /* I'm almost certain I forgot something here */
612 #if 0 /* This should work now.. */
613 FALLBACK_IF(ctx->Color.AlphaEnabled); // GL_ALPHA_TEST
614 FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
615 #endif
616 FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG
617 FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH
618 FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE
619 FALLBACK_IF(ctx->Point.SmoothFlag); // GL_POINT_SMOOTH
620 if (ctx->Extensions.NV_point_sprite || ctx->Extensions.ARB_point_sprite)
621 FALLBACK_IF(ctx->Point.PointSprite); // GL_POINT_SPRITE_NV
622 FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
623 FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
624 //FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
625 if(ctx->Polygon.OffsetFill)WARN_ONCE("Polygon.OffsetFill not implemented, ignoring\n");
626 FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH
627 FALLBACK_IF(ctx->Polygon.StippleFlag); // GL_POLYGON_STIPPLE
628 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
629 FALLBACK_IF(ctx->Multisample.Enabled); // GL_MULTISAMPLE_ARB
630
631 /* One step at a time - let one texture pass.. */
632 for (i = 1; i < ctx->Const.MaxTextureUnits; i++)
633 FALLBACK_IF(ctx->Texture.Unit[i].Enabled);
634
635 /* let r300_run_render do its job */
636 #if 0
637 stage->active = GL_FALSE;
638 #endif
639 }
640
641
642 static void dtr(struct tnl_pipeline_stage *stage)
643 {
644 (void)stage;
645 }
646
647 const struct tnl_pipeline_stage _r300_render_stage = {
648 "r300 hw rasterize",
649 _NEW_ALL, /* re-check (always re-check for now) */
650 0, /* re-run (always runs) */
651 GL_TRUE, /* active */
652 0, 0, /* inputs (set in check_render), outputs */
653 0, 0, /* changed_inputs, private */
654 dtr, /* destructor */
655 r300_check_render, /* check */
656 r300_run_render /* run */
657 };