2 Copyright (C) The Weather Channel, Inc. 2002.
3 Copyright (C) 2004 Nicolai Haehnle.
6 The Weather Channel (TM) funded Tungsten Graphics to develop the
7 initial release of the Radeon 8500 driver under the XFree86 license.
8 This notice must be preserved.
10 Permission is hereby granted, free of charge, to any person obtaining
11 a copy of this software and associated documentation files (the
12 "Software"), to deal in the Software without restriction, including
13 without limitation the rights to use, copy, modify, merge, publish,
14 distribute, sublicense, and/or sell copies of the Software, and to
15 permit persons to whom the Software is furnished to do so, subject to
16 the following conditions:
18 The above copyright notice and this permission notice (including the
19 next paragraph) shall be included in all copies or substantial
20 portions of the Software.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
26 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 **************************************************************************/
34 * Keith Whitwell <keith@tungstengraphics.com>
35 * Nicolai Haehnle <prefect_@gmx.net>
45 #include "swrast/swrast.h"
47 #include "r300_context.h"
48 #include "radeon_ioctl.h"
49 #include "r300_ioctl.h"
50 #include "r300_cmdbuf.h"
51 #include "r300_state.h"
52 #include "r300_program.h"
53 #include "radeon_reg.h"
58 #define CLEARBUFFER_COLOR 0x1
59 #define CLEARBUFFER_DEPTH 0x2
61 static void r300ClearBuffer(r300ContextPtr r300
, int flags
, int buffer
)
63 GLcontext
* ctx
= r300
->radeon
.glCtx
;
64 __DRIdrawablePrivate
*dPriv
= r300
->radeon
.dri
.drawable
;
66 GLuint cboffset
, cbpitch
;
67 drm_r300_cmd_header_t
* cmd
;
69 if (RADEON_DEBUG
& DEBUG_IOCTL
)
70 fprintf(stderr
, "%s: %s buffer (%i,%i %ix%i)\n",
71 __FUNCTION__
, buffer
? "back" : "front",
72 dPriv
->x
, dPriv
->y
, dPriv
->w
, dPriv
->h
);
75 cboffset
= r300
->radeon
.radeonScreen
->backOffset
;
76 cbpitch
= r300
->radeon
.radeonScreen
->backPitch
;
78 cboffset
= r300
->radeon
.radeonScreen
->frontOffset
;
79 cbpitch
= r300
->radeon
.radeonScreen
->frontPitch
;
82 cboffset
+= r300
->radeon
.radeonScreen
->fbLocation
;
84 R300_STATECHANGE(r300
, vir
[0]);
85 ((drm_r300_cmd_header_t
*)r300
->hw
.vir
[0].cmd
)->unchecked_state
.count
= 1;
86 r300
->hw
.vir
[0].cmd
[1] = 0x21030003;
88 R300_STATECHANGE(r300
, vir
[1]);
89 ((drm_r300_cmd_header_t
*)r300
->hw
.vir
[1].cmd
)->unchecked_state
.count
= 1;
90 r300
->hw
.vir
[1].cmd
[1] = 0xF688F688;
92 R300_STATECHANGE(r300
, vic
);
93 r300
->hw
.vic
.cmd
[R300_VIR_CNTL_0
] = 0x00000001;
94 r300
->hw
.vic
.cmd
[R300_VIR_CNTL_1
] = 0x00000405;
96 R300_STATECHANGE(r300
, vof
);
97 r300
->hw
.vof
.cmd
[R300_VOF_CNTL_0
] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
98 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT
;
99 r300
->hw
.vof
.cmd
[R300_VOF_CNTL_1
] = 0; /* no textures */
101 R300_STATECHANGE(r300
, txe
);
102 r300
->hw
.txe
.cmd
[R300_TXE_ENABLE
] = 0;
104 R300_STATECHANGE(r300
, vpt
);
105 r300
->hw
.vpt
.cmd
[R300_VPT_XSCALE
] = r300PackFloat32(1.0);
106 r300
->hw
.vpt
.cmd
[R300_VPT_XOFFSET
] = r300PackFloat32(dPriv
->x
);
107 r300
->hw
.vpt
.cmd
[R300_VPT_YSCALE
] = r300PackFloat32(1.0);
108 r300
->hw
.vpt
.cmd
[R300_VPT_YOFFSET
] = r300PackFloat32(dPriv
->y
);
109 r300
->hw
.vpt
.cmd
[R300_VPT_ZSCALE
] = r300PackFloat32(1.0);
110 r300
->hw
.vpt
.cmd
[R300_VPT_ZOFFSET
] = r300PackFloat32(0.0);
112 R300_STATECHANGE(r300
, at
);
113 r300
->hw
.at
.cmd
[R300_AT_ALPHA_TEST
] = 0;
115 R300_STATECHANGE(r300
, bld
);
116 r300
->hw
.bld
.cmd
[R300_BLD_CBLEND
] = 0;
117 r300
->hw
.bld
.cmd
[R300_BLD_ABLEND
] = 0;
119 R300_STATECHANGE(r300
, cb
);
120 r300
->hw
.cb
.cmd
[R300_CB_OFFSET
] = cboffset
;
121 r300
->hw
.cb
.cmd
[R300_CB_PITCH
] = cbpitch
| R300_COLOR_UNKNOWN_22_23
;
123 R300_STATECHANGE(r300
, unk221C
);
124 r300
->hw
.unk221C
.cmd
[1] = R300_221C_CLEAR
;
126 R300_STATECHANGE(r300
, ps
);
127 r300
->hw
.ps
.cmd
[R300_PS_POINTSIZE
] =
128 ((dPriv
->w
* 6) << R300_POINTSIZE_X_SHIFT
) |
129 ((dPriv
->h
* 6) << R300_POINTSIZE_Y_SHIFT
);
131 R300_STATECHANGE(r300
, ri
);
132 for(i
= 1; i
<= 8; ++i
)
133 r300
->hw
.ri
.cmd
[i
] = R300_RS_INTERP_USED
;
135 R300_STATECHANGE(r300
, rc
);
136 /* The second constant is needed to get glxgears display anything .. */
137 r300
->hw
.rc
.cmd
[1] = R300_RS_CNTL_0_UNKNOWN_7
| R300_RS_CNTL_0_UNKNOWN_18
;
138 r300
->hw
.rc
.cmd
[2] = 0;
140 R300_STATECHANGE(r300
, rr
);
141 ((drm_r300_cmd_header_t
*)r300
->hw
.rr
.cmd
)->unchecked_state
.count
= 1;
142 r300
->hw
.rr
.cmd
[1] = 0x00004000;
144 R300_STATECHANGE(r300
, cmk
);
145 if (flags
& CLEARBUFFER_COLOR
) {
146 r300
->hw
.cmk
.cmd
[R300_CMK_COLORMASK
] =
147 (ctx
->Color
.ColorMask
[BCOMP
] ? R300_COLORMASK0_B
: 0) |
148 (ctx
->Color
.ColorMask
[GCOMP
] ? R300_COLORMASK0_G
: 0) |
149 (ctx
->Color
.ColorMask
[RCOMP
] ? R300_COLORMASK0_R
: 0) |
150 (ctx
->Color
.ColorMask
[ACOMP
] ? R300_COLORMASK0_A
: 0);
152 r300
->hw
.cmk
.cmd
[R300_CMK_COLORMASK
] = 0;
155 R300_STATECHANGE(r300
, fp
);
156 r300
->hw
.fp
.cmd
[R300_FP_CNTL0
] = 0; /* 1 pass, no textures */
157 r300
->hw
.fp
.cmd
[R300_FP_CNTL1
] = 0; /* no temporaries */
158 r300
->hw
.fp
.cmd
[R300_FP_CNTL2
] = 0; /* no offset, one ALU instr */
159 r300
->hw
.fp
.cmd
[R300_FP_NODE0
] = 0;
160 r300
->hw
.fp
.cmd
[R300_FP_NODE1
] = 0;
161 r300
->hw
.fp
.cmd
[R300_FP_NODE2
] = 0;
162 r300
->hw
.fp
.cmd
[R300_FP_NODE3
] = R300_PFS_NODE_LAST_NODE
;
164 R300_STATECHANGE(r300
, fpi
[0]);
165 R300_STATECHANGE(r300
, fpi
[1]);
166 R300_STATECHANGE(r300
, fpi
[2]);
167 R300_STATECHANGE(r300
, fpi
[3]);
168 ((drm_r300_cmd_header_t
*)r300
->hw
.fpi
[0].cmd
)->unchecked_state
.count
= 1;
169 ((drm_r300_cmd_header_t
*)r300
->hw
.fpi
[1].cmd
)->unchecked_state
.count
= 1;
170 ((drm_r300_cmd_header_t
*)r300
->hw
.fpi
[2].cmd
)->unchecked_state
.count
= 1;
171 ((drm_r300_cmd_header_t
*)r300
->hw
.fpi
[3].cmd
)->unchecked_state
.count
= 1;
174 r300
->hw
.fpi
[0].cmd
[1] = FP_INSTRC(MAD
, FP_ARGC(SRC0C_XYZ
), FP_ARGC(ONE
), FP_ARGC(ZERO
));
175 r300
->hw
.fpi
[1].cmd
[1] = FP_SELC(0,NO
,XYZ
,FP_TMP(0),0,0);
176 r300
->hw
.fpi
[2].cmd
[1] = FP_INSTRA(MAD
, FP_ARGA(SRC0A
), FP_ARGA(ONE
), FP_ARGA(ZERO
));
177 r300
->hw
.fpi
[3].cmd
[1] = FP_SELA(0,NO
,W
,FP_TMP(0),0,0);
179 R300_STATECHANGE(r300
, pvs
);
180 r300
->hw
.pvs
.cmd
[R300_PVS_CNTL_1
] =
181 (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT
) |
182 (0 << R300_PVS_CNTL_1_UNKNOWN_SHIFT
) |
183 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT
);
184 r300
->hw
.pvs
.cmd
[R300_PVS_CNTL_2
] = 0; /* no parameters */
185 r300
->hw
.pvs
.cmd
[R300_PVS_CNTL_3
] =
186 (1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT
);
188 R300_STATECHANGE(r300
, vpi
);
189 ((drm_r300_cmd_header_t
*)r300
->hw
.vpi
.cmd
)->unchecked_state
.count
= 8;
192 r300
->hw
.vpi
.cmd
[1] = VP_OUT(ADD
,OUT
,0,XYZW
);
193 r300
->hw
.vpi
.cmd
[2] = VP_IN(IN
,0);
194 r300
->hw
.vpi
.cmd
[3] = VP_ZERO();
195 r300
->hw
.vpi
.cmd
[4] = 0;
198 r300
->hw
.vpi
.cmd
[5] = VP_OUT(ADD
,OUT
,1,XYZW
);
199 r300
->hw
.vpi
.cmd
[6] = VP_IN(IN
,1);
200 r300
->hw
.vpi
.cmd
[7] = VP_ZERO();
201 r300
->hw
.vpi
.cmd
[8] = 0;
203 R300_STATECHANGE(r300
, zc
);
204 if (flags
& CLEARBUFFER_DEPTH
) {
205 r300
->hw
.zc
.cmd
[R300_ZC_CNTL_0
] = 0x6; // test and write
206 r300
->hw
.zc
.cmd
[R300_ZC_CNTL_1
] = R300_Z_TEST_ALWAYS
;
208 R300_STATECHANGE(r300, zb);
209 r300->hw.zb.cmd[R300_ZB_OFFSET] =
211 r300->radeon.radeonScreen->frontOffset +
212 r300->radeon.radeonScreen->fbLocation;
213 r300->hw.zb.cmd[R300_ZB_PITCH] =
214 r300->radeon.radeonScreen->depthPitch;
217 r300
->hw
.zc
.cmd
[R300_ZC_CNTL_0
] = 0; // disable
218 r300
->hw
.zc
.cmd
[R300_ZC_CNTL_1
] = 0;
221 /* Make sure we have enough space */
222 r300EnsureCmdBufSpace(r300
, r300
->hw
.max_state_size
+ 9, __FUNCTION__
);
226 cmd
= (drm_r300_cmd_header_t
*)r300AllocCmdBuf(r300
, 9, __FUNCTION__
);
227 cmd
[0].packet3
.cmd_type
= R300_CMD_PACKET3
;
228 cmd
[0].packet3
.packet
= R300_CMD_PACKET3_CLEAR
;
229 cmd
[1].u
= r300PackFloat32(dPriv
->w
/ 2.0);
230 cmd
[2].u
= r300PackFloat32(dPriv
->h
/ 2.0);
231 cmd
[3].u
= r300PackFloat32(ctx
->Depth
.Clear
);
232 cmd
[4].u
= r300PackFloat32(1.0);
233 cmd
[5].u
= r300PackFloat32(ctx
->Color
.ClearColor
[0]);
234 cmd
[6].u
= r300PackFloat32(ctx
->Color
.ClearColor
[1]);
235 cmd
[7].u
= r300PackFloat32(ctx
->Color
.ClearColor
[2]);
236 cmd
[8].u
= r300PackFloat32(ctx
->Color
.ClearColor
[3]);
243 static void r300Clear(GLcontext
* ctx
, GLbitfield mask
, GLboolean all
,
244 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
246 r300ContextPtr r300
= R300_CONTEXT(ctx
);
247 __DRIdrawablePrivate
*dPriv
= r300
->radeon
.dri
.drawable
;
252 if (RADEON_DEBUG
& DEBUG_IOCTL
)
253 fprintf(stderr
, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
254 __FUNCTION__
, all
, cx
, cy
, cw
, ch
);
257 LOCK_HARDWARE(&r300
->radeon
);
258 UNLOCK_HARDWARE(&r300
->radeon
);
259 if (dPriv
->numClipRects
== 0)
263 if (mask
& DD_FRONT_LEFT_BIT
) {
264 flags
|= DD_FRONT_LEFT_BIT
;
265 mask
&= ~DD_FRONT_LEFT_BIT
;
268 if (mask
& DD_BACK_LEFT_BIT
) {
269 flags
|= DD_BACK_LEFT_BIT
;
270 mask
&= ~DD_BACK_LEFT_BIT
;
273 if (mask
& DD_DEPTH_BIT
) {
274 bits
|= CLEARBUFFER_DEPTH
;
275 mask
&= ~DD_DEPTH_BIT
;
279 if (RADEON_DEBUG
& DEBUG_FALLBACKS
)
280 fprintf(stderr
, "%s: swrast clear, mask: %x\n",
282 _swrast_Clear(ctx
, mask
, all
, cx
, cy
, cw
, ch
);
285 swapped
= r300
->radeon
.doPageFlip
&& (r300
->radeon
.sarea
->pfCurrentPage
== 1);
287 if (flags
& DD_FRONT_LEFT_BIT
) {
288 r300ClearBuffer(r300
, bits
| CLEARBUFFER_COLOR
, swapped
);
292 if (flags
& DD_BACK_LEFT_BIT
) {
293 r300ClearBuffer(r300
, bits
| CLEARBUFFER_COLOR
, swapped
^ 1);
298 r300ClearBuffer(r300
, bits
, 0);
300 /* Recalculate the hardware state. This could be done more efficiently,
301 * but do keep it like this for now.
303 r300ResetHwState(r300
);
306 void r300Flush(GLcontext
* ctx
)
308 r300ContextPtr r300
= R300_CONTEXT(ctx
);
310 if (RADEON_DEBUG
& DEBUG_IOCTL
)
311 fprintf(stderr
, "%s\n", __FUNCTION__
);
313 if (r300
->cmdbuf
.count_used
> r300
->cmdbuf
.count_reemit
)
314 r300FlushCmdBuf(r300
, __FUNCTION__
);
317 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa
)
319 struct r200_dma_buffer
*dmabuf
;
320 int fd
= rmesa
->radeon
.dri
.fd
;
326 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
))
327 fprintf(stderr
, "%s\n", __FUNCTION__
);
329 if (rmesa
->dma
.flush
) {
330 rmesa
->dma
.flush(rmesa
);
333 if (rmesa
->dma
.current
.buf
)
334 r300ReleaseDmaRegion(rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
336 if (rmesa
->dma
.nr_released_bufs
> 4)
337 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
339 dma
.context
= rmesa
->radeon
.dri
.hwContext
;
341 dma
.send_list
= NULL
;
342 dma
.send_sizes
= NULL
;
344 dma
.request_count
= 1;
345 dma
.request_size
= RADEON_BUFFER_SIZE
;
346 dma
.request_list
= &index
;
347 dma
.request_sizes
= &size
;
348 dma
.granted_count
= 0;
350 LOCK_HARDWARE(&rmesa
->radeon
); /* no need to validate */
353 ret
= drmDMA(fd
, &dma
);
357 if (rmesa
->dma
.nr_released_bufs
) {
358 r200FlushCmdBufLocked(rmesa
, __FUNCTION__
);
361 if (rmesa
->radeon
.do_usleeps
) {
362 UNLOCK_HARDWARE(&rmesa
->radeon
);
364 LOCK_HARDWARE(&rmesa
->radeon
);
368 UNLOCK_HARDWARE(&rmesa
->radeon
);
370 if (RADEON_DEBUG
& DEBUG_DMA
)
371 fprintf(stderr
, "Allocated buffer %d\n", index
);
373 dmabuf
= CALLOC_STRUCT(r300_dma_buffer
);
374 dmabuf
->buf
= &rmesa
->radeon
.radeonScreen
->buffers
->list
[index
];
375 dmabuf
->refcount
= 1;
377 rmesa
->dma
.current
.buf
= dmabuf
;
378 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
379 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
380 rmesa
->dma
.current
.start
= 0;
381 rmesa
->dma
.current
.ptr
= 0;
384 void r300ReleaseDmaRegion(r300ContextPtr rmesa
,
385 struct r300_dma_region
*region
, const char *caller
)
387 if (RADEON_DEBUG
& DEBUG_IOCTL
)
388 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
393 if (rmesa
->dma
.flush
)
394 rmesa
->dma
.flush(rmesa
);
396 if (--region
->buf
->refcount
== 0) {
397 drm_radeon_cmd_header_t
*cmd
;
399 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
))
400 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
401 region
->buf
->buf
->idx
);
404 (drm_radeon_cmd_header_t
*) r300AllocCmdBuf(rmesa
,
407 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
408 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
410 rmesa
->dma
.nr_released_bufs
++;
417 /* Allocates a region from rmesa->dma.current. If there isn't enough
418 * space in current, grab a new buffer (and discard what was left of current)
420 void r300AllocDmaRegion(r300ContextPtr rmesa
,
421 struct r300_dma_region
*region
,
422 int bytes
, int alignment
)
424 if (RADEON_DEBUG
& DEBUG_IOCTL
)
425 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
427 if (rmesa
->dma
.flush
)
428 rmesa
->dma
.flush(rmesa
);
431 r300ReleaseDmaRegion(rmesa
, region
, __FUNCTION__
);
434 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
435 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
437 if (rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
438 r300RefillCurrentDmaRegion(rmesa
);
440 region
->start
= rmesa
->dma
.current
.start
;
441 region
->ptr
= rmesa
->dma
.current
.start
;
442 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
443 region
->address
= rmesa
->dma
.current
.address
;
444 region
->buf
= rmesa
->dma
.current
.buf
;
445 region
->buf
->refcount
++;
447 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
448 rmesa
->dma
.current
.start
=
449 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
451 assert(rmesa
->dma
.current
.ptr
<= rmesa
->dma
.current
.end
);
454 /* Called via glXGetMemoryOffsetMESA() */
455 GLuint
r300GetMemoryOffsetMESA(__DRInativeDisplay
* dpy
, int scrn
,
456 const GLvoid
* pointer
)
458 GET_CURRENT_CONTEXT(ctx
);
459 r300ContextPtr rmesa
;
462 if (!ctx
|| !(rmesa
= R300_CONTEXT(ctx
))) {
463 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
467 if (!r300IsGartMemory(rmesa
, pointer
, 0))
470 if (rmesa
->radeon
.dri
.drmMinor
< 6)
473 card_offset
= r300GartOffsetFromVirtual(rmesa
, pointer
);
475 return card_offset
- rmesa
->radeon
.radeonScreen
->gart_base
;
478 GLboolean
r300IsGartMemory(r300ContextPtr rmesa
, const GLvoid
* pointer
,
482 (char *)pointer
- (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
483 int valid
= (size
>= 0 && offset
>= 0
484 && offset
+ size
< rmesa
->radeon
.radeonScreen
->gartTextures
.size
);
486 if (RADEON_DEBUG
& DEBUG_IOCTL
)
487 fprintf(stderr
, "r300IsGartMemory( %p ) : %d\n", pointer
,
493 GLuint
r300GartOffsetFromVirtual(r300ContextPtr rmesa
, const GLvoid
* pointer
)
496 (char *)pointer
- (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
498 fprintf(stderr
, "offset=%08x\n", offset
);
500 if (offset
< 0 || offset
> rmesa
->radeon
.radeonScreen
->gartTextures
.size
)
503 return rmesa
->radeon
.radeonScreen
->gart_texture_offset
+ offset
;
506 void r300InitIoctlFuncs(struct dd_function_table
*functions
)
508 functions
->Clear
= r300Clear
;
509 functions
->Finish
= radeonFinish
;
510 functions
->Flush
= r300Flush
;