1 /**************************************************************************
3 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
4 VA Linux Systems Inc., Fremont, California.
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 **************************************************************************/
32 * Kevin E. Martin <martin@valinux.com>
33 * Gareth Hughes <gareth@valinux.com>
34 * Keith Whitwell <keith@tungstengraphics.com>
40 #include "main/attrib.h"
41 #include "main/bufferobj.h"
42 #include "swrast/swrast.h"
44 #include "main/glheader.h"
45 #include "main/imports.h"
46 #include "main/simple_list.h"
48 #include "radeon_context.h"
49 #include "radeon_common.h"
50 #include "radeon_ioctl.h"
52 #define STANDALONE_MMIO
56 #define RADEON_TIMEOUT 512
57 #define RADEON_IDLE_RETRY 16
60 /* =============================================================
61 * Kernel command buffer handling
64 /* The state atoms will be emitted in the order they appear in the atom list,
65 * so this step is important.
67 void radeonSetUpAtomList( r100ContextPtr rmesa
)
69 int i
, mtu
= rmesa
->radeon
.glCtx
->Const
.MaxTextureUnits
;
71 make_empty_list(&rmesa
->radeon
.hw
.atomlist
);
72 rmesa
->radeon
.hw
.atomlist
.name
= "atom-list";
74 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.ctx
);
75 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.set
);
76 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.lin
);
77 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.msk
);
78 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.vpt
);
79 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.tcl
);
80 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.msc
);
81 for (i
= 0; i
< mtu
; ++i
) {
82 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.tex
[i
]);
83 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.txr
[i
]);
84 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.cube
[i
]);
86 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.zbs
);
87 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.mtl
);
88 for (i
= 0; i
< 3 + mtu
; ++i
)
89 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.mat
[i
]);
90 for (i
= 0; i
< 8; ++i
)
91 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.lit
[i
]);
92 for (i
= 0; i
< 6; ++i
)
93 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.ucp
[i
]);
94 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.stp
);
95 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.eye
);
96 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.grd
);
97 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.fog
);
98 insert_at_tail(&rmesa
->radeon
.hw
.atomlist
, &rmesa
->hw
.glt
);
101 static void radeonEmitScissor(r100ContextPtr rmesa
)
103 BATCH_LOCALS(&rmesa
->radeon
);
104 if (rmesa
->radeon
.state
.scissor
.enabled
) {
106 OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL
, 0));
107 OUT_BATCH(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] | RADEON_SCISSOR_ENABLE
);
108 OUT_BATCH(CP_PACKET0(RADEON_RE_TOP_LEFT
, 0));
109 OUT_BATCH((rmesa
->radeon
.state
.scissor
.rect
.y1
<< 16) |
110 rmesa
->radeon
.state
.scissor
.rect
.x1
);
111 OUT_BATCH(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT
, 0));
112 OUT_BATCH(((rmesa
->radeon
.state
.scissor
.rect
.y2
) << 16) |
113 (rmesa
->radeon
.state
.scissor
.rect
.x2
));
117 OUT_BATCH(CP_PACKET0(RADEON_PP_CNTL
, 0));
118 OUT_BATCH(rmesa
->hw
.ctx
.cmd
[CTX_PP_CNTL
] & ~RADEON_SCISSOR_ENABLE
);
123 /* Fire a section of the retained (indexed_verts) buffer as a regular
126 extern void radeonEmitVbufPrim( r100ContextPtr rmesa
,
127 GLuint vertex_format
,
131 BATCH_LOCALS(&rmesa
->radeon
);
133 assert(!(primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
135 radeonEmitState(&rmesa
->radeon
);
136 radeonEmitScissor(rmesa
);
138 #if RADEON_OLD_PACKETS
140 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
, 3);
141 OUT_BATCH(rmesa
->ioctl
.vertex_offset
);
143 OUT_BATCH(vertex_nr
);
144 OUT_BATCH(vertex_format
);
145 OUT_BATCH(primitive
| RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
146 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
147 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
148 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
150 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
152 RADEON_GEM_DOMAIN_GTT
,
159 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_DRAW_VBUF
, 1);
160 OUT_BATCH(vertex_format
);
161 OUT_BATCH(primitive
|
162 RADEON_CP_VC_CNTL_PRIM_WALK_LIST
|
163 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
164 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
165 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
|
166 (vertex_nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
));
171 void radeonFlushElts( struct gl_context
*ctx
)
173 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
174 BATCH_LOCALS(&rmesa
->radeon
);
176 uint32_t *cmd
= (uint32_t *)(rmesa
->radeon
.cmdbuf
.cs
->packets
+ rmesa
->tcl
.elt_cmd_start
);
177 int dwords
= (rmesa
->radeon
.cmdbuf
.cs
->section_ndw
- rmesa
->radeon
.cmdbuf
.cs
->section_cdw
);
179 if (RADEON_DEBUG
& RADEON_IOCTL
)
180 fprintf(stderr
, "%s\n", __FUNCTION__
);
182 assert( rmesa
->radeon
.dma
.flush
== radeonFlushElts
);
183 rmesa
->radeon
.dma
.flush
= NULL
;
185 nr
= rmesa
->tcl
.elt_used
;
187 #if RADEON_OLD_PACKETS
191 #if RADEON_OLD_PACKETS
192 cmd
[1] |= (dwords
+ 3) << 16;
193 cmd
[5] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
195 cmd
[1] |= (dwords
+ 2) << 16;
196 cmd
[3] |= nr
<< RADEON_CP_VC_CNTL_NUM_SHIFT
;
199 rmesa
->radeon
.cmdbuf
.cs
->cdw
+= dwords
;
200 rmesa
->radeon
.cmdbuf
.cs
->section_cdw
+= dwords
;
202 #if RADEON_OLD_PACKETS
203 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
205 RADEON_GEM_DOMAIN_GTT
,
211 if (RADEON_DEBUG
& RADEON_SYNC
) {
212 fprintf(stderr
, "%s: Syncing\n", __FUNCTION__
);
213 radeonFinish( rmesa
->radeon
.glCtx
);
218 GLushort
*radeonAllocEltsOpenEnded( r100ContextPtr rmesa
,
219 GLuint vertex_format
,
225 BATCH_LOCALS(&rmesa
->radeon
);
227 if (RADEON_DEBUG
& RADEON_IOCTL
)
228 fprintf(stderr
, "%s %d prim %x\n", __FUNCTION__
, min_nr
, primitive
);
230 assert((primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
232 radeonEmitState(&rmesa
->radeon
);
233 radeonEmitScissor(rmesa
);
235 rmesa
->tcl
.elt_cmd_start
= rmesa
->radeon
.cmdbuf
.cs
->cdw
;
237 /* round up min_nr to align the state */
238 align_min_nr
= (min_nr
+ 1) & ~1;
240 #if RADEON_OLD_PACKETS
241 BEGIN_BATCH_NO_AUTOSTATE(2+ELTS_BUFSZ(align_min_nr
)/4);
242 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM
, 0);
243 OUT_BATCH(rmesa
->ioctl
.vertex_offset
);
244 OUT_BATCH(rmesa
->ioctl
.vertex_max
);
245 OUT_BATCH(vertex_format
);
246 OUT_BATCH(primitive
|
247 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
248 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
249 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
251 BEGIN_BATCH_NO_AUTOSTATE(ELTS_BUFSZ(align_min_nr
)/4);
252 OUT_BATCH_PACKET3_CLIP(RADEON_CP_PACKET3_DRAW_INDX
, 0);
253 OUT_BATCH(vertex_format
);
254 OUT_BATCH(primitive
|
255 RADEON_CP_VC_CNTL_PRIM_WALK_IND
|
256 RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA
|
257 RADEON_CP_VC_CNTL_MAOS_ENABLE
|
258 RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE
);
262 rmesa
->tcl
.elt_cmd_offset
= rmesa
->radeon
.cmdbuf
.cs
->cdw
;
263 rmesa
->tcl
.elt_used
= min_nr
;
265 retval
= (GLushort
*)(rmesa
->radeon
.cmdbuf
.cs
->packets
+ rmesa
->tcl
.elt_cmd_offset
);
267 if (RADEON_DEBUG
& RADEON_RENDER
)
268 fprintf(stderr
, "%s: header prim %x \n",
269 __FUNCTION__
, primitive
);
271 assert(!rmesa
->radeon
.dma
.flush
);
272 rmesa
->radeon
.glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
273 rmesa
->radeon
.dma
.flush
= radeonFlushElts
;
278 void radeonEmitVertexAOS( r100ContextPtr rmesa
,
280 struct radeon_bo
*bo
,
283 #if RADEON_OLD_PACKETS
284 rmesa
->ioctl
.vertex_offset
= offset
;
285 rmesa
->ioctl
.bo
= bo
;
287 BATCH_LOCALS(&rmesa
->radeon
);
289 if (RADEON_DEBUG
& (RADEON_PRIMS
|DEBUG_IOCTL
))
290 fprintf(stderr
, "%s: vertex_size 0x%x offset 0x%x \n",
291 __FUNCTION__
, vertex_size
, offset
);
294 OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR
, 2);
296 OUT_BATCH(vertex_size
| (vertex_size
<< 8));
297 OUT_BATCH_RELOC(offset
, bo
, offset
, RADEON_GEM_DOMAIN_GTT
, 0, 0);
304 void radeonEmitAOS( r100ContextPtr rmesa
,
308 #if RADEON_OLD_PACKETS
310 rmesa
->ioctl
.bo
= rmesa
->radeon
.tcl
.aos
[0].bo
;
311 rmesa
->ioctl
.vertex_offset
=
312 (rmesa
->radeon
.tcl
.aos
[0].offset
+ offset
* rmesa
->radeon
.tcl
.aos
[0].stride
* 4);
313 rmesa
->ioctl
.vertex_max
= rmesa
->radeon
.tcl
.aos
[0].count
;
315 BATCH_LOCALS(&rmesa
->radeon
);
317 // int sz = AOS_BUFSZ(nr);
318 int sz
= 1 + (nr
>> 1) * 3 + (nr
& 1) * 2;
321 if (RADEON_DEBUG
& RADEON_IOCTL
)
322 fprintf(stderr
, "%s\n", __FUNCTION__
);
324 BEGIN_BATCH(sz
+2+(nr
* 2));
325 OUT_BATCH_PACKET3(RADEON_CP_PACKET3_3D_LOAD_VBPNTR
, sz
- 1);
329 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
330 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[i
].components
<< 0) |
331 (rmesa
->radeon
.tcl
.aos
[i
].stride
<< 8) |
332 (rmesa
->radeon
.tcl
.aos
[i
+ 1].components
<< 16) |
333 (rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
<< 24));
335 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 0].offset
+
336 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 0].stride
;
338 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 1].offset
+
339 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
;
344 OUT_BATCH((rmesa
->radeon
.tcl
.aos
[nr
- 1].components
<< 0) |
345 (rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
<< 8));
346 voffset
= rmesa
->radeon
.tcl
.aos
[nr
- 1].offset
+
347 offset
* 4 * rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
;
350 for (i
= 0; i
+ 1 < nr
; i
+= 2) {
351 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 0].offset
+
352 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 0].stride
;
353 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
354 rmesa
->radeon
.tcl
.aos
[i
+0].bo
,
355 RADEON_GEM_DOMAIN_GTT
,
357 voffset
= rmesa
->radeon
.tcl
.aos
[i
+ 1].offset
+
358 offset
* 4 * rmesa
->radeon
.tcl
.aos
[i
+ 1].stride
;
359 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
360 rmesa
->radeon
.tcl
.aos
[i
+1].bo
,
361 RADEON_GEM_DOMAIN_GTT
,
365 voffset
= rmesa
->radeon
.tcl
.aos
[nr
- 1].offset
+
366 offset
* 4 * rmesa
->radeon
.tcl
.aos
[nr
- 1].stride
;
367 radeon_cs_write_reloc(rmesa
->radeon
.cmdbuf
.cs
,
368 rmesa
->radeon
.tcl
.aos
[nr
-1].bo
,
369 RADEON_GEM_DOMAIN_GTT
,
378 /* ================================================================
381 #define RADEON_MAX_CLEARS 256
383 static void radeonClear( struct gl_context
*ctx
, GLbitfield mask
)
385 r100ContextPtr rmesa
= R100_CONTEXT(ctx
);
387 GLuint orig_mask
= mask
;
389 if (mask
& (BUFFER_BIT_FRONT_LEFT
| BUFFER_BIT_FRONT_RIGHT
)) {
390 rmesa
->radeon
.front_buffer_dirty
= GL_TRUE
;
393 if ( RADEON_DEBUG
& RADEON_IOCTL
) {
394 fprintf( stderr
, "radeonClear\n");
397 radeon_firevertices(&rmesa
->radeon
);
399 if ( mask
& BUFFER_BIT_FRONT_LEFT
) {
400 flags
|= RADEON_FRONT
;
401 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
404 if ( mask
& BUFFER_BIT_BACK_LEFT
) {
405 flags
|= RADEON_BACK
;
406 mask
&= ~BUFFER_BIT_BACK_LEFT
;
409 if ( mask
& BUFFER_BIT_DEPTH
) {
410 flags
|= RADEON_DEPTH
;
411 mask
&= ~BUFFER_BIT_DEPTH
;
414 if ( (mask
& BUFFER_BIT_STENCIL
) ) {
415 flags
|= RADEON_STENCIL
;
416 mask
&= ~BUFFER_BIT_STENCIL
;
420 if (RADEON_DEBUG
& RADEON_FALLBACKS
)
421 fprintf(stderr
, "%s: swrast clear, mask: %x\n", __FUNCTION__
, mask
);
422 _swrast_Clear( ctx
, mask
);
428 if (rmesa
->using_hyperz
) {
429 flags
|= RADEON_USE_COMP_ZBUF
;
430 /* if (rmesa->radeon.radeonScreen->chipset & RADEON_CHIPSET_TCL)
431 flags |= RADEON_USE_HIERZ; */
432 if (((flags
& RADEON_DEPTH
) && (flags
& RADEON_STENCIL
) &&
433 ((rmesa
->radeon
.state
.stencil
.clear
& RADEON_STENCIL_WRITE_MASK
) == RADEON_STENCIL_WRITE_MASK
))) {
434 flags
|= RADEON_CLEAR_FASTZ
;
438 radeonUserClear(ctx
, orig_mask
);
441 void radeonInitIoctlFuncs( struct gl_context
*ctx
)
443 ctx
->Driver
.Clear
= radeonClear
;
444 ctx
->Driver
.Finish
= radeonFinish
;
445 ctx
->Driver
.Flush
= radeonFlush
;