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
);
304 /* r300ClearBuffer has trampled all over the hardware state.. */
305 r300
->hw
.all_dirty
=GL_TRUE
;
308 void r300Flush(GLcontext
* ctx
)
310 r300ContextPtr r300
= R300_CONTEXT(ctx
);
312 if (RADEON_DEBUG
& DEBUG_IOCTL
)
313 fprintf(stderr
, "%s\n", __FUNCTION__
);
315 if (r300
->cmdbuf
.count_used
> r300
->cmdbuf
.count_reemit
)
316 r300FlushCmdBuf(r300
, __FUNCTION__
);
319 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa
)
321 struct r200_dma_buffer
*dmabuf
;
322 int fd
= rmesa
->radeon
.dri
.fd
;
328 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
))
329 fprintf(stderr
, "%s\n", __FUNCTION__
);
331 if (rmesa
->dma
.flush
) {
332 rmesa
->dma
.flush(rmesa
);
335 if (rmesa
->dma
.current
.buf
)
336 r300ReleaseDmaRegion(rmesa
, &rmesa
->dma
.current
, __FUNCTION__
);
338 if (rmesa
->dma
.nr_released_bufs
> 4)
339 r300FlushCmdBuf(rmesa
, __FUNCTION__
);
341 dma
.context
= rmesa
->radeon
.dri
.hwContext
;
343 dma
.send_list
= NULL
;
344 dma
.send_sizes
= NULL
;
346 dma
.request_count
= 1;
347 dma
.request_size
= RADEON_BUFFER_SIZE
;
348 dma
.request_list
= &index
;
349 dma
.request_sizes
= &size
;
350 dma
.granted_count
= 0;
352 LOCK_HARDWARE(&rmesa
->radeon
); /* no need to validate */
355 ret
= drmDMA(fd
, &dma
);
359 if (rmesa
->dma
.nr_released_bufs
) {
360 r200FlushCmdBufLocked(rmesa
, __FUNCTION__
);
363 if (rmesa
->radeon
.do_usleeps
) {
364 UNLOCK_HARDWARE(&rmesa
->radeon
);
366 LOCK_HARDWARE(&rmesa
->radeon
);
370 UNLOCK_HARDWARE(&rmesa
->radeon
);
372 if (RADEON_DEBUG
& DEBUG_DMA
)
373 fprintf(stderr
, "Allocated buffer %d\n", index
);
375 dmabuf
= CALLOC_STRUCT(r300_dma_buffer
);
376 dmabuf
->buf
= &rmesa
->radeon
.radeonScreen
->buffers
->list
[index
];
377 dmabuf
->refcount
= 1;
379 rmesa
->dma
.current
.buf
= dmabuf
;
380 rmesa
->dma
.current
.address
= dmabuf
->buf
->address
;
381 rmesa
->dma
.current
.end
= dmabuf
->buf
->total
;
382 rmesa
->dma
.current
.start
= 0;
383 rmesa
->dma
.current
.ptr
= 0;
386 void r300ReleaseDmaRegion(r300ContextPtr rmesa
,
387 struct r300_dma_region
*region
, const char *caller
)
389 if (RADEON_DEBUG
& DEBUG_IOCTL
)
390 fprintf(stderr
, "%s from %s\n", __FUNCTION__
, caller
);
395 if (rmesa
->dma
.flush
)
396 rmesa
->dma
.flush(rmesa
);
398 if (--region
->buf
->refcount
== 0) {
399 drm_radeon_cmd_header_t
*cmd
;
401 if (RADEON_DEBUG
& (DEBUG_IOCTL
| DEBUG_DMA
))
402 fprintf(stderr
, "%s -- DISCARD BUF %d\n", __FUNCTION__
,
403 region
->buf
->buf
->idx
);
406 (drm_radeon_cmd_header_t
*) r300AllocCmdBuf(rmesa
,
409 cmd
->dma
.cmd_type
= RADEON_CMD_DMA_DISCARD
;
410 cmd
->dma
.buf_idx
= region
->buf
->buf
->idx
;
412 rmesa
->dma
.nr_released_bufs
++;
419 /* Allocates a region from rmesa->dma.current. If there isn't enough
420 * space in current, grab a new buffer (and discard what was left of current)
422 void r300AllocDmaRegion(r300ContextPtr rmesa
,
423 struct r300_dma_region
*region
,
424 int bytes
, int alignment
)
426 if (RADEON_DEBUG
& DEBUG_IOCTL
)
427 fprintf(stderr
, "%s %d\n", __FUNCTION__
, bytes
);
429 if (rmesa
->dma
.flush
)
430 rmesa
->dma
.flush(rmesa
);
433 r300ReleaseDmaRegion(rmesa
, region
, __FUNCTION__
);
436 rmesa
->dma
.current
.start
= rmesa
->dma
.current
.ptr
=
437 (rmesa
->dma
.current
.ptr
+ alignment
) & ~alignment
;
439 if (rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
440 r300RefillCurrentDmaRegion(rmesa
);
442 region
->start
= rmesa
->dma
.current
.start
;
443 region
->ptr
= rmesa
->dma
.current
.start
;
444 region
->end
= rmesa
->dma
.current
.start
+ bytes
;
445 region
->address
= rmesa
->dma
.current
.address
;
446 region
->buf
= rmesa
->dma
.current
.buf
;
447 region
->buf
->refcount
++;
449 rmesa
->dma
.current
.ptr
+= bytes
; /* bug - if alignment > 7 */
450 rmesa
->dma
.current
.start
=
451 rmesa
->dma
.current
.ptr
= (rmesa
->dma
.current
.ptr
+ 0x7) & ~0x7;
453 assert(rmesa
->dma
.current
.ptr
<= rmesa
->dma
.current
.end
);
456 /* Called via glXGetMemoryOffsetMESA() */
457 GLuint
r300GetMemoryOffsetMESA(__DRInativeDisplay
* dpy
, int scrn
,
458 const GLvoid
* pointer
)
460 GET_CURRENT_CONTEXT(ctx
);
461 r300ContextPtr rmesa
;
464 if (!ctx
|| !(rmesa
= R300_CONTEXT(ctx
))) {
465 fprintf(stderr
, "%s: no context\n", __FUNCTION__
);
469 if (!r300IsGartMemory(rmesa
, pointer
, 0))
472 if (rmesa
->radeon
.dri
.drmMinor
< 6)
475 card_offset
= r300GartOffsetFromVirtual(rmesa
, pointer
);
477 return card_offset
- rmesa
->radeon
.radeonScreen
->gart_base
;
480 GLboolean
r300IsGartMemory(r300ContextPtr rmesa
, const GLvoid
* pointer
,
484 (char *)pointer
- (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
485 int valid
= (size
>= 0 && offset
>= 0
486 && offset
+ size
< rmesa
->radeon
.radeonScreen
->gartTextures
.size
);
488 if (RADEON_DEBUG
& DEBUG_IOCTL
)
489 fprintf(stderr
, "r300IsGartMemory( %p ) : %d\n", pointer
,
495 GLuint
r300GartOffsetFromVirtual(r300ContextPtr rmesa
, const GLvoid
* pointer
)
498 (char *)pointer
- (char *)rmesa
->radeon
.radeonScreen
->gartTextures
.map
;
500 fprintf(stderr
, "offset=%08x\n", offset
);
502 if (offset
< 0 || offset
> rmesa
->radeon
.radeonScreen
->gartTextures
.size
)
505 return rmesa
->radeon
.radeonScreen
->gart_texture_offset
+ offset
;
508 void r300InitIoctlFuncs(struct dd_function_table
*functions
)
510 functions
->Clear
= r300Clear
;
511 functions
->Finish
= radeonFinish
;
512 functions
->Flush
= r300Flush
;