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