build fix
[mesa.git] / src / mesa / drivers / dri / r128 / r128_ioctl.c
1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c,v 1.10 2002/12/16 16:18:53 dawes Exp $ */
2 /**************************************************************************
3
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
5 Cedar Park, Texas.
6 All Rights Reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
17 Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Gareth Hughes <gareth@valinux.com>
32 *
33 */
34
35 #include "r128_context.h"
36 #include "r128_state.h"
37 #include "r128_ioctl.h"
38
39 #include "imports.h"
40 #include "macros.h"
41
42 #include "swrast/swrast.h"
43
44 #include "vblank.h"
45
46 #define R128_TIMEOUT 2048
47 #define R128_IDLE_RETRY 32
48
49
50 /* =============================================================
51 * Hardware vertex buffer handling
52 */
53
54 /* Get a new VB from the pool of vertex buffers in AGP space.
55 */
56 drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa )
57 {
58 int fd = rmesa->r128Screen->driScreen->fd;
59 int index = 0;
60 int size = 0;
61 drmDMAReq dma;
62 drmBufPtr buf = NULL;
63 int to = 0;
64 int ret;
65
66 dma.context = rmesa->hHWContext;
67 dma.send_count = 0;
68 dma.send_list = NULL;
69 dma.send_sizes = NULL;
70 dma.flags = 0;
71 dma.request_count = 1;
72 dma.request_size = R128_BUFFER_SIZE;
73 dma.request_list = &index;
74 dma.request_sizes = &size;
75 dma.granted_count = 0;
76
77 while ( !buf && ( to++ < R128_TIMEOUT ) ) {
78 ret = drmDMA( fd, &dma );
79
80 if ( ret == 0 ) {
81 buf = &rmesa->r128Screen->buffers->list[index];
82 buf->used = 0;
83 #if ENABLE_PERF_BOXES
84 /* Bump the performance counter */
85 rmesa->c_vertexBuffers++;
86 #endif
87 return buf;
88 }
89 }
90
91 if ( !buf ) {
92 drmCommandNone( fd, DRM_R128_CCE_RESET);
93 UNLOCK_HARDWARE( rmesa );
94 fprintf( stderr, "Error: Could not get new VB... exiting\n" );
95 exit( -1 );
96 }
97
98 return buf;
99 }
100
101 void r128FlushVerticesLocked( r128ContextPtr rmesa )
102 {
103 XF86DRIClipRectPtr pbox = rmesa->pClipRects;
104 int nbox = rmesa->numClipRects;
105 drmBufPtr buffer = rmesa->vert_buf;
106 int count = rmesa->num_verts;
107 int prim = rmesa->hw_primitive;
108 int fd = rmesa->driScreen->fd;
109 drmR128Vertex vertex;
110 int i;
111
112 rmesa->num_verts = 0;
113 rmesa->vert_buf = NULL;
114
115 if ( !buffer )
116 return;
117
118 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS )
119 r128EmitHwStateLocked( rmesa );
120
121 if ( !nbox )
122 count = 0;
123
124 if ( nbox >= R128_NR_SAREA_CLIPRECTS )
125 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
126
127 if ( !count || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
128 {
129 if ( nbox < 3 ) {
130 rmesa->sarea->nbox = 0;
131 } else {
132 rmesa->sarea->nbox = nbox;
133 }
134
135 vertex.prim = prim;
136 vertex.idx = buffer->idx;
137 vertex.count = count;
138 vertex.discard = 1;
139 drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
140 }
141 else
142 {
143 for ( i = 0 ; i < nbox ; ) {
144 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
145 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
146 int discard = 0;
147
148 rmesa->sarea->nbox = nr - i;
149 for ( ; i < nr ; i++ ) {
150 *b++ = pbox[i];
151 }
152
153 /* Finished with the buffer?
154 */
155 if ( nr == nbox ) {
156 discard = 1;
157 }
158
159 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
160
161 vertex.prim = prim;
162 vertex.idx = buffer->idx;
163 vertex.count = count;
164 vertex.discard = discard;
165 drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
166 }
167 }
168
169 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
170 }
171
172
173
174
175
176 /* ================================================================
177 * Texture uploads
178 */
179
180 void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
181 GLint offset, GLint pitch, GLint format,
182 GLint x, GLint y, GLint width, GLint height )
183 {
184 drmR128Blit blit;
185 GLint ret;
186
187 blit.idx = buffer->idx;
188 blit.offset = offset;
189 blit.pitch = pitch;
190 blit.format = format;
191 blit.x = x;
192 blit.y = y;
193 blit.width = width;
194 blit.height = height;
195
196 ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT,
197 &blit, sizeof(drmR128Blit) );
198
199 if ( ret ) {
200 UNLOCK_HARDWARE( rmesa );
201 fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret );
202 exit( 1 );
203 }
204 }
205
206
207 /* ================================================================
208 * SwapBuffers with client-side throttling
209 */
210
211 static void delay( void ) {
212 /* Prevent an optimizing compiler from removing a spin loop */
213 }
214
215 #define R128_MAX_OUTSTANDING 2
216
217 /* Throttle the frame rate -- only allow one pending swap buffers
218 * request at a time.
219 * GH: We probably don't want a timeout here, as we can wait as
220 * long as we want for a frame to complete. If it never does, then
221 * the card has locked.
222 */
223 static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
224 {
225 unsigned char *R128MMIO = rmesa->r128Screen->mmio.map;
226 CARD32 frame;
227 int i;
228 int wait = 0;
229
230 while ( 1 ) {
231 frame = INREG( R128_LAST_FRAME_REG );
232 if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) {
233 break;
234 }
235
236 /* Spin in place a bit so we aren't hammering the register */
237 wait++;
238 for ( i = 0 ; i < 1024 ; i++ ) {
239 delay();
240 }
241 }
242
243 return wait;
244 }
245
246 /* Copy the back color buffer to the front color buffer.
247 */
248 void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
249 {
250 r128ContextPtr rmesa;
251 GLint nbox, i, ret;
252 GLboolean missed_target;
253
254 assert(dPriv);
255 assert(dPriv->driContextPriv);
256 assert(dPriv->driContextPriv->driverPrivate);
257
258 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
259
260 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
261 fprintf( stderr, "\n********************************\n" );
262 fprintf( stderr, "\n%s( %p )\n\n",
263 __FUNCTION__, rmesa->glCtx );
264 fflush( stderr );
265 }
266
267 FLUSH_BATCH( rmesa );
268
269 LOCK_HARDWARE( rmesa );
270
271 /* Throttle the frame rate -- only allow one pending swap buffers
272 * request at a time.
273 */
274 if ( !r128WaitForFrameCompletion( rmesa ) ) {
275 rmesa->hardwareWentIdle = 1;
276 } else {
277 rmesa->hardwareWentIdle = 0;
278 }
279
280 UNLOCK_HARDWARE( rmesa );
281 driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
282 LOCK_HARDWARE( rmesa );
283
284 nbox = dPriv->numClipRects; /* must be in locked region */
285
286 for ( i = 0 ; i < nbox ; ) {
287 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox );
288 XF86DRIClipRectPtr box = dPriv->pClipRects;
289 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
290 GLint n = 0;
291
292 for ( ; i < nr ; i++ ) {
293 *b++ = *(XF86DRIClipRectRec *)&box[i];
294 n++;
295 }
296 rmesa->sarea->nbox = n;
297
298 ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP );
299
300 if ( ret ) {
301 UNLOCK_HARDWARE( rmesa );
302 fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret );
303 exit( 1 );
304 }
305 }
306
307 if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) {
308 i = 0;
309 do {
310 ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE);
311 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
312 }
313
314 UNLOCK_HARDWARE( rmesa );
315
316 rmesa->new_state |= R128_NEW_CONTEXT;
317 rmesa->dirty |= (R128_UPLOAD_CONTEXT |
318 R128_UPLOAD_MASKS |
319 R128_UPLOAD_CLIPRECTS);
320
321 #if ENABLE_PERF_BOXES
322 /* Log the performance counters if necessary */
323 r128PerformanceCounters( rmesa );
324 #endif
325 }
326
327 void r128PageFlip( const __DRIdrawablePrivate *dPriv )
328 {
329 r128ContextPtr rmesa;
330 GLint ret;
331 GLboolean missed_target;
332
333 assert(dPriv);
334 assert(dPriv->driContextPriv);
335 assert(dPriv->driContextPriv->driverPrivate);
336
337 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
338
339 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
340 fprintf( stderr, "\n%s( %p ): page=%d\n\n",
341 __FUNCTION__, rmesa->glCtx, rmesa->sarea->pfCurrentPage );
342 }
343
344 FLUSH_BATCH( rmesa );
345
346 LOCK_HARDWARE( rmesa );
347
348 /* Throttle the frame rate -- only allow one pending swap buffers
349 * request at a time.
350 */
351 if ( !r128WaitForFrameCompletion( rmesa ) ) {
352 rmesa->hardwareWentIdle = 1;
353 } else {
354 rmesa->hardwareWentIdle = 0;
355 }
356
357 UNLOCK_HARDWARE( rmesa );
358 driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
359 LOCK_HARDWARE( rmesa );
360
361 /* The kernel will have been initialized to perform page flipping
362 * on a swapbuffers ioctl.
363 */
364 ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP );
365
366 UNLOCK_HARDWARE( rmesa );
367
368 if ( ret ) {
369 fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret );
370 exit( 1 );
371 }
372
373 if ( rmesa->sarea->pfCurrentPage == 1 ) {
374 rmesa->drawOffset = rmesa->r128Screen->frontOffset;
375 rmesa->drawPitch = rmesa->r128Screen->frontPitch;
376 } else {
377 rmesa->drawOffset = rmesa->r128Screen->backOffset;
378 rmesa->drawPitch = rmesa->r128Screen->backPitch;
379 }
380
381 rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
382 (rmesa->drawOffset >> 5));
383 rmesa->new_state |= R128_NEW_WINDOW;
384
385 /* FIXME: Do we need this anymore? */
386 rmesa->new_state |= R128_NEW_CONTEXT;
387 rmesa->dirty |= (R128_UPLOAD_CONTEXT |
388 R128_UPLOAD_MASKS |
389 R128_UPLOAD_CLIPRECTS);
390
391 #if ENABLE_PERF_BOXES
392 /* Log the performance counters if necessary */
393 r128PerformanceCounters( rmesa );
394 #endif
395 }
396
397
398 /* ================================================================
399 * Buffer clear
400 */
401
402 static void r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
403 GLint cx, GLint cy, GLint cw, GLint ch )
404 {
405 r128ContextPtr rmesa = R128_CONTEXT(ctx);
406 __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
407 drmR128Clear clear;
408 GLuint flags = 0;
409 GLint i;
410 GLint ret;
411
412 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
413 fprintf( stderr, "%s:\n", __FUNCTION__ );
414 }
415
416 FLUSH_BATCH( rmesa );
417
418 /* The only state change we care about here is the RGBA colormask
419 * We'll just update that state, if needed. If we do more then
420 * there's some strange side-effects that the conformance tests find.
421 */
422 if ( rmesa->new_state & R128_NEW_MASKS) {
423 const GLuint save_state = rmesa->new_state;
424 rmesa->new_state = R128_NEW_MASKS;
425 r128DDUpdateHWState( ctx );
426 rmesa->new_state = save_state & ~R128_NEW_MASKS;
427 }
428
429 if ( mask & DD_FRONT_LEFT_BIT ) {
430 flags |= DRM_R128_FRONT_BUFFER;
431 mask &= ~DD_FRONT_LEFT_BIT;
432 }
433
434 if ( mask & DD_BACK_LEFT_BIT ) {
435 flags |= DRM_R128_BACK_BUFFER;
436 mask &= ~DD_BACK_LEFT_BIT;
437 }
438
439 if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
440 flags |= DRM_R128_DEPTH_BUFFER;
441 mask &= ~DD_DEPTH_BIT;
442 }
443 #if 0
444 /* FIXME: Add stencil support */
445 if ( mask & DD_STENCIL_BIT ) {
446 flags |= DRM_R128_DEPTH_BUFFER;
447 mask &= ~DD_STENCIL_BIT;
448 }
449 #endif
450
451 if ( flags ) {
452
453 /* Flip top to bottom */
454 cx += dPriv->x;
455 cy = dPriv->y + dPriv->h - cy - ch;
456
457 LOCK_HARDWARE( rmesa );
458
459 /* FIXME: Do we actually need this?
460 */
461 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
462 r128EmitHwStateLocked( rmesa );
463 }
464
465 for ( i = 0 ; i < rmesa->numClipRects ; ) {
466 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
467 XF86DRIClipRectPtr box = rmesa->pClipRects;
468 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
469 GLint n = 0;
470
471 if ( !all ) {
472 for ( ; i < nr ; i++ ) {
473 GLint x = box[i].x1;
474 GLint y = box[i].y1;
475 GLint w = box[i].x2 - x;
476 GLint h = box[i].y2 - y;
477
478 if ( x < cx ) w -= cx - x, x = cx;
479 if ( y < cy ) h -= cy - y, y = cy;
480 if ( x + w > cx + cw ) w = cx + cw - x;
481 if ( y + h > cy + ch ) h = cy + ch - y;
482 if ( w <= 0 ) continue;
483 if ( h <= 0 ) continue;
484
485 b->x1 = x;
486 b->y1 = y;
487 b->x2 = x + w;
488 b->y2 = y + h;
489 b++;
490 n++;
491 }
492 } else {
493 for ( ; i < nr ; i++ ) {
494 *b++ = *(XF86DRIClipRectPtr)&box[i];
495 n++;
496 }
497 }
498
499 rmesa->sarea->nbox = n;
500
501 if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
502 fprintf( stderr,
503 "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
504 flags,
505 (GLuint)rmesa->ClearColor,
506 (GLuint)rmesa->ClearDepth,
507 rmesa->sarea->nbox );
508 }
509
510 clear.flags = flags;
511 clear.clear_color = rmesa->ClearColor;
512 clear.clear_depth = rmesa->ClearDepth;
513 clear.color_mask = rmesa->setup.plane_3d_mask_c;
514 clear.depth_mask = ~0;
515
516 ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
517 &clear, sizeof(drmR128Clear) );
518
519 if ( ret ) {
520 UNLOCK_HARDWARE( rmesa );
521 fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
522 exit( 1 );
523 }
524 }
525
526 UNLOCK_HARDWARE( rmesa );
527
528 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
529 }
530
531 if ( mask )
532 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
533 }
534
535
536 /* ================================================================
537 * Depth spans, pixels
538 */
539
540 void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
541 GLuint n, GLint x, GLint y,
542 const GLdepth depth[],
543 const GLubyte mask[] )
544 {
545 XF86DRIClipRectPtr pbox = rmesa->pClipRects;
546 drmR128Depth d;
547 int nbox = rmesa->numClipRects;
548 int fd = rmesa->driScreen->fd;
549 int i;
550
551 if ( !nbox || !n ) {
552 return;
553 }
554 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
555 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
556 }
557
558 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
559 {
560 if ( nbox < 3 ) {
561 rmesa->sarea->nbox = 0;
562 } else {
563 rmesa->sarea->nbox = nbox;
564 }
565
566 d.func = DRM_R128_WRITE_SPAN;
567 d.n = n;
568 d.x = (int*)&x;
569 d.y = (int*)&y;
570 d.buffer = (unsigned int *)depth;
571 d.mask = (unsigned char *)mask;
572
573 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
574
575 }
576 else
577 {
578 for (i = 0 ; i < nbox ; ) {
579 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
580 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
581
582 rmesa->sarea->nbox = nr - i;
583 for ( ; i < nr ; i++) {
584 *b++ = pbox[i];
585 }
586
587 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
588
589 d.func = DRM_R128_WRITE_SPAN;
590 d.n = n;
591 d.x = (int*)&x;
592 d.y = (int*)&y;
593 d.buffer = (unsigned int *)depth;
594 d.mask = (unsigned char *)mask;
595
596 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
597 }
598 }
599
600 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
601 }
602
603 void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
604 const GLint x[], const GLint y[],
605 const GLdepth depth[],
606 const GLubyte mask[] )
607 {
608 XF86DRIClipRectPtr pbox = rmesa->pClipRects;
609 drmR128Depth d;
610 int nbox = rmesa->numClipRects;
611 int fd = rmesa->driScreen->fd;
612 int i;
613
614 if ( !nbox || !n ) {
615 return;
616 }
617 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
618 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
619 }
620
621 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
622 {
623 if ( nbox < 3 ) {
624 rmesa->sarea->nbox = 0;
625 } else {
626 rmesa->sarea->nbox = nbox;
627 }
628
629 d.func = DRM_R128_WRITE_PIXELS;
630 d.n = n;
631 d.x = (int*)&x;
632 d.y = (int*)&y;
633 d.buffer = (unsigned int *)depth;
634 d.mask = (unsigned char *)mask;
635
636 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
637 }
638 else
639 {
640 for (i = 0 ; i < nbox ; ) {
641 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
642 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
643
644 rmesa->sarea->nbox = nr - i;
645 for ( ; i < nr ; i++) {
646 *b++ = pbox[i];
647 }
648
649 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
650
651 d.func = DRM_R128_WRITE_PIXELS;
652 d.n = n;
653 d.x = (int*)&x;
654 d.y = (int*)&y;
655 d.buffer = (unsigned int *)depth;
656 d.mask = (unsigned char *)mask;
657
658 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
659 }
660 }
661
662 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
663 }
664
665 void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
666 GLuint n, GLint x, GLint y )
667 {
668 XF86DRIClipRectPtr pbox = rmesa->pClipRects;
669 drmR128Depth d;
670 int nbox = rmesa->numClipRects;
671 int fd = rmesa->driScreen->fd;
672 int i;
673
674 if ( !nbox || !n ) {
675 return;
676 }
677 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
678 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
679 }
680
681 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
682 {
683 if ( nbox < 3 ) {
684 rmesa->sarea->nbox = 0;
685 } else {
686 rmesa->sarea->nbox = nbox;
687 }
688
689 d.func = DRM_R128_READ_SPAN;
690 d.n = n;
691 d.x = (int*)&x;
692 d.y = (int*)&y;
693 d.buffer = NULL;
694 d.mask = NULL;
695
696 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
697 }
698 else
699 {
700 for (i = 0 ; i < nbox ; ) {
701 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
702 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
703
704 rmesa->sarea->nbox = nr - i;
705 for ( ; i < nr ; i++) {
706 *b++ = pbox[i];
707 }
708
709 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
710
711 d.func = DRM_R128_READ_SPAN;
712 d.n = n;
713 d.x = (int*)&x;
714 d.y = (int*)&y;
715 d.buffer = NULL;
716 d.mask = NULL;
717
718 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
719 }
720 }
721
722 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
723 }
724
725 void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
726 const GLint x[], const GLint y[] )
727 {
728 XF86DRIClipRectPtr pbox = rmesa->pClipRects;
729 drmR128Depth d;
730 int nbox = rmesa->numClipRects;
731 int fd = rmesa->driScreen->fd;
732 int i;
733
734 if ( !nbox || !n ) {
735 return;
736 }
737 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
738 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
739 }
740
741 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
742 {
743 if ( nbox < 3 ) {
744 rmesa->sarea->nbox = 0;
745 } else {
746 rmesa->sarea->nbox = nbox;
747 }
748
749 d.func = DRM_R128_READ_PIXELS;
750 d.n = n;
751 d.x = (int*)&x;
752 d.y = (int*)&y;
753 d.buffer = NULL;
754 d.mask = NULL;
755
756 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
757 }
758 else
759 {
760 for (i = 0 ; i < nbox ; ) {
761 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
762 XF86DRIClipRectPtr b = rmesa->sarea->boxes;
763
764 rmesa->sarea->nbox = nr - i;
765 for ( ; i < nr ; i++) {
766 *b++ = pbox[i];
767 }
768
769 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
770
771 d.func = DRM_R128_READ_PIXELS;
772 d.n = n;
773 d.x = (int*)&x;
774 d.y = (int*)&y;
775 d.buffer = NULL;
776 d.mask = NULL;
777
778 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
779 }
780 }
781
782 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
783 }
784
785
786 void r128WaitForIdleLocked( r128ContextPtr rmesa )
787 {
788 int fd = rmesa->r128Screen->driScreen->fd;
789 int to = 0;
790 int ret, i;
791
792 do {
793 i = 0;
794 do {
795 ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
796 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
797 } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
798
799 if ( ret < 0 ) {
800 drmCommandNone( fd, DRM_R128_CCE_RESET);
801 UNLOCK_HARDWARE( rmesa );
802 fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
803 exit( -1 );
804 }
805 }
806
807 void r128DDInitIoctlFuncs( GLcontext *ctx )
808 {
809 ctx->Driver.Clear = r128DDClear;
810 }