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