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 ***WARN_ONCE*** 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
);
211 fprintf(stderr
, "FIXME: Dont know how to handle GL_ARB_vertex_buffer_object "
215 /* A packet cannot have more than 16383 data words.. */
216 if(((end
-start
)*4*rmesa
->state
.aos_count
)>16380){
217 fprintf(stderr
, "%s:%s: Too many vertices to paint. Fix me !\n");
221 //fprintf(stderr, "aos_count=%d start=%d end=%d\n", rmesa->state.aos_count, start, end);
223 start_immediate_packet(end
-start
, type
, 4*rmesa
->state
.aos_count
);
225 for(i
=start
;i
<end
;i
++){
227 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
228 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
229 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
230 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
231 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
233 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
234 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
235 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
236 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
242 if(tnl
->render_inputs
& _TNL_BIT_POS
)
243 output_vector(VB
->ObjPtr
, i
);
244 if(tnl
->render_inputs
& _TNL_BIT_NORMAL
)
245 output_vector(VB
->NormalPtr
, i
);
247 /* color components */
248 if(tnl
->render_inputs
& _TNL_BIT_COLOR0
)
249 output_vector(VB
->ColorPtr
[0], i
);
250 if(tnl
->render_inputs
& _TNL_BIT_COLOR1
)
251 output_vector(VB
->SecondaryColorPtr
[0], i
);
253 if(tnl
->render_inputs
& _TNL_BIT_FOG
)
254 output_vector(VB
->FogCoordPtr
, i
);
256 /* texture coordinates */
257 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
258 if(tnl
->render_inputs
& (_TNL_BIT_TEX0
<<k
))
259 output_vector(VB
->TexCoordPtr
[k
], i
);
261 if(tnl
->render_inputs
& _TNL_BIT_INDEX
)
262 output_vector(VB
->IndexPtr
[0], i
);
263 if(tnl
->render_inputs
& _TNL_BIT_POINTSIZE
)
264 output_vector(VB
->PointSizePtr
, i
);
270 static GLboolean
r300_run_immediate_render(GLcontext
*ctx
,
271 struct tnl_pipeline_stage
*stage
)
273 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
274 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
275 struct vertex_buffer
*VB
= &tnl
->vb
;
277 /* Only do 2d textures */
278 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
279 r300TexObjPtr t
=to
->DriverData
;
283 /* Update texture state - needs to be done only when actually changed..
284 All the time for now.. */
287 if (RADEON_DEBUG
== DEBUG_PRIMS
)
288 fprintf(stderr
, "%s\n", __FUNCTION__
);
290 #if 1 /* we need this, somehow */
291 /* Flush state - make sure command buffer is nice and large */
293 /* Make sure we have enough space */
295 /* Count is very imprecize, but should be good upper bound */
296 r300EnsureCmdBufSpace(rmesa
, rmesa
->hw
.max_state_size
+ 4+2+30
297 +VB
->PrimitiveCount
*(1+8)+VB
->Count
*4*rmesa
->state
.texture
.tc_count
+4, __FUNCTION__
);
300 /* needed before starting 3d operation .. */
301 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
308 #if 0 /* looks like the Z offset issue got fixed */
309 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
310 | R300_VPORT_X_OFFSET_ENA
311 | R300_VPORT_Y_SCALE_ENA
312 | R300_VPORT_Y_OFFSET_ENA
314 R300_STATECHANGE(rmesa
, vte
);
319 /* Magic register - note it is right after 20b0 */
322 if(rmesa
->state
.texture
.tc_count
>0){
328 r300EmitState(rmesa
);
331 reg_start(R300_RB3D_COLORMASK
, 0);
334 vsf_start_fragment(0x406, 4);
340 vsf_start_fragment(0x400, 4);
347 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
348 r300EmitLOAD_VBPNTR(rmesa
, 0);
350 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
351 GLuint prim
= VB
->Primitive
[i
].mode
;
352 GLuint start
= VB
->Primitive
[i
].start
;
353 GLuint length
= VB
->Primitive
[i
].count
;
354 r300_render_immediate_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
357 /* This sequence is required after any 3d drawing packet
358 I suspect it work arounds a bug (or deficiency) in hardware */
360 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
370 /* vertex buffer implementation */
372 /* We use the start part of GART texture buffer for vertices */
375 static void upload_vertex_buffer(r300ContextPtr rmesa
, GLcontext
*ctx
)
377 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
378 struct vertex_buffer
*VB
= &tnl
->vb
;
381 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
383 /* A hack - we don't want to overwrite vertex buffers, so we
384 just use AGP space for them.. Fix me ! */
386 if(offset
>2*1024*1024){
387 //fprintf(stderr, "Wrapping agp vertex buffer offset\n");
390 /* Not the most efficient implementation, but, for now, I just want something that
392 /* to do - make single memcpy per column (is it possible ?) */
393 /* to do - use dirty flags to avoid redundant copies */
394 #define UPLOAD_VECTOR(v)\
396 /* Is the data dirty ? */ \
397 if (v->flags & ((1<<v->size)-1)) { \
398 /* fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); */ \
399 if(v->size*4==v->stride){\
401 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
403 for(i=0;i<VB->Count;i++){ \
404 /* copy one vertex at a time*/ \
405 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
408 /* v->flags &= ~((1<<v->size)-1);*/ \
410 rmesa->state.aos[idx].offset=rsp->gartTextures.handle+offset; \
411 offset+=v->size*4*VB->Count; \
415 UPLOAD_VECTOR(VB
->ObjPtr
);
416 UPLOAD_VECTOR(VB
->ColorPtr
[0]);
417 /* texture coordinates */
418 for(k
=0;k
< ctx
->Const
.MaxTextureUnits
;k
++)
419 if(ctx
->Texture
.Unit
[k
].Enabled
)
420 UPLOAD_VECTOR(VB
->TexCoordPtr
[k
]);
422 if(idx
>=R300_MAX_AOS_ARRAYS
){
423 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
428 static void r300_render_vb_primitive(r300ContextPtr rmesa
,
437 if(end
<=start
)return; /* do we need to watch for this ? */
439 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
442 fire_AOS(PASS_PREFIX end
-start
, type
);
445 static GLboolean
r300_run_vb_render(GLcontext
*ctx
,
446 struct tnl_pipeline_stage
*stage
)
448 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
449 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
450 struct vertex_buffer
*VB
= &tnl
->vb
;
454 if (RADEON_DEBUG
== DEBUG_PRIMS
)
455 fprintf(stderr
, "%s\n", __FUNCTION__
);
458 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
464 r300_setup_routing(ctx
, GL_FALSE
);
466 r300EmitState(rmesa
);
468 /* setup array of structures data */
469 LOCK_HARDWARE(&(rmesa
->radeon
));
471 upload_vertex_buffer(rmesa
, ctx
);
472 //fprintf(stderr, "Using %d AOS arrays\n", n_arrays);
474 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
475 GLuint prim
= VB
->Primitive
[i
].mode
;
476 GLuint start
= VB
->Primitive
[i
].start
;
477 GLuint length
= VB
->Primitive
[i
].count
;
479 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. */
480 r300EmitLOAD_VBPNTR(rmesa
, start
);
482 r300_render_vb_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
485 /* This sequence is required after any 3d drawing packet
486 I suspect it works around a bug (or deficiency) in hardware */
488 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
494 end_3d(PASS_PREFIX_VOID
);
496 /* Flush state - we are done drawing.. */
497 r300FlushCmdBufLocked(ctx
, __FUNCTION__
);
498 radeonWaitForIdleLocked(&(rmesa
->radeon
));
500 UNLOCK_HARDWARE(&(rmesa
->radeon
));
506 * Called by the pipeline manager to render a batch of primitives.
507 * We can return true to pass on to the next stage (i.e. software
508 * rasterization) or false to indicate that the pipeline has finished
509 * after we render something.
511 static GLboolean
r300_run_render(GLcontext
*ctx
,
512 struct tnl_pipeline_stage
*stage
)
514 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
515 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
516 struct vertex_buffer
*VB
= &tnl
->vb
;
519 if (RADEON_DEBUG
== DEBUG_PRIMS
)
520 fprintf(stderr
, "%s\n", __FUNCTION__
);
526 return r300_run_immediate_render(ctx
, stage
);
528 return r300_run_vb_render(ctx
, stage
);
535 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
536 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
537 struct vertex_buffer
*VB
= &tnl
->vb
;
540 /* Don't handle clipping or indexed vertices or vertex manipulations.
542 if (mmesa
->RenderIndex
!= 0 ||
543 !mga_validate_render( ctx
, VB
)) {
547 tnl
->Driver
.Render
.Start( ctx
);
548 mmesa
->SetupNewInputs
= ~0;
550 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
552 GLuint prim
= VB
->Primitive
[i
].mode
;
553 GLuint start
= VB
->Primitive
[i
].start
;
554 GLuint length
= VB
->Primitive
[i
].count
;
559 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
563 tnl
->Driver
.Render
.Finish( ctx
);
565 return GL_FALSE
; /* finished the pipe */
571 * Called by the pipeline manager once before rendering.
572 * We check the GL state here to
573 * a) decide whether we can do the current state in hardware and
574 * b) update hardware registers
576 #define FALLBACK_IF(expr) \
579 if (1 || RADEON_DEBUG & DEBUG_FALLBACKS) \
580 fprintf(stderr, "%s: fallback:%s\n", \
581 __FUNCTION__, #expr); \
582 stage->active = GL_FALSE; \
587 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
589 r300ContextPtr r300
= R300_CONTEXT(ctx
);
592 if (RADEON_DEBUG
& DEBUG_STATE
)
593 fprintf(stderr
, "%s\n", __FUNCTION__
);
595 /* We only support rendering in hardware for now */
596 if (ctx
->RenderMode
!= GL_RENDER
) {
597 stage
->active
= GL_FALSE
;
601 // I failed to figure out how dither works in hardware,
602 // let's just ignore it for now
603 //FALLBACK_IF(ctx->Color.DitherFlag);
605 /* I'm almost certain I forgot something here */
606 #if 0 /* This should work now.. */
607 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
608 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
610 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
611 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
612 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
613 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
614 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
615 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
616 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
617 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
618 //FALLBACK_IF(ctx->Polygon.OffsetFill); // GL_POLYGON_OFFSET_FILL
619 if(ctx
->Polygon
.OffsetFill
)WARN_ONCE("Polygon.OffsetFill not implemented, ignoring\n");
620 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
621 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
622 //FALLBACK_IF(ctx->Stencil.Enabled); // GL_STENCIL_TEST
623 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
625 /* One step at a time - let one texture pass.. */
626 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
627 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
629 /* let r300_run_render do its job */
631 stage
->active
= GL_FALSE
;
636 static void dtr(struct tnl_pipeline_stage
*stage
)
641 const struct tnl_pipeline_stage _r300_render_stage
= {
643 _NEW_ALL
, /* re-check (always re-check for now) */
644 0, /* re-run (always runs) */
645 GL_TRUE
, /* active */
646 0, 0, /* inputs (set in check_render), outputs */
647 0, 0, /* changed_inputs, private */
648 dtr
, /* destructor */
649 r300_check_render
, /* check */
650 r300_run_render
/* run */