2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
33 * \author Keith Whitwell <keith@tungstengraphics.com>
43 #include "swrast_setup/swrast_setup.h"
44 #include "math/m_translate.h"
46 #include "tnl/t_context.h"
48 #include "r300_context.h"
49 #include "radeon_ioctl.h"
50 #include "r300_state.h"
51 #include "r300_emit.h"
52 #include "r300_ioctl.h"
58 #if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
59 SWIZZLE_Y != R300_INPUT_ROUTE_SELECT_Y || \
60 SWIZZLE_Z != R300_INPUT_ROUTE_SELECT_Z || \
61 SWIZZLE_W != R300_INPUT_ROUTE_SELECT_W || \
62 SWIZZLE_ZERO != R300_INPUT_ROUTE_SELECT_ZERO || \
63 SWIZZLE_ONE != R300_INPUT_ROUTE_SELECT_ONE
64 #error Cannot change these!
67 #define DEBUG_ALL DEBUG_VERTS
69 #if defined(USE_X86_ASM)
70 #define COPY_DWORDS( dst, src, nr ) \
73 __asm__ __volatile__( "rep ; movsl" \
74 : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
80 #define COPY_DWORDS( dst, src, nr ) \
83 for ( j = 0 ; j < nr ; j++ ) \
84 dst[j] = ((int *)src)[j]; \
89 static void r300EmitVec4(GLcontext
* ctx
, struct r300_dma_region
*rvb
,
90 GLvoid
* data
, int stride
, int count
)
93 int *out
= (int *)(rvb
->address
+ rvb
->start
);
95 if (RADEON_DEBUG
& DEBUG_VERTS
)
96 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
97 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
100 COPY_DWORDS(out
, data
, count
);
102 for (i
= 0; i
< count
; i
++) {
103 out
[0] = *(int *)data
;
109 static void r300EmitVec8(GLcontext
* ctx
, struct r300_dma_region
*rvb
,
110 GLvoid
* data
, int stride
, int count
)
113 int *out
= (int *)(rvb
->address
+ rvb
->start
);
115 if (RADEON_DEBUG
& DEBUG_VERTS
)
116 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
117 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
120 COPY_DWORDS(out
, data
, count
* 2);
122 for (i
= 0; i
< count
; i
++) {
123 out
[0] = *(int *)data
;
124 out
[1] = *(int *)(data
+ 4);
130 static void r300EmitVec12(GLcontext
* ctx
, struct r300_dma_region
*rvb
,
131 GLvoid
* data
, int stride
, int count
)
134 int *out
= (int *)(rvb
->address
+ rvb
->start
);
136 if (RADEON_DEBUG
& DEBUG_VERTS
)
137 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
138 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
141 COPY_DWORDS(out
, data
, count
* 3);
143 for (i
= 0; i
< count
; i
++) {
144 out
[0] = *(int *)data
;
145 out
[1] = *(int *)(data
+ 4);
146 out
[2] = *(int *)(data
+ 8);
152 static void r300EmitVec16(GLcontext
* ctx
, struct r300_dma_region
*rvb
,
153 GLvoid
* data
, int stride
, int count
)
156 int *out
= (int *)(rvb
->address
+ rvb
->start
);
158 if (RADEON_DEBUG
& DEBUG_VERTS
)
159 fprintf(stderr
, "%s count %d stride %d out %p data %p\n",
160 __FUNCTION__
, count
, stride
, (void *)out
, (void *)data
);
163 COPY_DWORDS(out
, data
, count
* 4);
165 for (i
= 0; i
< count
; i
++) {
166 out
[0] = *(int *)data
;
167 out
[1] = *(int *)(data
+ 4);
168 out
[2] = *(int *)(data
+ 8);
169 out
[3] = *(int *)(data
+ 12);
175 static void r300EmitVec(GLcontext
* ctx
, struct r300_dma_region
*rvb
,
176 GLvoid
* data
, int size
, int stride
, int count
)
178 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
181 r300AllocDmaRegion(rmesa
, rvb
, size
* 4, 4);
183 rvb
->aos_offset
= GET_START(rvb
);
186 r300AllocDmaRegion(rmesa
, rvb
, size
* count
* 4, 4);
187 rvb
->aos_offset
= GET_START(rvb
);
188 rvb
->aos_stride
= size
;
193 r300EmitVec4(ctx
, rvb
, data
, stride
, count
);
196 r300EmitVec8(ctx
, rvb
, data
, stride
, count
);
199 r300EmitVec12(ctx
, rvb
, data
, stride
, count
);
202 r300EmitVec16(ctx
, rvb
, data
, stride
, count
);
210 static GLuint
r300VAPInputRoute0(uint32_t * dst
, GLvector4f
** attribptr
,
211 int *inputs
, GLint
* tab
, GLuint nr
)
215 /* type, inputs, stop bit, size */
216 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
217 dw
= R300_INPUT_ROUTE_FLOAT
| (inputs
[tab
[i
]] << 8) | (attribptr
[tab
[i
]]->size
- 1);
218 dw
|= (R300_INPUT_ROUTE_FLOAT
| (inputs
[tab
[i
+ 1]] << 8) | (attribptr
[tab
[i
+ 1]]->size
- 1)) << 16;
220 dw
|= (R300_VAP_INPUT_ROUTE_END
<< 16);
226 dw
= R300_INPUT_ROUTE_FLOAT
| (inputs
[tab
[nr
- 1]] << 8) | (attribptr
[tab
[nr
- 1]]->size
- 1);
227 dw
|= R300_VAP_INPUT_ROUTE_END
;
231 return (nr
+ 1) >> 1;
234 static GLuint
r300VAPInputRoute1Swizzle(int swizzle
[4])
236 return (swizzle
[0] << R300_INPUT_ROUTE_X_SHIFT
) |
237 (swizzle
[1] << R300_INPUT_ROUTE_Y_SHIFT
) |
238 (swizzle
[2] << R300_INPUT_ROUTE_Z_SHIFT
) |
239 (swizzle
[3] << R300_INPUT_ROUTE_W_SHIFT
);
242 GLuint
r300VAPInputRoute1(uint32_t * dst
, int swizzle
[][4], GLuint nr
)
246 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
247 dst
[i
>> 1] = r300VAPInputRoute1Swizzle(swizzle
[i
]) | R300_INPUT_ROUTE_ENABLE
;
248 dst
[i
>> 1] |= (r300VAPInputRoute1Swizzle(swizzle
[i
+ 1]) | R300_INPUT_ROUTE_ENABLE
) << 16;
252 dst
[nr
>> 1] = r300VAPInputRoute1Swizzle(swizzle
[nr
- 1]) | R300_INPUT_ROUTE_ENABLE
;
255 return (nr
+ 1) >> 1;
258 GLuint
r300VAPInputCntl0(GLcontext
* ctx
, GLuint InputsRead
)
260 /* No idea what this value means. I have seen other values written to
261 * this register... */
265 GLuint
r300VAPInputCntl1(GLcontext
* ctx
, GLuint InputsRead
)
267 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
270 if (InputsRead
& (1 << VERT_ATTRIB_POS
))
271 vic_1
|= R300_INPUT_CNTL_POS
;
273 if (InputsRead
& (1 << VERT_ATTRIB_NORMAL
))
274 vic_1
|= R300_INPUT_CNTL_NORMAL
;
276 if (InputsRead
& (1 << VERT_ATTRIB_COLOR0
))
277 vic_1
|= R300_INPUT_CNTL_COLOR
;
279 rmesa
->state
.texture
.tc_count
= 0;
280 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++)
281 if (InputsRead
& (1 << (VERT_ATTRIB_TEX0
+ i
))) {
282 rmesa
->state
.texture
.tc_count
++;
283 vic_1
|= R300_INPUT_CNTL_TC0
<< i
;
289 GLuint
r300VAPOutputCntl0(GLcontext
* ctx
, GLuint OutputsWritten
)
293 if (OutputsWritten
& (1 << VERT_RESULT_HPOS
))
294 ret
|= R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
;
296 if (OutputsWritten
& (1 << VERT_RESULT_COL0
))
297 ret
|= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT
;
299 if (OutputsWritten
& (1 << VERT_RESULT_COL1
))
300 ret
|= R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT
;
302 if (OutputsWritten
& (1 << VERT_RESULT_BFC0
)
303 || OutputsWritten
& (1 << VERT_RESULT_BFC1
))
305 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_1_PRESENT
|
306 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_2_PRESENT
|
307 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_3_PRESENT
;
310 if (OutputsWritten
& (1 << VERT_RESULT_FOGC
)) ;
313 if (OutputsWritten
& (1 << VERT_RESULT_PSIZ
))
314 ret
|= R300_VAP_OUTPUT_VTX_FMT_0__PT_SIZE_PRESENT
;
319 GLuint
r300VAPOutputCntl1(GLcontext
* ctx
, GLuint OutputsWritten
)
323 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
324 if (OutputsWritten
& (1 << (VERT_RESULT_TEX0
+ i
))) {
325 ret
|= (4 << (3 * i
));
332 /* Emit vertex data to GART memory
333 * Route inputs to the vertex processor
334 * This function should never return R300_FALLBACK_TCL when using software tcl.
336 int r300EmitArrays(GLcontext
* ctx
)
338 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
339 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
340 struct vertex_buffer
*vb
= &tnl
->vb
;
342 GLuint count
= vb
->Count
;
344 GLuint InputsRead
= 0, OutputsWritten
= 0;
346 int vir_inputs
[VERT_ATTRIB_MAX
];
347 GLint tab
[VERT_ATTRIB_MAX
];
348 int swizzle
[VERT_ATTRIB_MAX
][4];
349 struct r300_vertex_program
*prog
=
350 (struct r300_vertex_program
*)CURRENT_VERTEX_SHADER(ctx
);
353 inputs
= prog
->inputs
;
354 InputsRead
= prog
->key
.InputsRead
;
355 OutputsWritten
= prog
->key
.OutputsWritten
;
357 inputs
= rmesa
->state
.sw_tcl_inputs
;
359 DECLARE_RENDERINPUTS(render_inputs_bitset
);
360 RENDERINPUTS_COPY(render_inputs_bitset
, tnl
->render_inputs_bitset
);
362 vb
->AttribPtr
[VERT_ATTRIB_POS
] = vb
->ClipPtr
;
364 assert(RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_POS
));
365 assert(RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_NORMAL
) == 0);
366 //assert(RENDERINPUTS_TEST(render_inputs_bitset, _TNL_ATTRIB_COLOR0));
368 if (RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_POS
)) {
369 InputsRead
|= 1 << VERT_ATTRIB_POS
;
370 OutputsWritten
|= 1 << VERT_RESULT_HPOS
;
373 if (RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_COLOR0
)) {
374 InputsRead
|= 1 << VERT_ATTRIB_COLOR0
;
375 OutputsWritten
|= 1 << VERT_RESULT_COL0
;
378 if (RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_COLOR1
)) {
379 InputsRead
|= 1 << VERT_ATTRIB_COLOR1
;
380 OutputsWritten
|= 1 << VERT_RESULT_COL1
;
383 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
384 if (RENDERINPUTS_TEST(render_inputs_bitset
, _TNL_ATTRIB_TEX(i
))) {
385 InputsRead
|= 1 << (VERT_ATTRIB_TEX0
+ i
);
386 OutputsWritten
|= 1 << (VERT_RESULT_TEX0
+ i
);
390 for (i
= 0, nr
= 0; i
< VERT_ATTRIB_MAX
; i
++) {
391 if (InputsRead
& (1 << i
)) {
398 /* Fixed, apply to vir0 only */
399 memcpy(vir_inputs
, inputs
, VERT_ATTRIB_MAX
* sizeof(int));
401 if (InputsRead
& VERT_ATTRIB_POS
)
402 inputs
[VERT_ATTRIB_POS
] = 0;
403 if (InputsRead
& (1 << VERT_ATTRIB_COLOR0
))
404 inputs
[VERT_ATTRIB_COLOR0
] = 2;
405 if (InputsRead
& (1 << VERT_ATTRIB_COLOR1
))
406 inputs
[VERT_ATTRIB_COLOR1
] = 3;
407 for (i
= VERT_ATTRIB_TEX0
; i
<= VERT_ATTRIB_TEX7
; i
++)
408 if (InputsRead
& (1 << i
))
409 inputs
[i
] = 6 + (i
- VERT_ATTRIB_TEX0
);
411 RENDERINPUTS_COPY(rmesa
->state
.render_inputs_bitset
, render_inputs_bitset
);
415 assert(OutputsWritten
);
417 for (i
= 0, nr
= 0; i
< VERT_ATTRIB_MAX
; i
++) {
418 if (InputsRead
& (1 << i
)) {
423 if (nr
> R300_MAX_AOS_ARRAYS
) {
424 return R300_FALLBACK_TCL
;
427 for (i
= 0; i
< nr
; i
++) {
428 int ci
, fix
, found
= 0;
430 swizzle
[i
][0] = SWIZZLE_ZERO
;
431 swizzle
[i
][1] = SWIZZLE_ZERO
;
432 swizzle
[i
][2] = SWIZZLE_ZERO
;
433 swizzle
[i
][3] = SWIZZLE_ONE
;
435 for (ci
= 0; ci
< vb
->AttribPtr
[tab
[i
]]->size
; ci
++) {
439 if (r300IsGartMemory(rmesa
, vb
->AttribPtr
[tab
[i
]]->data
, 4)) {
440 if (vb
->AttribPtr
[tab
[i
]]->stride
% 4) {
441 return R300_FALLBACK_TCL
;
443 rmesa
->state
.aos
[i
].address
= (void *)(vb
->AttribPtr
[tab
[i
]]->data
);
444 rmesa
->state
.aos
[i
].start
= 0;
445 rmesa
->state
.aos
[i
].aos_offset
= r300GartOffsetFromVirtual(rmesa
, vb
->AttribPtr
[tab
[i
]]->data
);
446 rmesa
->state
.aos
[i
].aos_stride
= vb
->AttribPtr
[tab
[i
]]->stride
/ 4;
447 rmesa
->state
.aos
[i
].aos_size
= vb
->AttribPtr
[tab
[i
]]->size
;
449 r300EmitVec(ctx
, &rmesa
->state
.aos
[i
],
450 vb
->AttribPtr
[tab
[i
]]->data
,
451 vb
->AttribPtr
[tab
[i
]]->size
,
452 vb
->AttribPtr
[tab
[i
]]->stride
, count
);
455 rmesa
->state
.aos
[i
].aos_size
= vb
->AttribPtr
[tab
[i
]]->size
;
457 for (fix
= 0; fix
<= 4 - vb
->AttribPtr
[tab
[i
]]->size
; fix
++) {
458 if ((rmesa
->state
.aos
[i
].aos_offset
- _mesa_sizeof_type(GL_FLOAT
) * fix
) % 4) {
467 WARN_ONCE("Feeling lucky?\n");
469 rmesa
->state
.aos
[i
].aos_offset
-= _mesa_sizeof_type(GL_FLOAT
) * fix
;
470 for (ci
= 0; ci
< vb
->AttribPtr
[tab
[i
]]->size
; ci
++) {
471 swizzle
[i
][ci
] += fix
;
475 ("Cannot handle offset %x with stride %d, comp %d\n",
476 rmesa
->state
.aos
[i
].aos_offset
,
477 rmesa
->state
.aos
[i
].aos_stride
,
478 vb
->AttribPtr
[tab
[i
]]->size
);
479 return R300_FALLBACK_TCL
;
483 /* Setup INPUT_ROUTE. */
484 R300_STATECHANGE(rmesa
, vir
[0]);
485 ((drm_r300_cmd_header_t
*) rmesa
->hw
.vir
[0].cmd
)->packet0
.count
=
486 r300VAPInputRoute0(&rmesa
->hw
.vir
[0].cmd
[R300_VIR_CNTL_0
],
487 vb
->AttribPtr
, inputs
, tab
, nr
);
488 R300_STATECHANGE(rmesa
, vir
[1]);
489 ((drm_r300_cmd_header_t
*) rmesa
->hw
.vir
[1].cmd
)->packet0
.count
=
490 r300VAPInputRoute1(&rmesa
->hw
.vir
[1].cmd
[R300_VIR_CNTL_0
], swizzle
,
493 /* Setup INPUT_CNTL. */
494 R300_STATECHANGE(rmesa
, vic
);
495 rmesa
->hw
.vic
.cmd
[R300_VIC_CNTL_0
] = r300VAPInputCntl0(ctx
, InputsRead
);
496 rmesa
->hw
.vic
.cmd
[R300_VIC_CNTL_1
] = r300VAPInputCntl1(ctx
, InputsRead
);
498 /* Setup OUTPUT_VTX_FMT. */
499 R300_STATECHANGE(rmesa
, vof
);
500 rmesa
->hw
.vof
.cmd
[R300_VOF_CNTL_0
] =
501 r300VAPOutputCntl0(ctx
, OutputsWritten
);
502 rmesa
->hw
.vof
.cmd
[R300_VOF_CNTL_1
] =
503 r300VAPOutputCntl1(ctx
, OutputsWritten
);
505 rmesa
->state
.aos_count
= nr
;
507 return R300_FALLBACK_NONE
;
511 void r300UseArrays(GLcontext
* ctx
)
513 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
516 if (rmesa
->state
.elt_dma
.buf
)
517 r300_mem_use(rmesa
, rmesa
->state
.elt_dma
.buf
->id
);
519 for (i
= 0; i
< rmesa
->state
.aos_count
; i
++) {
520 if (rmesa
->state
.aos
[i
].buf
)
521 r300_mem_use(rmesa
, rmesa
->state
.aos
[i
].buf
->id
);
526 void r300ReleaseArrays(GLcontext
* ctx
)
528 r300ContextPtr rmesa
= R300_CONTEXT(ctx
);
531 r300ReleaseDmaRegion(rmesa
, &rmesa
->state
.elt_dma
, __FUNCTION__
);
532 for (i
= 0; i
< rmesa
->state
.aos_count
; i
++) {
533 r300ReleaseDmaRegion(rmesa
, &rmesa
->state
.aos
[i
], __FUNCTION__
);
537 void r300EmitCacheFlush(r300ContextPtr rmesa
)
539 int cmd_reserved
= 0;
542 drm_radeon_cmd_header_t
*cmd
= NULL
;
544 reg_start(R300_RB3D_DSTCACHE_CTLSTAT
, 0);
545 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A
);
547 reg_start(R300_RB3D_ZCACHE_CTLSTAT
, 0);
548 e32(R300_RB3D_ZCACHE_UNKNOWN_03
);