swtcl: gears works
[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 * \file
34 *
35 * \author Keith Whitwell <keith@tungstengraphics.com>
36 *
37 * \author Nicolai Haehnle <prefect_@gmx.net>
38 */
39
40 #include <sched.h>
41 #include <errno.h>
42
43 #include "glheader.h"
44 #include "imports.h"
45 #include "macros.h"
46 #include "context.h"
47 #include "swrast/swrast.h"
48
49 #include "r300_context.h"
50 #include "radeon_ioctl.h"
51 #include "r300_ioctl.h"
52 #include "r300_cmdbuf.h"
53 #include "r300_state.h"
54 #include "r300_program.h"
55 #include "radeon_reg.h"
56 #include "r300_emit.h"
57
58 #include "vblank.h"
59
60 #define CLEARBUFFER_COLOR 0x1
61 #define CLEARBUFFER_DEPTH 0x2
62 #define CLEARBUFFER_STENCIL 0x4
63
64 static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
65 {
66 GLcontext *ctx = r300->radeon.glCtx;
67 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
68 GLuint cboffset, cbpitch;
69 drm_r300_cmd_header_t *cmd2;
70 int cmd_reserved = 0;
71 int cmd_written = 0;
72 drm_radeon_cmd_header_t *cmd = NULL;
73 r300ContextPtr rmesa = r300;
74
75 if (RADEON_DEBUG & DEBUG_IOCTL)
76 fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n",
77 __FUNCTION__, buffer ? "back" : "front",
78 dPriv->x, dPriv->y, dPriv->w, dPriv->h);
79
80 if (buffer) {
81 cboffset = r300->radeon.radeonScreen->backOffset;
82 cbpitch = r300->radeon.radeonScreen->backPitch;
83 } else {
84 cboffset = r300->radeon.radeonScreen->frontOffset;
85 cbpitch = r300->radeon.radeonScreen->frontPitch;
86 }
87
88 cboffset += r300->radeon.radeonScreen->fbLocation;
89
90 cp_wait(r300, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
91 end_3d(rmesa);
92
93 R300_STATECHANGE(r300, cb);
94 reg_start(R300_RB3D_COLOROFFSET0, 0);
95 e32(cboffset);
96
97 if (r300->radeon.radeonScreen->cpp == 4)
98 cbpitch |= R300_COLOR_FORMAT_ARGB8888;
99 else
100 cbpitch |= R300_COLOR_FORMAT_RGB565;
101
102 if (r300->radeon.sarea->tiling_enabled)
103 cbpitch |= R300_COLOR_TILE_ENABLE;
104
105 reg_start(R300_RB3D_COLORPITCH0, 0);
106 e32(cbpitch);
107
108 R300_STATECHANGE(r300, cmk);
109 reg_start(R300_RB3D_COLORMASK, 0);
110
111 if (flags & CLEARBUFFER_COLOR) {
112 e32((ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) |
113 (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) |
114 (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) |
115 (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0));
116 } else {
117 e32(0x0);
118 }
119
120 R300_STATECHANGE(r300, zs);
121 reg_start(R300_RB3D_ZSTENCIL_CNTL_0, 2);
122
123 {
124 uint32_t t1, t2;
125
126 t1 = 0x0;
127 t2 = 0x0;
128
129 if (flags & CLEARBUFFER_DEPTH) {
130 t1 |= R300_RB3D_Z_WRITE_ONLY;
131 t2 |=
132 (R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
133 } else {
134 t1 |= R300_RB3D_Z_DISABLED_1; // disable
135 }
136
137 if (flags & CLEARBUFFER_STENCIL) {
138 t1 |= R300_RB3D_STENCIL_ENABLE;
139 t2 |=
140 (R300_ZS_ALWAYS <<
141 R300_RB3D_ZS1_FRONT_FUNC_SHIFT) |
142 (R300_ZS_REPLACE <<
143 R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) |
144 (R300_ZS_REPLACE <<
145 R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) |
146 (R300_ZS_REPLACE <<
147 R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) |
148 (R300_ZS_ALWAYS <<
149 R300_RB3D_ZS1_BACK_FUNC_SHIFT) |
150 (R300_ZS_REPLACE <<
151 R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) |
152 (R300_ZS_REPLACE <<
153 R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) |
154 (R300_ZS_REPLACE <<
155 R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT);
156 }
157
158 e32(t1);
159 e32(t2);
160 e32(r300->state.stencil.clear);
161 }
162
163 cmd2 = (drm_r300_cmd_header_t *) r300AllocCmdBuf(r300, 9, __FUNCTION__);
164 cmd2[0].packet3.cmd_type = R300_CMD_PACKET3;
165 cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
166 cmd2[1].u = r300PackFloat32(dPriv->w / 2.0);
167 cmd2[2].u = r300PackFloat32(dPriv->h / 2.0);
168 cmd2[3].u = r300PackFloat32(ctx->Depth.Clear);
169 cmd2[4].u = r300PackFloat32(1.0);
170 cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
171 cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
172 cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
173 cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
174
175 reg_start(R300_RB3D_DSTCACHE_CTLSTAT, 0);
176 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
177
178 reg_start(R300_RB3D_ZCACHE_CTLSTAT, 0);
179 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
180 cp_wait(rmesa, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
181 }
182
183 static void r300EmitClearState(GLcontext * ctx)
184 {
185 r300ContextPtr r300 = R300_CONTEXT(ctx);
186 r300ContextPtr rmesa = r300;
187 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
188 int i;
189 int cmd_reserved = 0;
190 int cmd_written = 0;
191 drm_radeon_cmd_header_t *cmd = NULL;
192 int has_tcl = 1;
193
194 if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
195 has_tcl = 0;
196
197 /* FIXME: the values written to R300_VAP_INPUT_ROUTE_0_0 and
198 * R300_VAP_INPUT_ROUTE_0_1 are in fact known, however, the values are
199 * quite complex; see the functions in r300_emit.c.
200 *
201 * I believe it would be a good idea to extend the functions in
202 * r300_emit.c so that they can be used to setup the default values for
203 * these registers, as well as the actual values used for rendering.
204 */
205 R300_STATECHANGE(r300, vir[0]);
206 reg_start(R300_VAP_INPUT_ROUTE_0_0, 0);
207 if (!has_tcl)
208 e32(0x22030003);
209 else
210 e32(0x21030003);
211
212 /* disable fog */
213 R300_STATECHANGE(r300, fogs);
214 reg_start(R300_RE_FOG_STATE, 0);
215 e32(0x0);
216
217 R300_STATECHANGE(r300, vir[1]);
218 reg_start(R300_VAP_INPUT_ROUTE_1_0, 0);
219 e32(0xF688F688);
220
221 /* R300_VAP_INPUT_CNTL_0, R300_VAP_INPUT_CNTL_1 */
222 R300_STATECHANGE(r300, vic);
223 reg_start(R300_VAP_INPUT_CNTL_0, 1);
224 e32(R300_INPUT_CNTL_0_COLOR);
225 e32(R300_INPUT_CNTL_POS | R300_INPUT_CNTL_COLOR | R300_INPUT_CNTL_TC0);
226
227 R300_STATECHANGE(r300, vte);
228 /* comes from fglrx startup of clear */
229 reg_start(R300_SE_VTE_CNTL, 1);
230 e32(R300_VTX_W0_FMT | R300_VPORT_X_SCALE_ENA |
231 R300_VPORT_X_OFFSET_ENA | R300_VPORT_Y_SCALE_ENA |
232 R300_VPORT_Y_OFFSET_ENA | R300_VPORT_Z_SCALE_ENA |
233 R300_VPORT_Z_OFFSET_ENA);
234 e32(0x8);
235
236 reg_start(0x21dc, 0);
237 e32(0xaaaaaaaa);
238
239 R300_STATECHANGE(r300, vof);
240 reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1);
241 e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
242 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT);
243 e32(0x0); /* no textures */
244
245 R300_STATECHANGE(r300, txe);
246 reg_start(R300_TX_ENABLE, 0);
247 e32(0x0);
248
249 R300_STATECHANGE(r300, vpt);
250 reg_start(R300_SE_VPORT_XSCALE, 5);
251 efloat(1.0);
252 efloat(dPriv->x);
253 efloat(1.0);
254 efloat(dPriv->y);
255 efloat(1.0);
256 efloat(0.0);
257
258 R300_STATECHANGE(r300, at);
259 reg_start(R300_PP_ALPHA_TEST, 0);
260 e32(0x0);
261
262 R300_STATECHANGE(r300, bld);
263 reg_start(R300_RB3D_CBLEND, 1);
264 e32(0x0);
265 e32(0x0);
266
267 R300_STATECHANGE(r300, unk221C);
268 reg_start(R300_VAP_UNKNOWN_221C, 0);
269 e32(R300_221C_CLEAR);
270
271 R300_STATECHANGE(r300, ps);
272 reg_start(R300_RE_POINTSIZE, 0);
273 e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
274 ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
275
276 R300_STATECHANGE(r300, ri);
277 reg_start(R300_RS_INTERP_0, 8);
278 for (i = 0; i < 8; ++i) {
279 e32(R300_RS_INTERP_USED);
280 }
281
282 R300_STATECHANGE(r300, rc);
283 /* The second constant is needed to get glxgears display anything .. */
284 reg_start(R300_RS_CNTL_0, 1);
285 e32((1 << R300_RS_CNTL_CI_CNT_SHIFT) | R300_RS_CNTL_0_UNKNOWN_18);
286 e32(0x0);
287
288 R300_STATECHANGE(r300, rr);
289 reg_start(R300_RS_ROUTE_0, 0);
290 e32(R300_RS_ROUTE_0_COLOR);
291
292 R300_STATECHANGE(r300, fp);
293 reg_start(R300_PFS_CNTL_0, 2);
294 e32(0x0);
295 e32(0x0);
296 e32(0x0);
297 reg_start(R300_PFS_NODE_0, 3);
298 e32(0x0);
299 e32(0x0);
300 e32(0x0);
301 e32(R300_PFS_NODE_OUTPUT_COLOR);
302
303 R300_STATECHANGE(r300, fpi[0]);
304 R300_STATECHANGE(r300, fpi[1]);
305 R300_STATECHANGE(r300, fpi[2]);
306 R300_STATECHANGE(r300, fpi[3]);
307
308 reg_start(R300_PFS_INSTR0_0, 0);
309 e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
310
311 reg_start(R300_PFS_INSTR1_0, 0);
312 e32(FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
313
314 reg_start(R300_PFS_INSTR2_0, 0);
315 e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
316
317 reg_start(R300_PFS_INSTR3_0, 0);
318 e32(FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
319
320 if (has_tcl) {
321 R300_STATECHANGE(r300, pvs);
322 reg_start(R300_VAP_PVS_CNTL_1, 2);
323 e32((0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) |
324 (0 << R300_PVS_CNTL_1_POS_END_SHIFT) |
325 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT));
326 e32(0x0);
327 e32(1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT);
328
329 R300_STATECHANGE(r300, vpi);
330 vsf_start_fragment(0x0, 8);
331 e32(VP_OUT(ADD, OUT, 0, XYZW));
332 e32(VP_IN(IN, 0));
333 e32(VP_ZERO());
334 e32(0x0);
335
336 e32(VP_OUT(ADD, OUT, 1, XYZW));
337 e32(VP_IN(IN, 1));
338 e32(VP_ZERO());
339 e32(0x0);
340 }
341 }
342
343 /**
344 * Buffer clear
345 */
346 static void r300Clear(GLcontext * ctx, GLbitfield mask)
347 {
348 r300ContextPtr r300 = R300_CONTEXT(ctx);
349 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
350 int flags = 0;
351 int bits = 0;
352 int swapped;
353
354 if (RADEON_DEBUG & DEBUG_IOCTL)
355 fprintf(stderr, "r300Clear\n");
356
357 {
358 LOCK_HARDWARE(&r300->radeon);
359 UNLOCK_HARDWARE(&r300->radeon);
360 if (dPriv->numClipRects == 0)
361 return;
362 }
363
364 if (mask & BUFFER_BIT_FRONT_LEFT) {
365 flags |= BUFFER_BIT_FRONT_LEFT;
366 mask &= ~BUFFER_BIT_FRONT_LEFT;
367 }
368
369 if (mask & BUFFER_BIT_BACK_LEFT) {
370 flags |= BUFFER_BIT_BACK_LEFT;
371 mask &= ~BUFFER_BIT_BACK_LEFT;
372 }
373
374 if (mask & BUFFER_BIT_DEPTH) {
375 bits |= CLEARBUFFER_DEPTH;
376 mask &= ~BUFFER_BIT_DEPTH;
377 }
378
379 if ((mask & BUFFER_BIT_STENCIL) && r300->state.stencil.hw_stencil) {
380 bits |= CLEARBUFFER_STENCIL;
381 mask &= ~BUFFER_BIT_STENCIL;
382 }
383
384 if (mask) {
385 if (RADEON_DEBUG & DEBUG_FALLBACKS)
386 fprintf(stderr, "%s: swrast clear, mask: %x\n",
387 __FUNCTION__, mask);
388 _swrast_Clear(ctx, mask);
389 }
390
391 swapped = r300->radeon.sarea->pfCurrentPage == 1;
392
393 /* Make sure it fits there. */
394 r300EnsureCmdBufSpace(r300, 421 * 3, __FUNCTION__);
395 if (flags || bits)
396 r300EmitClearState(ctx);
397
398 if (flags & BUFFER_BIT_FRONT_LEFT) {
399 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
400 bits = 0;
401 }
402
403 if (flags & BUFFER_BIT_BACK_LEFT) {
404 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
405 bits = 0;
406 }
407
408 if (bits)
409 r300ClearBuffer(r300, bits, 0);
410
411 }
412
413 void r300Flush(GLcontext * ctx)
414 {
415 r300ContextPtr rmesa = R300_CONTEXT(ctx);
416
417 if (RADEON_DEBUG & DEBUG_IOCTL)
418 fprintf(stderr, "%s\n", __FUNCTION__);
419
420 if (rmesa->dma.flush)
421 rmesa->dma.flush( rmesa );
422
423 if (rmesa->cmdbuf.count_used > rmesa->cmdbuf.count_reemit)
424 r300FlushCmdBuf(rmesa, __FUNCTION__);
425 }
426
427 #ifdef USER_BUFFERS
428 #include "r300_mem.h"
429
430 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
431 {
432 struct r300_dma_buffer *dmabuf;
433 size = MAX2(size, RADEON_BUFFER_SIZE * 16);
434
435 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
436 fprintf(stderr, "%s\n", __FUNCTION__);
437
438 if (rmesa->dma.flush) {
439 rmesa->dma.flush(rmesa);
440 }
441
442 if (rmesa->dma.current.buf)
443 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
444
445 if (rmesa->dma.nr_released_bufs > 4)
446 r300FlushCmdBuf(rmesa, __FUNCTION__);
447
448 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
449 dmabuf->buf = (void *)1; /* hack */
450 dmabuf->refcount = 1;
451
452 dmabuf->id = r300_mem_alloc(rmesa, 4, size);
453 if (dmabuf->id == 0) {
454 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
455
456 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
457 radeonWaitForIdleLocked(&rmesa->radeon);
458
459 dmabuf->id = r300_mem_alloc(rmesa, 4, size);
460
461 UNLOCK_HARDWARE(&rmesa->radeon);
462
463 if (dmabuf->id == 0) {
464 fprintf(stderr,
465 "Error: Could not get dma buffer... exiting\n");
466 _mesa_exit(-1);
467 }
468 }
469
470 rmesa->dma.current.buf = dmabuf;
471 rmesa->dma.current.address = r300_mem_ptr(rmesa, dmabuf->id);
472 rmesa->dma.current.end = size;
473 rmesa->dma.current.start = 0;
474 rmesa->dma.current.ptr = 0;
475 }
476
477 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
478 struct r300_dma_region *region, const char *caller)
479 {
480 if (RADEON_DEBUG & DEBUG_IOCTL)
481 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
482
483 if (!region->buf)
484 return;
485
486 if (rmesa->dma.flush)
487 rmesa->dma.flush(rmesa);
488
489 if (--region->buf->refcount == 0) {
490 r300_mem_free(rmesa, region->buf->id);
491 FREE(region->buf);
492 rmesa->dma.nr_released_bufs++;
493 }
494
495 region->buf = 0;
496 region->start = 0;
497 }
498
499 /* Allocates a region from rmesa->dma.current. If there isn't enough
500 * space in current, grab a new buffer (and discard what was left of current)
501 */
502 void r300AllocDmaRegion(r300ContextPtr rmesa,
503 struct r300_dma_region *region,
504 int bytes, int alignment)
505 {
506 if (RADEON_DEBUG & DEBUG_IOCTL)
507 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
508
509 if (rmesa->dma.flush)
510 rmesa->dma.flush(rmesa);
511
512 if (region->buf)
513 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
514
515 alignment--;
516 rmesa->dma.current.start = rmesa->dma.current.ptr =
517 (rmesa->dma.current.ptr + alignment) & ~alignment;
518
519 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
520 r300RefillCurrentDmaRegion(rmesa, (bytes + 0x7) & ~0x7);
521
522 region->start = rmesa->dma.current.start;
523 region->ptr = rmesa->dma.current.start;
524 region->end = rmesa->dma.current.start + bytes;
525 region->address = rmesa->dma.current.address;
526 region->buf = rmesa->dma.current.buf;
527 region->buf->refcount++;
528
529 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
530 rmesa->dma.current.start =
531 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
532
533 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
534 }
535
536 #else
537 static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
538 {
539 struct r300_dma_buffer *dmabuf;
540 int fd = rmesa->radeon.dri.fd;
541 int index = 0;
542 int size = 0;
543 drmDMAReq dma;
544 int ret;
545
546 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
547 fprintf(stderr, "%s\n", __FUNCTION__);
548
549 if (rmesa->dma.flush) {
550 rmesa->dma.flush(rmesa);
551 }
552
553 if (rmesa->dma.current.buf)
554 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
555
556 if (rmesa->dma.nr_released_bufs > 4)
557 r300FlushCmdBuf(rmesa, __FUNCTION__);
558
559 dma.context = rmesa->radeon.dri.hwContext;
560 dma.send_count = 0;
561 dma.send_list = NULL;
562 dma.send_sizes = NULL;
563 dma.flags = 0;
564 dma.request_count = 1;
565 dma.request_size = RADEON_BUFFER_SIZE;
566 dma.request_list = &index;
567 dma.request_sizes = &size;
568 dma.granted_count = 0;
569
570 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
571
572 ret = drmDMA(fd, &dma);
573
574 if (ret != 0) {
575 /* Try to release some buffers and wait until we can't get any more */
576 if (rmesa->dma.nr_released_bufs) {
577 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
578 }
579
580 if (RADEON_DEBUG & DEBUG_DMA)
581 fprintf(stderr, "Waiting for buffers\n");
582
583 radeonWaitForIdleLocked(&rmesa->radeon);
584 ret = drmDMA(fd, &dma);
585
586 if (ret != 0) {
587 UNLOCK_HARDWARE(&rmesa->radeon);
588 fprintf(stderr,
589 "Error: Could not get dma buffer... exiting\n");
590 _mesa_exit(-1);
591 }
592 }
593
594 UNLOCK_HARDWARE(&rmesa->radeon);
595
596 if (RADEON_DEBUG & DEBUG_DMA)
597 fprintf(stderr, "Allocated buffer %d\n", index);
598
599 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
600 dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
601 dmabuf->refcount = 1;
602
603 rmesa->dma.current.buf = dmabuf;
604 rmesa->dma.current.address = dmabuf->buf->address;
605 rmesa->dma.current.end = dmabuf->buf->total;
606 rmesa->dma.current.start = 0;
607 rmesa->dma.current.ptr = 0;
608 }
609
610 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
611 struct r300_dma_region *region, const char *caller)
612 {
613 if (RADEON_DEBUG & DEBUG_IOCTL)
614 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
615
616 if (!region->buf)
617 return;
618
619 if (rmesa->dma.flush)
620 rmesa->dma.flush(rmesa);
621
622 if (--region->buf->refcount == 0) {
623 drm_radeon_cmd_header_t *cmd;
624
625 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
626 fprintf(stderr, "%s -- DISCARD BUF %d\n",
627 __FUNCTION__, region->buf->buf->idx);
628 cmd =
629 (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
630 sizeof
631 (*cmd) / 4,
632 __FUNCTION__);
633 cmd->dma.cmd_type = R300_CMD_DMA_DISCARD;
634 cmd->dma.buf_idx = region->buf->buf->idx;
635
636 FREE(region->buf);
637 rmesa->dma.nr_released_bufs++;
638 }
639
640 region->buf = 0;
641 region->start = 0;
642 }
643
644 /* Allocates a region from rmesa->dma.current. If there isn't enough
645 * space in current, grab a new buffer (and discard what was left of current)
646 */
647 void r300AllocDmaRegion(r300ContextPtr rmesa,
648 struct r300_dma_region *region,
649 int bytes, int alignment)
650 {
651 if (RADEON_DEBUG & DEBUG_IOCTL)
652 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
653
654 if (rmesa->dma.flush)
655 rmesa->dma.flush(rmesa);
656
657 if (region->buf)
658 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
659
660 alignment--;
661 rmesa->dma.current.start = rmesa->dma.current.ptr =
662 (rmesa->dma.current.ptr + alignment) & ~alignment;
663
664 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
665 r300RefillCurrentDmaRegion(rmesa);
666
667 region->start = rmesa->dma.current.start;
668 region->ptr = rmesa->dma.current.start;
669 region->end = rmesa->dma.current.start + bytes;
670 region->address = rmesa->dma.current.address;
671 region->buf = rmesa->dma.current.buf;
672 region->buf->refcount++;
673
674 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
675 rmesa->dma.current.start =
676 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
677
678 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
679 }
680
681 #endif
682
683 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
684 GLint size)
685 {
686 int offset =
687 (char *)pointer -
688 (char *)rmesa->radeon.radeonScreen->gartTextures.map;
689 int valid = (size >= 0 && offset >= 0
690 && offset + size <
691 rmesa->radeon.radeonScreen->gartTextures.size);
692
693 if (RADEON_DEBUG & DEBUG_IOCTL)
694 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
695 valid);
696
697 return valid;
698 }
699
700 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
701 {
702 int offset =
703 (char *)pointer -
704 (char *)rmesa->radeon.radeonScreen->gartTextures.map;
705
706 //fprintf(stderr, "offset=%08x\n", offset);
707
708 if (offset < 0
709 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
710 return ~0;
711 else
712 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
713 }
714
715 void r300InitIoctlFuncs(struct dd_function_table *functions)
716 {
717 functions->Clear = r300Clear;
718 functions->Finish = radeonFinish;
719 functions->Flush = r300Flush;
720 }