Start beginning of pixel shader generator..
[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
59 #define CLEARBUFFER_COLOR 0x1
60 #define CLEARBUFFER_DEPTH 0x2
61
62 static void r300ClearBuffer(r300ContextPtr r300, int flags, int buffer)
63 {
64 GLcontext* ctx = r300->radeon.glCtx;
65 r300ContextPtr rmesa=r300;
66 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
67 int i;
68 GLuint cboffset, cbpitch;
69 drm_r300_cmd_header_t* cmd2;
70 LOCAL_VARS;
71
72 if (RADEON_DEBUG & DEBUG_IOCTL)
73 fprintf(stderr, "%s: %s buffer (%i,%i %ix%i)\n",
74 __FUNCTION__, buffer ? "back" : "front",
75 dPriv->x, dPriv->y, dPriv->w, dPriv->h);
76
77 if (buffer) {
78 cboffset = r300->radeon.radeonScreen->backOffset;
79 cbpitch = r300->radeon.radeonScreen->backPitch;
80 } else {
81 cboffset = r300->radeon.radeonScreen->frontOffset;
82 cbpitch = r300->radeon.radeonScreen->frontPitch;
83 }
84
85 cboffset += r300->radeon.radeonScreen->fbLocation;
86
87 R300_STATECHANGE(r300, vir[0]);
88 ((drm_r300_cmd_header_t*)r300->hw.vir[0].cmd)->unchecked_state.count = 1;
89 r300->hw.vir[0].cmd[1] = 0x21030003;
90
91 R300_STATECHANGE(r300, vir[1]);
92 ((drm_r300_cmd_header_t*)r300->hw.vir[1].cmd)->unchecked_state.count = 1;
93 r300->hw.vir[1].cmd[1] = 0xF688F688;
94
95 R300_STATECHANGE(r300, vic);
96 r300->hw.vic.cmd[R300_VIC_CNTL_0] = 0x00000001;
97 r300->hw.vic.cmd[R300_VIC_CNTL_1] = 0x00000405;
98
99 R300_STATECHANGE(r300, vof);
100 r300->hw.vof.cmd[R300_VOF_CNTL_0] = R300_VAP_OUTPUT_VTX_FMT_0__POS_PRESENT
101 | R300_VAP_OUTPUT_VTX_FMT_0__COLOR_PRESENT;
102 r300->hw.vof.cmd[R300_VOF_CNTL_1] = 0; /* no textures */
103
104 R300_STATECHANGE(r300, txe);
105 r300->hw.txe.cmd[R300_TXE_ENABLE] = 0;
106
107 R300_STATECHANGE(r300, vpt);
108 r300->hw.vpt.cmd[R300_VPT_XSCALE] = r300PackFloat32(1.0);
109 r300->hw.vpt.cmd[R300_VPT_XOFFSET] = r300PackFloat32(dPriv->x);
110 r300->hw.vpt.cmd[R300_VPT_YSCALE] = r300PackFloat32(1.0);
111 r300->hw.vpt.cmd[R300_VPT_YOFFSET] = r300PackFloat32(dPriv->y);
112 r300->hw.vpt.cmd[R300_VPT_ZSCALE] = r300PackFloat32(1.0);
113 r300->hw.vpt.cmd[R300_VPT_ZOFFSET] = r300PackFloat32(0.0);
114
115 R300_STATECHANGE(r300, at);
116 r300->hw.at.cmd[R300_AT_ALPHA_TEST] = 0;
117
118 R300_STATECHANGE(r300, bld);
119 r300->hw.bld.cmd[R300_BLD_CBLEND] = 0;
120 r300->hw.bld.cmd[R300_BLD_ABLEND] = 0;
121
122 R300_STATECHANGE(r300, cb);
123 r300->hw.cb.cmd[R300_CB_OFFSET] = cboffset;
124 r300->hw.cb.cmd[R300_CB_PITCH] = cbpitch | R300_COLOR_UNKNOWN_22_23;
125
126 R300_STATECHANGE(r300, unk221C);
127 r300->hw.unk221C.cmd[1] = R300_221C_CLEAR;
128
129 R300_STATECHANGE(r300, ps);
130 r300->hw.ps.cmd[R300_PS_POINTSIZE] =
131 ((dPriv->w * 6) << R300_POINTSIZE_X_SHIFT) |
132 ((dPriv->h * 6) << R300_POINTSIZE_Y_SHIFT);
133
134 R300_STATECHANGE(r300, ri);
135 for(i = 1; i <= 8; ++i)
136 r300->hw.ri.cmd[i] = R300_RS_INTERP_USED;
137
138 R300_STATECHANGE(r300, rc);
139 /* The second constant is needed to get glxgears display anything .. */
140 r300->hw.rc.cmd[1] = R300_RS_CNTL_0_UNKNOWN_7 | R300_RS_CNTL_0_UNKNOWN_18;
141 r300->hw.rc.cmd[2] = 0;
142
143 R300_STATECHANGE(r300, rr);
144 ((drm_r300_cmd_header_t*)r300->hw.rr.cmd)->unchecked_state.count = 1;
145 r300->hw.rr.cmd[1] = 0x00004000;
146
147 R300_STATECHANGE(r300, cmk);
148 if (flags & CLEARBUFFER_COLOR) {
149 r300->hw.cmk.cmd[R300_CMK_COLORMASK] =
150 (ctx->Color.ColorMask[BCOMP] ? R300_COLORMASK0_B : 0) |
151 (ctx->Color.ColorMask[GCOMP] ? R300_COLORMASK0_G : 0) |
152 (ctx->Color.ColorMask[RCOMP] ? R300_COLORMASK0_R : 0) |
153 (ctx->Color.ColorMask[ACOMP] ? R300_COLORMASK0_A : 0);
154 } else {
155 r300->hw.cmk.cmd[R300_CMK_COLORMASK] = 0;
156 }
157
158 R300_STATECHANGE(r300, fp);
159 r300->hw.fp.cmd[R300_FP_CNTL0] = 0; /* 1 pass, no textures */
160 r300->hw.fp.cmd[R300_FP_CNTL1] = 0; /* no temporaries */
161 r300->hw.fp.cmd[R300_FP_CNTL2] = 0; /* no offset, one ALU instr */
162 r300->hw.fp.cmd[R300_FP_NODE0] = 0;
163 r300->hw.fp.cmd[R300_FP_NODE1] = 0;
164 r300->hw.fp.cmd[R300_FP_NODE2] = 0;
165 r300->hw.fp.cmd[R300_FP_NODE3] = R300_PFS_NODE_LAST_NODE;
166
167 R300_STATECHANGE(r300, fpi[0]);
168 R300_STATECHANGE(r300, fpi[1]);
169 R300_STATECHANGE(r300, fpi[2]);
170 R300_STATECHANGE(r300, fpi[3]);
171 ((drm_r300_cmd_header_t*)r300->hw.fpi[0].cmd)->unchecked_state.count = 1;
172 ((drm_r300_cmd_header_t*)r300->hw.fpi[1].cmd)->unchecked_state.count = 1;
173 ((drm_r300_cmd_header_t*)r300->hw.fpi[2].cmd)->unchecked_state.count = 1;
174 ((drm_r300_cmd_header_t*)r300->hw.fpi[3].cmd)->unchecked_state.count = 1;
175
176 /* MOV o0, t0 */
177 r300->hw.fpi[0].cmd[1] = FP_INSTRC(MAD, FP_ARGC(SRC0C_XYZ), FP_ARGC(ONE), FP_ARGC(ZERO));
178 r300->hw.fpi[1].cmd[1] = FP_SELC(0,NO,XYZ,FP_TMP(0),0,0);
179 r300->hw.fpi[2].cmd[1] = FP_INSTRA(MAD, FP_ARGA(SRC0A), FP_ARGA(ONE), FP_ARGA(ZERO));
180 r300->hw.fpi[3].cmd[1] = FP_SELA(0,NO,W,FP_TMP(0),0,0);
181
182 R300_STATECHANGE(r300, pvs);
183 r300->hw.pvs.cmd[R300_PVS_CNTL_1] =
184 (0 << R300_PVS_CNTL_1_PROGRAM_START_SHIFT) |
185 (0 << R300_PVS_CNTL_1_UNKNOWN_SHIFT) |
186 (1 << R300_PVS_CNTL_1_PROGRAM_END_SHIFT);
187 r300->hw.pvs.cmd[R300_PVS_CNTL_2] = 0; /* no parameters */
188 r300->hw.pvs.cmd[R300_PVS_CNTL_3] =
189 (1 << R300_PVS_CNTL_3_PROGRAM_UNKNOWN_SHIFT);
190
191 R300_STATECHANGE(r300, vpi);
192 ((drm_r300_cmd_header_t*)r300->hw.vpi.cmd)->unchecked_state.count = 8;
193
194 /* MOV o0, i0; */
195 r300->hw.vpi.cmd[1] = VP_OUT(ADD,OUT,0,XYZW);
196 r300->hw.vpi.cmd[2] = VP_IN(IN,0);
197 r300->hw.vpi.cmd[3] = VP_ZERO();
198 r300->hw.vpi.cmd[4] = 0;
199
200 /* MOV o1, i1; */
201 r300->hw.vpi.cmd[5] = VP_OUT(ADD,OUT,1,XYZW);
202 r300->hw.vpi.cmd[6] = VP_IN(IN,1);
203 r300->hw.vpi.cmd[7] = VP_ZERO();
204 r300->hw.vpi.cmd[8] = 0;
205
206 R300_STATECHANGE(r300, zs);
207 if (flags & CLEARBUFFER_DEPTH) {
208 r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0x6; // test and write
209 r300->hw.zs.cmd[R300_ZS_CNTL_1] = (R300_ZS_ALWAYS<<R300_RB3D_ZS1_DEPTH_FUNC_SHIFT);
210 /*
211 R300_STATECHANGE(r300, zb);
212 r300->hw.zb.cmd[R300_ZB_OFFSET] =
213 1024*4*300 +
214 r300->radeon.radeonScreen->frontOffset +
215 r300->radeon.radeonScreen->fbLocation;
216 r300->hw.zb.cmd[R300_ZB_PITCH] =
217 r300->radeon.radeonScreen->depthPitch;
218 */
219 } else {
220 r300->hw.zs.cmd[R300_ZS_CNTL_0] = 0; // disable
221 r300->hw.zs.cmd[R300_ZS_CNTL_1] = 0;
222 }
223
224 /* Make sure we have enough space */
225 r300EnsureCmdBufSpace(r300, r300->hw.max_state_size + 9+8, __FUNCTION__);
226
227 /* needed before starting 3d operation .. */
228 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
229 e32(0x0000000a);
230
231 reg_start(0x4f18,0);
232 e32(0x00000003);
233
234 r300EmitState(r300);
235
236 cmd2 = (drm_r300_cmd_header_t*)r300AllocCmdBuf(r300, 9, __FUNCTION__);
237 cmd2[0].packet3.cmd_type = R300_CMD_PACKET3;
238 cmd2[0].packet3.packet = R300_CMD_PACKET3_CLEAR;
239 cmd2[1].u = r300PackFloat32(dPriv->w / 2.0);
240 cmd2[2].u = r300PackFloat32(dPriv->h / 2.0);
241 cmd2[3].u = r300PackFloat32(ctx->Depth.Clear);
242 cmd2[4].u = r300PackFloat32(1.0);
243 cmd2[5].u = r300PackFloat32(ctx->Color.ClearColor[0]);
244 cmd2[6].u = r300PackFloat32(ctx->Color.ClearColor[1]);
245 cmd2[7].u = r300PackFloat32(ctx->Color.ClearColor[2]);
246 cmd2[8].u = r300PackFloat32(ctx->Color.ClearColor[3]);
247
248 /* This sequence is required after any 3d drawing packet
249 I suspect it work arounds a bug (or deficiency) in hardware */
250
251 reg_start(R300_RB3D_DSTCACHE_CTLSTAT,0);
252 e32(0x0000000a);
253
254 reg_start(0x4f18,0);
255 e32(0x00000003);
256
257 }
258
259
260 /**
261 * Buffer clear
262 */
263 static void r300Clear(GLcontext * ctx, GLbitfield mask, GLboolean all,
264 GLint cx, GLint cy, GLint cw, GLint ch)
265 {
266 r300ContextPtr r300 = R300_CONTEXT(ctx);
267 __DRIdrawablePrivate *dPriv = r300->radeon.dri.drawable;
268 int flags = 0;
269 int bits = 0;
270 int swapped;
271
272 if (RADEON_DEBUG & DEBUG_IOCTL)
273 fprintf(stderr, "%s: all=%d cx=%d cy=%d cw=%d ch=%d\n",
274 __FUNCTION__, all, cx, cy, cw, ch);
275
276 {
277 LOCK_HARDWARE(&r300->radeon);
278 UNLOCK_HARDWARE(&r300->radeon);
279 if (dPriv->numClipRects == 0)
280 return;
281 }
282
283 if (mask & DD_FRONT_LEFT_BIT) {
284 flags |= DD_FRONT_LEFT_BIT;
285 mask &= ~DD_FRONT_LEFT_BIT;
286 }
287
288 if (mask & DD_BACK_LEFT_BIT) {
289 flags |= DD_BACK_LEFT_BIT;
290 mask &= ~DD_BACK_LEFT_BIT;
291 }
292
293 if (mask & DD_DEPTH_BIT) {
294 bits |= CLEARBUFFER_DEPTH;
295 mask &= ~DD_DEPTH_BIT;
296 }
297
298 if (mask) {
299 if (RADEON_DEBUG & DEBUG_FALLBACKS)
300 fprintf(stderr, "%s: swrast clear, mask: %x\n",
301 __FUNCTION__, mask);
302 _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
303 }
304
305 swapped = r300->radeon.doPageFlip && (r300->radeon.sarea->pfCurrentPage == 1);
306
307 if (flags & DD_FRONT_LEFT_BIT) {
308 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped);
309 bits = 0;
310 }
311
312 if (flags & DD_BACK_LEFT_BIT) {
313 r300ClearBuffer(r300, bits | CLEARBUFFER_COLOR, swapped ^ 1);
314 bits = 0;
315 }
316
317 if (bits)
318 r300ClearBuffer(r300, bits, 0);
319
320 /* Recalculate the hardware state. This could be done more efficiently,
321 * but do keep it like this for now.
322 */
323 r300ResetHwState(r300);
324 /* r300ClearBuffer has trampled all over the hardware state.. */
325 r300->hw.all_dirty=GL_TRUE;
326 }
327
328 void r300Flush(GLcontext * ctx)
329 {
330 r300ContextPtr r300 = R300_CONTEXT(ctx);
331
332 if (RADEON_DEBUG & DEBUG_IOCTL)
333 fprintf(stderr, "%s\n", __FUNCTION__);
334
335 if (r300->cmdbuf.count_used > r300->cmdbuf.count_reemit)
336 r300FlushCmdBuf(r300, __FUNCTION__);
337 }
338
339 void r300RefillCurrentDmaRegion(r300ContextPtr rmesa)
340 {
341 struct r200_dma_buffer *dmabuf;
342 int fd = rmesa->radeon.dri.fd;
343 int index = 0;
344 int size = 0;
345 drmDMAReq dma;
346 int ret;
347
348 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
349 fprintf(stderr, "%s\n", __FUNCTION__);
350
351 if (rmesa->dma.flush) {
352 rmesa->dma.flush(rmesa);
353 }
354
355 if (rmesa->dma.current.buf)
356 r300ReleaseDmaRegion(rmesa, &rmesa->dma.current, __FUNCTION__);
357
358 if (rmesa->dma.nr_released_bufs > 4)
359 r300FlushCmdBuf(rmesa, __FUNCTION__);
360
361 dma.context = rmesa->radeon.dri.hwContext;
362 dma.send_count = 0;
363 dma.send_list = NULL;
364 dma.send_sizes = NULL;
365 dma.flags = 0;
366 dma.request_count = 1;
367 dma.request_size = RADEON_BUFFER_SIZE;
368 dma.request_list = &index;
369 dma.request_sizes = &size;
370 dma.granted_count = 0;
371
372 LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
373
374 while (1) {
375 ret = drmDMA(fd, &dma);
376 if (ret == 0)
377 break;
378
379 if (rmesa->dma.nr_released_bufs) {
380 r200FlushCmdBufLocked(rmesa, __FUNCTION__);
381 }
382
383 if (rmesa->radeon.do_usleeps) {
384 UNLOCK_HARDWARE(&rmesa->radeon);
385 DO_USLEEP(1);
386 LOCK_HARDWARE(&rmesa->radeon);
387 }
388 }
389
390 UNLOCK_HARDWARE(&rmesa->radeon);
391
392 if (RADEON_DEBUG & DEBUG_DMA)
393 fprintf(stderr, "Allocated buffer %d\n", index);
394
395 dmabuf = CALLOC_STRUCT(r300_dma_buffer);
396 dmabuf->buf = &rmesa->radeon.radeonScreen->buffers->list[index];
397 dmabuf->refcount = 1;
398
399 rmesa->dma.current.buf = dmabuf;
400 rmesa->dma.current.address = dmabuf->buf->address;
401 rmesa->dma.current.end = dmabuf->buf->total;
402 rmesa->dma.current.start = 0;
403 rmesa->dma.current.ptr = 0;
404 }
405
406 void r300ReleaseDmaRegion(r300ContextPtr rmesa,
407 struct r300_dma_region *region, const char *caller)
408 {
409 if (RADEON_DEBUG & DEBUG_IOCTL)
410 fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
411
412 if (!region->buf)
413 return;
414
415 if (rmesa->dma.flush)
416 rmesa->dma.flush(rmesa);
417
418 if (--region->buf->refcount == 0) {
419 drm_radeon_cmd_header_t *cmd;
420
421 if (RADEON_DEBUG & (DEBUG_IOCTL | DEBUG_DMA))
422 fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
423 region->buf->buf->idx);
424
425 cmd =
426 (drm_radeon_cmd_header_t *) r300AllocCmdBuf(rmesa,
427 sizeof(*cmd),
428 __FUNCTION__);
429 cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
430 cmd->dma.buf_idx = region->buf->buf->idx;
431 FREE(region->buf);
432 rmesa->dma.nr_released_bufs++;
433 }
434
435 region->buf = 0;
436 region->start = 0;
437 }
438
439 /* Allocates a region from rmesa->dma.current. If there isn't enough
440 * space in current, grab a new buffer (and discard what was left of current)
441 */
442 void r300AllocDmaRegion(r300ContextPtr rmesa,
443 struct r300_dma_region *region,
444 int bytes, int alignment)
445 {
446 if (RADEON_DEBUG & DEBUG_IOCTL)
447 fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
448
449 if (rmesa->dma.flush)
450 rmesa->dma.flush(rmesa);
451
452 if (region->buf)
453 r300ReleaseDmaRegion(rmesa, region, __FUNCTION__);
454
455 alignment--;
456 rmesa->dma.current.start = rmesa->dma.current.ptr =
457 (rmesa->dma.current.ptr + alignment) & ~alignment;
458
459 if (rmesa->dma.current.ptr + bytes > rmesa->dma.current.end)
460 r300RefillCurrentDmaRegion(rmesa);
461
462 region->start = rmesa->dma.current.start;
463 region->ptr = rmesa->dma.current.start;
464 region->end = rmesa->dma.current.start + bytes;
465 region->address = rmesa->dma.current.address;
466 region->buf = rmesa->dma.current.buf;
467 region->buf->refcount++;
468
469 rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
470 rmesa->dma.current.start =
471 rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;
472
473 assert(rmesa->dma.current.ptr <= rmesa->dma.current.end);
474 }
475
476 /* Called via glXGetMemoryOffsetMESA() */
477 GLuint r300GetMemoryOffsetMESA(__DRInativeDisplay * dpy, int scrn,
478 const GLvoid * pointer)
479 {
480 GET_CURRENT_CONTEXT(ctx);
481 r300ContextPtr rmesa;
482 GLuint card_offset;
483
484 if (!ctx || !(rmesa = R300_CONTEXT(ctx))) {
485 fprintf(stderr, "%s: no context\n", __FUNCTION__);
486 return ~0;
487 }
488
489 if (!r300IsGartMemory(rmesa, pointer, 0))
490 return ~0;
491
492 if (rmesa->radeon.dri.drmMinor < 6)
493 return ~0;
494
495 card_offset = r300GartOffsetFromVirtual(rmesa, pointer);
496
497 return card_offset - rmesa->radeon.radeonScreen->gart_base;
498 }
499
500 GLboolean r300IsGartMemory(r300ContextPtr rmesa, const GLvoid * pointer,
501 GLint size)
502 {
503 int offset =
504 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
505 int valid = (size >= 0 && offset >= 0
506 && offset + size < rmesa->radeon.radeonScreen->gartTextures.size);
507
508 if (RADEON_DEBUG & DEBUG_IOCTL)
509 fprintf(stderr, "r300IsGartMemory( %p ) : %d\n", pointer,
510 valid);
511
512 return valid;
513 }
514
515 GLuint r300GartOffsetFromVirtual(r300ContextPtr rmesa, const GLvoid * pointer)
516 {
517 int offset =
518 (char *)pointer - (char *)rmesa->radeon.radeonScreen->gartTextures.map;
519
520 fprintf(stderr, "offset=%08x\n", offset);
521
522 if (offset < 0 || offset > rmesa->radeon.radeonScreen->gartTextures.size)
523 return ~0;
524 else
525 return rmesa->radeon.radeonScreen->gart_texture_offset + offset;
526 }
527
528 void r300InitIoctlFuncs(struct dd_function_table *functions)
529 {
530 functions->Clear = r300Clear;
531 functions->Finish = radeonFinish;
532 functions->Flush = r300Flush;
533 }