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_ioctl.h"
49 #include "radeon_state.h"
50 #include "r300_context.h"
51 #include "r300_ioctl.h"
52 #include "r300_state.h"
54 #include "r300_program.h"
59 /**********************************************************************
60 * Hardware rasterization
62 * When we fell back to software TCL, we still try to use the
63 * rasterization hardware for rendering.
64 **********************************************************************/
66 static int r300_get_primitive_type(r300ContextPtr rmesa
,
72 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
73 struct vertex_buffer
*VB
= &tnl
->vb
;
77 if(end
<=start
)return -1; /* do we need to watch for this ? */
79 fprintf(stderr
, "[%d-%d]", start
, end
);
80 switch (prim
& PRIM_MODE_MASK
) {
82 fprintf(stderr
, "L ");
83 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
85 fprintf(stderr
, "Not enough vertices\n");
86 return -1; /* need enough vertices for Q */
90 fprintf(stderr
, "LS ");
91 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
93 fprintf(stderr
, "Not enough vertices\n");
94 return -1; /* need enough vertices for Q */
98 fprintf(stderr
, "LL ");
101 fprintf(stderr
, "Not enough vertices\n");
102 return -1; /* need enough vertices for Q */
106 fprintf(stderr
, "T ");
107 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
109 fprintf(stderr
, "Not enough vertices\n");
110 return -1; /* need enough vertices for Q */
113 case GL_TRIANGLE_STRIP
:
114 fprintf(stderr
, "TS ");
115 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
117 fprintf(stderr
, "Not enough vertices\n");
118 return -1; /* need enough vertices for Q */
121 case GL_TRIANGLE_FAN
:
122 fprintf(stderr
, "TF ");
123 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
125 fprintf(stderr
, "Not enough vertices\n");
126 return -1; /* need enough vertices for Q */
130 fprintf(stderr
, "Q ");
131 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
133 fprintf(stderr
, "Not enough vertices\n");
134 return -1; /* need enough vertices for Q */
138 fprintf(stderr
, "QS ");
139 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
141 fprintf(stderr
, "Not enough vertices\n");
142 return -1; /* need enough vertices for Q */
146 fprintf(stderr
, "Cannot handle primitive %02x ", prim
& PRIM_MODE_MASK
);
155 /* Immediate implementation - vertex data is sent via command stream */
157 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
159 #define output_vector(v, i) \
162 for(_i=0;_i<v->size;_i++){ \
163 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
165 for(_i=v->size;_i<4;_i++){ \
166 efloat(default_vector[_i]); \
170 static void r300_render_flat_primitive(r300ContextPtr rmesa
,
176 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
177 struct vertex_buffer
*VB
= &tnl
->vb
;
182 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
186 start_immediate_packet(end
-start
, type
, 8);
188 for(i
=start
;i
<end
;i
++){
190 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
191 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
192 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
193 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
194 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
196 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
197 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
198 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
199 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
206 output_vector(VB
->ObjPtr
, i
);
208 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0]);
209 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1]);
210 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2]);
212 efloat(VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3]);
218 /* color components */
220 output_vector(VB
->ColorPtr
[0], i
);
222 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0]);
223 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1]);
224 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2]);
226 efloat(VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]);
235 static GLboolean
r300_run_flat_render(GLcontext
*ctx
,
236 struct tnl_pipeline_stage
*stage
)
238 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
239 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
240 struct vertex_buffer
*VB
= &tnl
->vb
;
242 AOS_DATA vb_arrays
[2];
245 if (RADEON_DEBUG
== DEBUG_PRIMS
)
246 fprintf(stderr
, "%s\n", __FUNCTION__
);
248 /* setup array of structures data */
250 /* Note: immediate vertex data includes all coordinates.
251 To save bandwidth use either VBUF or state-based vertex generation */
253 vb_arrays
[0].element_size
=4;
254 vb_arrays
[0].stride
=4;
255 vb_arrays
[0].offset
=0; /* Not used */
256 vb_arrays
[0].format
=AOS_FORMAT_FLOAT
;
257 vb_arrays
[0].ncomponents
=4;
258 vb_arrays
[0].reg
=REG_COORDS
;
261 vb_arrays
[1].element_size
=4;
262 vb_arrays
[1].stride
=4;
263 vb_arrays
[1].offset
=0; /* Not used */
264 vb_arrays
[1].format
=AOS_FORMAT_FLOAT_COLOR
;
265 vb_arrays
[1].ncomponents
=4;
266 vb_arrays
[1].reg
=REG_COLOR0
;
268 r300EmitState(rmesa
);
270 /* needed before starting 3d operation .. */
271 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
281 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
283 #if 0 /* Turn on for smooth color on teeth.. why ??.. */
284 set_cull_cntl(PASS_PREFIX
0);
286 reg_start(R300_RE_OCCLUSION_CNTL
, 0);
287 e32(R300_OCCLUSION_ON
);
289 // set_quad0(PASS_PREFIX 1.0,1.0,1.0,1.0);
290 set_init21(PASS_PREFIX
0.0,1.0);
292 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
293 setup_AOS(PASS_PREFIX vb_arrays
, 2);
295 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
296 GLuint prim
= VB
->Primitive
[i
].mode
;
297 GLuint start
= VB
->Primitive
[i
].start
;
298 GLuint length
= VB
->Primitive
[i
].count
;
299 r300_render_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
302 end_3d(PASS_PREFIX_VOID
);
304 fprintf(stderr
, "\n");
308 /* vertex buffer implementation */
310 /* We use the start part of GART texture buffer for vertices */
312 #define R300_MAX_AOS_ARRAYS 16
314 static void upload_vertex_buffer(r300ContextPtr rmesa
,
315 GLcontext
*ctx
, AOS_DATA
*array
, int *n_arrays
)
317 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
318 struct vertex_buffer
*VB
= &tnl
->vb
;
321 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
322 /* Not the most efficient implementation, but, for now, I just want something that
324 /* to do - make single memcpy per column (is it possible ?) */
325 /* to do - use dirty flags to avoid redundant copies */
326 #define UPLOAD_VECTOR(v, r, f)\
328 /* Is the data dirty ? */ \
329 if (v->flags & ((1<<v->size)-1)) { \
330 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
331 if(v->size*4==v->stride){\
333 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
335 for(i=0;i<VB->Count;i++){ \
336 /* copy one vertex at a time*/ \
337 memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \
340 /* v->flags &= ~((1<<v->size)-1);*/ \
342 array[idx].element_size=v->size; \
343 array[idx].stride=v->size; \
344 array[idx].format=(f); \
345 array[idx].ncomponents=v->size; \
346 array[idx].offset=rsp->gartTextures.handle+offset; \
348 offset+=v->size*4*VB->Count; \
350 /* Fill in the rest with the components of default_vector */\
353 array[idx].element_size=4-v->size; \
354 array[idx].stride=0; \
355 array[idx].format=(f); \
356 array[idx].ncomponents=4-v->size; \
357 array[idx].offset=rsp->gartTextures.handle+v->size*4;\
364 /* Put a copy of default vector */
365 memcpy(rsp
->gartTextures
.map
, default_vector
, 16);
368 UPLOAD_VECTOR(VB
->ObjPtr
, REG_COORDS
, AOS_FORMAT_FLOAT
);
369 UPLOAD_VECTOR(VB
->ColorPtr
[0], REG_COLOR0
, AOS_FORMAT_FLOAT_COLOR
);
372 if(idx
>=R300_MAX_AOS_ARRAYS
){
373 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
378 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa
,
384 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
385 struct vertex_buffer
*VB
= &tnl
->vb
;
387 int k
, type
, n_arrays
;
390 if(end
<=start
)return; /* do we need to watch for this ? */
392 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
395 fire_AOS(PASS_PREFIX end
-start
, type
);
398 static VERTEX_SHADER_FRAGMENT default_vector_vsf
={
401 f
: {0.0, 0.0, 0.0, 1.0}
405 static GLboolean
r300_run_vb_flat_render(GLcontext
*ctx
,
406 struct tnl_pipeline_stage
*stage
)
408 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
409 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
410 struct vertex_buffer
*VB
= &tnl
->vb
;
412 AOS_DATA vb_arrays
[R300_MAX_AOS_ARRAYS
];
413 AOS_DATA vb_arrays2
[R300_MAX_AOS_ARRAYS
];
416 if (RADEON_DEBUG
== DEBUG_PRIMS
)
417 fprintf(stderr
, "%s\n", __FUNCTION__
);
419 /* setup array of structures data */
421 upload_vertex_buffer(rmesa
, ctx
, vb_arrays
, &n_arrays
);
422 fprintf(stderr
, "Using %d AOS arrays\n", n_arrays
);
424 r300EmitState(rmesa
);
426 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
435 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
437 //upload_vertex_shader_fragment(PASS_PREFIX VSF_DEST_UNKNOWN1, &default_vector_vsf);
439 reg_start(R300_RE_OCCLUSION_CNTL
, 0);
440 e32(R300_OCCLUSION_ON
);
442 set_quad0(PASS_PREFIX
1.0,1.0,1.0,1.0);
443 set_init21(PASS_PREFIX
0.0,1.0);
445 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
446 GLuint prim
= VB
->Primitive
[i
].mode
;
447 GLuint start
= VB
->Primitive
[i
].start
;
448 GLuint length
= VB
->Primitive
[i
].count
;
451 memcpy(vb_arrays2
, vb_arrays
, sizeof(AOS_DATA
)*n_arrays
);
452 for(j
=0;j
<n_arrays
;j
++){
453 vb_arrays2
[j
].offset
+=vb_arrays2
[j
].stride
*start
;
456 setup_AOS(PASS_PREFIX vb_arrays2
, n_arrays
);
458 r300_render_vb_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
461 end_3d(PASS_PREFIX_VOID
);
463 /* Flush state - we are done drawing.. */
465 fprintf(stderr
, "\n");
470 * Called by the pipeline manager to render a batch of primitives.
471 * We can return true to pass on to the next stage (i.e. software
472 * rasterization) or false to indicate that the pipeline has finished
473 * after we render something.
475 static GLboolean
r300_run_render(GLcontext
*ctx
,
476 struct tnl_pipeline_stage
*stage
)
478 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
479 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
480 struct vertex_buffer
*VB
= &tnl
->vb
;
483 if (RADEON_DEBUG
== DEBUG_PRIMS
)
484 fprintf(stderr
, "%s\n", __FUNCTION__
);
486 return r300_run_flat_render(ctx
, stage
);
494 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
495 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
496 struct vertex_buffer
*VB
= &tnl
->vb
;
499 /* Don't handle clipping or indexed vertices or vertex manipulations.
501 if (mmesa
->RenderIndex
!= 0 ||
502 !mga_validate_render( ctx
, VB
)) {
506 tnl
->Driver
.Render
.Start( ctx
);
507 mmesa
->SetupNewInputs
= ~0;
509 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
511 GLuint prim
= VB
->Primitive
[i
].mode
;
512 GLuint start
= VB
->Primitive
[i
].start
;
513 GLuint length
= VB
->Primitive
[i
].count
;
518 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
522 tnl
->Driver
.Render
.Finish( ctx
);
524 return GL_FALSE
; /* finished the pipe */
530 * Called by the pipeline manager once before rendering.
531 * We check the GL state here to
532 * a) decide whether we can do the current state in hardware and
533 * b) update hardware registers
535 #define FALLBACK_IF(expr) \
538 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
539 fprintf(stderr, "%s: fallback:%s\n", \
540 __FUNCTION__, #expr); \
541 stage->active = GL_FALSE; \
546 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
548 r300ContextPtr r300
= R300_CONTEXT(ctx
);
551 if (RADEON_DEBUG
& DEBUG_STATE
)
552 fprintf(stderr
, "%s\n", __FUNCTION__
);
554 /* We only support rendering in hardware for now */
555 if (ctx
->RenderMode
!= GL_RENDER
) {
556 stage
->active
= GL_FALSE
;
560 // I failed to figure out how dither works in hardware,
561 // let's just ignore it for now
562 //FALLBACK_IF(ctx->Color.DitherFlag);
564 /* I'm almost certain I forgot something here */
565 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
566 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
567 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
568 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
569 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
570 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
571 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
572 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
573 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
574 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
575 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
576 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
577 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
578 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
579 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
581 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
582 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
585 /* let r300_run_render do its job */
587 stage
->active
= GL_FALSE
;
592 static void dtr(struct tnl_pipeline_stage
*stage
)
597 const struct tnl_pipeline_stage _r300_render_stage
= {
599 _NEW_ALL
, /* re-check (always re-check for now) */
600 0, /* re-run (always runs) */
601 GL_TRUE
, /* active */
602 0, 0, /* inputs (set in check_render), outputs */
603 0, 0, /* changed_inputs, private */
604 dtr
, /* destructor */
605 r300_check_render
, /* check */
606 r300_run_render
/* run */