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 /* Fallback for rectangular texture */
457 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
458 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
& TEXTURE_RECT_BIT
)
459 return R300_FALLBACK_TCL
;
461 return R300_FALLBACK_NONE
;
465 * Called by the pipeline manager to render a batch of primitives.
466 * We can return true to pass on to the next stage (i.e. software
467 * rasterization) or false to indicate that the pipeline has finished
468 * after we render something.
470 static GLboolean
r300_run_render(GLcontext
*ctx
,
471 struct tnl_pipeline_stage
*stage
)
474 if (RADEON_DEBUG
& DEBUG_PRIMS
)
475 fprintf(stderr
, "%s\n", __FUNCTION__
);
477 if (r300Fallback(ctx
) >= R300_FALLBACK_RAST
)
480 return r300_run_vb_render(ctx
, stage
);
483 const struct tnl_pipeline_stage _r300_render_stage
= {
489 r300_run_render
/* run */
492 static GLboolean
r300_run_tcl_render(GLcontext
*ctx
,
493 struct tnl_pipeline_stage
*stage
)
495 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
496 struct r300_vertex_program
*vp
;
498 hw_tcl_on
=future_hw_tcl_on
;
500 if (RADEON_DEBUG
& DEBUG_PRIMS
)
501 fprintf(stderr
, "%s\n", __FUNCTION__
);
502 if(hw_tcl_on
== GL_FALSE
)
505 if (r300Fallback(ctx
) >= R300_FALLBACK_TCL
) {
506 hw_tcl_on
= GL_FALSE
;
510 r300UpdateShaders(rmesa
);
512 vp
= (struct r300_vertex_program
*)CURRENT_VERTEX_SHADER(ctx
);
513 #if 0 /* Draw every second request with software arb vp */
516 //vp->native = GL_FALSE;
519 #if 0 /* You dont want to know what this does... */
520 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
521 struct tnl_cache
*cache
;
522 struct tnl_cache_item
*c
;
524 cache
= tnl
->vp_cache
;
525 c
= cache
->items
[0xc000cc0e % cache
->size
];
527 if(c
&& c
->data
== vp
)
528 vp
->native
= GL_FALSE
;
532 vp
->native
= GL_FALSE
;
534 if (vp
->native
== GL_FALSE
) {
535 hw_tcl_on
= GL_FALSE
;
538 //r300UpdateShaderStates(rmesa);
540 return r300_run_vb_render(ctx
, stage
);
543 const struct tnl_pipeline_stage _r300_tcl_stage
= {
549 r300_run_tcl_render
/* run */
552 /* R300 texture rectangle expects coords in 0..1 range, not 0..dimension
553 * as in the extension spec. Need to translate here.
555 * Note that swrast expects 0..dimension, so if a fallback is active,
556 * don't do anything. (Maybe need to configure swrast to match hw)
558 struct texrect_stage_data
{
559 GLvector4f texcoord
[MAX_TEXTURE_UNITS
];
562 #define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
565 static GLboolean
run_texrect_stage( GLcontext
*ctx
,
566 struct tnl_pipeline_stage
*stage
)
568 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
569 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
570 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
571 struct vertex_buffer
*VB
= &tnl
->vb
;
574 if (rmesa
->radeon
.Fallback
)
577 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
578 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
& TEXTURE_RECT_BIT
) {
579 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
].CurrentRect
;
580 struct gl_texture_image
*texImage
= texObj
->Image
[0][texObj
->BaseLevel
];
581 const GLfloat iw
= 1.0/texImage
->Width
;
582 const GLfloat ih
= 1.0/texImage
->Height
;
583 GLfloat
*in
= (GLfloat
*)VB
->TexCoordPtr
[i
]->data
;
584 GLint instride
= VB
->TexCoordPtr
[i
]->stride
;
585 GLfloat (*out
)[4] = store
->texcoord
[i
].data
;
588 store
->texcoord
[i
].size
= VB
->TexCoordPtr
[i
]->size
;
589 for (j
= 0 ; j
< VB
->Count
; j
++) {
590 switch (VB
->TexCoordPtr
[i
]->size
) {
598 out
[j
][0] = in
[0] * iw
;
599 out
[j
][1] = in
[1] * ih
;
601 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
604 VB
->AttribPtr
[VERT_ATTRIB_TEX0
+i
] = VB
->TexCoordPtr
[i
] = &store
->texcoord
[i
];
612 /* Called the first time stage->run() is invoked.
614 static GLboolean
alloc_texrect_data( GLcontext
*ctx
,
615 struct tnl_pipeline_stage
*stage
)
617 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
618 struct texrect_stage_data
*store
;
621 stage
->privatePtr
= CALLOC(sizeof(*store
));
622 store
= TEXRECT_STAGE_DATA(stage
);
626 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
627 _mesa_vector4f_alloc( &store
->texcoord
[i
], 0, VB
->Size
, 32 );
632 static void free_texrect_data( struct tnl_pipeline_stage
*stage
)
634 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
638 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
639 if (store
->texcoord
[i
].data
)
640 _mesa_vector4f_free( &store
->texcoord
[i
] );
642 stage
->privatePtr
= NULL
;
646 const struct tnl_pipeline_stage _r300_texrect_stage
=
648 "r300 texrect stage", /* name */