b4b1aebc4d80693ce9db8ecd3ca3000d042f56f9
[mesa.git] / src / mesa / drivers / dri / r300 / r300_ioctl.c
1 /*
2 Copyright (C) The Weather Channel, Inc. 2002.
3 Copyright (C) 2004 Nicolai Haehnle.
4 All Rights Reserved.
5
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.
9
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:
17
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.
21
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.
29
30 **************************************************************************/
31
32 /*
33 * Authors:
34 * Keith Whitwell <keith@tungstengraphics.com>
35 * Nicolai Haehnle <prefect_@gmx.net>
36 */
37
38 #include <sched.h>
39 #include <errno.h>
40
41 #include "glheader.h"
42 #include "imports.h"
43 #include "macros.h"
44 #include "context.h"
45 #include "swrast/swrast.h"
46
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"
54
55 #include "vblank.h"
56
57
58 #define CLEARBUFFER_COLOR 0x1
59 #define CLEARBUFFER_DEPTH 0x2
60
61 static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
62 {
63 GLcontext* ctx = r300->radeon.glCtx;
64 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
65 int i;
66 GLuint cboffset, cbpitch;
67 drm_r300_cmd_header_t* cmd;
68
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);
73
74 if (buffer) {
75 cboffset = r300->radeon.radeonScreen->backOffset;
76 cbpitch = r300->radeon.radeonScreen->backPitch;
77 } else {
78 cboffset = r300->radeon.radeonScreen->frontOffset;
79 cbpitch = r300->radeon.radeonScreen->frontPitch;
80 }
81
82 cboffset += r300->radeon.radeonScreen->fbLocation;
83
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;
87
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;
91
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;
95
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 */
100
101 R300_STATECHANGE(r300, txe);
102 r300->hw.txe.cmd[R300_TXE_ENABLE] = 0;
103
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);
111
112 R300_STATECHANGE(r300, at);
113 r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0;
114
115 R300_STATECHANGE(r300, bld);
116 r300->hw.bld.cmd[R300_BLD_CBLEND] = 0;
117 r300->hw.bld.cmd[R300_BLD_ABLEND] = 0;
118
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;
122
123 R300_STATECHANGE(r300, unk221C);
124 r300->hw.unk221C.cmd[1] = R300_221C_CLEAR;
125
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);
130
131 R300_STATECHANGE(r300, ri);
132 for(i = 1; i <= 8; ++i)
133 r300->hw.ri.cmd[i] = R300_RS_INTERP_USED;
134
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;
139
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;
143
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);
151 } else {
152 r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0;
153 }
154
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;
163
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;
172
173 /* MOV o0, t0 */
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);
178
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);
187
188 R300_STATECHANGE(r300, vpi);
189 ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->unchecked_state.count = 8;
190
191 /* MOV o0, i0; */
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;
196
197 /* MOV o1, i1; */
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;
202
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;
207 /*
208 R300_STATECHANGE(r300, zb);
209 r300->hw.zb.cmd[R300_ZB_OFFSET] =
210 1024*4*300 +
211 r300->radeon.radeonScreen->frontOffset +
212 r300->radeon.radeonScreen->fbLocation;
213 r300->hw.zb.cmd[R300_ZB_PITCH] =
214 r300->radeon.radeonScreen->depthPitch;
215 */
216 } else {
217 r300->hw.zc.cmd[R300_ZC_CNTL_0] = 0; // disable
218 r300->hw.zc.cmd[R300_ZC_CNTL_1] = 0;
219 }
220
221 /* Make sure we have enough space */
222 r300EnsureCmdBufSpace(r300, r300->hw.max_state_size + 9, __FUNCTION__);
223
224 r300EmitState(r300);
225
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]);
237 }
238
239
240 /**
241 * Buffer clear
242 */
243 static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all,
244 GLint cx, GLint cy, GLint cw, GLint ch)
245 {
246 r300ContextPtr r300 = R300_CONTEXT(ctx);
247 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
248 int flags = 0;
249 int bits = 0;
250 int swapped;
251
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);
255
256 {
257 LOCK_HARDWARE(&r300->radeon);
258 UNLOCK_HARDWARE(&r300->radeon);
259 if (dPriv->numClipRects == 0)
260 return;
261 }
262
263 if (mask & DD_FRONT_LEFT_BIT) {
264 flags |= DD_FRONT_LEFT_BIT;
265 mask &= ~DD_FRONT_LEFT_BIT;
266 }
267
268 if (mask & DD_BACK_LEFT_BIT) {
269 flags |= DD_BACK_LEFT_BIT;
270 mask &= ~DD_BACK_LEFT_BIT;
271 }
272
273 if (mask & DD_DEPTH_BIT) {
274 bits |= CLEARBUFFER_DEPTH;
275 mask &= ~DD_DEPTH_BIT;
276 }
277
278 if (mask) {
279 if (RADEON_DEBUG & DEBUG_FALLBACKS)
280 fprintf(stderr, "%s: swrast clear, mask: %x\n",
281 __FUNCTION__, mask);
282 _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
283 }
284
285 swapped = r300->radeon.doPageFlip && (r300->radeon.sarea->pfCurrentPage == 1);
286
287 if (flags & DD_FRONT_LEFT_BIT) {
288 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
289 bits = 0;
290 }
291
292 if (flags & DD_BACK_LEFT_BIT) {
293 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
294 bits = 0;
295 }
296
297 if (bits)
298 r300ClearBuffer(r300, bits, 0);
299
300 /* Recalculate the hardware state. This could be done more efficiently,
301 * but do keep it like this for now.
302 */
303 r300ResetHwState(r300);
304 }
305
306 void r300Flush(GLcontext * ctx)
307 {
308 r300ContextPtr r300 = R300_CONTEXT(ctx);
309
310 if (RADEON_DEBUG & DEBUG_IOCTL)
311 fprintf(stderr, "%s\n", __FUNCTION__);
312
313 if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit)
314 r300FlushCmdBuf(r300, __FUNCTION__);
315 }
316
317 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
318 {
319 struct r200_dma_buffer *dmabuf;
320 int fd = rmesa->radeon.dri.fd;
321 int index = 0;
322 int size = 0;
323 drmDMAReq dma;
324 int ret;
325
326 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
327 fprintf(stderr, "%s\n", __FUNCTION__);
328
329 if (rmesa->dma.flush) {
330 rmesa->dma.flush(rmesa);
331 }
332
333 if (rmesa->dma.current.buf)
334 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
335
336 if (rmesa->dma.nr_released_bufs > 4)
337 r300FlushCmdBuf(rmesa, __FUNCTION__);
338
339 dma.context = rmesa->radeon.dri.hwContext;
340 dma.send_count = 0;
341 dma.send_list = NULL;
342 dma.send_sizes = NULL;
343 dma.flags = 0;
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;
349
350 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
351
352 while (1) {
353 ret = drmDMA(fd, &dma);
354 if (ret == 0)
355 break;
356
357 if (rmesa->dma.nr_released_bufs) {
358 r200FlushCmdBufLocked(rmesa, __FUNCTION__);
359 }
360
361 if (rmesa->radeon.do_usleeps) {
362 UNLOCK_HARDWARE(&rmesa->radeon);
363 DO_USLEEP(1);
364 LOCK_HARDWARE(&rmesa->radeon);
365 }
366 }
367
368 UNLOCK_HARDWARE(&rmesa->radeon);
369
370 if (RADEON_DEBUG & DEBUG_DMA)
371 fprintf(stderr, "Allocated buffer %d\n", index);
372
373 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
374 dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
375 dmabuf->refcount = 1;
376
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;
382 }
383
384 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
385 struct r300_dma_region *region, const char *caller)
386 {
387 if (RADEON_DEBUG & DEBUG_IOCTL)
388 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
389
390 if (!region->buf)
391 return;
392
393 if (rmesa->dma.flush)
394 rmesa->dma.flush(rmesa);
395
396 if (--region->buf->refcount == 0) {
397 drm_radeon_cmd_header_t *cmd;
398
399 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
400 fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
401 region->buf->buf->idx);
402
403 cmd =
404 (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
405 sizeof(*cmd),
406 __FUNCTION__);
407 cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
408 cmd->dma.buf_idx = region->buf->buf->idx;
409 FREE(region->buf);
410 rmesa->dma.nr_released_bufs++;
411 }
412
413 region->buf = 0;
414 region->start = 0;
415 }
416
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)
419 */
420 void r300AllocDmaRegion(r300ContextPtr rmesa,
421 struct r300_dma_region *region,
422 int bytes, int alignment)
423 {
424 if (RADEON_DEBUG & DEBUG_IOCTL)
425 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
426
427 if (rmesa->dma.flush)
428 rmesa->dma.flush(rmesa);
429
430 if (region->buf)
431 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
432
433 alignment--;
434 rmesa->dma.current.start = rmesa->dma.current.ptr =
435 (rmesa->dma.current.ptr + alignment) & ~alignment;
436
437 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
438 r300RefillCurrentDmaRegion(rmesa);
439
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++;
446
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;
450
451 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
452 }
453
454 /* Called via glXGetMemoryOffsetMESA() */
455 GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn,
456 const GLvoid * pointer)
457 {
458 GET_CURRENT_CONTEXT(ctx);
459 r300ContextPtr rmesa;
460 GLuint card_offset;
461
462 if (!ctx || !(rmesa = R300_CONTEXT(ctx))) {
463 fprintf(stderr, "%s: no context\n", __FUNCTION__);
464 return ~0;
465 }
466
467 if (!r300IsGartMemory(rmesa, pointer, 0))
468 return ~0;
469
470 if (rmesa->radeon.dri.drmMinor < 6)
471 return ~0;
472
473 card_offset = r300GartOffsetFromVirtual(rmesa, pointer);
474
475 return card_offset - rmesa->radeon.radeonScreen->gart_base;
476 }
477
478 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
479 GLint size)
480 {
481 int offset =
482 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
483 int valid = (size >= 0 && offset >= 0
484 && offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
485
486 if (RADEON_DEBUG & DEBUG_IOCTL)
487 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
488 valid);
489
490 return valid;
491 }
492
493 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
494 {
495 int offset =
496 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
497
498 fprintf(stderr, "offset=%08x\n", offset);
499
500 if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
501 return ~0;
502 else
503 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
504 }
505
506 void r300InitIoctlFuncs(struct dd_function_table *functions)
507 {
508 functions->Clear = r300Clear;
509 functions->Finish = radeonFinish;
510 functions->Flush = r300Flush;
511 }