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