1 /**************************************************************************
3 Copyright (C) 2004 Nicolai Haehnle.
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:
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
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.
26 **************************************************************************/
30 * Nicolai Haehnle <prefect_@gmx.net>
40 #include "simple_list.h"
42 #include "api_arrayelt.h"
43 #include "swrast/swrast.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "array_cache/acache.h"
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"
56 #include "r300_program.h"
58 #include "r300_maos.h"
59 #include "r300_emit.h"
61 /**********************************************************************
62 * Hardware rasterization
64 * When we fell back to software TCL, we still try to use the
65 * rasterization hardware for rendering.
66 **********************************************************************/
68 static int r300_get_primitive_type(r300ContextPtr rmesa
, GLcontext
*ctx
, int prim
)
70 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
71 struct vertex_buffer
*VB
= &tnl
->vb
;
75 switch (prim
& PRIM_MODE_MASK
) {
77 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
80 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
83 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
86 type
=R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
89 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
91 case GL_TRIANGLE_STRIP
:
92 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
95 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
98 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
101 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
104 type
=R300_VAP_VF_CNTL__PRIM_POLYGON
;
107 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
108 __FILE__
, __FUNCTION__
,
109 prim
& PRIM_MODE_MASK
);
116 static int r300_get_num_verts(r300ContextPtr rmesa
,
121 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
122 struct vertex_buffer
*VB
= &tnl
->vb
;
124 int type
=-1, verts_off
=0;
125 char *name
="UNKNOWN";
127 switch (prim
& PRIM_MODE_MASK
) {
134 verts_off
= num_verts
% 2;
139 verts_off
= num_verts
;
144 verts_off
= num_verts
;
148 verts_off
= num_verts
% 3;
150 case GL_TRIANGLE_STRIP
:
153 verts_off
= num_verts
;
155 case GL_TRIANGLE_FAN
:
158 verts_off
= num_verts
;
162 verts_off
= num_verts
% 4;
167 verts_off
= num_verts
;
169 verts_off
= num_verts
% 2;
174 verts_off
= num_verts
;
177 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
178 __FILE__
, __FUNCTION__
,
179 prim
& PRIM_MODE_MASK
);
184 if(num_verts
- verts_off
== 0){
185 WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts
, name
);
190 WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts
, name
);
193 return num_verts
- verts_off
;
196 void dump_inputs(GLcontext
*ctx
, int render_inputs
)
199 fprintf(stderr
, "inputs:");
200 fprintf(stderr
, "%08x ", render_inputs
);
202 if(render_inputs
& _TNL_BIT_POS
)
203 fprintf(stderr
, "_TNL_BIT_POS ");
204 if(render_inputs
& _TNL_BIT_NORMAL
)
205 fprintf(stderr
, "_TNL_BIT_NORMAL ");
207 /* color components */
208 if(render_inputs
& _TNL_BIT_COLOR0
)
209 fprintf(stderr
, "_TNL_BIT_COLOR0 ");
210 if(render_inputs
& _TNL_BIT_COLOR1
)
211 fprintf(stderr
, "_TNL_BIT_COLOR1 ");
213 if(render_inputs
& _TNL_BIT_FOG
)
214 fprintf(stderr
, "_TNL_BIT_FOG ");
216 /* texture coordinates */
217 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
218 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
219 fprintf(stderr
, "_TNL_BIT_TEX%d ", k
);
221 if(render_inputs
& _TNL_BIT_INDEX
)
222 fprintf(stderr
, "_TNL_BIT_INDEX ");
223 if(render_inputs
& _TNL_BIT_POINTSIZE
)
224 fprintf(stderr
, "_TNL_BIT_POINTSIZE ");
226 fprintf(stderr
, "\n");
229 /* This function compiles GL context into state registers that
230 describe data routing inside of R300 pipeline.
232 In particular, it programs input_route, output_vtx_fmt, texture
233 unit configuration and gb_output_vtx_fmt
235 This function encompasses setup_AOS() from r300_lib.c
241 /* Immediate implementation - vertex data is sent via command stream */
243 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
245 #define output_vector(v, i) \
248 for(_i=0;_i<v->size;_i++){ \
249 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
251 for(_i=v->size;_i<4;_i++){ \
252 efloat(default_vector[_i]); \
256 /* Immediate implementation - vertex data is sent via command stream */
258 static void r300_render_immediate_primitive(r300ContextPtr rmesa
,
264 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
265 struct vertex_buffer
*VB
= &tnl
->vb
;
266 GLuint i
, render_inputs
;
267 int k
, type
, num_verts
;
270 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
271 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
274 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
275 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
276 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
277 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
278 fprintf(stderr
,"TexCoordPtr[0]: size=%d stride=%d\n",
279 VB
->TexCoordPtr
[0]->size
, VB
->TexCoordPtr
[0]->stride
);
282 if(type
<0 || num_verts
<= 0)return;
285 WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
288 /* A packet cannot have more than 16383 data words.. */
289 if((num_verts
*4*rmesa
->state
.aos_count
)>16380){
290 WARN_ONCE("Too many vertices to paint. Fix me !\n");
294 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
296 if(rmesa
->state
.aos_count
==0){
297 WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n");
301 render_inputs
= rmesa
->state
.render_inputs
;
304 WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
308 //dump_inputs(ctx, render_inputs); return ;
310 start_immediate_packet(num_verts
, type
, 4*rmesa
->state
.aos_count
);
312 for(i
=start
;i
<start
+num_verts
;i
++){
314 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
315 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
316 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
317 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
318 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
320 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
321 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
322 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
323 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
329 if(render_inputs
& _TNL_BIT_POS
)
330 output_vector(VB
->ObjPtr
, i
);
331 if(render_inputs
& _TNL_BIT_NORMAL
)
332 output_vector(VB
->NormalPtr
, i
);
334 /* color components */
335 if(render_inputs
& _TNL_BIT_COLOR0
)
336 output_vector(VB
->ColorPtr
[0], i
);
337 if(render_inputs
& _TNL_BIT_COLOR1
)
338 output_vector(VB
->SecondaryColorPtr
[0], i
);
340 /* if(render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on
341 output_vector(VB->FogCoordPtr, i);*/
343 /* texture coordinates */
344 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
345 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
346 output_vector(VB
->TexCoordPtr
[k
], i
);
348 if(render_inputs
& _TNL_BIT_INDEX
)
349 output_vector(VB
->IndexPtr
[0], i
);
350 if(render_inputs
& _TNL_BIT_POINTSIZE
)
351 output_vector(VB
->PointSizePtr
, i
);
357 static GLboolean
r300_run_immediate_render(GLcontext
*ctx
,
358 struct tnl_pipeline_stage
*stage
)
360 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
361 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
362 struct vertex_buffer
*VB
= &tnl
->vb
;
364 /* Only do 2d textures */
365 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
366 r300TexObjPtr t
=to
->DriverData
;
370 /* Update texture state - needs to be done only when actually changed..
371 All the time for now.. */
374 if (RADEON_DEBUG
== DEBUG_PRIMS
)
375 fprintf(stderr
, "%s\n", __FUNCTION__
);
377 #if 1 /* we need this, somehow */
378 /* Flush state - make sure command buffer is nice and large */
380 /* Make sure we have enough space */
382 /* Count is very imprecize, but should be good upper bound */
383 r300EnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
+ 4+2+30
384 +VB
->PrimitiveCount
*(1+8)+VB
->Count
*4*rmesa
->state
.texture
.tc_count
+4, __FUNCTION__
);
387 /* needed before starting 3d operation .. */
388 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
395 #if 0 /* looks like the Z offset issue got fixed */
396 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
397 | R300_VPORT_X_OFFSET_ENA
398 | R300_VPORT_Y_SCALE_ENA
399 | R300_VPORT_Y_OFFSET_ENA
401 R300_STATECHANGE(rmesa
, vte
);
406 /* Magic register - note it is right after 20b0 */
409 if(rmesa
->state
.texture
.tc_count
>0){
415 r300EmitState(rmesa
);
418 reg_start(R300_RB3D_COLORMASK
, 0);
421 vsf_start_fragment(0x406, 4);
427 vsf_start_fragment(0x400, 4);
434 /* Setup INPUT_ROUTE and INPUT_CNTL */
435 r300EmitArrays(ctx
, GL_TRUE
);
437 /* Why do we need this for immediate mode?? Vertex processor needs it to know proper regs */
438 // r300EmitLOAD_VBPNTR(rmesa, 0);
439 /* Okay, it seems I misunderstood something, EmitAOS does the same thing */
440 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, 0);
442 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
443 GLuint prim
= VB
->Primitive
[i
].mode
;
444 GLuint start
= VB
->Primitive
[i
].start
;
445 GLuint length
= VB
->Primitive
[i
].count
;
447 r300_render_immediate_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
450 /* This sequence is required after any 3d drawing packet
451 I suspect it work arounds a bug (or deficiency) in hardware */
453 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
462 /* vertex buffer implementation */
464 static void inline fire_EB(PREFIX
unsigned long addr
, int vertex_count
, int type
)
467 unsigned long addr_a
;
470 WARN_ONCE("Badly aligned buffer\n");
473 addr_a
= 0; /*addr & 0x1c;*/
477 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2
, 0);
478 /* TODO: R300_VAP_VF_CNTL__INDEX_SIZE_32bit . */
479 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<<16) | type
);
481 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER
, 2);
482 e32(R300_EB_UNK1
| (addr_a
<< 16) | R300_EB_UNK2
);
483 e32(addr
/*& 0xffffffe3*/);
484 e32((vertex_count
+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */
487 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
494 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
496 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
497 struct vertex_buffer
*VB
= &tnl
->vb
;
500 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
501 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
503 if(type
<0 || num_verts
<= 0)return;
505 if(rmesa
->state
.Elts
){
506 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, 0);
508 start_index32_packet(num_verts
, type
);
509 for(i
=0; i
< num_verts
; i
++)
510 e32(rmesa
->state
.Elts
[start
+i
]); /* start ? */
512 WARN_ONCE("Rendering with elt buffers\n");
514 start_index32_packet(num_verts
, type
);
515 e32(rmesa
->state
.Elts
[start
]);
519 if(num_verts
> 65535){ /* not implemented yet */
520 WARN_ONCE("Too many elts\n");
523 r300EmitElts(ctx
, rmesa
->state
.Elts
+start
, num_verts
);
524 fire_EB(PASS_PREFIX
GET_START(&(rmesa
->state
.elt_dma
)), num_verts
, type
);
527 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
528 fire_AOS(PASS_PREFIX num_verts
, type
);
532 static GLboolean
r300_run_vb_render(GLcontext
*ctx
,
533 struct tnl_pipeline_stage
*stage
)
535 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
536 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
537 struct vertex_buffer
*VB
= &tnl
->vb
;
541 if (RADEON_DEBUG
& DEBUG_PRIMS
)
542 fprintf(stderr
, "%s\n", __FUNCTION__
);
545 r300ReleaseArrays(ctx
);
546 r300EmitArrays(ctx
, GL_FALSE
);
547 //dump_inputs(ctx, rmesa->state.render_inputs);
549 // LOCK_HARDWARE(&(rmesa->radeon));
551 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
556 r300EmitState(rmesa
);
558 rmesa
->state
.Elts
= VB
->Elts
;
560 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
561 GLuint prim
= VB
->Primitive
[i
].mode
;
562 GLuint start
= VB
->Primitive
[i
].start
;
563 GLuint length
= VB
->Primitive
[i
].count
;
565 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
568 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
574 // end_3d(PASS_PREFIX_VOID);
576 /* Flush state - we are done drawing.. */
577 // r300FlushCmdBufLocked(rmesa, __FUNCTION__);
578 // radeonWaitForIdleLocked(&(rmesa->radeon));
580 // UNLOCK_HARDWARE(&(rmesa->radeon));
585 * Called by the pipeline manager to render a batch of primitives.
586 * We can return true to pass on to the next stage (i.e. software
587 * rasterization) or false to indicate that the pipeline has finished
588 * after we render something.
590 static GLboolean
r300_run_render(GLcontext
*ctx
,
591 struct tnl_pipeline_stage
*stage
)
593 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
594 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
595 struct vertex_buffer
*VB
= &tnl
->vb
;
598 if (RADEON_DEBUG
& DEBUG_PRIMS
)
599 fprintf(stderr
, "%s\n", __FUNCTION__
);
605 return r300_run_immediate_render(ctx
, stage
);
607 return r300_run_vb_render(ctx
, stage
);
614 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
615 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
616 struct vertex_buffer
*VB
= &tnl
->vb
;
619 /* Don't handle clipping or indexed vertices or vertex manipulations.
621 if (mmesa
->RenderIndex
!= 0 ||
622 !mga_validate_render( ctx
, VB
)) {
626 tnl
->Driver
.Render
.Start( ctx
);
627 mmesa
->SetupNewInputs
= ~0;
629 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
631 GLuint prim
= VB
->Primitive
[i
].mode
;
632 GLuint start
= VB
->Primitive
[i
].start
;
633 GLuint length
= VB
->Primitive
[i
].count
;
638 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
642 tnl
->Driver
.Render
.Finish( ctx
);
644 return GL_FALSE
; /* finished the pipe */
650 * Called by the pipeline manager once before rendering.
651 * We check the GL state here to
652 * a) decide whether we can do the current state in hardware and
653 * b) update hardware registers
655 #define FALLBACK_IF(expr) \
658 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
659 fprintf(stderr, "%s: fallback:%s\n", \
660 __FUNCTION__, #expr); \
661 stage->active = GL_FALSE; \
666 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
668 r300ContextPtr r300
= R300_CONTEXT(ctx
);
671 if (RADEON_DEBUG
& DEBUG_STATE
)
672 fprintf(stderr
, "%s\n", __FUNCTION__
);
674 /* We only support rendering in hardware for now */
675 if (ctx
->RenderMode
!= GL_RENDER
) {
676 stage
->active
= GL_FALSE
;
681 /* I'm almost certain I forgot something here */
682 #if 0 /* These should work now.. */
683 FALLBACK_IF(ctx
->Color
.DitherFlag
);
684 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
685 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
686 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
688 //FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
689 //FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
690 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
692 //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this
693 //FALLBACK_IF(ctx->Polygon.SmoothFlag); // GL_POLYGON_SMOOTH disabling to get blender going
694 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
695 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
697 #if 0 /* ut2k3 fails to start if this is on */
698 /* One step at a time - let one texture pass.. */
699 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
700 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
703 /* Assumed factor reg is found but pattern is still missing */
704 //FALLBACK_IF(ctx->Line.StippleFlag); // GL_LINE_STIPPLE disabling to get blender going
706 /* HW doesnt appear to directly support these */
707 //FALLBACK_IF(ctx->Line.SmoothFlag); // GL_LINE_SMOOTH disabling to get blender going
708 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
709 /* Rest could be done with vertex fragments */
710 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
711 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
712 //GL_POINT_DISTANCE_ATTENUATION_ARB
713 //GL_POINT_FADE_THRESHOLD_SIZE_ARB
715 /* let r300_run_render do its job */
717 stage
->active
= GL_FALSE
;
722 static void dtr(struct tnl_pipeline_stage
*stage
)
727 const struct tnl_pipeline_stage _r300_render_stage
= {
729 _NEW_ALL
, /* re-check (always re-check for now) */
730 0, /* re-run (always runs) */
731 GL_TRUE
, /* active */
732 0, 0, /* inputs (set in check_render), outputs */
733 0, 0, /* changed_inputs, private */
734 dtr
, /* destructor */
735 r300_check_render
, /* check */
736 r300_run_render
/* run */
739 static GLboolean
r300_run_tcl_render(GLcontext
*ctx
,
740 struct tnl_pipeline_stage
*stage
)
742 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
743 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
744 struct vertex_buffer
*VB
= &tnl
->vb
;
747 if (RADEON_DEBUG
& DEBUG_PRIMS
)
748 fprintf(stderr
, "%s\n", __FUNCTION__
);
750 return r300_run_vb_render(ctx
, stage
);
753 static void r300_check_tcl_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
755 r300ContextPtr r300
= R300_CONTEXT(ctx
);
758 if (RADEON_DEBUG
& DEBUG_STATE
)
759 fprintf(stderr
, "%s\n", __FUNCTION__
);
761 /* We only support rendering in hardware for now */
762 if (ctx
->RenderMode
!= GL_RENDER
) {
763 stage
->active
= GL_FALSE
;
766 if(VERTPROG_ACTIVE(ctx
)) {
767 stage
->active
= GL_TRUE
;
768 stage
->inputs
= ctx
->VertexProgram
.Current
->InputsRead
;
770 stage
->active
= GL_FALSE
;
774 const struct tnl_pipeline_stage _r300_tcl_stage
= {
776 _NEW_ALL
, /* re-check (always re-check for now) */
777 0, /* re-run (always runs) */
778 GL_TRUE
, /* active */
779 0, 0, /* inputs (set in check_render), outputs */
780 0, 0, /* changed_inputs, private */
781 dtr
, /* destructor */
782 r300_check_tcl_render
, /* check */
783 r300_run_tcl_render
/* run */