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_ioctl.h"
49 #include "radeon_state.h"
50 #include "r300_context.h"
51 #include "r300_ioctl.h"
52 #include "r300_state.h"
54 #include "r300_program.h"
59 /**********************************************************************
60 * Hardware rasterization
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
66 static int r300_get_primitive_type(r300ContextPtr rmesa
,
72 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
73 struct vertex_buffer
*VB
= &tnl
->vb
;
75 int type
=-1, min_vertices
=0;
78 if(end
<=start
)return -1; /* do we need to watch for this ? */
80 switch (prim
& PRIM_MODE_MASK
) {
83 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
88 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
93 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
103 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
106 case GL_TRIANGLE_STRIP
:
108 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
111 case GL_TRIANGLE_FAN
:
113 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
118 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
123 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
127 fprintf(stderr
, "Cannot handle primitive %02x ", prim
& PRIM_MODE_MASK
);
132 fprintf(stderr
, "[%d-%d]%s ", start
, end
, name
);
134 if(start
+min_vertices
>=end
){
135 fprintf(stderr
, "Not enough vertices\n");
143 /* Immediate implementation - vertex data is sent via command stream */
145 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
147 #define output_vector(v, i) \
150 for(_i=0;_i<v->size;_i++){ \
151 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
153 for(_i=v->size;_i<4;_i++){ \
154 efloat(default_vector[_i]); \
158 static void r300_render_flat_primitive(r300ContextPtr rmesa
,
164 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
165 struct vertex_buffer
*VB
= &tnl
->vb
;
170 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
175 start_immediate_packet(end
-start
, type
, 8);
177 for(i
=start
;i
<end
;i
++){
179 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
180 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
181 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
182 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
183 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
185 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
186 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
187 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
188 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
194 output_vector(VB
->ObjPtr
, i
);
196 /* color components */
197 output_vector(VB
->ColorPtr
[0], i
);
202 static GLboolean
r300_run_flat_render(GLcontext
*ctx
,
203 struct tnl_pipeline_stage
*stage
)
205 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
206 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
207 struct vertex_buffer
*VB
= &tnl
->vb
;
209 AOS_DATA vb_arrays
[2];
212 /* Flush state - make sure command buffer is nice and large */
215 if (RADEON_DEBUG
== DEBUG_PRIMS
)
216 fprintf(stderr
, "%s\n", __FUNCTION__
);
218 /* setup array of structures data */
220 /* Note: immediate vertex data includes all coordinates.
221 To save bandwidth use either VBUF or state-based vertex generation */
223 vb_arrays
[0].element_size
=4;
224 vb_arrays
[0].stride
=4;
225 vb_arrays
[0].offset
=0; /* Not used */
226 vb_arrays
[0].format
=AOS_FORMAT_FLOAT
;
227 vb_arrays
[0].ncomponents
=4;
228 vb_arrays
[0].reg
=REG_COORDS
;
231 vb_arrays
[1].element_size
=4;
232 vb_arrays
[1].stride
=4;
233 vb_arrays
[1].offset
=0; /* Not used */
234 vb_arrays
[1].format
=AOS_FORMAT_FLOAT_COLOR
;
235 vb_arrays
[1].ncomponents
=4;
236 vb_arrays
[1].reg
=REG_COLOR0
;
239 /* needed before starting 3d operation .. */
240 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
246 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
247 | R300_VPORT_X_OFFSET_ENA
248 | R300_VPORT_Y_SCALE_ENA
249 | R300_VPORT_Y_OFFSET_ENA
251 R300_STATECHANGE(rmesa
, vte
);
253 r300EmitState(rmesa
);
255 FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
256 memcpy(FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
258 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.length
=4;
259 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
260 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
261 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
262 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
264 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
265 cp_delay(PASS_PREFIX
15);
267 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
268 setup_AOS(PASS_PREFIX vb_arrays
, 2);
270 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
271 GLuint prim
= VB
->Primitive
[i
].mode
;
272 GLuint start
= VB
->Primitive
[i
].start
;
273 GLuint length
= VB
->Primitive
[i
].count
;
274 r300_render_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
277 sync_VAP(PASS_PREFIX_VOID
);
279 end_3d(PASS_PREFIX_VOID
);
281 /* Flush state - this reduces the chance that something else will mess with
282 the hardware in between */
284 //fprintf(stderr, "\n");
288 /* vertex buffer implementation */
290 /* We use the start part of GART texture buffer for vertices */
292 /* 8 is somewhat bogus... it is probably something like 24 */
293 #define R300_MAX_AOS_ARRAYS 8
295 static void upload_vertex_buffer(r300ContextPtr rmesa
,
296 GLcontext
*ctx
, AOS_DATA
*array
, int *n_arrays
)
298 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
299 struct vertex_buffer
*VB
= &tnl
->vb
;
302 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
303 /* Not the most efficient implementation, but, for now, I just want something that
305 /* to do - make single memcpy per column (is it possible ?) */
306 /* to do - use dirty flags to avoid redundant copies */
307 #define UPLOAD_VECTOR(v, r, f)\
309 /* Is the data dirty ? */ \
310 if (v->flags & ((1<<v->size)-1)) { \
311 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
312 if(v->size*4==v->stride){\
314 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
316 for(i=0;i<VB->Count;i++){ \
317 /* copy one vertex at a time*/ \
318 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
321 /* v->flags &= ~((1<<v->size)-1);*/ \
323 array[idx].element_size=v->size; \
324 array[idx].stride=v->size; \
325 array[idx].format=(f); \
326 array[idx].ncomponents=v->size; \
327 array[idx].offset=rsp->gartTextures.handle+offset; \
329 offset+=v->size*4*VB->Count; \
333 UPLOAD_VECTOR(VB
->ObjPtr
, REG_COORDS
, AOS_FORMAT_FLOAT
);
334 UPLOAD_VECTOR(VB
->ColorPtr
[0], REG_COLOR0
, AOS_FORMAT_FLOAT_COLOR
);
337 if(idx
>=R300_MAX_AOS_ARRAYS
){
338 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
343 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa
,
349 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
350 struct vertex_buffer
*VB
= &tnl
->vb
;
352 int k
, type
, n_arrays
;
355 if(end
<=start
)return; /* do we need to watch for this ? */
357 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
360 fire_AOS(PASS_PREFIX end
-start
, type
);
363 static VERTEX_SHADER_FRAGMENT default_vector_vsf
={
366 f
: {0.0, 0.0, 0.0, 1.0}
370 static GLboolean
r300_run_vb_flat_render(GLcontext
*ctx
,
371 struct tnl_pipeline_stage
*stage
)
373 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
374 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
375 struct vertex_buffer
*VB
= &tnl
->vb
;
377 AOS_DATA vb_arrays
[R300_MAX_AOS_ARRAYS
];
378 AOS_DATA vb_arrays2
[R300_MAX_AOS_ARRAYS
];
381 if (RADEON_DEBUG
== DEBUG_PRIMS
)
382 fprintf(stderr
, "%s\n", __FUNCTION__
);
384 /* setup array of structures data */
386 upload_vertex_buffer(rmesa
, ctx
, vb_arrays
, &n_arrays
);
387 fprintf(stderr
, "Using %d AOS arrays\n", n_arrays
);
389 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
395 r300EmitState(rmesa
);
397 FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
398 memcpy(FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
400 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.length
=4;
401 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
402 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
403 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
404 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
406 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
408 set_quad0(PASS_PREFIX
1.0,1.0,1.0,1.0);
409 set_init21(PASS_PREFIX
0.0,1.0);
411 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
412 GLuint prim
= VB
->Primitive
[i
].mode
;
413 GLuint start
= VB
->Primitive
[i
].start
;
414 GLuint length
= VB
->Primitive
[i
].count
;
417 memcpy(vb_arrays2
, vb_arrays
, sizeof(AOS_DATA
)*n_arrays
);
418 for(j
=0;j
<n_arrays
;j
++){
419 vb_arrays2
[j
].offset
+=vb_arrays2
[j
].stride
*start
*4;
422 setup_AOS(PASS_PREFIX vb_arrays2
, n_arrays
);
424 r300_render_vb_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
427 end_3d(PASS_PREFIX_VOID
);
429 /* Flush state - we are done drawing.. */
431 fprintf(stderr
, "\n");
437 /* Immediate implementation - vertex data is sent via command stream */
439 static void r300_render_tex_primitive(r300ContextPtr rmesa
,
445 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
446 struct vertex_buffer
*VB
= &tnl
->vb
;
451 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
453 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
454 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
455 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
456 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
461 start_immediate_packet(end
-start
, type
, 12);
463 for(i
=start
;i
<end
;i
++){
465 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
466 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
467 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
468 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
469 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
471 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
472 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
473 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
474 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
480 output_vector(VB
->ObjPtr
, i
);
482 /* color components */
483 output_vector(VB
->ColorPtr
[0], i
);
485 /* texture coordinates */
486 output_vector(VB
->TexCoordPtr
[0], i
);
491 static GLboolean
r300_run_tex_render(GLcontext
*ctx
,
492 struct tnl_pipeline_stage
*stage
)
494 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
495 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
496 struct vertex_buffer
*VB
= &tnl
->vb
;
498 AOS_DATA vb_arrays
[3];
499 /* Only do 2d textures */
500 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
501 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
505 /* Flush state - make sure command buffer is nice and large */
508 fprintf(stderr
, "You can enable texture drawing in %s:%s \n", __FILE__
, __FUNCTION__
);
511 if (RADEON_DEBUG
== DEBUG_PRIMS
)
512 fprintf(stderr
, "%s\n", __FUNCTION__
);
514 /* setup array of structures data */
516 /* Note: immediate vertex data includes all coordinates.
517 To save bandwidth use either VBUF or state-based vertex generation */
519 vb_arrays
[0].element_size
=4;
520 vb_arrays
[0].stride
=4;
521 vb_arrays
[0].offset
=0; /* Not used */
522 vb_arrays
[0].format
=AOS_FORMAT_FLOAT
;
523 vb_arrays
[0].ncomponents
=4;
524 vb_arrays
[0].reg
=REG_COORDS
;
527 vb_arrays
[1].element_size
=4;
528 vb_arrays
[1].stride
=4;
529 vb_arrays
[1].offset
=0; /* Not used */
530 vb_arrays
[1].format
=AOS_FORMAT_FLOAT_COLOR
;
531 vb_arrays
[1].ncomponents
=4;
532 vb_arrays
[1].reg
=REG_COLOR0
;
534 /* texture coordinates */
535 vb_arrays
[2].element_size
=4;
536 vb_arrays
[2].stride
=4;
537 vb_arrays
[2].offset
=0; /* Not used */
538 vb_arrays
[2].format
=AOS_FORMAT_FLOAT
;
539 vb_arrays
[2].ncomponents
=4;
540 vb_arrays
[2].reg
=REG_TEX0
;
543 /* needed before starting 3d operation .. */
544 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
551 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
552 | R300_VPORT_X_OFFSET_ENA
553 | R300_VPORT_Y_SCALE_ENA
554 | R300_VPORT_Y_OFFSET_ENA
556 R300_STATECHANGE(rmesa
, vte
);
558 r300EmitState(rmesa
);
560 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
561 memcpy(SINGLE_TEXTURE_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
563 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.length
=4;
564 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
565 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
566 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
567 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
569 /* Put it in the beginning of texture memory */
570 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].offset
=rsp
->gartTextures
.handle
;
572 /* Fill texture with some random data */
573 for(i
=0;i
<1000;i
++)((int *)(rsp
->gartTextures
.map
))[i
]=rand();
575 /* Upload texture, a hack, really we can do a lot better */
577 memcpy(rsp
->gartTextures
.map
, to
->Image
[0][0]->Data
, to
->Image
[0][0]->RowStride
*to
->Image
[0][0]->Height
*4);
580 /* Program RS unit. This needs to be moved into R300 pipeline */
581 reg_start(R300_RS_CNTL_0
,1);
582 /* R300_RS_CNTL_0(4300) */
584 /* RS_INST_COUNT(4304) */
587 reg_start(R300_RS_ROUTE_0
,0);
590 reg_start(R300_RS_INTERP_0
,7);
608 reg_start(R300_RS_CNTL_0
,0);
611 /* Magic register - note it is right after 20b0 */
616 program_pipeline(PASS_PREFIX
&SINGLE_TEXTURE_PIPELINE
);
618 sync_VAP(PASS_PREFIX_VOID
);
619 cp_delay(PASS_PREFIX
15);
621 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
622 setup_AOS(PASS_PREFIX vb_arrays
, 3);
624 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
625 GLuint prim
= VB
->Primitive
[i
].mode
;
626 GLuint start
= VB
->Primitive
[i
].start
;
627 GLuint length
= VB
->Primitive
[i
].count
;
628 r300_render_tex_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
631 sync_VAP(PASS_PREFIX_VOID
);
633 end_3d(PASS_PREFIX_VOID
);
635 /* Flush state - this reduces the chance that something else will mess with
636 the hardware in between */
639 fprintf(stderr
, "\n");
645 * Called by the pipeline manager to render a batch of primitives.
646 * We can return true to pass on to the next stage (i.e. software
647 * rasterization) or false to indicate that the pipeline has finished
648 * after we render something.
650 static GLboolean
r300_run_render(GLcontext
*ctx
,
651 struct tnl_pipeline_stage
*stage
)
653 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
654 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
655 struct vertex_buffer
*VB
= &tnl
->vb
;
658 if (RADEON_DEBUG
== DEBUG_PRIMS
)
659 fprintf(stderr
, "%s\n", __FUNCTION__
);
662 /* Just switch between pipelines.. We could possibly do better.. (?) */
663 if(ctx
->Texture
.Unit
[0].Enabled
)
664 return r300_run_tex_render(ctx
, stage
);
666 return r300_run_flat_render(ctx
, stage
);
672 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
673 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
674 struct vertex_buffer
*VB
= &tnl
->vb
;
677 /* Don't handle clipping or indexed vertices or vertex manipulations.
679 if (mmesa
->RenderIndex
!= 0 ||
680 !mga_validate_render( ctx
, VB
)) {
684 tnl
->Driver
.Render
.Start( ctx
);
685 mmesa
->SetupNewInputs
= ~0;
687 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
689 GLuint prim
= VB
->Primitive
[i
].mode
;
690 GLuint start
= VB
->Primitive
[i
].start
;
691 GLuint length
= VB
->Primitive
[i
].count
;
696 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
700 tnl
->Driver
.Render
.Finish( ctx
);
702 return GL_FALSE
; /* finished the pipe */
708 * Called by the pipeline manager once before rendering.
709 * We check the GL state here to
710 * a) decide whether we can do the current state in hardware and
711 * b) update hardware registers
713 #define FALLBACK_IF(expr) \
716 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
717 fprintf(stderr, "%s: fallback:%s\n", \
718 __FUNCTION__, #expr); \
719 stage->active = GL_FALSE; \
724 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
726 r300ContextPtr r300
= R300_CONTEXT(ctx
);
729 if (RADEON_DEBUG
& DEBUG_STATE
)
730 fprintf(stderr
, "%s\n", __FUNCTION__
);
732 /* We only support rendering in hardware for now */
733 if (ctx
->RenderMode
!= GL_RENDER
) {
734 stage
->active
= GL_FALSE
;
738 // I failed to figure out how dither works in hardware,
739 // let's just ignore it for now
740 //FALLBACK_IF(ctx->Color.DitherFlag);
742 /* I'm almost certain I forgot something here */
743 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
744 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
745 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
746 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
747 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
748 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
749 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
750 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
751 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
752 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
753 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
754 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
755 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
756 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
757 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
759 /* One step at a time - let one texture pass.. */
760 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
761 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
764 /* let r300_run_render do its job */
766 stage
->active
= GL_FALSE
;
771 static void dtr(struct tnl_pipeline_stage
*stage
)
776 const struct tnl_pipeline_stage _r300_render_stage
= {
778 _NEW_ALL
, /* re-check (always re-check for now) */
779 0, /* re-run (always runs) */
780 GL_TRUE
, /* active */
781 0, 0, /* inputs (set in check_render), outputs */
782 0, 0, /* changed_inputs, private */
783 dtr
, /* destructor */
784 r300_check_render
, /* check */
785 r300_run_render
/* run */