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