7dbb5e5ddab97640bfb61374c09a4fd53dd7d8ca
[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, GLboolean allFoo,
403 GLint cxFoo, GLint cyFoo, GLint cwFoo, GLint chFoo )
404 {
405 r128ContextPtr rmesa = R128_CONTEXT(ctx);
406 __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
407 drm_r128_clear_t clear;
408 GLuint flags = 0;
409 GLint i;
410 GLint ret;
411 GLuint depthmask = 0;
412 GLint cx, cy, cw, ch;
413
414 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
415 fprintf( stderr, "%s:\n", __FUNCTION__ );
416 }
417
418 FLUSH_BATCH( rmesa );
419
420 /* The only state change we care about here is the RGBA colormask
421 * We'll just update that state, if needed. If we do more then
422 * there's some strange side-effects that the conformance tests find.
423 */
424 if ( rmesa->new_state & R128_NEW_MASKS) {
425 const GLuint save_state = rmesa->new_state;
426 rmesa->new_state = R128_NEW_MASKS;
427 r128DDUpdateHWState( ctx );
428 rmesa->new_state = save_state & ~R128_NEW_MASKS;
429 }
430
431 if ( mask & BUFFER_BIT_FRONT_LEFT ) {
432 flags |= R128_FRONT;
433 mask &= ~BUFFER_BIT_FRONT_LEFT;
434 }
435
436 if ( mask & BUFFER_BIT_BACK_LEFT ) {
437 flags |= R128_BACK;
438 mask &= ~BUFFER_BIT_BACK_LEFT;
439 }
440
441 if ( ( mask & BUFFER_BIT_DEPTH ) && ctx->Depth.Mask ) {
442 flags |= R128_DEPTH;
443 /* if we're at 16 bits, extra plane mask won't hurt */
444 depthmask |= 0x00ffffff;
445 mask &= ~BUFFER_BIT_DEPTH;
446 }
447
448 if ( mask & BUFFER_BIT_STENCIL &&
449 (ctx->Visual.stencilBits > 0 && ctx->Visual.depthBits == 24) ) {
450 flags |= R128_DEPTH;
451 depthmask |= ctx->Stencil.WriteMask[0] << 24;
452 mask &= ~BUFFER_BIT_STENCIL;
453 }
454
455 if ( flags ) {
456
457 LOCK_HARDWARE( rmesa );
458
459 /* compute region after locking: */
460 cx = ctx->DrawBuffer->_Xmin;
461 cy = ctx->DrawBuffer->_Ymin;
462 cw = ctx->DrawBuffer->_Xmax - cx;
463 ch = ctx->DrawBuffer->_Ymax - cy;
464
465 /* Flip top to bottom */
466 cx += dPriv->x;
467 cy = dPriv->y + dPriv->h - cy - ch;
468
469 /* FIXME: Do we actually need this?
470 */
471 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
472 r128EmitHwStateLocked( rmesa );
473 }
474
475 for ( i = 0 ; i < rmesa->numClipRects ; ) {
476 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
477 drm_clip_rect_t *box = rmesa->pClipRects;
478 drm_clip_rect_t *b = rmesa->sarea->boxes;
479 GLint n = 0;
480
481 if (cw != dPriv->w || ch != dPriv->h) {
482 /* clear subregion */
483 for ( ; i < nr ; i++ ) {
484 GLint x = box[i].x1;
485 GLint y = box[i].y1;
486 GLint w = box[i].x2 - x;
487 GLint h = box[i].y2 - y;
488
489 if ( x < cx ) w -= cx - x, x = cx;
490 if ( y < cy ) h -= cy - y, y = cy;
491 if ( x + w > cx + cw ) w = cx + cw - x;
492 if ( y + h > cy + ch ) h = cy + ch - y;
493 if ( w <= 0 ) continue;
494 if ( h <= 0 ) continue;
495
496 b->x1 = x;
497 b->y1 = y;
498 b->x2 = x + w;
499 b->y2 = y + h;
500 b++;
501 n++;
502 }
503 } else {
504 /* clear whole window */
505 for ( ; i < nr ; i++ ) {
506 *b++ = box[i];
507 n++;
508 }
509 }
510
511 rmesa->sarea->nbox = n;
512
513 if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
514 fprintf( stderr,
515 "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
516 flags,
517 (GLuint)rmesa->ClearColor,
518 (GLuint)rmesa->ClearDepth,
519 rmesa->sarea->nbox );
520 }
521
522 clear.flags = flags;
523 clear.clear_color = rmesa->ClearColor;
524 clear.clear_depth = rmesa->ClearDepth;
525 clear.color_mask = rmesa->setup.plane_3d_mask_c;
526 clear.depth_mask = depthmask;
527
528 ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
529 &clear, sizeof(clear) );
530
531 if ( ret ) {
532 UNLOCK_HARDWARE( rmesa );
533 fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
534 exit( 1 );
535 }
536 }
537
538 UNLOCK_HARDWARE( rmesa );
539
540 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
541 }
542
543 if ( mask )
544 _swrast_Clear( ctx, mask, 0, 0, 0, 0, 0 );
545 }
546
547
548 /* ================================================================
549 * Depth spans, pixels
550 */
551
552 void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
553 GLuint n, GLint x, GLint y,
554 const GLuint depth[],
555 const GLubyte mask[] )
556 {
557 drm_clip_rect_t *pbox = rmesa->pClipRects;
558 drm_r128_depth_t d;
559 int nbox = rmesa->numClipRects;
560 int fd = rmesa->driScreen->fd;
561 int i;
562
563 if ( !nbox || !n ) {
564 return;
565 }
566 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
567 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
568 }
569
570 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
571 {
572 if ( nbox < 3 ) {
573 rmesa->sarea->nbox = 0;
574 } else {
575 rmesa->sarea->nbox = nbox;
576 }
577
578 d.func = R128_WRITE_SPAN;
579 d.n = n;
580 d.x = (int*)&x;
581 d.y = (int*)&y;
582 d.buffer = (unsigned int *)depth;
583 d.mask = (unsigned char *)mask;
584
585 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
586
587 }
588 else
589 {
590 for (i = 0 ; i < nbox ; ) {
591 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
592 drm_clip_rect_t *b = rmesa->sarea->boxes;
593
594 rmesa->sarea->nbox = nr - i;
595 for ( ; i < nr ; i++) {
596 *b++ = pbox[i];
597 }
598
599 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
600
601 d.func = R128_WRITE_SPAN;
602 d.n = n;
603 d.x = (int*)&x;
604 d.y = (int*)&y;
605 d.buffer = (unsigned int *)depth;
606 d.mask = (unsigned char *)mask;
607
608 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
609 }
610 }
611
612 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
613 }
614
615 void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
616 const GLint x[], const GLint y[],
617 const GLuint depth[],
618 const GLubyte mask[] )
619 {
620 drm_clip_rect_t *pbox = rmesa->pClipRects;
621 drm_r128_depth_t d;
622 int nbox = rmesa->numClipRects;
623 int fd = rmesa->driScreen->fd;
624 int i;
625
626 if ( !nbox || !n ) {
627 return;
628 }
629 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
630 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
631 }
632
633 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
634 {
635 if ( nbox < 3 ) {
636 rmesa->sarea->nbox = 0;
637 } else {
638 rmesa->sarea->nbox = nbox;
639 }
640
641 d.func = R128_WRITE_PIXELS;
642 d.n = n;
643 d.x = (int*)&x;
644 d.y = (int*)&y;
645 d.buffer = (unsigned int *)depth;
646 d.mask = (unsigned char *)mask;
647
648 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
649 }
650 else
651 {
652 for (i = 0 ; i < nbox ; ) {
653 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
654 drm_clip_rect_t *b = rmesa->sarea->boxes;
655
656 rmesa->sarea->nbox = nr - i;
657 for ( ; i < nr ; i++) {
658 *b++ = pbox[i];
659 }
660
661 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
662
663 d.func = R128_WRITE_PIXELS;
664 d.n = n;
665 d.x = (int*)&x;
666 d.y = (int*)&y;
667 d.buffer = (unsigned int *)depth;
668 d.mask = (unsigned char *)mask;
669
670 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
671 }
672 }
673
674 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
675 }
676
677 void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
678 GLuint n, GLint x, GLint y )
679 {
680 drm_clip_rect_t *pbox = rmesa->pClipRects;
681 drm_r128_depth_t d;
682 int nbox = rmesa->numClipRects;
683 int fd = rmesa->driScreen->fd;
684 int i;
685
686 if ( !nbox || !n ) {
687 return;
688 }
689 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
690 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
691 }
692
693 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
694 {
695 if ( nbox < 3 ) {
696 rmesa->sarea->nbox = 0;
697 } else {
698 rmesa->sarea->nbox = nbox;
699 }
700
701 d.func = R128_READ_SPAN;
702 d.n = n;
703 d.x = (int*)&x;
704 d.y = (int*)&y;
705 d.buffer = NULL;
706 d.mask = NULL;
707
708 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
709 }
710 else
711 {
712 for (i = 0 ; i < nbox ; ) {
713 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
714 drm_clip_rect_t *b = rmesa->sarea->boxes;
715
716 rmesa->sarea->nbox = nr - i;
717 for ( ; i < nr ; i++) {
718 *b++ = pbox[i];
719 }
720
721 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
722
723 d.func = R128_READ_SPAN;
724 d.n = n;
725 d.x = (int*)&x;
726 d.y = (int*)&y;
727 d.buffer = NULL;
728 d.mask = NULL;
729
730 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
731 }
732 }
733
734 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
735 }
736
737 void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
738 const GLint x[], const GLint y[] )
739 {
740 drm_clip_rect_t *pbox = rmesa->pClipRects;
741 drm_r128_depth_t d;
742 int nbox = rmesa->numClipRects;
743 int fd = rmesa->driScreen->fd;
744 int i;
745
746 if ( !nbox || !n ) {
747 return;
748 }
749 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
750 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
751 }
752
753 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
754 {
755 if ( nbox < 3 ) {
756 rmesa->sarea->nbox = 0;
757 } else {
758 rmesa->sarea->nbox = nbox;
759 }
760
761 d.func = R128_READ_PIXELS;
762 d.n = n;
763 d.x = (int*)&x;
764 d.y = (int*)&y;
765 d.buffer = NULL;
766 d.mask = NULL;
767
768 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
769 }
770 else
771 {
772 for (i = 0 ; i < nbox ; ) {
773 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
774 drm_clip_rect_t *b = rmesa->sarea->boxes;
775
776 rmesa->sarea->nbox = nr - i;
777 for ( ; i < nr ; i++) {
778 *b++ = pbox[i];
779 }
780
781 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
782
783 d.func = R128_READ_PIXELS;
784 d.n = n;
785 d.x = (int*)&x;
786 d.y = (int*)&y;
787 d.buffer = NULL;
788 d.mask = NULL;
789
790 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
791 }
792 }
793
794 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
795 }
796
797
798 void r128WaitForIdleLocked( r128ContextPtr rmesa )
799 {
800 int fd = rmesa->r128Screen->driScreen->fd;
801 int to = 0;
802 int ret, i;
803
804 do {
805 i = 0;
806 do {
807 ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
808 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
809 } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
810
811 if ( ret < 0 ) {
812 drmCommandNone( fd, DRM_R128_CCE_RESET);
813 UNLOCK_HARDWARE( rmesa );
814 fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
815 exit( -1 );
816 }
817 }
818
819 void r128InitIoctlFuncs( struct dd_function_table *functions )
820 {
821 functions->Clear = r128Clear;
822 }