If an application cleared before any state had been emitted, that clear would
[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 uint32_t frame;
229 int i;
230 int wait = 0;
231
232 while ( 1 ) {
233 frame = *(volatile unsigned int *)(R128MMIO + R128_LAST_FRAME_REG);
234
235 if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) {
236 break;
237 }
238
239 /* Spin in place a bit so we aren't hammering the register */
240 wait++;
241 for ( i = 0 ; i < 1024 ; i++ ) {
242 delay();
243 }
244 }
245
246 return wait;
247 }
248
249 /* Copy the back color buffer to the front color buffer.
250 */
251 void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
252 {
253 r128ContextPtr rmesa;
254 GLint nbox, i, ret;
255 GLboolean missed_target;
256
257 assert(dPriv);
258 assert(dPriv->driContextPriv);
259 assert(dPriv->driContextPriv->driverPrivate);
260
261 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
262
263 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
264 fprintf( stderr, "\n********************************\n" );
265 fprintf( stderr, "\n%s( %p )\n\n",
266 __FUNCTION__, (void *)rmesa->glCtx );
267 fflush( stderr );
268 }
269
270 FLUSH_BATCH( rmesa );
271
272 LOCK_HARDWARE( rmesa );
273
274 /* Throttle the frame rate -- only allow one pending swap buffers
275 * request at a time.
276 */
277 if ( !r128WaitForFrameCompletion( rmesa ) ) {
278 rmesa->hardwareWentIdle = 1;
279 } else {
280 rmesa->hardwareWentIdle = 0;
281 }
282
283 UNLOCK_HARDWARE( rmesa );
284 driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
285 LOCK_HARDWARE( rmesa );
286
287 nbox = dPriv->numClipRects; /* must be in locked region */
288
289 for ( i = 0 ; i < nbox ; ) {
290 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox );
291 drm_clip_rect_t *box = dPriv->pClipRects;
292 drm_clip_rect_t *b = rmesa->sarea->boxes;
293 GLint n = 0;
294
295 for ( ; i < nr ; i++ ) {
296 *b++ = box[i];
297 n++;
298 }
299 rmesa->sarea->nbox = n;
300
301 ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP );
302
303 if ( ret ) {
304 UNLOCK_HARDWARE( rmesa );
305 fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret );
306 exit( 1 );
307 }
308 }
309
310 if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) {
311 i = 0;
312 do {
313 ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE);
314 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
315 }
316
317 UNLOCK_HARDWARE( rmesa );
318
319 rmesa->new_state |= R128_NEW_CONTEXT;
320 rmesa->dirty |= (R128_UPLOAD_CONTEXT |
321 R128_UPLOAD_MASKS |
322 R128_UPLOAD_CLIPRECTS);
323
324 #if ENABLE_PERF_BOXES
325 /* Log the performance counters if necessary */
326 r128PerformanceCounters( rmesa );
327 #endif
328 }
329
330 void r128PageFlip( const __DRIdrawablePrivate *dPriv )
331 {
332 r128ContextPtr rmesa;
333 GLint ret;
334 GLboolean missed_target;
335
336 assert(dPriv);
337 assert(dPriv->driContextPriv);
338 assert(dPriv->driContextPriv->driverPrivate);
339
340 rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
341
342 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
343 fprintf( stderr, "\n%s( %p ): page=%d\n\n",
344 __FUNCTION__, (void *)rmesa->glCtx, rmesa->sarea->pfCurrentPage );
345 }
346
347 FLUSH_BATCH( rmesa );
348
349 LOCK_HARDWARE( rmesa );
350
351 /* Throttle the frame rate -- only allow one pending swap buffers
352 * request at a time.
353 */
354 if ( !r128WaitForFrameCompletion( rmesa ) ) {
355 rmesa->hardwareWentIdle = 1;
356 } else {
357 rmesa->hardwareWentIdle = 0;
358 }
359
360 UNLOCK_HARDWARE( rmesa );
361 driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
362 LOCK_HARDWARE( rmesa );
363
364 /* The kernel will have been initialized to perform page flipping
365 * on a swapbuffers ioctl.
366 */
367 ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP );
368
369 UNLOCK_HARDWARE( rmesa );
370
371 if ( ret ) {
372 fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret );
373 exit( 1 );
374 }
375
376 if ( rmesa->sarea->pfCurrentPage == 1 ) {
377 rmesa->drawOffset = rmesa->r128Screen->frontOffset;
378 rmesa->drawPitch = rmesa->r128Screen->frontPitch;
379 } else {
380 rmesa->drawOffset = rmesa->r128Screen->backOffset;
381 rmesa->drawPitch = rmesa->r128Screen->backPitch;
382 }
383
384 rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
385 (rmesa->drawOffset >> 5));
386 rmesa->new_state |= R128_NEW_WINDOW;
387
388 /* FIXME: Do we need this anymore? */
389 rmesa->new_state |= R128_NEW_CONTEXT;
390 rmesa->dirty |= (R128_UPLOAD_CONTEXT |
391 R128_UPLOAD_MASKS |
392 R128_UPLOAD_CLIPRECTS);
393
394 #if ENABLE_PERF_BOXES
395 /* Log the performance counters if necessary */
396 r128PerformanceCounters( rmesa );
397 #endif
398 }
399
400
401 /* ================================================================
402 * Buffer clear
403 */
404
405 static void r128Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
406 GLint cx, GLint cy, GLint cw, GLint ch )
407 {
408 r128ContextPtr rmesa = R128_CONTEXT(ctx);
409 __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
410 drm_r128_clear_t clear;
411 GLuint flags = 0;
412 GLint i;
413 GLint ret;
414
415 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
416 fprintf( stderr, "%s:\n", __FUNCTION__ );
417 }
418
419 FLUSH_BATCH( rmesa );
420
421 /* The only state change we care about here is the RGBA colormask
422 * We'll just update that state, if needed. If we do more then
423 * there's some strange side-effects that the conformance tests find.
424 */
425 if ( rmesa->new_state & R128_NEW_MASKS) {
426 const GLuint save_state = rmesa->new_state;
427 rmesa->new_state = R128_NEW_MASKS;
428 r128DDUpdateHWState( ctx );
429 rmesa->new_state = save_state & ~R128_NEW_MASKS;
430 }
431
432 if ( mask & DD_FRONT_LEFT_BIT ) {
433 flags |= R128_FRONT;
434 mask &= ~DD_FRONT_LEFT_BIT;
435 }
436
437 if ( mask & DD_BACK_LEFT_BIT ) {
438 flags |= R128_BACK;
439 mask &= ~DD_BACK_LEFT_BIT;
440 }
441
442 if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
443 flags |= R128_DEPTH;
444 mask &= ~DD_DEPTH_BIT;
445 }
446 #if 0
447 /* FIXME: Add stencil support */
448 if ( mask & DD_STENCIL_BIT ) {
449 flags |= DRM_R128_DEPTH_BUFFER;
450 mask &= ~DD_STENCIL_BIT;
451 }
452 #endif
453
454 if ( flags ) {
455
456 /* Flip top to bottom */
457 cx += dPriv->x;
458 cy = dPriv->y + dPriv->h - cy - ch;
459
460 LOCK_HARDWARE( rmesa );
461
462 /* FIXME: Do we actually need this?
463 */
464 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
465 r128EmitHwStateLocked( rmesa );
466 }
467
468 for ( i = 0 ; i < rmesa->numClipRects ; ) {
469 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
470 drm_clip_rect_t *box = rmesa->pClipRects;
471 drm_clip_rect_t *b = rmesa->sarea->boxes;
472 GLint n = 0;
473
474 if ( !all ) {
475 for ( ; i < nr ; i++ ) {
476 GLint x = box[i].x1;
477 GLint y = box[i].y1;
478 GLint w = box[i].x2 - x;
479 GLint h = box[i].y2 - y;
480
481 if ( x < cx ) w -= cx - x, x = cx;
482 if ( y < cy ) h -= cy - y, y = cy;
483 if ( x + w > cx + cw ) w = cx + cw - x;
484 if ( y + h > cy + ch ) h = cy + ch - y;
485 if ( w <= 0 ) continue;
486 if ( h <= 0 ) continue;
487
488 b->x1 = x;
489 b->y1 = y;
490 b->x2 = x + w;
491 b->y2 = y + h;
492 b++;
493 n++;
494 }
495 } else {
496 for ( ; i < nr ; i++ ) {
497 *b++ = box[i];
498 n++;
499 }
500 }
501
502 rmesa->sarea->nbox = n;
503
504 if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
505 fprintf( stderr,
506 "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
507 flags,
508 (GLuint)rmesa->ClearColor,
509 (GLuint)rmesa->ClearDepth,
510 rmesa->sarea->nbox );
511 }
512
513 clear.flags = flags;
514 clear.clear_color = rmesa->ClearColor;
515 clear.clear_depth = rmesa->ClearDepth;
516 clear.color_mask = rmesa->setup.plane_3d_mask_c;
517 clear.depth_mask = ~0;
518
519 ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
520 &clear, sizeof(clear) );
521
522 if ( ret ) {
523 UNLOCK_HARDWARE( rmesa );
524 fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
525 exit( 1 );
526 }
527 }
528
529 UNLOCK_HARDWARE( rmesa );
530
531 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
532 }
533
534 if ( mask )
535 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
536 }
537
538
539 /* ================================================================
540 * Depth spans, pixels
541 */
542
543 void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
544 GLuint n, GLint x, GLint y,
545 const GLdepth depth[],
546 const GLubyte mask[] )
547 {
548 drm_clip_rect_t *pbox = rmesa->pClipRects;
549 drm_r128_depth_t d;
550 int nbox = rmesa->numClipRects;
551 int fd = rmesa->driScreen->fd;
552 int i;
553
554 if ( !nbox || !n ) {
555 return;
556 }
557 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
558 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
559 }
560
561 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
562 {
563 if ( nbox < 3 ) {
564 rmesa->sarea->nbox = 0;
565 } else {
566 rmesa->sarea->nbox = nbox;
567 }
568
569 d.func = R128_WRITE_SPAN;
570 d.n = n;
571 d.x = (int*)&x;
572 d.y = (int*)&y;
573 d.buffer = (unsigned int *)depth;
574 d.mask = (unsigned char *)mask;
575
576 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
577
578 }
579 else
580 {
581 for (i = 0 ; i < nbox ; ) {
582 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
583 drm_clip_rect_t *b = rmesa->sarea->boxes;
584
585 rmesa->sarea->nbox = nr - i;
586 for ( ; i < nr ; i++) {
587 *b++ = pbox[i];
588 }
589
590 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
591
592 d.func = R128_WRITE_SPAN;
593 d.n = n;
594 d.x = (int*)&x;
595 d.y = (int*)&y;
596 d.buffer = (unsigned int *)depth;
597 d.mask = (unsigned char *)mask;
598
599 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
600 }
601 }
602
603 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
604 }
605
606 void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
607 const GLint x[], const GLint y[],
608 const GLdepth depth[],
609 const GLubyte mask[] )
610 {
611 drm_clip_rect_t *pbox = rmesa->pClipRects;
612 drm_r128_depth_t d;
613 int nbox = rmesa->numClipRects;
614 int fd = rmesa->driScreen->fd;
615 int i;
616
617 if ( !nbox || !n ) {
618 return;
619 }
620 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
621 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
622 }
623
624 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
625 {
626 if ( nbox < 3 ) {
627 rmesa->sarea->nbox = 0;
628 } else {
629 rmesa->sarea->nbox = nbox;
630 }
631
632 d.func = R128_WRITE_PIXELS;
633 d.n = n;
634 d.x = (int*)&x;
635 d.y = (int*)&y;
636 d.buffer = (unsigned int *)depth;
637 d.mask = (unsigned char *)mask;
638
639 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
640 }
641 else
642 {
643 for (i = 0 ; i < nbox ; ) {
644 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
645 drm_clip_rect_t *b = rmesa->sarea->boxes;
646
647 rmesa->sarea->nbox = nr - i;
648 for ( ; i < nr ; i++) {
649 *b++ = pbox[i];
650 }
651
652 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
653
654 d.func = R128_WRITE_PIXELS;
655 d.n = n;
656 d.x = (int*)&x;
657 d.y = (int*)&y;
658 d.buffer = (unsigned int *)depth;
659 d.mask = (unsigned char *)mask;
660
661 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
662 }
663 }
664
665 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
666 }
667
668 void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
669 GLuint n, GLint x, GLint y )
670 {
671 drm_clip_rect_t *pbox = rmesa->pClipRects;
672 drm_r128_depth_t d;
673 int nbox = rmesa->numClipRects;
674 int fd = rmesa->driScreen->fd;
675 int i;
676
677 if ( !nbox || !n ) {
678 return;
679 }
680 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
681 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
682 }
683
684 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
685 {
686 if ( nbox < 3 ) {
687 rmesa->sarea->nbox = 0;
688 } else {
689 rmesa->sarea->nbox = nbox;
690 }
691
692 d.func = R128_READ_SPAN;
693 d.n = n;
694 d.x = (int*)&x;
695 d.y = (int*)&y;
696 d.buffer = NULL;
697 d.mask = NULL;
698
699 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
700 }
701 else
702 {
703 for (i = 0 ; i < nbox ; ) {
704 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
705 drm_clip_rect_t *b = rmesa->sarea->boxes;
706
707 rmesa->sarea->nbox = nr - i;
708 for ( ; i < nr ; i++) {
709 *b++ = pbox[i];
710 }
711
712 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
713
714 d.func = R128_READ_SPAN;
715 d.n = n;
716 d.x = (int*)&x;
717 d.y = (int*)&y;
718 d.buffer = NULL;
719 d.mask = NULL;
720
721 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
722 }
723 }
724
725 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
726 }
727
728 void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
729 const GLint x[], const GLint y[] )
730 {
731 drm_clip_rect_t *pbox = rmesa->pClipRects;
732 drm_r128_depth_t d;
733 int nbox = rmesa->numClipRects;
734 int fd = rmesa->driScreen->fd;
735 int i;
736
737 if ( !nbox || !n ) {
738 return;
739 }
740 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
741 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
742 }
743
744 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
745 {
746 if ( nbox < 3 ) {
747 rmesa->sarea->nbox = 0;
748 } else {
749 rmesa->sarea->nbox = nbox;
750 }
751
752 d.func = R128_READ_PIXELS;
753 d.n = n;
754 d.x = (int*)&x;
755 d.y = (int*)&y;
756 d.buffer = NULL;
757 d.mask = NULL;
758
759 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
760 }
761 else
762 {
763 for (i = 0 ; i < nbox ; ) {
764 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
765 drm_clip_rect_t *b = rmesa->sarea->boxes;
766
767 rmesa->sarea->nbox = nr - i;
768 for ( ; i < nr ; i++) {
769 *b++ = pbox[i];
770 }
771
772 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
773
774 d.func = R128_READ_PIXELS;
775 d.n = n;
776 d.x = (int*)&x;
777 d.y = (int*)&y;
778 d.buffer = NULL;
779 d.mask = NULL;
780
781 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
782 }
783 }
784
785 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
786 }
787
788
789 void r128WaitForIdleLocked( r128ContextPtr rmesa )
790 {
791 int fd = rmesa->r128Screen->driScreen->fd;
792 int to = 0;
793 int ret, i;
794
795 do {
796 i = 0;
797 do {
798 ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
799 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
800 } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
801
802 if ( ret < 0 ) {
803 drmCommandNone( fd, DRM_R128_CCE_RESET);
804 UNLOCK_HARDWARE( rmesa );
805 fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
806 exit( -1 );
807 }
808 }
809
810 void r128InitIoctlFuncs( struct dd_function_table *functions )
811 {
812 functions->Clear = r128Clear;
813 }