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"
61 /* Turns out we might not need this after all... */
62 void update_zbias(GLcontext
* ctx
, int prim
)
64 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
68 switch(prim
& PRIM_MODE_MASK
) {
70 if(ctx
->Polygon
.OffsetPoint
== GL_TRUE
)
76 if(ctx
->Polygon
.OffsetLine
== GL_TRUE
)
80 case GL_TRIANGLE_STRIP
:
85 if(ctx
->Polygon
.OffsetFill
== GL_TRUE
)
89 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
90 __FILE__
, __FUNCTION__
,
91 prim
& PRIM_MODE_MASK
);
96 values
[0]=values
[2]=r300PackFloat32(ctx
->Polygon
.OffsetFactor
* 12.0);
97 values
[1]=values
[3]=r300PackFloat32(ctx
->Polygon
.OffsetUnits
* 4.0);
99 values
[0]=values
[2]=r300PackFloat32(0.0);
100 values
[1]=values
[3]=r300PackFloat32(0.0);
103 if(values
[0] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_FACTOR
] ||
104 values
[1] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_CONSTANT
] ||
105 values
[2] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_FACTOR
] ||
106 values
[3] != rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_CONSTANT
]){
108 R300_STATECHANGE(rmesa
, zbs
);
109 rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_FACTOR
] = values
[0];
110 rmesa
->hw
.zbs
.cmd
[R300_ZBS_T_CONSTANT
] = values
[1];
111 rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_FACTOR
] = values
[2];
112 rmesa
->hw
.zbs
.cmd
[R300_ZBS_W_CONSTANT
] = values
[3];
117 /**********************************************************************
118 * Hardware rasterization
120 * When we fell back to software TCL, we still try to use the
121 * rasterization hardware for rendering.
122 **********************************************************************/
124 static int r300_get_primitive_type(r300ContextPtr rmesa
, GLcontext
*ctx
, int prim
)
126 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
127 struct vertex_buffer
*VB
= &tnl
->vb
;
131 switch (prim
& PRIM_MODE_MASK
) {
133 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
136 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
139 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
142 type
=R300_VAP_VF_CNTL__PRIM_LINE_LOOP
;
145 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
147 case GL_TRIANGLE_STRIP
:
148 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
150 case GL_TRIANGLE_FAN
:
151 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
154 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
157 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
160 type
=R300_VAP_VF_CNTL__PRIM_POLYGON
;
163 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
164 __FILE__
, __FUNCTION__
,
165 prim
& PRIM_MODE_MASK
);
172 static int r300_get_num_verts(r300ContextPtr rmesa
,
177 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
178 struct vertex_buffer
*VB
= &tnl
->vb
;
180 int type
=-1, verts_off
=0;
181 char *name
="UNKNOWN";
183 switch (prim
& PRIM_MODE_MASK
) {
190 verts_off
= num_verts
% 2;
195 verts_off
= num_verts
;
200 verts_off
= num_verts
;
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 void dump_inputs(GLcontext
*ctx
, int render_inputs
)
255 fprintf(stderr
, "inputs:");
256 if(render_inputs
& _TNL_BIT_POS
)
257 fprintf(stderr
, "_TNL_BIT_POS ");
258 if(render_inputs
& _TNL_BIT_NORMAL
)
259 fprintf(stderr
, "_TNL_BIT_NORMAL ");
261 /* color components */
262 if(render_inputs
& _TNL_BIT_COLOR0
)
263 fprintf(stderr
, "_TNL_BIT_COLOR0 ");
264 if(render_inputs
& _TNL_BIT_COLOR1
)
265 fprintf(stderr
, "_TNL_BIT_COLOR1 ");
267 if(render_inputs
& _TNL_BIT_FOG
)
268 fprintf(stderr
, "_TNL_BIT_FOG ");
270 /* texture coordinates */
271 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
272 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
273 fprintf(stderr
, "_TNL_BIT_TEX%d ", k
);
275 if(render_inputs
& _TNL_BIT_INDEX
)
276 fprintf(stderr
, "_TNL_BIT_INDEX ");
277 if(render_inputs
& _TNL_BIT_POINTSIZE
)
278 fprintf(stderr
, "_TNL_BIT_POINTSIZE ");
280 fprintf(stderr
, "\n");
283 /* This function compiles GL context into state registers that
284 describe data routing inside of R300 pipeline.
286 In particular, it programs input_route, output_vtx_fmt, texture
287 unit configuration and gb_output_vtx_fmt
289 This function encompasses setup_AOS() from r300_lib.c
295 /* Immediate implementation - vertex data is sent via command stream */
297 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
299 #define output_vector(v, i) \
302 for(_i=0;_i<v->size;_i++){ \
303 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
305 for(_i=v->size;_i<4;_i++){ \
306 efloat(default_vector[_i]); \
310 /* Immediate implementation - vertex data is sent via command stream */
312 static void r300_render_immediate_primitive(r300ContextPtr rmesa
,
318 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
319 struct vertex_buffer
*VB
= &tnl
->vb
;
320 GLuint i
, render_inputs
;
321 int k
, type
, num_verts
;
324 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
325 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
328 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
329 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
330 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
331 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
332 fprintf(stderr
,"TexCoordPtr[0]: size=%d stride=%d\n",
333 VB
->TexCoordPtr
[0]->size
, VB
->TexCoordPtr
[0]->stride
);
336 if(type
<0 || num_verts
<= 0)return;
339 WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
342 /* A packet cannot have more than 16383 data words.. */
343 if((num_verts
*4*rmesa
->state
.aos_count
)>16380){
344 WARN_ONCE("Too many vertices to paint. Fix me !\n");
348 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
350 if(rmesa
->state
.aos_count
==0){
351 WARN_ONCE("Aeiee ! aos_count==0, while it shouldn't. Skipping rendering\n");
355 render_inputs
= rmesa
->state
.render_inputs
;
358 WARN_ONCE("Aeiee ! render_inputs==0. Skipping rendering.\n");
362 //dump_inputs(ctx, render_inputs); return ;
364 start_immediate_packet(num_verts
, type
, 4*rmesa
->state
.aos_count
);
366 for(i
=start
;i
<start
+num_verts
;i
++){
368 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
369 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
370 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
371 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
372 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
374 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
375 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
376 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
377 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
383 if(render_inputs
& _TNL_BIT_POS
)
384 output_vector(VB
->ObjPtr
, i
);
385 if(render_inputs
& _TNL_BIT_NORMAL
)
386 output_vector(VB
->NormalPtr
, i
);
388 /* color components */
389 if(render_inputs
& _TNL_BIT_COLOR0
)
390 output_vector(VB
->ColorPtr
[0], i
);
391 if(render_inputs
& _TNL_BIT_COLOR1
)
392 output_vector(VB
->SecondaryColorPtr
[0], i
);
394 /* if(render_inputs & _TNL_BIT_FOG) // Causes lock ups when immediate mode is on
395 output_vector(VB->FogCoordPtr, i);*/
397 /* texture coordinates */
398 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
399 if(render_inputs
& (_TNL_BIT_TEX0
<<k
))
400 output_vector(VB
->TexCoordPtr
[k
], i
);
402 if(render_inputs
& _TNL_BIT_INDEX
)
403 output_vector(VB
->IndexPtr
[0], i
);
404 if(render_inputs
& _TNL_BIT_POINTSIZE
)
405 output_vector(VB
->PointSizePtr
, i
);
411 static GLboolean
r300_run_immediate_render(GLcontext
*ctx
,
412 struct tnl_pipeline_stage
*stage
)
414 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
415 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
416 struct vertex_buffer
*VB
= &tnl
->vb
;
418 /* Only do 2d textures */
419 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
420 r300TexObjPtr t
=to
->DriverData
;
424 /* Update texture state - needs to be done only when actually changed..
425 All the time for now.. */
428 if (RADEON_DEBUG
== DEBUG_PRIMS
)
429 fprintf(stderr
, "%s\n", __FUNCTION__
);
431 #if 1 /* we need this, somehow */
432 /* Flush state - make sure command buffer is nice and large */
434 /* Make sure we have enough space */
436 /* Count is very imprecize, but should be good upper bound */
437 r300EnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
+ 4+2+30
438 +VB
->PrimitiveCount
*(1+8)+VB
->Count
*4*rmesa
->state
.texture
.tc_count
+4, __FUNCTION__
);
441 /* needed before starting 3d operation .. */
442 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
449 #if 0 /* looks like the Z offset issue got fixed */
450 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
451 | R300_VPORT_X_OFFSET_ENA
452 | R300_VPORT_Y_SCALE_ENA
453 | R300_VPORT_Y_OFFSET_ENA
455 R300_STATECHANGE(rmesa
, vte
);
460 /* Magic register - note it is right after 20b0 */
463 if(rmesa
->state
.texture
.tc_count
>0){
469 r300EmitState(rmesa
);
472 reg_start(R300_RB3D_COLORMASK
, 0);
475 vsf_start_fragment(0x406, 4);
481 vsf_start_fragment(0x400, 4);
488 /* Setup INPUT_ROUTE and INPUT_CNTL */
489 r300EmitArrays(ctx
, GL_TRUE
);
491 /* Why do we need this for immediate mode?? Vertex processor needs it to know proper regs */
492 // r300EmitLOAD_VBPNTR(rmesa, 0);
494 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
495 GLuint prim
= VB
->Primitive
[i
].mode
;
496 GLuint start
= VB
->Primitive
[i
].start
;
497 GLuint length
= VB
->Primitive
[i
].count
;
499 r300_render_immediate_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
502 /* This sequence is required after any 3d drawing packet
503 I suspect it work arounds a bug (or deficiency) in hardware */
505 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
514 /* vertex buffer implementation */
516 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
525 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
526 num_verts
=r300_get_num_verts(rmesa
, ctx
, end
-start
, prim
);
528 if(type
<0 || num_verts
<= 0)return;
531 fire_AOS(PASS_PREFIX num_verts
, type
);
534 static GLboolean
r300_run_vb_render(GLcontext
*ctx
,
535 struct tnl_pipeline_stage
*stage
)
537 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
538 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
539 struct vertex_buffer
*VB
= &tnl
->vb
;
543 if (RADEON_DEBUG
== DEBUG_PRIMS
)
544 fprintf(stderr
, "%s\n", __FUNCTION__
);
547 r300ReleaseArrays(ctx
);
548 r300EmitArrays(ctx
, GL_FALSE
);
550 // LOCK_HARDWARE(&(rmesa->radeon));
552 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
558 r300EmitState(rmesa
);
560 rmesa
->state
.Elts
= VB
->Elts
;
562 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
563 GLuint prim
= VB
->Primitive
[i
].mode
;
564 GLuint start
= VB
->Primitive
[i
].start
;
565 GLuint length
= VB
->Primitive
[i
].count
;
567 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
569 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
572 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
578 // end_3d(PASS_PREFIX_VOID);
580 /* Flush state - we are done drawing.. */
581 // r300FlushCmdBufLocked(rmesa, __FUNCTION__);
582 // radeonWaitForIdleLocked(&(rmesa->radeon));
584 // UNLOCK_HARDWARE(&(rmesa->radeon));
589 * Called by the pipeline manager to render a batch of primitives.
590 * We can return true to pass on to the next stage (i.e. software
591 * rasterization) or false to indicate that the pipeline has finished
592 * after we render something.
594 static GLboolean
r300_run_render(GLcontext
*ctx
,
595 struct tnl_pipeline_stage
*stage
)
597 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
598 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
599 struct vertex_buffer
*VB
= &tnl
->vb
;
602 if (RADEON_DEBUG
== DEBUG_PRIMS
)
603 fprintf(stderr
, "%s\n", __FUNCTION__
);
609 return r300_run_immediate_render(ctx
, stage
);
611 return r300_run_vb_render(ctx
, stage
);
618 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
619 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
620 struct vertex_buffer
*VB
= &tnl
->vb
;
623 /* Don't handle clipping or indexed vertices or vertex manipulations.
625 if (mmesa
->RenderIndex
!= 0 ||
626 !mga_validate_render( ctx
, VB
)) {
630 tnl
->Driver
.Render
.Start( ctx
);
631 mmesa
->SetupNewInputs
= ~0;
633 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
635 GLuint prim
= VB
->Primitive
[i
].mode
;
636 GLuint start
= VB
->Primitive
[i
].start
;
637 GLuint length
= VB
->Primitive
[i
].count
;
642 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
646 tnl
->Driver
.Render
.Finish( ctx
);
648 return GL_FALSE
; /* finished the pipe */
654 * Called by the pipeline manager once before rendering.
655 * We check the GL state here to
656 * a) decide whether we can do the current state in hardware and
657 * b) update hardware registers
659 #define FALLBACK_IF(expr) \
662 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
663 fprintf(stderr, "%s: fallback:%s\n", \
664 __FUNCTION__, #expr); \
665 stage->active = GL_FALSE; \
670 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
672 r300ContextPtr r300
= R300_CONTEXT(ctx
);
675 if (RADEON_DEBUG
& DEBUG_STATE
)
676 fprintf(stderr
, "%s\n", __FUNCTION__
);
678 /* We only support rendering in hardware for now */
679 if (ctx
->RenderMode
!= GL_RENDER
) {
680 stage
->active
= GL_FALSE
;
684 // I failed to figure out how dither works in hardware,
685 // let's just ignore it for now
686 //FALLBACK_IF(ctx->Color.DitherFlag);
688 /* I'm almost certain I forgot something here */
689 #if 0 /* This should work now.. */
690 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
691 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
693 //FALLBACK_IF(ctx->Fog.Enabled); // GL_FOG disable as swtcl doesnt seem to support this
694 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
695 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
696 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
697 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
698 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
699 //FALLBACK_IF(ctx->Polygon.OffsetPoint); // GL_POLYGON_OFFSET_POINT
700 //FALLBACK_IF(ctx->Polygon.OffsetLine); // GL_POLYGON_OFFSET_LINE
701 //FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
702 //if(ctx->Polygon.OffsetFill)WARN_ONCE("Polygon.OffsetFill not implemented, ignoring\n");
703 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
704 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
705 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
706 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
708 /* One step at a time - let one texture pass.. */
709 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
710 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
712 /* let r300_run_render do its job */
714 stage
->active
= GL_FALSE
;
719 static void dtr(struct tnl_pipeline_stage
*stage
)
724 const struct tnl_pipeline_stage _r300_render_stage
= {
726 _NEW_ALL
, /* re-check (always re-check for now) */
727 0, /* re-run (always runs) */
728 GL_TRUE
, /* active */
729 0, 0, /* inputs (set in check_render), outputs */
730 0, 0, /* changed_inputs, private */
731 dtr
, /* destructor */
732 r300_check_render
, /* check */
733 r300_run_render
/* run */