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