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 /**********************************************************************
62 * Hardware rasterization
64 * When we fell back to software TCL, we still try to use the
65 * rasterization hardware for rendering.
66 **********************************************************************/
68 static int r300_get_primitive_type(r300ContextPtr rmesa
,
74 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
75 struct vertex_buffer
*VB
= &tnl
->vb
;
77 int type
=-1, min_vertices
=0;
80 if(end
<=start
)return -1; /* do we need to watch for this ? */
82 switch (prim
& PRIM_MODE_MASK
) {
85 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
90 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
95 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
105 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
108 case GL_TRIANGLE_STRIP
:
110 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
113 case GL_TRIANGLE_FAN
:
115 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
120 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
125 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
130 type
=R300_VAP_VF_CNTL__PRIM_POLYGON
;
134 fprintf(stderr
, "%s:%s Do not know how to handle primitive %02x - help me !\n",
135 __FILE__
, __FUNCTION__
,
136 prim
& PRIM_MODE_MASK
);
141 fprintf(stderr
, "[%d-%d]%s ", start
, end
, name
);
143 if(start
+min_vertices
>end
){
144 static int warn_once
=1;
146 fprintf(stderr
, "%s:%s Not enough vertices to draw primitive %02x - help me !\n",
147 __FILE__
, __FUNCTION__
,
148 prim
& PRIM_MODE_MASK
);
156 /* This function compiles GL context into state registers that
157 describe data routing inside of R300 pipeline.
159 In particular, it programs input_route, output_vtx_fmt, texture
160 unit configuration and gb_output_vtx_fmt
162 This function encompasses setup_AOS() from r300_lib.c
168 /* Immediate implementation - vertex data is sent via command stream */
170 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
172 #define output_vector(v, i) \
175 for(_i=0;_i<v->size;_i++){ \
176 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
178 for(_i=v->size;_i<4;_i++){ \
179 efloat(default_vector[_i]); \
183 /* Immediate implementation - vertex data is sent via command stream */
185 static void r300_render_immediate_primitive(r300ContextPtr rmesa
,
191 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
192 struct vertex_buffer
*VB
= &tnl
->vb
;
197 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
200 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
201 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
202 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
203 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
204 fprintf(stderr
,"TexCoordPtr[0]: size=%d stride=%d\n",
205 VB
->TexCoordPtr
[0]->size
, VB
->TexCoordPtr
[0]->stride
);
210 /* A packet cannot have more than 16383 data words.. */
211 if(((end
-start
)*8+4*rmesa
->state
.texture
.tc_count
)>16380){
212 fprintf(stderr
, "%s:%s: Too many vertices to paint. Fix me !\n");
216 start_immediate_packet(end
-start
, type
, 8+4*rmesa
->state
.texture
.tc_count
);
218 for(i
=start
;i
<end
;i
++){
220 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
221 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
222 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
223 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
224 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
226 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
227 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
228 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
229 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
235 output_vector(VB
->ObjPtr
, i
);
237 /* color components */
238 output_vector(VB
->ColorPtr
[0], i
);
240 /* texture coordinates */
241 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
242 if(ctx
->Texture
.Unit
[k
].Enabled
)
243 output_vector(VB
->TexCoordPtr
[k
], i
);
249 static GLboolean
r300_run_immediate_render(GLcontext
*ctx
,
250 struct tnl_pipeline_stage
*stage
)
252 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
253 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
254 struct vertex_buffer
*VB
= &tnl
->vb
;
256 /* Only do 2d textures */
257 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
258 r300TexObjPtr t
=to
->DriverData
;
262 /* Update texture state - needs to be done only when actually changed..
263 All the time for now.. */
266 if (RADEON_DEBUG
== DEBUG_PRIMS
)
267 fprintf(stderr
, "%s\n", __FUNCTION__
);
269 #if 1 /* we need this, somehow */
270 /* Flush state - make sure command buffer is nice and large */
272 /* Make sure we have enough space */
274 /* Count is very imprecize, but should be good upper bound */
275 r300EnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
+ 4+2+30
276 +VB
->PrimitiveCount
*(1+8)+VB
->Count
*4*rmesa
->state
.texture
.tc_count
+4, __FUNCTION__
);
279 /* needed before starting 3d operation .. */
280 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
287 #if 0 /* looks like the Z offset issue got fixed */
288 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
289 | R300_VPORT_X_OFFSET_ENA
290 | R300_VPORT_Y_SCALE_ENA
291 | R300_VPORT_Y_OFFSET_ENA
293 R300_STATECHANGE(rmesa
, vte
);
297 /* Magic register - note it is right after 20b0 */
300 if(rmesa
->state
.texture
.tc_count
>0){
306 r300EmitState(rmesa
);
309 reg_start(R300_RB3D_COLORMASK
, 0);
312 /* ----------------------------------- */
314 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
315 r300EmitLOAD_VBPNTR(rmesa
, 0);
317 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
318 GLuint prim
= VB
->Primitive
[i
].mode
;
319 GLuint start
= VB
->Primitive
[i
].start
;
320 GLuint length
= VB
->Primitive
[i
].count
;
321 r300_render_immediate_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
324 /* This sequence is required after any 3d drawing packet
325 I suspect it work arounds a bug (or deficiency) in hardware */
327 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
337 /* vertex buffer implementation */
339 /* We use the start part of GART texture buffer for vertices */
342 static void upload_vertex_buffer(r300ContextPtr rmesa
, GLcontext
*ctx
)
344 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
345 struct vertex_buffer
*VB
= &tnl
->vb
;
348 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
350 /* A hack - we don't want to overwrite vertex buffers, so we
351 just use AGP space for them.. Fix me ! */
353 if(offset
>2*1024*1024){
354 //fprintf(stderr, "Wrapping agp vertex buffer offset\n");
357 /* Not the most efficient implementation, but, for now, I just want something that
359 /* to do - make single memcpy per column (is it possible ?) */
360 /* to do - use dirty flags to avoid redundant copies */
361 #define UPLOAD_VECTOR(v)\
363 /* Is the data dirty ? */ \
364 if (v->flags & ((1<<v->size)-1)) { \
365 /* fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); */ \
366 if(v->size*4==v->stride){\
368 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
370 for(i=0;i<VB->Count;i++){ \
371 /* copy one vertex at a time*/ \
372 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
375 /* v->flags &= ~((1<<v->size)-1);*/ \
377 rmesa->state.aos[idx].offset=rsp->gartTextures.handle+offset; \
378 offset+=v->size*4*VB->Count; \
382 UPLOAD_VECTOR(VB
->ObjPtr
);
383 UPLOAD_VECTOR(VB
->ColorPtr
[0]);
384 /* texture coordinates */
385 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
386 if(ctx
->Texture
.Unit
[k
].Enabled
)
387 UPLOAD_VECTOR(VB
->TexCoordPtr
[k
]);
389 if(idx
>=R300_MAX_AOS_ARRAYS
){
390 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
395 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
404 if(end
<=start
)return; /* do we need to watch for this ? */
406 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
409 fire_AOS(PASS_PREFIX end
-start
, type
);
412 static GLboolean
r300_run_vb_render(GLcontext
*ctx
,
413 struct tnl_pipeline_stage
*stage
)
415 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
416 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
417 struct vertex_buffer
*VB
= &tnl
->vb
;
421 if (RADEON_DEBUG
== DEBUG_PRIMS
)
422 fprintf(stderr
, "%s\n", __FUNCTION__
);
425 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
431 r300_setup_routing(ctx
, GL_FALSE
);
433 r300EmitState(rmesa
);
435 /* setup array of structures data */
436 LOCK_HARDWARE(&(rmesa
->radeon
));
438 upload_vertex_buffer(rmesa
, ctx
);
439 //fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
441 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
442 GLuint prim
= VB
->Primitive
[i
].mode
;
443 GLuint start
= VB
->Primitive
[i
].start
;
444 GLuint length
= VB
->Primitive
[i
].count
;
446 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. */
447 r300EmitLOAD_VBPNTR(rmesa
, start
);
449 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
452 /* This sequence is required after any 3d drawing packet
453 I suspect it works around a bug (or deficiency) in hardware */
455 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
461 end_3d(PASS_PREFIX_VOID
);
463 /* Flush state - we are done drawing.. */
464 r300FlushCmdBufLocked(ctx
, __FUNCTION__
);
465 radeonWaitForIdleLocked(&(rmesa
->radeon
));
467 UNLOCK_HARDWARE(&(rmesa
->radeon
));
473 * Called by the pipeline manager to render a batch of primitives.
474 * We can return true to pass on to the next stage (i.e. software
475 * rasterization) or false to indicate that the pipeline has finished
476 * after we render something.
478 static GLboolean
r300_run_render(GLcontext
*ctx
,
479 struct tnl_pipeline_stage
*stage
)
481 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
482 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
483 struct vertex_buffer
*VB
= &tnl
->vb
;
486 if (RADEON_DEBUG
== DEBUG_PRIMS
)
487 fprintf(stderr
, "%s\n", __FUNCTION__
);
493 return r300_run_immediate_render(ctx
, stage
);
495 return r300_run_vb_render(ctx
, stage
);
502 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
503 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
504 struct vertex_buffer
*VB
= &tnl
->vb
;
507 /* Don't handle clipping or indexed vertices or vertex manipulations.
509 if (mmesa
->RenderIndex
!= 0 ||
510 !mga_validate_render( ctx
, VB
)) {
514 tnl
->Driver
.Render
.Start( ctx
);
515 mmesa
->SetupNewInputs
= ~0;
517 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
519 GLuint prim
= VB
->Primitive
[i
].mode
;
520 GLuint start
= VB
->Primitive
[i
].start
;
521 GLuint length
= VB
->Primitive
[i
].count
;
526 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
530 tnl
->Driver
.Render
.Finish( ctx
);
532 return GL_FALSE
; /* finished the pipe */
538 * Called by the pipeline manager once before rendering.
539 * We check the GL state here to
540 * a) decide whether we can do the current state in hardware and
541 * b) update hardware registers
543 #define FALLBACK_IF(expr) \
546 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
547 fprintf(stderr, "%s: fallback:%s\n", \
548 __FUNCTION__, #expr); \
549 stage->active = GL_FALSE; \
554 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
556 r300ContextPtr r300
= R300_CONTEXT(ctx
);
559 if (RADEON_DEBUG
& DEBUG_STATE
)
560 fprintf(stderr
, "%s\n", __FUNCTION__
);
562 /* We only support rendering in hardware for now */
563 if (ctx
->RenderMode
!= GL_RENDER
) {
564 stage
->active
= GL_FALSE
;
568 // I failed to figure out how dither works in hardware,
569 // let's just ignore it for now
570 //FALLBACK_IF(ctx->Color.DitherFlag);
572 /* I'm almost certain I forgot something here */
573 #if 0 /* This should work now.. */
574 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
576 //FALLBACK_IF(ctx->Color.BlendEnabled); // GL_BLEND
577 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
578 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
579 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
580 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
581 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
582 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
583 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
584 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
585 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
586 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
587 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
588 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
589 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
591 /* One step at a time - let one texture pass.. */
592 for (i
= 2; i
< ctx
->Const
.MaxTextureUnits
; i
++)
593 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
596 /* let r300_run_render do its job */
598 stage
->active
= GL_FALSE
;
603 static void dtr(struct tnl_pipeline_stage
*stage
)
608 const struct tnl_pipeline_stage _r300_render_stage
= {
610 _NEW_ALL
, /* re-check (always re-check for now) */
611 0, /* re-run (always runs) */
612 GL_TRUE
, /* active */
613 0, 0, /* inputs (set in check_render), outputs */
614 0, 0, /* changed_inputs, private */
615 dtr
, /* destructor */
616 r300_check_render
, /* check */
617 r300_run_render
/* run */