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");
141 /* This function compiles GL context into state registers that
142 describe data routing inside of R300 pipeline.
144 In particular, it programs input_route, output_vtx_fmt, texture
145 unit configuration and gb_output_vtx_fmt
147 This function encompasses setup_AOS() from r300_lib.c
152 static void inline r300_setup_routing(r300ContextPtr r300
, GLcontext
*ctx
, GLboolean immediate
)
154 int i
, count
=0,reg
=0;
156 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
157 struct vertex_buffer
*VB
= &tnl
->vb
;
160 /* Stage 1 - input to VAP */
162 /* Assign register number automatically, retaining it in rmesa->state.reg */
164 /* Note: immediate vertex data includes all coordinates.
165 To save bandwidth use either VBUF or state-based vertex generation */
167 #define CONFIGURE_AOS(v, o, r, f) \
170 r300->state.aos[count].element_size=4; \
171 r300->state.aos[count].stride=4; \
172 r300->state.aos[count].ncomponents=4; \
174 r300->state.aos[count].element_size=v->size; \
175 r300->state.aos[count].stride=v->size; \
176 r300->state.aos[count].ncomponents=v->size; \
178 r300->state.aos[count].offset=o; \
179 r300->state.aos[count].reg=reg; \
180 r300->state.aos[count].format=(f); \
181 r300->state.vap_reg.r=reg; \
186 /* All offsets are 0 - for use by immediate mode.
187 Should change later to handle vertex buffers */
188 CONFIGURE_AOS(VB
->ObjPtr
, 0, i_coords
, AOS_FORMAT_FLOAT
);
189 CONFIGURE_AOS(VB
->ColorPtr
[0], 0, i_color
[0], AOS_FORMAT_FLOAT_COLOR
);
190 for(i
=0;i
< ctx
->Const
.MaxTextureUnits
;i
++)
191 if(ctx
->Texture
.Unit
[i
].Enabled
)
192 CONFIGURE_AOS(VB
->TexCoordPtr
[i
], 0, i_tex
[i
], AOS_FORMAT_FLOAT
);
194 r300
->state
.aos_count
=count
;
196 if(count
>R300_MAX_AOS_ARRAYS
){
197 fprintf(stderr
, "Aieee ! AOS array count exceeded !\n");
204 /* setup INPUT_ROUTE */
206 R300_STATECHANGE(r300
, vir
[0]);
207 for(i
=0;i
+1<count
;i
+=2){
208 dw
=(r300
->state
.aos
[i
].ncomponents
-1)
209 | ((r300
->state
.aos
[i
].reg
)<<8)
210 | (r300
->state
.aos
[i
].format
<<14)
211 | (((r300
->state
.aos
[i
+1].ncomponents
-1)
212 | ((r300
->state
.aos
[i
+1].reg
)<<8)
213 | (r300
->state
.aos
[i
+1].format
<<14))<<16);
218 r300
->hw
.vir
[0].cmd
[R300_VIR_CNTL_0
+(i
>>1)]=dw
;
221 dw
=(r300
->state
.aos
[count
-1].ncomponents
-1)
222 | (r300
->state
.aos
[count
-1].format
<<14)
223 | ((r300
->state
.aos
[count
-1].reg
)<<8)
225 r300
->hw
.vir
[0].cmd
[R300_VIR_CNTL_0
+(count
>>1)]=dw
;
227 /* Set the rest of INPUT_ROUTE_0 to 0 */
228 for(i
=((count
+1)>>1); i
<8; i
++)r300
->hw
.vir
[0].cmd
[R300_VIR_CNTL_0
+i
]=(0x0);
230 /* Mesa assumes that all missing components are from (0, 0, 0, 1) */
231 #define ALL_COMPONENTS ((R300_INPUT_ROUTE_SELECT_X<<R300_INPUT_ROUTE_X_SHIFT) \
232 | (R300_INPUT_ROUTE_SELECT_Y<<R300_INPUT_ROUTE_Y_SHIFT) \
233 | (R300_INPUT_ROUTE_SELECT_Z<<R300_INPUT_ROUTE_Z_SHIFT) \
234 | (R300_INPUT_ROUTE_SELECT_W<<R300_INPUT_ROUTE_W_SHIFT))
236 #define ALL_DEFAULT ((R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_X_SHIFT) \
237 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Y_SHIFT) \
238 | (R300_INPUT_ROUTE_SELECT_ZERO<<R300_INPUT_ROUTE_Z_SHIFT) \
239 | (R300_INPUT_ROUTE_SELECT_ONE<<R300_INPUT_ROUTE_W_SHIFT))
241 R300_STATECHANGE(r300
, vir
[1]);
243 for(i
=0;i
+1<count
;i
+=2){
245 mask
=(1<<(r300
->state
.aos
[i
].ncomponents
*3))-1;
246 dw
=(ALL_COMPONENTS
& mask
)
247 | (ALL_DEFAULT
& ~mask
)
248 | R300_INPUT_ROUTE_ENABLE
;
251 mask
=(1<<(r300
->state
.aos
[i
+1].ncomponents
*3))-1;
253 (ALL_COMPONENTS
& mask
)
254 | (ALL_DEFAULT
& ~mask
)
255 | R300_INPUT_ROUTE_ENABLE
258 r300
->hw
.vir
[1].cmd
[R300_VIR_CNTL_0
+(i
>>1)]=dw
;
261 mask
=(1<<(r300
->state
.aos
[count
-1].ncomponents
*3))-1;
262 dw
=(ALL_COMPONENTS
& mask
)
263 | (ALL_DEFAULT
& ~mask
)
264 | R300_INPUT_ROUTE_ENABLE
;
265 r300
->hw
.vir
[1].cmd
[R300_VIR_CNTL_0
+(count
>>1)]=dw
;
267 /* Set the rest of INPUT_ROUTE_1 to 0 */
268 for(i
=((count
+1)>>1); i
<8; i
++)r300
->hw
.vir
[1].cmd
[R300_VIR_CNTL_0
+i
]=(0x0);
270 /* Set up input_cntl */
272 R300_STATECHANGE(r300
, vic
);
273 r300
->hw
.vic
.cmd
[R300_VIC_CNTL_0
]=0x5555; /* Hard coded value, no idea what it means */
275 r300
->hw
.vic
.cmd
[R300_VIC_CNTL_1
]=R300_INPUT_CNTL_POS
276 | R300_INPUT_CNTL_COLOR
;
278 for(i
=0;i
< ctx
->Const
.MaxTextureUnits
;i
++)
279 if(ctx
->Texture
.Unit
[i
].Enabled
)
280 r300
->hw
.vic
.cmd
[R300_VIC_CNTL_1
]|=(R300_INPUT_CNTL_TC0
<<i
);
282 /* Stage 3: VAP output */
283 R300_STATECHANGE(r300
, vof
);
284 r300
->hw
.vof
.cmd
[R300_VOF_CNTL_0
]=R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
285 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT
;
287 r300
->hw
.vof
.cmd
[R300_VOF_CNTL_1
]=0;
288 for(i
=0;i
< ctx
->Const
.MaxTextureUnits
;i
++)
289 if(ctx
->Texture
.Unit
[i
].Enabled
)
290 r300
->hw
.vof
.cmd
[R300_VOF_CNTL_1
]|=(4<<(3*i
));
293 static inline void r300_setup_textures(r300ContextPtr r300
, GLcontext
*ctx
)
296 struct r300_tex_obj
*t
;
298 R300_STATECHANGE(r300
, txe
);
299 R300_STATECHANGE(r300
, tex
.filter
);
300 R300_STATECHANGE(r300
, tex
.unknown1
);
301 R300_STATECHANGE(r300
, tex
.size
);
302 R300_STATECHANGE(r300
, tex
.format
);
303 R300_STATECHANGE(r300
, tex
.offset
);
304 R300_STATECHANGE(r300
, tex
.unknown4
);
305 R300_STATECHANGE(r300
, tex
.unknown5
);
307 r300
->hw
.txe
.cmd
[R300_TXE_ENABLE
]=0x0;
309 for(i
=0;i
<R300_MAX_TEXTURE_UNITS
;i
++){
310 if((t
=r300
->state
.texture
.unit
[i
].texobj
)!=NULL
){
311 r300
->hw
.txe
.cmd
[R300_TXE_ENABLE
]|=(1<<i
);
313 r300
->hw
.tex
.filter
.cmd
[R300_TEX_CMD_0
+i
]=t
->filter
;
314 r300
->hw
.tex
.unknown1
.cmd
[R300_TEX_CMD_0
+i
]=t
->pitch
;
315 r300
->hw
.tex
.size
.cmd
[R300_TEX_CMD_0
+i
]=t
->size
;
316 r300
->hw
.tex
.format
.cmd
[R300_TEX_CMD_0
+i
]=t
->format
;
317 r300
->hw
.tex
.offset
.cmd
[R300_TEX_CMD_0
+i
]=r300
->radeon
.radeonScreen
->fbLocation
+t
->offset
;
318 r300
->hw
.tex
.unknown4
.cmd
[R300_TEX_CMD_0
+i
]=0x0;
319 r300
->hw
.tex
.unknown5
.cmd
[R300_TEX_CMD_0
+i
]=0x0;
321 /* We don't know how to set this yet */
322 r300
->hw
.tex
.format
.cmd
[R300_TEX_CMD_0
+i
]=0x88a0c;
327 /* Immediate implementation - vertex data is sent via command stream */
329 static GLfloat default_vector
[4]={0.0, 0.0, 0.0, 1.0};
331 #define output_vector(v, i) \
334 for(_i=0;_i<v->size;_i++){ \
335 efloat(VEC_ELT(v, GLfloat, i)[_i]); \
337 for(_i=v->size;_i<4;_i++){ \
338 efloat(default_vector[_i]); \
342 static void r300_render_flat_primitive(r300ContextPtr rmesa
,
348 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
349 struct vertex_buffer
*VB
= &tnl
->vb
;
354 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
359 start_immediate_packet(end
-start
, type
, 8);
361 for(i
=start
;i
<end
;i
++){
363 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
364 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
365 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
366 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
367 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
369 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
370 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
371 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
372 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
378 output_vector(VB
->ObjPtr
, i
);
380 /* color components */
381 output_vector(VB
->ColorPtr
[0], i
);
386 static void assign_pipeline(r300ContextPtr rmesa
, R300_PIPELINE
*p
)
388 /* Watch out ! This is buggy .. but will do for now */
390 /* At least one sanity check is in order */
391 if(sizeof(rmesa
->state
.vertex_shader
) != sizeof(p
->vertex_shader
)){
392 fprintf(stderr
, "Aieee ! vertex_shader sizes don't match.\n");
395 if(sizeof(rmesa
->state
.pixel_shader
) != sizeof(p
->pixel_shader
)){
396 fprintf(stderr
, "Aieee ! vertex_shader sizes don't match.\n");
400 memcpy(&rmesa
->state
.vertex_shader
, &(p
->vertex_shader
), sizeof(rmesa
->state
.vertex_shader
));
401 memcpy(&rmesa
->state
.pixel_shader
, &(p
->pixel_shader
), sizeof(rmesa
->state
.pixel_shader
));
405 static GLboolean
r300_run_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
;
414 /* Flush state - make sure command buffer is nice and large */
417 if (RADEON_DEBUG
== DEBUG_PRIMS
)
418 fprintf(stderr
, "%s\n", __FUNCTION__
);
420 /* needed before starting 3d operation .. */
421 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
427 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
428 | R300_VPORT_X_OFFSET_ENA
429 | R300_VPORT_Y_SCALE_ENA
430 | R300_VPORT_Y_OFFSET_ENA
432 R300_STATECHANGE(rmesa
, vte
);
434 r300_setup_routing(rmesa
, ctx
, GL_TRUE
);
435 r300_setup_textures(rmesa
, ctx
);
437 r300EmitState(rmesa
);
439 assign_pipeline(rmesa
, &FLAT_COLOR_PIPELINE
);
441 rmesa
->state
.vertex_shader
.matrix
[0].length
=16;
442 memcpy(rmesa
->state
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
444 rmesa
->state
.vertex_shader
.unknown2
.length
=4;
445 rmesa
->state
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
446 rmesa
->state
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
447 rmesa
->state
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
448 rmesa
->state
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
450 r300EmitVertexShader(rmesa
);
451 r300EmitPixelShader(rmesa
);
453 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
454 r300EmitLOAD_VBPNTR(rmesa
, 0);
456 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
457 GLuint prim
= VB
->Primitive
[i
].mode
;
458 GLuint start
= VB
->Primitive
[i
].start
;
459 GLuint length
= VB
->Primitive
[i
].count
;
460 r300_render_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
463 /* This sequence is required after any 3d drawing packet
464 I suspect it work arounds a bug (or deficiency) in hardware */
465 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
474 /* vertex buffer implementation */
476 /* We use the start part of GART texture buffer for vertices */
479 static void upload_vertex_buffer(r300ContextPtr rmesa
,
480 GLcontext
*ctx
, AOS_DATA
*array
, int *n_arrays
)
482 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
483 struct vertex_buffer
*VB
= &tnl
->vb
;
486 radeonScreenPtr rsp
=rmesa
->radeon
.radeonScreen
;
487 /* Not the most efficient implementation, but, for now, I just want something that
489 /* to do - make single memcpy per column (is it possible ?) */
490 /* to do - use dirty flags to avoid redundant copies */
491 #define UPLOAD_VECTOR(v, r, f)\
493 /* Is the data dirty ? */ \
494 if (v->flags & ((1<<v->size)-1)) { \
495 fprintf(stderr, "size=%d vs stride=%d\n", v->size, v->stride); \
496 if(v->size*4==v->stride){\
498 memcpy(rsp->gartTextures.map+offset, v->data, v->stride*VB->Count); \
500 for(i=0;i<VB->Count;i++){ \
501 /* copy one vertex at a time*/ \
502 memcpy(rsp->gartTextures.map+offset+i*v->size*4, VEC_ELT(v, GLfloat, i), v->size*4); \
505 /* v->flags &= ~((1<<v->size)-1);*/ \
507 array[idx].element_size=v->size; \
508 array[idx].stride=v->size; \
509 array[idx].format=(f); \
510 array[idx].ncomponents=v->size; \
511 array[idx].offset=rsp->gartTextures.handle+offset; \
513 offset+=v->size*4*VB->Count; \
517 UPLOAD_VECTOR(VB
->ObjPtr
, REG_COORDS
, AOS_FORMAT_FLOAT
);
518 UPLOAD_VECTOR(VB
->ColorPtr
[0], REG_COLOR0
, AOS_FORMAT_FLOAT_COLOR
);
521 if(idx
>=R300_MAX_AOS_ARRAYS
){
522 fprintf(stderr
, "Aieee ! Maximum AOS arrays count exceeded.. \n");
527 static void r300_render_vb_flat_primitive(r300ContextPtr rmesa
,
533 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
534 struct vertex_buffer
*VB
= &tnl
->vb
;
536 int k
, type
, n_arrays
;
539 if(end
<=start
)return; /* do we need to watch for this ? */
541 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
544 fire_AOS(PASS_PREFIX end
-start
, type
);
547 static VERTEX_SHADER_FRAGMENT default_vector_vsf
={
550 f
: {0.0, 0.0, 0.0, 1.0}
554 static GLboolean
r300_run_vb_flat_render(GLcontext
*ctx
,
555 struct tnl_pipeline_stage
*stage
)
557 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
558 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
559 struct vertex_buffer
*VB
= &tnl
->vb
;
561 AOS_DATA vb_arrays
[R300_MAX_AOS_ARRAYS
];
562 AOS_DATA vb_arrays2
[R300_MAX_AOS_ARRAYS
];
565 if (RADEON_DEBUG
== DEBUG_PRIMS
)
566 fprintf(stderr
, "%s\n", __FUNCTION__
);
568 /* setup array of structures data */
570 upload_vertex_buffer(rmesa
, ctx
, vb_arrays
, &n_arrays
);
571 fprintf(stderr
, "Using %d AOS arrays\n", n_arrays
);
573 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
579 r300_setup_routing(rmesa
, ctx
, GL_FALSE
);
581 r300EmitState(rmesa
);
583 FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
584 memcpy(FLAT_COLOR_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
586 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.length
=4;
587 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
588 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
589 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
590 FLAT_COLOR_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
592 program_pipeline(PASS_PREFIX
&FLAT_COLOR_PIPELINE
);
594 set_quad0(PASS_PREFIX
1.0,1.0,1.0,1.0);
595 set_init21(PASS_PREFIX
0.0,1.0);
597 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
598 GLuint prim
= VB
->Primitive
[i
].mode
;
599 GLuint start
= VB
->Primitive
[i
].start
;
600 GLuint length
= VB
->Primitive
[i
].count
;
603 memcpy(vb_arrays2
, vb_arrays
, sizeof(AOS_DATA
)*n_arrays
);
604 for(j
=0;j
<n_arrays
;j
++){
605 vb_arrays2
[j
].offset
+=vb_arrays2
[j
].stride
*start
*4;
608 setup_AOS(PASS_PREFIX vb_arrays2
, n_arrays
);
610 r300_render_vb_flat_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
613 /* This sequence is required after any 3d drawing packet
614 I suspect it work arounds a bug (or deficiency) in hardware */
616 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
622 end_3d(PASS_PREFIX_VOID
);
624 /* Flush state - we are done drawing.. */
626 fprintf(stderr
, "\n");
632 /* Immediate implementation - vertex data is sent via command stream */
634 static void r300_render_tex_primitive(r300ContextPtr rmesa
,
640 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
641 struct vertex_buffer
*VB
= &tnl
->vb
;
646 type
=r300_get_primitive_type(rmesa
, ctx
, start
, end
, prim
);
649 fprintf(stderr
,"ObjPtr: size=%d stride=%d\n",
650 VB
->ObjPtr
->size
, VB
->ObjPtr
->stride
);
651 fprintf(stderr
,"ColorPtr[0]: size=%d stride=%d\n",
652 VB
->ColorPtr
[0]->size
, VB
->ColorPtr
[0]->stride
);
653 fprintf(stderr
,"TexCoordPtr[0]: size=%d stride=%d\n",
654 VB
->TexCoordPtr
[0]->size
, VB
->TexCoordPtr
[0]->stride
);
660 start_immediate_packet(end
-start
, type
, 12);
662 for(i
=start
;i
<end
;i
++){
664 fprintf(stderr
, "* (%f %f %f %f) (%f %f %f %f)\n",
665 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[0],
666 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[1],
667 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[2],
668 VEC_ELT(VB
->ObjPtr
, GLfloat
, i
)[3],
670 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[0],
671 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[1],
672 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[2],
673 VEC_ELT(VB
->ColorPtr
[0], GLfloat
, i
)[3]
679 output_vector(VB
->ObjPtr
, i
);
681 /* color components */
682 output_vector(VB
->ColorPtr
[0], i
);
684 /* texture coordinates */
685 output_vector(VB
->TexCoordPtr
[0], i
);
690 static GLboolean
r300_run_tex_render(GLcontext
*ctx
,
691 struct tnl_pipeline_stage
*stage
)
693 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
694 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
695 struct vertex_buffer
*VB
= &tnl
->vb
;
697 /* Only do 2d textures */
698 struct gl_texture_object
*to
=ctx
->Texture
.Unit
[0].Current2D
;
699 r300TexObjPtr t
=to
->DriverData
;
703 /* Update texture state - needs to be done only when actually changed..
704 All the time for now.. */
705 r300UpdateTextureState(ctx
);
707 r300_setup_routing(rmesa
, ctx
, GL_TRUE
);
708 r300_setup_textures(rmesa
, ctx
);
711 /* Flush state - make sure command buffer is nice and large */
714 //fprintf(stderr, "You can enable texture drawing in %s:%s \n", __FILE__, __FUNCTION__);
718 if (RADEON_DEBUG
== DEBUG_PRIMS
)
719 fprintf(stderr
, "%s\n", __FUNCTION__
);
722 /* needed before starting 3d operation .. */
723 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
730 rmesa
->hw
.vte
.cmd
[1] = R300_VPORT_X_SCALE_ENA
731 | R300_VPORT_X_OFFSET_ENA
732 | R300_VPORT_Y_SCALE_ENA
733 | R300_VPORT_Y_OFFSET_ENA
735 R300_STATECHANGE(rmesa
, vte
);
737 r300EmitState(rmesa
);
739 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.matrix
[0].length
=16;
740 memcpy(SINGLE_TEXTURE_PIPELINE
.vertex_shader
.matrix
[0].body
.f
, ctx
->_ModelProjectMatrix
.m
, 16*4);
742 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.length
=4;
743 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[0]=0.0;
744 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[1]=0.0;
745 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[2]=1.0;
746 SINGLE_TEXTURE_PIPELINE
.vertex_shader
.unknown2
.body
.f
[3]=0.0;
748 /* Use actual texture offset */
750 fprintf(stderr
,"pp_border_color=%08x pp_cubic_faces=%08x format=%08x size=%08x format_x=%08x\n",
751 t
->pp_border_color
, t
->pp_cubic_faces
, t
->format
, t
->size
, t
->format_x
);
753 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].offset
=rmesa
->radeon
.radeonScreen
->fbLocation
+t
->offset
;
755 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].format
=t
->format
;
757 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].size
=t
->size
;
758 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].filter
=t
->filter
;
759 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].unknown1
=t
->pitch
; /* Unknown 1 is pitch ! */
760 SINGLE_TEXTURE_PIPELINE
.texture_unit
[0].filter
=t
->filter
;
763 /* Program RS unit. This needs to be moved into R300 pipeline */
764 reg_start(R300_RS_CNTL_0
,1);
765 /* R300_RS_CNTL_0(4300) */
767 /* RS_INST_COUNT(4304) */
770 reg_start(R300_RS_ROUTE_0
,0);
773 reg_start(R300_RS_INTERP_0
,7);
791 reg_start(R300_RS_CNTL_0
,0);
794 /* Magic register - note it is right after 20b0 */
799 program_pipeline(PASS_PREFIX
&SINGLE_TEXTURE_PIPELINE
);
801 /* We need LOAD_VBPNTR to setup AOS_ATTR fields.. the offsets are irrelevant */
802 r300EmitLOAD_VBPNTR(rmesa
, 0);
804 for(i
=0; i
< VB
->PrimitiveCount
; i
++){
805 GLuint prim
= VB
->Primitive
[i
].mode
;
806 GLuint start
= VB
->Primitive
[i
].start
;
807 GLuint length
= VB
->Primitive
[i
].count
;
808 r300_render_tex_primitive(rmesa
, ctx
, start
, start
+ length
, prim
);
811 /* This sequence is required after any 3d drawing packet
812 I suspect it work arounds a bug (or deficiency) in hardware */
814 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
,0);
821 fprintf(stderr
, "\n");
827 * Called by the pipeline manager to render a batch of primitives.
828 * We can return true to pass on to the next stage (i.e. software
829 * rasterization) or false to indicate that the pipeline has finished
830 * after we render something.
832 static GLboolean
r300_run_render(GLcontext
*ctx
,
833 struct tnl_pipeline_stage
*stage
)
835 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
836 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
837 struct vertex_buffer
*VB
= &tnl
->vb
;
840 if (RADEON_DEBUG
== DEBUG_PRIMS
)
841 fprintf(stderr
, "%s\n", __FUNCTION__
);
845 /* Just switch between pipelines.. We could possibly do better.. (?) */
846 if(ctx
->Texture
.Unit
[0].Enabled
)
847 return r300_run_tex_render(ctx
, stage
);
849 return r300_run_flat_render(ctx
, stage
);
855 mgaContextPtr mmesa
= MGA_CONTEXT(ctx
);
856 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
857 struct vertex_buffer
*VB
= &tnl
->vb
;
860 /* Don't handle clipping or indexed vertices or vertex manipulations.
862 if (mmesa
->RenderIndex
!= 0 ||
863 !mga_validate_render( ctx
, VB
)) {
867 tnl
->Driver
.Render
.Start( ctx
);
868 mmesa
->SetupNewInputs
= ~0;
870 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
872 GLuint prim
= VB
->Primitive
[i
].mode
;
873 GLuint start
= VB
->Primitive
[i
].start
;
874 GLuint length
= VB
->Primitive
[i
].count
;
879 mga_render_tab_verts
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
,
883 tnl
->Driver
.Render
.Finish( ctx
);
885 return GL_FALSE
; /* finished the pipe */
891 * Called by the pipeline manager once before rendering.
892 * We check the GL state here to
893 * a) decide whether we can do the current state in hardware and
894 * b) update hardware registers
896 #define FALLBACK_IF(expr) \
899 if (RADEON_DEBUG & DEBUG_FALLBACKS) \
900 fprintf(stderr, "%s: fallback:%s\n", \
901 __FUNCTION__, #expr); \
902 stage->active = GL_FALSE; \
907 static void r300_check_render(GLcontext
*ctx
, struct tnl_pipeline_stage
*stage
)
909 r300ContextPtr r300
= R300_CONTEXT(ctx
);
912 if (RADEON_DEBUG
& DEBUG_STATE
)
913 fprintf(stderr
, "%s\n", __FUNCTION__
);
915 /* We only support rendering in hardware for now */
916 if (ctx
->RenderMode
!= GL_RENDER
) {
917 stage
->active
= GL_FALSE
;
921 // I failed to figure out how dither works in hardware,
922 // let's just ignore it for now
923 //FALLBACK_IF(ctx->Color.DitherFlag);
925 /* I'm almost certain I forgot something here */
926 #if 0 /* This should work now.. */
927 FALLBACK_IF(ctx
->Color
.AlphaEnabled
); // GL_ALPHA_TEST
929 FALLBACK_IF(ctx
->Color
.BlendEnabled
); // GL_BLEND
930 FALLBACK_IF(ctx
->Fog
.Enabled
); // GL_FOG
931 FALLBACK_IF(ctx
->Line
.SmoothFlag
); // GL_LINE_SMOOTH
932 FALLBACK_IF(ctx
->Line
.StippleFlag
); // GL_LINE_STIPPLE
933 FALLBACK_IF(ctx
->Point
.SmoothFlag
); // GL_POINT_SMOOTH
934 if (ctx
->Extensions
.NV_point_sprite
|| ctx
->Extensions
.ARB_point_sprite
)
935 FALLBACK_IF(ctx
->Point
.PointSprite
); // GL_POINT_SPRITE_NV
936 FALLBACK_IF(ctx
->Polygon
.OffsetPoint
); // GL_POLYGON_OFFSET_POINT
937 FALLBACK_IF(ctx
->Polygon
.OffsetLine
); // GL_POLYGON_OFFSET_LINE
938 FALLBACK_IF(ctx
->Polygon
.OffsetFill
); // GL_POLYGON_OFFSET_FILL
939 FALLBACK_IF(ctx
->Polygon
.SmoothFlag
); // GL_POLYGON_SMOOTH
940 FALLBACK_IF(ctx
->Polygon
.StippleFlag
); // GL_POLYGON_STIPPLE
941 FALLBACK_IF(ctx
->Stencil
.Enabled
); // GL_STENCIL_TEST
942 FALLBACK_IF(ctx
->Multisample
.Enabled
); // GL_MULTISAMPLE_ARB
944 /* One step at a time - let one texture pass.. */
945 for (i
= 1; i
< ctx
->Const
.MaxTextureUnits
; i
++)
946 FALLBACK_IF(ctx
->Texture
.Unit
[i
].Enabled
);
949 /* let r300_run_render do its job */
951 stage
->active
= GL_FALSE
;
956 static void dtr(struct tnl_pipeline_stage
*stage
)
961 const struct tnl_pipeline_stage _r300_render_stage
= {
963 _NEW_ALL
, /* re-check (always re-check for now) */
964 0, /* re-run (always runs) */
965 GL_TRUE
, /* active */
966 0, 0, /* inputs (set in check_render), outputs */
967 0, 0, /* changed_inputs, private */
968 dtr
, /* destructor */
969 r300_check_render
, /* check */
970 r300_run_render
/* run */