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
;
75 int type
=-1, min_vertices
=0;
78 if(end
<=start
)return -1; /* do we need to watch for this ? */
80 switch (prim
& PRIM_MODE_MASK
) {
83 type
=R300_VAP_VF_CNTL__PRIM_POINTS
;
88 type
=R300_VAP_VF_CNTL__PRIM_LINES
;
93 type
=R300_VAP_VF_CNTL__PRIM_LINE_STRIP
;
103 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLES
;
106 case GL_TRIANGLE_STRIP
:
108 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP
;
111 case GL_TRIANGLE_FAN
:
113 type
=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN
;
118 type
=R300_VAP_VF_CNTL__PRIM_QUADS
;
123 type
=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP
;
127 fprintf(stderr
, "Cannot handle primitive %02x ", prim
& PRIM_MODE_MASK
);
132 fprintf(stderr
, "[%d-%d]%s ", start
, end
, name
);
134 if(start
+min_vertices
>=end
){
135 fprintf(stderr
, "Not enough vertices\n");
143 /* Immediate implementation - vertex data is sent via command stream */
145 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
147 #define output_vector(v, i) \
150 for(_i=0;_i<v->size;_i++){ \
151 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
153 for(_i=v->size;_i<4;_i++){ \
154 efloat(default_vector[_i]); \
158 static void r300_render_flat_primitive(r300ContextPtr rmesa
,
164 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
165 struct vertex_buffer
*VB
= &tnl
->vb
;
170 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
174 start_immediate_packet(end
-start
, type
, 8);
176 for(i
=start
;i
<end
;i
++){
178 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
179 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
180 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
181 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
182 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
184 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
185 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
186 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
187 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
193 output_vector(VB
->ObjPtr
, i
);
195 /* color components */
196 output_vector(VB
->ColorPtr
[0], i
);
201 static GLboolean
r300_run_flat_render(GLcontext
*ctx
,
202 struct tnl_pipeline_stage
*stage
)
204 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
205 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
206 struct vertex_buffer
*VB
= &tnl
->vb
;
208 AOS_DATA vb_arrays
[2];
211 if (RADEON_DEBUG
== DEBUG_PRIMS
)
212 fprintf(stderr
, "%s\n", __FUNCTION__
);
214 /* setup array of structures data */
216 /* Note: immediate vertex data includes all coordinates.
217 To save bandwidth use either VBUF or state-based vertex generation */
219 vb_arrays
[0].element_size
=4;
220 vb_arrays
[0].stride
=4;
221 vb_arrays
[0].offset
=0; /* Not used */
222 vb_arrays
[0].format
=AOS_FORMAT_FLOAT
;
223 vb_arrays
[0].ncomponents
=4;
224 vb_arrays
[0].reg
=REG_COORDS
;
227 vb_arrays
[1].element_size
=4;
228 vb_arrays
[1].stride
=4;
229 vb_arrays
[1].offset
=0; /* Not used */
230 vb_arrays
[1].format
=AOS_FORMAT_FLOAT_COLOR
;
231 vb_arrays
[1].ncomponents
=4;
232 vb_arrays
[1].reg
=REG_COLOR0
;
235 /* needed before starting 3d operation .. */
236 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
242 r300EmitState(rmesa
);
247 FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
248 memcpy(FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
250 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.length
=4;
251 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
252 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
253 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
254 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
256 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
258 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
259 setup_AOS(PASS_PREFIX vb_arrays
, 2);
261 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
262 GLuint prim
= VB
->Primitive
[i
].mode
;
263 GLuint start
= VB
->Primitive
[i
].start
;
264 GLuint length
= VB
->Primitive
[i
].count
;
265 r300_render_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
268 end_3d(PASS_PREFIX_VOID
);
270 fprintf(stderr
, "\n");
274 /* vertex buffer implementation */
276 /* We use the start part of GART texture buffer for vertices */
278 #define R300_MAX_AOS_ARRAYS 16
280 static void upload_vertex_buffer(r300ContextPtr rmesa
,
281 GLcontext
*ctx
, AOS_DATA
*array
, int *n_arrays
)
283 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
284 struct vertex_buffer
*VB
= &tnl
->vb
;
287 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
288 /* Not the most efficient implementation, but, for now, I just want something that
290 /* to do - make single memcpy per column (is it possible ?) */
291 /* to do - use dirty flags to avoid redundant copies */
292 #define UPLOAD_VECTOR(v, r, f)\
294 /* Is the data dirty ? */ \
295 if (v->flags & ((1<<v->size)-1)) { \
296 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
297 if(v->size*4==v->stride){\
299 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
301 for(i=0;i<VB->Count;i++){ \
302 /* copy one vertex at a time*/ \
303 memcpy(rsp->gartTextures.map+offset, VEC_ELT(v, GLfloat, i), v->size*4); \
306 /* v->flags &= ~((1<<v->size)-1);*/ \
308 array[idx].element_size=v->size; \
309 array[idx].stride=v->size; \
310 array[idx].format=(f); \
311 array[idx].ncomponents=v->size; \
312 array[idx].offset=rsp->gartTextures.handle+offset; \
314 offset+=v->size*4*VB->Count; \
316 /* Fill in the rest with the components of default_vector */\
319 array[idx].element_size=4-v->size; \
320 array[idx].stride=0; \
321 array[idx].format=(f); \
322 array[idx].ncomponents=4-v->size; \
323 array[idx].offset=rsp->gartTextures.handle+v->size*4;\
330 /* Put a copy of default vector */
331 memcpy(rsp
->gartTextures
.map
, default_vector
, 16);
334 UPLOAD_VECTOR(VB
->ObjPtr
, REG_COORDS
, AOS_FORMAT_FLOAT
);
335 UPLOAD_VECTOR(VB
->ColorPtr
[0], REG_COLOR0
, AOS_FORMAT_FLOAT_COLOR
);
338 if(idx
>=R300_MAX_AOS_ARRAYS
){
339 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
344 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa
,
350 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
351 struct vertex_buffer
*VB
= &tnl
->vb
;
353 int k
, type
, n_arrays
;
356 if(end
<=start
)return; /* do we need to watch for this ? */
358 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
361 fire_AOS(PASS_PREFIX end
-start
, type
);
364 static VERTEX_SHADER_FRAGMENT default_vector_vsf
={
367 f
: {0.0, 0.0, 0.0, 1.0}
371 static GLboolean
r300_run_vb_flat_render(GLcontext
*ctx
,
372 struct tnl_pipeline_stage
*stage
)
374 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
375 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
376 struct vertex_buffer
*VB
= &tnl
->vb
;
378 AOS_DATA vb_arrays
[R300_MAX_AOS_ARRAYS
];
379 AOS_DATA vb_arrays2
[R300_MAX_AOS_ARRAYS
];
382 if (RADEON_DEBUG
== DEBUG_PRIMS
)
383 fprintf(stderr
, "%s\n", __FUNCTION__
);
385 /* setup array of structures data */
387 upload_vertex_buffer(rmesa
, ctx
, vb_arrays
, &n_arrays
);
388 fprintf(stderr
, "Using %d AOS arrays\n", n_arrays
);
390 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
396 r300EmitState(rmesa
);
401 FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
402 memcpy(FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
404 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.length
=4;
405 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
406 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
407 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
408 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
410 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
412 reg_start(R300_RE_OCCLUSION_CNTL
, 0);
413 e32(R300_OCCLUSION_ON
);
415 set_quad0(PASS_PREFIX
1.0,1.0,1.0,1.0);
416 set_init21(PASS_PREFIX
0.0,1.0);
418 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
419 GLuint prim
= VB
->Primitive
[i
].mode
;
420 GLuint start
= VB
->Primitive
[i
].start
;
421 GLuint length
= VB
->Primitive
[i
].count
;
424 memcpy(vb_arrays2
, vb_arrays
, sizeof(AOS_DATA
)*n_arrays
);
425 for(j
=0;j
<n_arrays
;j
++){
426 vb_arrays2
[j
].offset
+=vb_arrays2
[j
].stride
*start
;
429 setup_AOS(PASS_PREFIX vb_arrays2
, n_arrays
);
431 r300_render_vb_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
434 end_3d(PASS_PREFIX_VOID
);
436 /* Flush state - we are done drawing.. */
438 fprintf(stderr
, "\n");
443 * Called by the pipeline manager to render a batch of primitives.
444 * We can return true to pass on to the next stage (i.e. software
445 * rasterization) or false to indicate that the pipeline has finished
446 * after we render something.
448 static GLboolean
r300_run_render(GLcontext
*ctx
,
449 struct tnl_pipeline_stage
*stage
)
451 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
452 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
453 struct vertex_buffer
*VB
= &tnl
->vb
;
456 if (RADEON_DEBUG
== DEBUG_PRIMS
)
457 fprintf(stderr
, "%s\n", __FUNCTION__
);
460 return r300_run_flat_render(ctx
, stage
);
466 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
467 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
468 struct vertex_buffer
*VB
= &tnl
->vb
;
471 /* Don't handle clipping or indexed vertices or vertex manipulations.
473 if (mmesa
->RenderIndex
!= 0 ||
474 !mga_validate_render( ctx
, VB
)) {
478 tnl
->Driver
.Render
.Start( ctx
);
479 mmesa
->SetupNewInputs
= ~0;
481 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
483 GLuint prim
= VB
->Primitive
[i
].mode
;
484 GLuint start
= VB
->Primitive
[i
].start
;
485 GLuint length
= VB
->Primitive
[i
].count
;
490 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
494 tnl
->Driver
.Render
.Finish( ctx
);
496 return GL_FALSE
; /* finished the pipe */
502 * Called by the pipeline manager once before rendering.
503 * We check the GL state here to
504 * a) decide whether we can do the current state in hardware and
505 * b) update hardware registers
507 #define FALLBACK_IF(expr) \
510 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
511 fprintf(stderr, "%s: fallback:%s\n", \
512 __FUNCTION__, #expr); \
513 stage->active = GL_FALSE; \
518 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
520 r300ContextPtr r300
= R300_CONTEXT(ctx
);
523 if (RADEON_DEBUG
& DEBUG_STATE
)
524 fprintf(stderr
, "%s\n", __FUNCTION__
);
526 /* We only support rendering in hardware for now */
527 if (ctx
->RenderMode
!= GL_RENDER
) {
528 stage
->active
= GL_FALSE
;
532 // I failed to figure out how dither works in hardware,
533 // let's just ignore it for now
534 //FALLBACK_IF(ctx->Color.DitherFlag);
536 /* I'm almost certain I forgot something here */
537 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
538 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
539 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
540 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
541 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
542 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
543 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
544 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
545 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
546 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
547 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
548 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
549 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
550 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
551 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
553 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
554 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
557 /* let r300_run_render do its job */
559 stage
->active
= GL_FALSE
;
564 static void dtr(struct tnl_pipeline_stage
*stage
)
569 const struct tnl_pipeline_stage _r300_render_stage
= {
571 _NEW_ALL
, /* re-check (always re-check for now) */
572 0, /* re-run (always runs) */
573 GL_TRUE
, /* active */
574 0, 0, /* inputs (set in check_render), outputs */
575 0, 0, /* changed_inputs, private */
576 dtr
, /* destructor */
577 r300_check_render
, /* check */
578 r300_run_render
/* run */