r300: Added some more Doxygen documentation and made some functions static.
[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(0);
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 R300_STATECHANGE(r300, vir[0]);
198 reg_start(R300_VAP_INPUT_ROUTE_0_0, 0);
199 if (!has_tcl)
200 e32(0x22030003);
201 else
202 e32(0x21030003);
203
204 /* disable fog */
205 R300_STATECHANGE(r300, fogs);
206 reg_start(R300_RE_FOG_STATE, 0);
207 e32(0x0);
208
209 R300_STATECHANGE(r300, vir[1]);
210 reg_start(R300_VAP_INPUT_ROUTE_1_0, 0);
211 e32(0xF688F688);
212
213 R300_STATECHANGE(r300, vic);
214 reg_start(R300_VAP_INPUT_CNTL_0, 1);
215 e32(0x00000001);
216 e32(0x00000405);
217
218 if (!has_tcl) {
219 R300_STATECHANGE(r300, vte);
220 /* comes from fglrx startup of clear */
221 reg_start(R300_SE_VTE_CNTL, 1);
222 e32(0x043f);
223 e32(0x8);
224
225 reg_start(0x21dc, 0);
226 e32(0xaaaaaaaa);
227 }
228
229 R300_STATECHANGE(r300, vof);
230 reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1);
231 e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT |
232 R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT);
233 e32(0); /* no textures */
234
235 R300_STATECHANGE(r300, txe);
236 reg_start(R300_TX_ENABLE, 0);
237 e32(0);
238
239 R300_STATECHANGE(r300, vpt);
240 reg_start(R300_SE_VPORT_XSCALE, 5);
241 efloat(1.0);
242 efloat(dPriv->x);
243 efloat(1.0);
244 efloat(dPriv->y);
245 efloat(1.0);
246 efloat(0.0);
247
248 R300_STATECHANGE(r300, at);
249 reg_start(R300_PP_ALPHA_TEST, 0);
250 e32(0);
251
252 R300_STATECHANGE(r300, bld);
253 reg_start(R300_RB3D_CBLEND, 1);
254 e32(0);
255 e32(0);
256
257 R300_STATECHANGE(r300, unk221C);
258 reg_start(R300_VAP_UNKNOWN_221C, 0);
259 e32(R300_221C_CLEAR);
260
261 R300_STATECHANGE(r300, ps);
262 reg_start(R300_RE_POINTSIZE, 0);
263 e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
264 ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
265
266 R300_STATECHANGE(r300, ri);
267 reg_start(R300_RS_INTERP_0, 8);
268 for (i = 0; i < 8; ++i) {
269 e32(R300_RS_INTERP_USED);
270 }
271
272 R300_STATECHANGE(r300, rc);
273 /* The second constant is needed to get glxgears display anything .. */
274 reg_start(R300_RS_CNTL_0, 1);
275 e32((1 << R300_RS_CNTL_CI_CNT_SHIFT) | R300_RS_CNTL_0_UNKNOWN_18);
276 e32(0);
277
278 R300_STATECHANGE(r300, rr);
279 reg_start(R300_RS_ROUTE_0, 0);
280 e32(0x00004000);
281
282 R300_STATECHANGE(r300, fp);
283 reg_start(R300_PFS_CNTL_0, 2);
284 e32(0);
285 e32(0);
286 e32(0);
287 reg_start(R300_PFS_NODE_0, 3);
288 e32(0);
289 e32(0);
290 e32(0);
291 e32(R300_PFS_NODE_OUTPUT_COLOR);
292
293 R300_STATECHANGE(r300, fpi[0]);
294 R300_STATECHANGE(r300, fpi[1]);
295 R300_STATECHANGE(r300, fpi[2]);
296 R300_STATECHANGE(r300, fpi[3]);
297
298 reg_start(R300_PFS_INSTR0_0, 0);
299 e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
300
301 reg_start(R300_PFS_INSTR1_0, 0);
302 e32(FP_SELC(0, NO, XYZ, FP_TMP(0), 0, 0));
303
304 reg_start(R300_PFS_INSTR2_0, 0);
305 e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
306
307 reg_start(R300_PFS_INSTR3_0, 0);
308 e32(FP_SELA(0, NO, W, FP_TMP(0), 0, 0));
309
310 if (has_tcl) {
311 R300_STATECHANGE(r300, pvs);
312 reg_start(R300_VAP_PVS_CNTL_1, 2);
313 e32((0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) |
314 (0 << R300_PVS_CNTL_1_POS_END_SHIFT) |
315 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT));
316 e32(0);
317 e32(1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT);
318
319 R300_STATECHANGE(r300, vpi);
320 vsf_start_fragment(0x0, 8);
321 e32(VP_OUT(ADD, OUT, 0, XYZW));
322 e32(VP_IN(IN, 0));
323 e32(VP_ZERO());
324 e32(0);
325
326 e32(VP_OUT(ADD, OUT, 1, XYZW));
327 e32(VP_IN(IN, 1));
328 e32(VP_ZERO());
329 e32(0);
330 }
331 }
332
333 /**
334 * Buffer clear
335 */
336 static void r300Clear(GLcontext * ctx, GLbitfield mask)
337 {
338 r300ContextPtr r300 = R300_CONTEXT(ctx);
339 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
340 int flags = 0;
341 int bits = 0;
342 int swapped;
343
344 if (RADEON_DEBUG & DEBUG_IOCTL)
345 fprintf(stderr, "r300Clear\n");
346
347 {
348 LOCK_HARDWARE(&r300->radeon);
349 UNLOCK_HARDWARE(&r300->radeon);
350 if (dPriv->numClipRects == 0)
351 return;
352 }
353
354 if (mask & BUFFER_BIT_FRONT_LEFT) {
355 flags |= BUFFER_BIT_FRONT_LEFT;
356 mask &= ~BUFFER_BIT_FRONT_LEFT;
357 }
358
359 if (mask & BUFFER_BIT_BACK_LEFT) {
360 flags |= BUFFER_BIT_BACK_LEFT;
361 mask &= ~BUFFER_BIT_BACK_LEFT;
362 }
363
364 if (mask & BUFFER_BIT_DEPTH) {
365 bits |= CLEARBUFFER_DEPTH;
366 mask &= ~BUFFER_BIT_DEPTH;
367 }
368
369 if ((mask & BUFFER_BIT_STENCIL) && r300->state.stencil.hw_stencil) {
370 bits |= CLEARBUFFER_STENCIL;
371 mask &= ~BUFFER_BIT_STENCIL;
372 }
373
374 if (mask) {
375 if (RADEON_DEBUG & DEBUG_FALLBACKS)
376 fprintf(stderr, "%s: swrast clear, mask: %x\n",
377 __FUNCTION__, mask);
378 _swrast_Clear(ctx, mask);
379 }
380
381 swapped = r300->radeon.sarea->pfCurrentPage == 1;
382
383 /* Make sure it fits there. */
384 r300EnsureCmdBufSpace(r300, 421 * 3, __FUNCTION__);
385 if (flags || bits)
386 r300EmitClearState(ctx);
387
388 if (flags & BUFFER_BIT_FRONT_LEFT) {
389 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
390 bits = 0;
391 }
392
393 if (flags & BUFFER_BIT_BACK_LEFT) {
394 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
395 bits = 0;
396 }
397
398 if (bits)
399 r300ClearBuffer(r300, bits, 0);
400
401 }
402
403 void r300Flush(GLcontext * ctx)
404 {
405 r300ContextPtr r300 = R300_CONTEXT(ctx);
406
407 if (RADEON_DEBUG & DEBUG_IOCTL)
408 fprintf(stderr, "%s\n", __FUNCTION__);
409
410 if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit)
411 r300FlushCmdBuf(r300, __FUNCTION__);
412 }
413
414 #ifdef USER_BUFFERS
415 #include "r300_mem.h"
416
417 static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
418 {
419 struct r300_dma_buffer *dmabuf;
420 size = MAX2(size, RADEON_BUFFER_SIZE * 16);
421
422 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
423 fprintf(stderr, "%s\n", __FUNCTION__);
424
425 if (rmesa->dma.flush) {
426 rmesa->dma.flush(rmesa);
427 }
428
429 if (rmesa->dma.current.buf)
430 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
431
432 if (rmesa->dma.nr_released_bufs > 4)
433 r300FlushCmdBuf(rmesa, __FUNCTION__);
434
435 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
436 dmabuf->buf = (void *)1; /* hack */
437 dmabuf->refcount = 1;
438
439 dmabuf->id = r300_mem_alloc(rmesa, 4, size);
440 if (dmabuf->id == 0) {
441 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
442
443 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
444 radeonWaitForIdleLocked(&rmesa->radeon);
445
446 dmabuf->id = r300_mem_alloc(rmesa, 4, size);
447
448 UNLOCK_HARDWARE(&rmesa->radeon);
449
450 if (dmabuf->id == 0) {
451 fprintf(stderr,
452 "Error: Could not get dma buffer... exiting\n");
453 _mesa_exit(-1);
454 }
455 }
456
457 rmesa->dma.current.buf = dmabuf;
458 rmesa->dma.current.address = r300_mem_ptr(rmesa, dmabuf->id);
459 rmesa->dma.current.end = size;
460 rmesa->dma.current.start = 0;
461 rmesa->dma.current.ptr = 0;
462 }
463
464 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
465 struct r300_dma_region *region, const char *caller)
466 {
467 if (RADEON_DEBUG & DEBUG_IOCTL)
468 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
469
470 if (!region->buf)
471 return;
472
473 if (rmesa->dma.flush)
474 rmesa->dma.flush(rmesa);
475
476 if (--region->buf->refcount == 0) {
477 r300_mem_free(rmesa, region->buf->id);
478 FREE(region->buf);
479 rmesa->dma.nr_released_bufs++;
480 }
481
482 region->buf = 0;
483 region->start = 0;
484 }
485
486 /* Allocates a region from rmesa->dma.current. If there isn't enough
487 * space in current, grab a new buffer (and discard what was left of current)
488 */
489 void r300AllocDmaRegion(r300ContextPtr rmesa,
490 struct r300_dma_region *region,
491 int bytes, int alignment)
492 {
493 if (RADEON_DEBUG & DEBUG_IOCTL)
494 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
495
496 if (rmesa->dma.flush)
497 rmesa->dma.flush(rmesa);
498
499 if (region->buf)
500 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
501
502 alignment--;
503 rmesa->dma.current.start = rmesa->dma.current.ptr =
504 (rmesa->dma.current.ptr + alignment) & ~alignment;
505
506 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
507 r300RefillCurrentDmaRegion(rmesa, (bytes + 0x7) & ~0x7);
508
509 region->start = rmesa->dma.current.start;
510 region->ptr = rmesa->dma.current.start;
511 region->end = rmesa->dma.current.start + bytes;
512 region->address = rmesa->dma.current.address;
513 region->buf = rmesa->dma.current.buf;
514 region->buf->refcount++;
515
516 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
517 rmesa->dma.current.start =
518 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
519
520 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
521 }
522
523 #else
524 static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
525 {
526 struct r300_dma_buffer *dmabuf;
527 int fd = rmesa->radeon.dri.fd;
528 int index = 0;
529 int size = 0;
530 drmDMAReq dma;
531 int ret;
532
533 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
534 fprintf(stderr, "%s\n", __FUNCTION__);
535
536 if (rmesa->dma.flush) {
537 rmesa->dma.flush(rmesa);
538 }
539
540 if (rmesa->dma.current.buf)
541 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
542
543 if (rmesa->dma.nr_released_bufs > 4)
544 r300FlushCmdBuf(rmesa, __FUNCTION__);
545
546 dma.context = rmesa->radeon.dri.hwContext;
547 dma.send_count = 0;
548 dma.send_list = NULL;
549 dma.send_sizes = NULL;
550 dma.flags = 0;
551 dma.request_count = 1;
552 dma.request_size = RADEON_BUFFER_SIZE;
553 dma.request_list = &index;
554 dma.request_sizes = &size;
555 dma.granted_count = 0;
556
557 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
558
559 ret = drmDMA(fd, &dma);
560
561 if (ret != 0) {
562 /* Try to release some buffers and wait until we can't get any more */
563 if (rmesa->dma.nr_released_bufs) {
564 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
565 }
566
567 if (RADEON_DEBUG & DEBUG_DMA)
568 fprintf(stderr, "Waiting for buffers\n");
569
570 radeonWaitForIdleLocked(&rmesa->radeon);
571 ret = drmDMA(fd, &dma);
572
573 if (ret != 0) {
574 UNLOCK_HARDWARE(&rmesa->radeon);
575 fprintf(stderr,
576 "Error: Could not get dma buffer... exiting\n");
577 _mesa_exit(-1);
578 }
579 }
580
581 UNLOCK_HARDWARE(&rmesa->radeon);
582
583 if (RADEON_DEBUG & DEBUG_DMA)
584 fprintf(stderr, "Allocated buffer %d\n", index);
585
586 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
587 dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
588 dmabuf->refcount = 1;
589
590 rmesa->dma.current.buf = dmabuf;
591 rmesa->dma.current.address = dmabuf->buf->address;
592 rmesa->dma.current.end = dmabuf->buf->total;
593 rmesa->dma.current.start = 0;
594 rmesa->dma.current.ptr = 0;
595 }
596
597 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
598 struct r300_dma_region *region, const char *caller)
599 {
600 if (RADEON_DEBUG & DEBUG_IOCTL)
601 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
602
603 if (!region->buf)
604 return;
605
606 if (rmesa->dma.flush)
607 rmesa->dma.flush(rmesa);
608
609 if (--region->buf->refcount == 0) {
610 drm_radeon_cmd_header_t *cmd;
611
612 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
613 fprintf(stderr, "%s -- DISCARD BUF %d\n",
614 __FUNCTION__, region->buf->buf->idx);
615 cmd =
616 (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
617 sizeof
618 (*cmd) / 4,
619 __FUNCTION__);
620 cmd->dma.cmd_type = R300_CMD_DMA_DISCARD;
621 cmd->dma.buf_idx = region->buf->buf->idx;
622
623 FREE(region->buf);
624 rmesa->dma.nr_released_bufs++;
625 }
626
627 region->buf = 0;
628 region->start = 0;
629 }
630
631 /* Allocates a region from rmesa->dma.current. If there isn't enough
632 * space in current, grab a new buffer (and discard what was left of current)
633 */
634 void r300AllocDmaRegion(r300ContextPtr rmesa,
635 struct r300_dma_region *region,
636 int bytes, int alignment)
637 {
638 if (RADEON_DEBUG & DEBUG_IOCTL)
639 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
640
641 if (rmesa->dma.flush)
642 rmesa->dma.flush(rmesa);
643
644 if (region->buf)
645 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
646
647 alignment--;
648 rmesa->dma.current.start = rmesa->dma.current.ptr =
649 (rmesa->dma.current.ptr + alignment) & ~alignment;
650
651 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
652 r300RefillCurrentDmaRegion(rmesa);
653
654 region->start = rmesa->dma.current.start;
655 region->ptr = rmesa->dma.current.start;
656 region->end = rmesa->dma.current.start + bytes;
657 region->address = rmesa->dma.current.address;
658 region->buf = rmesa->dma.current.buf;
659 region->buf->refcount++;
660
661 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
662 rmesa->dma.current.start =
663 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
664
665 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
666 }
667
668 #endif
669
670 /* Called via glXGetMemoryOffsetMESA() */
671 GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn,
672 const GLvoid * pointer)
673 {
674 GET_CURRENT_CONTEXT(ctx);
675 r300ContextPtr rmesa;
676 GLuint card_offset;
677
678 if (!ctx || !(rmesa = R300_CONTEXT(ctx))) {
679 fprintf(stderr, "%s: no context\n", __FUNCTION__);
680 return ~0;
681 }
682
683 if (!r300IsGartMemory(rmesa, pointer, 0))
684 return ~0;
685
686 card_offset = r300GartOffsetFromVirtual(rmesa, pointer);
687
688 return card_offset - rmesa->radeon.radeonScreen->gart_base;
689 }
690
691 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
692 GLint size)
693 {
694 int offset =
695 (char *)pointer -
696 (char *)rmesa->radeon.radeonScreen->gartTextures.map;
697 int valid = (size >= 0 && offset >= 0
698 && offset + size <
699 rmesa->radeon.radeonScreen->gartTextures.size);
700
701 if (RADEON_DEBUG & DEBUG_IOCTL)
702 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
703 valid);
704
705 return valid;
706 }
707
708 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
709 {
710 int offset =
711 (char *)pointer -
712 (char *)rmesa->radeon.radeonScreen->gartTextures.map;
713
714 //fprintf(stderr, "offset=%08x\n", offset);
715
716 if (offset < 0
717 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
718 return ~0;
719 else
720 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
721 }
722
723 void r300InitIoctlFuncs(struct dd_function_table *functions)
724 {
725 functions->Clear = r300Clear;
726 functions->Finish = radeonFinish;
727 functions->Flush = r300Flush;
728 }