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"
47 #include "tnl/t_vp_build.h"
49 #include "radeon_reg.h"
50 #include "radeon_macros.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_state.h"
53 #include "r300_context.h"
54 #include "r300_ioctl.h"
55 #include "r300_state.h"
57 #include "r300_program.h"
59 #include "r300_maos.h"
60 #include "r300_emit.h"
62 extern int future_hw_tcl_on
;
64 /**********************************************************************
65 * Hardware rasterization
67 * When we fell back to software TCL, we still try to use the
68 * rasterization hardware for rendering.
69 **********************************************************************/
71 static int r300_get_primitive_type(r300ContextPtr rmesa
, GLcontext
*ctx
, int prim
)
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 int r300_get_num_verts(r300ContextPtr rmesa
, int num_verts
, int prim
)
119 char *name
="UNKNOWN";
121 switch (prim
& PRIM_MODE_MASK
) {
128 verts_off
= num_verts
% 2;
133 verts_off
= num_verts
;
138 verts_off
= num_verts
;
142 verts_off
= num_verts
% 3;
144 case GL_TRIANGLE_STRIP
:
147 verts_off
= num_verts
;
149 case GL_TRIANGLE_FAN
:
152 verts_off
= num_verts
;
156 verts_off
= num_verts
% 4;
161 verts_off
= num_verts
;
163 verts_off
= num_verts
% 2;
168 verts_off
= num_verts
;
171 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
172 __FILE__
, __FUNCTION__
,
173 prim
& PRIM_MODE_MASK
);
178 if (RADEON_DEBUG
& DEBUG_VERTS
) {
179 if (num_verts
- verts_off
== 0) {
180 WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts
, name
);
185 WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts
, name
);
189 return num_verts
- verts_off
;
192 /* Immediate implementation has been removed from CVS. */
194 /* vertex buffer implementation */
196 static void inline fire_EB(r300ContextPtr rmesa
, unsigned long addr
, int vertex_count
, int type
, int elt_size
)
198 int cmd_reserved
= 0;
200 drm_radeon_cmd_header_t
*cmd
= NULL
;
201 unsigned long addr_a
;
202 unsigned long t_addr
;
203 unsigned long magic_1
, magic_2
;
205 ctx
= rmesa
->radeon
.glCtx
;
207 assert(elt_size
== 2 || elt_size
== 4);
209 if(addr
& (elt_size
-1)){
210 WARN_ONCE("Badly aligned buffer\n");
216 magic_1
= (addr
% 32) / 4;
217 t_addr
= addr
& (~0x1d);
218 magic_2
= (vertex_count
+ 1 + (t_addr
& 0x2)) / 2 + magic_1
;
222 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2
, 0);
224 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<<16) | type
| R300_VAP_VF_CNTL__INDEX_SIZE_32bit
);
226 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<<16) | type
);
229 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER
, 2);
231 e32(R300_EB_UNK1
| (0 << 16) | R300_EB_UNK2
);
232 e32(addr
/*& 0xffffffe3*/);
234 e32(R300_EB_UNK1
| (magic_1
<< 16) | R300_EB_UNK2
);
239 e32(vertex_count
/*+ addr_a/4*/); /* Total number of dwords needed? */
241 e32(magic_2
); /* Total number of dwords needed? */
243 //cp_delay(rmesa, 1);
245 fprintf(stderr
, "magic_1 %d\n", magic_1
);
246 fprintf(stderr
, "t_addr %x\n", t_addr
);
247 fprintf(stderr
, "magic_2 %d\n", magic_2
);
251 (void)magic_2
, (void)magic_1
, (void)t_addr
;
257 start_packet3(RADEON_CP_PACKET3_3D_DRAW_INDX_2
, 0);
259 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<<16) | type
| R300_VAP_VF_CNTL__INDEX_SIZE_32bit
);
261 e32(R300_VAP_VF_CNTL__PRIM_WALK_INDICES
| (vertex_count
<<16) | type
);
264 start_packet3(RADEON_CP_PACKET3_INDX_BUFFER
, 2);
265 e32(R300_EB_UNK1
| (0 << 16) | R300_EB_UNK2
);
266 e32(addr
/*& 0xffffffe3*/);
269 e32(vertex_count
/*+ addr_a/4*/); /* Total number of dwords needed? */
271 e32((vertex_count
+1)/2 /*+ addr_a/4*/); /* Total number of dwords needed? */
273 //cp_delay(rmesa, 1);
277 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
285 type
=r300_get_primitive_type(rmesa
, ctx
, prim
);
286 num_verts
=r300_get_num_verts(rmesa
, end
-start
, prim
);
288 if(type
<0 || num_verts
<= 0)return;
290 if(rmesa
->state
.VB
.Elts
){
291 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, /*0*/start
);
293 int cmd_reserved
= 0;
295 drm_radeon_cmd_header_t
*cmd
= NULL
;
297 start_index32_packet(num_verts
, type
);
298 for(i
=0; i
< num_verts
; i
++)
299 e32(((unsigned long *)rmesa
->state
.VB
.Elts
)[i
]/*rmesa->state.Elts[start+i]*/); /* start ? */
302 //start_index32_packet(num_verts, type);
303 //e32(rmesa->state.Elts[start]);
307 if(num_verts
> 65535){ /* not implemented yet */
308 WARN_ONCE("Too many elts\n");
312 r300EmitElts(ctx
, rmesa
->state
.VB
.Elts
, num_verts
, rmesa
->state
.VB
.elt_size
);
313 fire_EB(rmesa
, rmesa
->state
.elt_dma
.aos_offset
, num_verts
, type
, rmesa
->state
.VB
.elt_size
);
316 r300EmitAOS(rmesa
, rmesa
->state
.aos_count
, start
);
317 fire_AOS(rmesa
, num_verts
, type
);
321 GLboolean
r300_run_vb_render(GLcontext
*ctx
,
322 struct tnl_pipeline_stage
*stage
)
324 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
325 struct radeon_vertex_buffer
*VB
= &rmesa
->state
.VB
;
327 int cmd_reserved
= 0;
329 drm_radeon_cmd_header_t
*cmd
= NULL
;
332 if (RADEON_DEBUG
& DEBUG_PRIMS
)
333 fprintf(stderr
, "%s\n", __FUNCTION__
);
336 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
337 radeon_vb_to_rvb(rmesa
, VB
, &tnl
->vb
);
340 r300UpdateShaders(rmesa
);
341 if (r300EmitArrays(ctx
))
344 r300UpdateShaderStates(rmesa
);
346 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
347 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
349 reg_start(R300_RB3D_ZCACHE_CTLSTAT
,0);
350 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);
352 r300EmitState(rmesa
);
354 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
355 GLuint prim
= _tnl_translate_prim(&VB
->Primitive
[i
]);
356 GLuint start
= VB
->Primitive
[i
].start
;
357 GLuint length
= VB
->Primitive
[i
].count
;
359 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
362 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
363 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
/*R300_RB3D_DSTCACHE_UNKNOWN_02*/);
365 reg_start(R300_RB3D_ZCACHE_CTLSTAT
,0);
366 e32(R300_RB3D_ZCACHE_UNKNOWN_03
/*R300_RB3D_ZCACHE_UNKNOWN_01*/);
371 r300ReleaseArrays(ctx
);
375 #define FALLBACK_IF(expr) \
378 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
379 WARN_ONCE("Software fallback:%s\n", \
381 return R300_FALLBACK_RAST; \
385 int r300Fallback(GLcontext
*ctx
)
387 r300ContextPtr r300
= R300_CONTEXT(ctx
);
388 struct r300_fragment_program
*rp
=
389 (struct r300_fragment_program
*)
390 (char *)ctx
->FragmentProgram
._Current
;
395 r300_translate_fragment_shader(r300
, rp
);
397 FALLBACK_IF(!rp
->translated
);
400 /* We do not do SELECT or FEEDBACK (yet ?)
401 * Is it worth doing them ?
403 FALLBACK_IF(ctx
->RenderMode
!= GL_RENDER
);
406 /* These should work now.. */
407 FALLBACK_IF(ctx
->Color
.DitherFlag
);
409 FALLBACK_IF(ctx
->Color
.AlphaEnabled
);
411 FALLBACK_IF(ctx
->Color
.BlendEnabled
);
412 /* GL_POLYGON_OFFSET_FILL */
413 FALLBACK_IF(ctx
->Polygon
.OffsetFill
);
414 /* FOG seems to trigger an unknown output
417 FALLBACK_IF(ctx
->Fog
.Enabled
);
419 FALLBACK_IF(ctx
->Stencil
._TestTwoSide
&&
420 (ctx
->Stencil
.Ref
[0] != ctx
->Stencil
.Ref
[1] ||
421 ctx
->Stencil
.ValueMask
[0] != ctx
->Stencil
.ValueMask
[1] ||
422 ctx
->Stencil
.WriteMask
[0] != ctx
->Stencil
.WriteMask
[1]));
424 if(!r300
->disable_lowimpact_fallback
){
425 /* GL_POLYGON_OFFSET_POINT */
426 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
);
427 /* GL_POLYGON_OFFSET_LINE */
428 FALLBACK_IF(ctx
->Polygon
.OffsetLine
);
430 /* GL_STENCIL_TEST */
431 FALLBACK_IF(ctx
->Stencil
.Enabled
);
432 /* GL_POLYGON_SMOOTH disabling to get blender going */
433 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
);
435 /* GL_POLYGON_STIPPLE */
436 FALLBACK_IF(ctx
->Polygon
.StippleFlag
);
437 /* GL_MULTISAMPLE_ARB */
438 FALLBACK_IF(ctx
->Multisample
.Enabled
);
440 FALLBACK_IF(ctx
->Line
.StippleFlag
);
442 FALLBACK_IF(ctx
->Line
.SmoothFlag
);
443 /* GL_POINT_SMOOTH */
444 FALLBACK_IF(ctx
->Point
.SmoothFlag
);
447 /* Fallback for LOGICOP */
448 FALLBACK_IF(ctx
->Color
.ColorLogicOpEnabled
);
450 /* Rest could be done with vertex fragments */
451 if (ctx
->Extensions
.NV_point_sprite
||
452 ctx
->Extensions
.ARB_point_sprite
)
453 /* GL_POINT_SPRITE_NV */
454 FALLBACK_IF(ctx
->Point
.PointSprite
);
456 return R300_FALLBACK_NONE
;
460 * Called by the pipeline manager to render a batch of primitives.
461 * We can return true to pass on to the next stage (i.e. software
462 * rasterization) or false to indicate that the pipeline has finished
463 * after we render something.
465 static GLboolean
r300_run_render(GLcontext
*ctx
,
466 struct tnl_pipeline_stage
*stage
)
469 if (RADEON_DEBUG
& DEBUG_PRIMS
)
470 fprintf(stderr
, "%s\n", __FUNCTION__
);
472 if (r300Fallback(ctx
) >= R300_FALLBACK_RAST
)
475 return r300_run_vb_render(ctx
, stage
);
478 const struct tnl_pipeline_stage _r300_render_stage
= {
484 r300_run_render
/* run */
487 static GLboolean
r300_run_tcl_render(GLcontext
*ctx
,
488 struct tnl_pipeline_stage
*stage
)
490 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
491 struct r300_vertex_program
*vp
;
493 hw_tcl_on
=future_hw_tcl_on
;
495 if (RADEON_DEBUG
& DEBUG_PRIMS
)
496 fprintf(stderr
, "%s\n", __FUNCTION__
);
497 if(hw_tcl_on
== GL_FALSE
)
500 if (r300Fallback(ctx
) >= R300_FALLBACK_TCL
) {
501 hw_tcl_on
= GL_FALSE
;
505 r300UpdateShaders(rmesa
);
507 vp
= (struct r300_vertex_program
*)CURRENT_VERTEX_SHADER(ctx
);
508 #if 0 /* Draw every second request with software arb vp */
511 //vp->native = GL_FALSE;
514 #if 0 /* You dont want to know what this does... */
515 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
516 struct tnl_cache
*cache
;
517 struct tnl_cache_item
*c
;
519 cache
= tnl
->vp_cache
;
520 c
= cache
->items
[0xc000cc0e % cache
->size
];
522 if(c
&& c
->data
== vp
)
523 vp
->native
= GL_FALSE
;
527 vp
->native
= GL_FALSE
;
529 if (vp
->native
== GL_FALSE
) {
530 hw_tcl_on
= GL_FALSE
;
533 //r300UpdateShaderStates(rmesa);
535 return r300_run_vb_render(ctx
, stage
);
538 const struct tnl_pipeline_stage _r300_tcl_stage
= {
544 r300_run_tcl_render
/* run */