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"
59 #include "r300_emit.h"
62 /* Turns out we might not need this after all... */
63 static void update_zbias(GLcontext
* ctx
, int prim
)
65 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
69 switch(prim
& PRIM_MODE_MASK
) {
71 if(ctx
->Polygon
.OffsetPoint
== GL_TRUE
)
77 if(ctx
->Polygon
.OffsetLine
== GL_TRUE
)
81 case GL_TRIANGLE_STRIP
:
86 if(ctx
->Polygon
.OffsetFill
== GL_TRUE
)
90 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
91 __FILE__
, __FUNCTION__
,
92 prim
& PRIM_MODE_MASK
);
97 values
[0]=values
[2]=r300PackFloat32(ctx
->Polygon
.OffsetFactor
* 12.0);
98 values
[1]=values
[3]=r300PackFloat32(ctx
->Polygon
.OffsetUnits
* 4.0);
100 values
[0]=values
[2]=r300PackFloat32(0.0);
101 values
[1]=values
[3]=r300PackFloat32(0.0);
104 if(values
[0] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_FACTOR
] ||
105 values
[1] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_CONSTANT
] ||
106 values
[2] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_FACTOR
] ||
107 values
[3] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_CONSTANT
]){
109 R300_STATECHANGE(rmesa
, zbs
);
110 rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_FACTOR
] = values
[0];
111 rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_CONSTANT
] = values
[1];
112 rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_FACTOR
] = values
[2];
113 rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_CONSTANT
] = values
[3];
119 /**********************************************************************
120 * Hardware rasterization
122 * When we fell back to software TCL, we still try to use the
123 * rasterization hardware for rendering.
124 **********************************************************************/
126 static int r300_get_primitive_type(r300ContextPtr rmesa
, GLcontext
*ctx
, int prim
)
128 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
129 struct vertex_buffer
*VB
= &tnl
->vb
;
133 switch (prim
& PRIM_MODE_MASK
) {
135 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
138 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
141 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
144 type
=R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
147 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
149 case GL_TRIANGLE_STRIP
:
150 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
152 case GL_TRIANGLE_FAN
:
153 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
156 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
159 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
162 type
=R300_VAP_VF_CNTL__PRIM_POLYGON
;
165 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
166 __FILE__
, __FUNCTION__
,
167 prim
& PRIM_MODE_MASK
);
174 static int r300_get_num_verts(r300ContextPtr rmesa
,
179 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
180 struct vertex_buffer
*VB
= &tnl
->vb
;
182 int type
=-1, verts_off
=0;
183 char *name
="UNKNOWN";
185 switch (prim
& PRIM_MODE_MASK
) {
192 verts_off
= num_verts
% 2;
196 verts_off
= num_verts
% 2;
200 verts_off
= num_verts
% 2;
204 verts_off
= num_verts
% 3;
206 case GL_TRIANGLE_STRIP
:
209 verts_off
= num_verts
;
211 case GL_TRIANGLE_FAN
:
214 verts_off
= num_verts
;
218 verts_off
= num_verts
% 4;
223 verts_off
= num_verts
;
225 verts_off
= num_verts
% 2;
230 verts_off
= num_verts
;
233 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
234 __FILE__
, __FUNCTION__
,
235 prim
& PRIM_MODE_MASK
);
240 if(num_verts
- verts_off
== 0){
241 WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts
, name
);
246 WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts
, name
);
249 return num_verts
- verts_off
;
252 /* This function compiles GL context into state registers that
253 describe data routing inside of R300 pipeline.
255 In particular, it programs input_route, output_vtx_fmt, texture
256 unit configuration and gb_output_vtx_fmt
258 This function encompasses setup_AOS() from r300_lib.c
264 /* Immediate implementation - vertex data is sent via command stream */
266 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
268 #define output_vector(v, i) \
271 for(_i=0;_i<v->size;_i++){ \
272 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
274 for(_i=v->size;_i<4;_i++){ \
275 efloat(default_vector[_i]); \
279 /* Immediate implementation - vertex data is sent via command stream */
281 static void r300_render_immediate_primitive(r300ContextPtr rmesa
,
287 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
288 struct vertex_buffer
*VB
= &tnl
->vb
;
289 GLuint i
, render_inputs
;
290 int k
, type
, num_verts
;
293 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
294 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
297 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
298 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
299 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
300 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
301 fprintf(stderr
,"TexCoordPtr[0]: size=%d stride=%d\n",
302 VB
->TexCoordPtr
[0]->size
, VB
->TexCoordPtr
[0]->stride
);
305 if(type
<0 || num_verts
<= 0)return;
308 WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
311 /* A packet cannot have more than 16383 data words.. */
312 if((num_verts
*4*rmesa
->state
.aos_count
)>16380){
313 WARN_ONCE("Too many vertices to paint. Fix me !\n");
317 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
319 if(rmesa
->state
.aos_count
==0){
320 WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n");
324 render_inputs
= rmesa
->state
.render_inputs
;
327 WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
331 start_immediate_packet(num_verts
, type
, 4*rmesa
->state
.aos_count
);
333 for(i
=start
;i
<start
+num_verts
;i
++){
335 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
336 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
337 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
338 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
339 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
341 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
342 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
343 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
344 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
350 if(render_inputs
& _TNL_BIT_POS
)
351 output_vector(VB
->ObjPtr
, i
);
352 if(render_inputs
& _TNL_BIT_NORMAL
)
353 output_vector(VB
->NormalPtr
, i
);
355 /* color components */
356 if(render_inputs
& _TNL_BIT_COLOR0
)
357 output_vector(VB
->ColorPtr
[0], i
);
358 if(render_inputs
& _TNL_BIT_COLOR1
)
359 output_vector(VB
->SecondaryColorPtr
[0], i
);
361 if(render_inputs
& _TNL_BIT_FOG
)
362 output_vector(VB
->FogCoordPtr
, i
);
364 /* texture coordinates */
365 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
366 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
367 output_vector(VB
->TexCoordPtr
[k
], i
);
369 if(render_inputs
& _TNL_BIT_INDEX
)
370 output_vector(VB
->IndexPtr
[0], i
);
371 if(render_inputs
& _TNL_BIT_POINTSIZE
)
372 output_vector(VB
->PointSizePtr
, i
);
378 static GLboolean
r300_run_immediate_render(GLcontext
*ctx
,
379 struct tnl_pipeline_stage
*stage
)
381 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
382 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
383 struct vertex_buffer
*VB
= &tnl
->vb
;
385 /* Only do 2d textures */
386 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
387 r300TexObjPtr t
=to
->DriverData
;
391 /* Update texture state - needs to be done only when actually changed..
392 All the time for now.. */
395 if (RADEON_DEBUG
== DEBUG_PRIMS
)
396 fprintf(stderr
, "%s\n", __FUNCTION__
);
398 #if 1 /* we need this, somehow */
399 /* Flush state - make sure command buffer is nice and large */
401 /* Make sure we have enough space */
403 /* Count is very imprecize, but should be good upper bound */
404 r300EnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
+ 4+2+30
405 +VB
->PrimitiveCount
*(1+8)+VB
->Count
*4*rmesa
->state
.texture
.tc_count
+4, __FUNCTION__
);
408 /* needed before starting 3d operation .. */
409 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
416 #if 0 /* looks like the Z offset issue got fixed */
417 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
418 | R300_VPORT_X_OFFSET_ENA
419 | R300_VPORT_Y_SCALE_ENA
420 | R300_VPORT_Y_OFFSET_ENA
422 R300_STATECHANGE(rmesa
, vte
);
427 /* Magic register - note it is right after 20b0 */
430 if(rmesa
->state
.texture
.tc_count
>0){
436 r300EmitState(rmesa
);
439 reg_start(R300_RB3D_COLORMASK
, 0);
442 vsf_start_fragment(0x406, 4);
448 vsf_start_fragment(0x400, 4);
455 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
456 r300EmitLOAD_VBPNTR(rmesa
, 0);
458 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
459 GLuint prim
= VB
->Primitive
[i
].mode
;
460 GLuint start
= VB
->Primitive
[i
].start
;
461 GLuint length
= VB
->Primitive
[i
].count
;
463 r300_render_immediate_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
466 /* This sequence is required after any 3d drawing packet
467 I suspect it work arounds a bug (or deficiency) in hardware */
469 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
479 /* vertex buffer implementation */
481 /* We use the start part of GART texture buffer for vertices */
484 static void upload_vertex_buffer(r300ContextPtr rmesa
, GLcontext
*ctx
)
486 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
487 struct vertex_buffer
*VB
= &tnl
->vb
;
490 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
491 GLuint render_inputs
;
493 /* A hack - we don't want to overwrite vertex buffers, so we
494 just use AGP space for them.. Fix me ! */
496 if(offset
>2*1024*1024){
497 //fprintf(stderr, "Wrapping agp vertex buffer offset\n");
500 /* Not the most efficient implementation, but, for now, I just want something that
502 /* to do - make single memcpy per column (is it possible ?) */
503 /* to do - use dirty flags to avoid redundant copies */
504 #define UPLOAD_VECTOR(v)\
506 /* Is the data dirty ? */ \
507 if (v->flags & ((1<<v->size)-1)) { \
508 /* fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); */ \
509 if(v->size*4==v->stride){\
511 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
513 for(i=0;i<VB->Count;i++){ \
514 /* copy one vertex at a time*/ \
515 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
518 /* v->flags &= ~((1<<v->size)-1);*/ \
520 rmesa->state.aos[idx].offset=rsp->gartTextures.handle+offset; \
521 offset+=v->size*4*VB->Count; \
525 render_inputs
= rmesa
->state
.render_inputs
;
528 WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
532 if(render_inputs
& _TNL_BIT_POS
)
533 UPLOAD_VECTOR(VB
->ObjPtr
);
534 if(render_inputs
& _TNL_BIT_NORMAL
)
535 UPLOAD_VECTOR(VB
->NormalPtr
);
537 /* color components */
538 if(render_inputs
& _TNL_BIT_COLOR0
)
539 UPLOAD_VECTOR(VB
->ColorPtr
[0]);
540 if(render_inputs
& _TNL_BIT_COLOR1
)
541 UPLOAD_VECTOR(VB
->SecondaryColorPtr
[0]);
543 if(render_inputs
& _TNL_BIT_FOG
)
544 UPLOAD_VECTOR(VB
->FogCoordPtr
);
546 /* texture coordinates */
547 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
548 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
549 UPLOAD_VECTOR(VB
->TexCoordPtr
[k
]);
551 if(render_inputs
& _TNL_BIT_INDEX
)
552 UPLOAD_VECTOR(VB
->IndexPtr
[0]);
553 if(render_inputs
& _TNL_BIT_POINTSIZE
)
554 UPLOAD_VECTOR(VB
->PointSizePtr
);
556 if(idx
>=R300_MAX_AOS_ARRAYS
){
557 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
562 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
571 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
572 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
574 if(type
<0 || num_verts
<= 0)return;
577 fire_AOS(PASS_PREFIX num_verts
, type
);
580 static GLboolean
r300_run_vb_render(GLcontext
*ctx
,
581 struct tnl_pipeline_stage
*stage
)
583 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
584 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
585 struct vertex_buffer
*VB
= &tnl
->vb
;
589 if (RADEON_DEBUG
== DEBUG_PRIMS
)
590 fprintf(stderr
, "%s\n", __FUNCTION__
);
593 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
599 r300_setup_routing(ctx
, GL_FALSE
);
601 r300EmitState(rmesa
);
603 /* setup array of structures data */
604 LOCK_HARDWARE(&(rmesa
->radeon
));
606 upload_vertex_buffer(rmesa
, ctx
);
607 //fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
609 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
610 GLuint prim
= VB
->Primitive
[i
].mode
;
611 GLuint start
= VB
->Primitive
[i
].start
;
612 GLuint length
= VB
->Primitive
[i
].count
;
614 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. */
615 r300EmitLOAD_VBPNTR(rmesa
, start
);
617 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
620 /* This sequence is required after any 3d drawing packet
621 I suspect it works around a bug (or deficiency) in hardware */
623 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
629 end_3d(PASS_PREFIX_VOID
);
631 /* Flush state - we are done drawing.. */
632 r300FlushCmdBufLocked(ctx
, __FUNCTION__
);
633 radeonWaitForIdleLocked(&(rmesa
->radeon
));
635 UNLOCK_HARDWARE(&(rmesa
->radeon
));
640 * Called by the pipeline manager to render a batch of primitives.
641 * We can return true to pass on to the next stage (i.e. software
642 * rasterization) or false to indicate that the pipeline has finished
643 * after we render something.
645 static GLboolean
r300_run_render(GLcontext
*ctx
,
646 struct tnl_pipeline_stage
*stage
)
648 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
649 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
650 struct vertex_buffer
*VB
= &tnl
->vb
;
653 if (RADEON_DEBUG
== DEBUG_PRIMS
)
654 fprintf(stderr
, "%s\n", __FUNCTION__
);
660 /* I dont recall fog locking up before polygon offset modifications.
661 Or then having fog on only locks up if immediate mode is on... */
665 return r300_run_immediate_render(ctx
, stage
);
667 return r300_run_vb_render(ctx
, stage
);
674 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
675 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
676 struct vertex_buffer
*VB
= &tnl
->vb
;
679 /* Don't handle clipping or indexed vertices or vertex manipulations.
681 if (mmesa
->RenderIndex
!= 0 ||
682 !mga_validate_render( ctx
, VB
)) {
686 tnl
->Driver
.Render
.Start( ctx
);
687 mmesa
->SetupNewInputs
= ~0;
689 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
691 GLuint prim
= VB
->Primitive
[i
].mode
;
692 GLuint start
= VB
->Primitive
[i
].start
;
693 GLuint length
= VB
->Primitive
[i
].count
;
698 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
702 tnl
->Driver
.Render
.Finish( ctx
);
704 return GL_FALSE
; /* finished the pipe */
710 * Called by the pipeline manager once before rendering.
711 * We check the GL state here to
712 * a) decide whether we can do the current state in hardware and
713 * b) update hardware registers
715 #define FALLBACK_IF(expr) \
718 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
719 fprintf(stderr, "%s: fallback:%s\n", \
720 __FUNCTION__, #expr); \
721 stage->active = GL_FALSE; \
726 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
728 r300ContextPtr r300
= R300_CONTEXT(ctx
);
731 if (RADEON_DEBUG
& DEBUG_STATE
)
732 fprintf(stderr
, "%s\n", __FUNCTION__
);
734 /* We only support rendering in hardware for now */
735 if (ctx
->RenderMode
!= GL_RENDER
) {
736 stage
->active
= GL_FALSE
;
740 // I failed to figure out how dither works in hardware,
741 // let's just ignore it for now
742 //FALLBACK_IF(ctx->Color.DitherFlag);
744 /* I'm almost certain I forgot something here */
745 #if 0 /* This should work now.. */
746 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
747 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
749 //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this
750 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
751 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
752 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
753 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
754 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
755 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
756 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
757 //FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
758 //if(ctx->Polygon.OffsetFill)WARN_ONCE("Polygon.OffsetFill not implemented, ignoring\n");
759 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
760 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
761 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
762 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
764 /* One step at a time - let one texture pass.. */
765 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
766 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
768 /* let r300_run_render do its job */
770 stage
->active
= GL_FALSE
;
775 static void dtr(struct tnl_pipeline_stage
*stage
)
780 const struct tnl_pipeline_stage _r300_render_stage
= {
782 _NEW_ALL
, /* re-check (always re-check for now) */
783 0, /* re-run (always runs) */
784 GL_TRUE
, /* active */
785 0, 0, /* inputs (set in check_render), outputs */
786 0, 0, /* changed_inputs, private */
787 dtr
, /* destructor */
788 r300_check_render
, /* check */
789 r300_run_render
/* run */