82414259df9966980bac78641ddb0dae6549ee4d
[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 |= (R300_ZS_ALWAYS << R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
130 } else {
131 t1 |= R300_RB3D_Z_DISABLED_1; // disable
132 }
133
134 if (flags & CLEARBUFFER_STENCIL) {
135 t1 |= R300_RB3D_STENCIL_ENABLE;
136 t2 |=
137 (R300_ZS_ALWAYS<<R300_RB3D_ZS1_FRONT_FUNC_SHIFT) |
138 (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_FAIL_OP_SHIFT) |
139 (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZPASS_OP_SHIFT) |
140 (R300_ZS_REPLACE<<R300_RB3D_ZS1_FRONT_ZFAIL_OP_SHIFT) |
141 (R300_ZS_ALWAYS<<R300_RB3D_ZS1_BACK_FUNC_SHIFT) |
142 (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_FAIL_OP_SHIFT) |
143 (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZPASS_OP_SHIFT) |
144 (R300_ZS_REPLACE<<R300_RB3D_ZS1_BACK_ZFAIL_OP_SHIFT) ;
145 }
146
147 e32(t1);
148 e32(t2);
149 e32(r300->state.stencil.clear);
150 }
151
152 cmd2 = (drm_r300_cmd_header_t*)r300AllocCmdBuf(r300, 9, __FUNCTION__);
153 cmd2[0].packet3.cmd_type = R300_CMD_PACKET3;
154 cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
155 cmd2[1].u = r300PackFloat32(dPriv->w / 2.0);
156 cmd2[2].u = r300PackFloat32(dPriv->h / 2.0);
157 cmd2[3].u = r300PackFloat32(ctx->Depth.Clear);
158 cmd2[4].u = r300PackFloat32(1.0);
159 cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
160 cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
161 cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
162 cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
163
164 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
165 e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
166
167
168 reg_start(R300_RB3D_ZCACHE_CTLSTAT,0);
169 e32(R300_RB3D_ZCACHE_UNKNOWN_03);
170 cp_wait(rmesa, R300_WAIT_3D | R300_WAIT_3D_CLEAN);
171 }
172
173 static void r300EmitClearState(GLcontext * ctx)
174 {
175 r300ContextPtr r300 = R300_CONTEXT(ctx);
176 r300ContextPtr rmesa=r300;
177 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
178 int i;
179 int cmd_reserved = 0;
180 int cmd_written = 0;
181 drm_radeon_cmd_header_t *cmd = NULL;
182 int has_tcl = 1;
183
184 if (!(r300->radeon.radeonScreen->chip_flags & RADEON_CHIPSET_TCL))
185 has_tcl = 0;
186
187 R300_STATECHANGE(r300, vir[0]);
188 reg_start(R300_VAP_INPUT_ROUTE_0_0, 0);
189 if (!has_tcl)
190 e32(0x22030003);
191 else
192 e32(0x21030003);
193
194 /* disable fog */
195 R300_STATECHANGE(r300, fogs);
196 reg_start(R300_RE_FOG_STATE, 0);
197 e32(0x0);
198
199 R300_STATECHANGE(r300, vir[1]);
200 reg_start(R300_VAP_INPUT_ROUTE_1_0, 0);
201 e32(0xF688F688);
202
203 R300_STATECHANGE(r300, vic);
204 reg_start(R300_VAP_INPUT_CNTL_0, 1);
205 e32(0x00000001);
206 e32(0x00000405);
207
208 if (!has_tcl) {
209 R300_STATECHANGE(r300, vte);
210 /* comes from fglrx startup of clear */
211 reg_start(R300_SE_VTE_CNTL, 1);
212 e32(0x043f);
213 e32(0x8);
214
215 reg_start(0x21dc, 0);
216 e32(0xaaaaaaaa);
217 }
218
219 R300_STATECHANGE(r300, vof);
220 reg_start(R300_VAP_OUTPUT_VTX_FMT_0, 1);
221 e32(R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT);
222 e32(0); /* no textures */
223
224
225 R300_STATECHANGE(r300, txe);
226 reg_start(R300_TX_ENABLE, 0);
227 e32(0);
228
229 R300_STATECHANGE(r300, vpt);
230 reg_start(R300_SE_VPORT_XSCALE, 5);
231 efloat(1.0);
232 efloat(dPriv->x);
233 efloat(1.0);
234 efloat(dPriv->y);
235 efloat(1.0);
236 efloat(0.0);
237
238 R300_STATECHANGE(r300, at);
239 reg_start(R300_PP_ALPHA_TEST, 0);
240 e32(0);
241
242 R300_STATECHANGE(r300, bld);
243 reg_start(R300_RB3D_CBLEND, 1);
244 e32(0);
245 e32(0);
246
247 R300_STATECHANGE(r300, unk221C);
248 reg_start(R300_VAP_UNKNOWN_221C, 0);
249 e32(R300_221C_CLEAR);
250
251 R300_STATECHANGE(r300, ps);
252 reg_start(R300_RE_POINTSIZE, 0);
253 e32(((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
254 ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT));
255
256 R300_STATECHANGE(r300, ri);
257 reg_start(R300_RS_INTERP_0, 8);
258 for(i = 0; i < 8; ++i){
259 e32(R300_RS_INTERP_USED);
260 }
261
262 R300_STATECHANGE(r300, rc);
263 /* The second constant is needed to get glxgears display anything .. */
264 reg_start(R300_RS_CNTL_0, 1);
265 e32((1 << R300_RS_CNTL_CI_CNT_SHIFT) | R300_RS_CNTL_0_UNKNOWN_18);
266 e32(0);
267
268 R300_STATECHANGE(r300, rr);
269 reg_start(R300_RS_ROUTE_0, 0);
270 e32(0x00004000);
271
272 R300_STATECHANGE(r300, fp);
273 reg_start(R300_PFS_CNTL_0, 2);
274 e32(0);
275 e32(0);
276 e32(0);
277 reg_start(R300_PFS_NODE_0, 3);
278 e32(0);
279 e32(0);
280 e32(0);
281 e32(R300_PFS_NODE_OUTPUT_COLOR);
282
283 R300_STATECHANGE(r300, fpi[0]);
284 R300_STATECHANGE(r300, fpi[1]);
285 R300_STATECHANGE(r300, fpi[2]);
286 R300_STATECHANGE(r300, fpi[3]);
287
288 reg_start(R300_PFS_INSTR0_0, 0);
289 e32(FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO)));
290
291 reg_start(R300_PFS_INSTR1_0, 0);
292 e32(FP_SELC(0,NO,XYZ,FP_TMP(0),0,0));
293
294 reg_start(R300_PFS_INSTR2_0, 0);
295 e32(FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO)));
296
297 reg_start(R300_PFS_INSTR3_0, 0);
298 e32(FP_SELA(0,NO,W,FP_TMP(0),0,0));
299
300 if (has_tcl) {
301 R300_STATECHANGE(r300, pvs);
302 reg_start(R300_VAP_PVS_CNTL_1, 2);
303 e32((0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) |
304 (0 << R300_PVS_CNTL_1_POS_END_SHIFT) |
305 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT));
306 e32(0);
307 e32(1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT);
308
309 R300_STATECHANGE(r300, vpi);
310 vsf_start_fragment(0x0, 8);
311 e32(VP_OUT(ADD,OUT,0,XYZW));
312 e32(VP_IN(IN,0));
313 e32(VP_ZERO());
314 e32(0);
315
316 e32(VP_OUT(ADD,OUT,1,XYZW));
317 e32(VP_IN(IN,1));
318 e32(VP_ZERO());
319 e32(0);
320 }
321
322 /*reg_start(0x4500,0);
323 e32(2560-1);*/
324 }
325
326 /**
327 * Buffer clear
328 */
329 static void r300Clear(GLcontext * ctx, GLbitfield mask)
330 {
331 r300ContextPtr r300 = R300_CONTEXT(ctx);
332 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
333 int flags = 0;
334 int bits = 0;
335 int swapped;
336
337 if (RADEON_DEBUG & DEBUG_IOCTL)
338 fprintf(stderr, "r300Clear\n");
339
340 {
341 LOCK_HARDWARE(&r300->radeon);
342 UNLOCK_HARDWARE(&r300->radeon);
343 if (dPriv->numClipRects == 0)
344 return;
345 }
346
347 if (mask & BUFFER_BIT_FRONT_LEFT) {
348 flags |= BUFFER_BIT_FRONT_LEFT;
349 mask &= ~BUFFER_BIT_FRONT_LEFT;
350 }
351
352 if (mask & BUFFER_BIT_BACK_LEFT) {
353 flags |= BUFFER_BIT_BACK_LEFT;
354 mask &= ~BUFFER_BIT_BACK_LEFT;
355 }
356
357 if (mask & BUFFER_BIT_DEPTH) {
358 bits |= CLEARBUFFER_DEPTH;
359 mask &= ~BUFFER_BIT_DEPTH;
360 }
361
362 if ( (mask & BUFFER_BIT_STENCIL) && r300->state.stencil.hw_stencil) {
363 bits |= CLEARBUFFER_STENCIL;
364 mask &= ~BUFFER_BIT_STENCIL;
365 }
366
367 if (mask) {
368 if (RADEON_DEBUG & DEBUG_FALLBACKS)
369 fprintf(stderr, "%s: swrast clear, mask: %x\n",
370 __FUNCTION__, mask);
371 _swrast_Clear(ctx, mask);
372 }
373
374 swapped = r300->radeon.sarea->pfCurrentPage == 1;
375
376 /* Make sure it fits there. */
377 r300EnsureCmdBufSpace(r300, 421*3, __FUNCTION__);
378 if(flags || bits)
379 r300EmitClearState(ctx);
380
381 if (flags & BUFFER_BIT_FRONT_LEFT) {
382 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
383 bits = 0;
384 }
385
386 if (flags & BUFFER_BIT_BACK_LEFT) {
387 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
388 bits = 0;
389 }
390
391 if (bits)
392 r300ClearBuffer(r300, bits, 0);
393
394 }
395
396
397 void r300Flush(GLcontext * ctx)
398 {
399 r300ContextPtr r300 = R300_CONTEXT(ctx);
400
401 if (RADEON_DEBUG & DEBUG_IOCTL)
402 fprintf(stderr, "%s\n", __FUNCTION__);
403
404 if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit)
405 r300FlushCmdBuf(r300, __FUNCTION__);
406 }
407
408 #ifdef USER_BUFFERS
409 #include "radeon_mm.h"
410
411 static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
412 {
413 struct r300_dma_buffer *dmabuf;
414 size = MAX2(size, RADEON_BUFFER_SIZE*16);
415
416 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
417 fprintf(stderr, "%s\n", __FUNCTION__);
418
419 if (rmesa->dma.flush) {
420 rmesa->dma.flush(rmesa);
421 }
422
423 if (rmesa->dma.current.buf)
424 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
425
426 if (rmesa->dma.nr_released_bufs > 4)
427 r300FlushCmdBuf(rmesa, __FUNCTION__);
428
429 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
430 dmabuf->buf = (void *)1; /* hack */
431 dmabuf->refcount = 1;
432
433 dmabuf->id = radeon_mm_alloc(rmesa, 4, size);
434 if (dmabuf->id == 0) {
435 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
436
437 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
438 radeonWaitForIdleLocked(&rmesa->radeon);
439
440 dmabuf->id = radeon_mm_alloc(rmesa, 4, size);
441
442 #ifdef HW_VBOS
443 if (dmabuf->id == 0) {
444 /* Just kick all */
445 r300_evict_vbos(rmesa->radeon.glCtx, /*RADEON_BUFFER_SIZE*16*/1<<30);
446 dmabuf->id = radeon_mm_alloc(rmesa, 4, size);
447 }
448 #endif
449 UNLOCK_HARDWARE(&rmesa->radeon);
450
451 if (dmabuf->id == 0) {
452 fprintf(stderr, "Error: Could not get dma buffer... exiting\n");
453 exit(-1);
454 }
455 }
456
457 rmesa->dma.current.buf = dmabuf;
458 rmesa->dma.current.address = radeon_mm_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 radeon_mm_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,
508 (bytes + 0x7) & ~0x7);
509
510 region->start = rmesa->dma.current.start;
511 region->ptr = rmesa->dma.current.start;
512 region->end = rmesa->dma.current.start + bytes;
513 region->address = rmesa->dma.current.address;
514 region->buf = rmesa->dma.current.buf;
515 region->buf->refcount++;
516
517 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
518 rmesa->dma.current.start =
519 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
520
521 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
522 }
523
524 #else
525 static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
526 {
527 struct r300_dma_buffer *dmabuf;
528 int fd = rmesa->radeon.dri.fd;
529 int index = 0;
530 int size = 0;
531 drmDMAReq dma;
532 int ret;
533
534 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
535 fprintf(stderr, "%s\n", __FUNCTION__);
536
537 if (rmesa->dma.flush) {
538 rmesa->dma.flush(rmesa);
539 }
540
541 if (rmesa->dma.current.buf)
542 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
543
544 if (rmesa->dma.nr_released_bufs > 4)
545 r300FlushCmdBuf(rmesa, __FUNCTION__);
546
547 dma.context = rmesa->radeon.dri.hwContext;
548 dma.send_count = 0;
549 dma.send_list = NULL;
550 dma.send_sizes = NULL;
551 dma.flags = 0;
552 dma.request_count = 1;
553 dma.request_size = RADEON_BUFFER_SIZE;
554 dma.request_list = &index;
555 dma.request_sizes = &size;
556 dma.granted_count = 0;
557
558 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
559
560 ret = drmDMA(fd, &dma);
561
562 if (ret != 0) {
563 /* Try to release some buffers and wait until we can't get any more */
564 if (rmesa->dma.nr_released_bufs) {
565 r300FlushCmdBufLocked(rmesa, __FUNCTION__);
566 }
567
568 if (RADEON_DEBUG & DEBUG_DMA)
569 fprintf(stderr, "Waiting for buffers\n");
570
571 radeonWaitForIdleLocked(&rmesa->radeon);
572 ret = drmDMA(fd, &dma);
573
574 if (ret != 0) {
575 UNLOCK_HARDWARE(&rmesa->radeon);
576 fprintf(stderr, "Error: Could not get dma buffer... exiting\n");
577 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", __FUNCTION__,
614 region->buf->buf->idx);
615 cmd =
616 (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
617 sizeof(*cmd) / 4,
618 __FUNCTION__);
619 cmd->dma.cmd_type = R300_CMD_DMA_DISCARD;
620 cmd->dma.buf_idx = region->buf->buf->idx;
621
622 FREE(region->buf);
623 rmesa->dma.nr_released_bufs++;
624 }
625
626 region->buf = 0;
627 region->start = 0;
628 }
629
630 /* Allocates a region from rmesa->dma.current. If there isn't enough
631 * space in current, grab a new buffer (and discard what was left of current)
632 */
633 void r300AllocDmaRegion(r300ContextPtr rmesa,
634 struct r300_dma_region *region,
635 int bytes, int alignment)
636 {
637 if (RADEON_DEBUG & DEBUG_IOCTL)
638 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
639
640 if (rmesa->dma.flush)
641 rmesa->dma.flush(rmesa);
642
643 if (region->buf)
644 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
645
646 alignment--;
647 rmesa->dma.current.start = rmesa->dma.current.ptr =
648 (rmesa->dma.current.ptr + alignment) & ~alignment;
649
650 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
651 r300RefillCurrentDmaRegion(rmesa);
652
653 region->start = rmesa->dma.current.start;
654 region->ptr = rmesa->dma.current.start;
655 region->end = rmesa->dma.current.start + bytes;
656 region->address = rmesa->dma.current.address;
657 region->buf = rmesa->dma.current.buf;
658 region->buf->refcount++;
659
660 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
661 rmesa->dma.current.start =
662 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
663
664 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
665 }
666
667 #endif
668
669 /* Called via glXGetMemoryOffsetMESA() */
670 GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn,
671 const GLvoid * pointer)
672 {
673 GET_CURRENT_CONTEXT(ctx);
674 r300ContextPtr rmesa;
675 GLuint card_offset;
676
677 if (!ctx || !(rmesa = R300_CONTEXT(ctx))) {
678 fprintf(stderr, "%s: no context\n", __FUNCTION__);
679 return ~0;
680 }
681
682 if (!r300IsGartMemory(rmesa, pointer, 0))
683 return ~0;
684
685 card_offset = r300GartOffsetFromVirtual(rmesa, pointer);
686
687 return card_offset - rmesa->radeon.radeonScreen->gart_base;
688 }
689
690 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
691 GLint size)
692 {
693 int offset =
694 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
695 int valid = (size >= 0 && offset >= 0
696 && offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
697
698 if (RADEON_DEBUG & DEBUG_IOCTL)
699 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
700 valid);
701
702 return valid;
703 }
704
705 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
706 {
707 int offset =
708 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
709
710 //fprintf(stderr, "offset=%08x\n", offset);
711
712 if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
713 return ~0;
714 else
715 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
716 }
717
718 void r300InitIoctlFuncs(struct dd_function_table *functions)
719 {
720 functions->Clear = r300Clear;
721 functions->Finish = radeonFinish;
722 functions->Flush = r300Flush;
723 }