draw: corrections to allow for different cliptest cases
[mesa.git] / src / mesa / drivers / dri / r128 / r128_ioctl.c
1 /**************************************************************************
2
3 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
4 Cedar Park, Texas.
5 All Rights Reserved.
6
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
13
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
16 Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Gareth Hughes <gareth@valinux.com>
31 *
32 */
33 #include <errno.h>
34
35 #define STANDALONE_MMIO
36 #include "r128_context.h"
37 #include "r128_state.h"
38 #include "r128_ioctl.h"
39 #include "main/imports.h"
40 #include "main/macros.h"
41
42 #include "swrast/swrast.h"
43
44 #include "vblank.h"
45 #include "mmio.h"
46 #include "drirenderbuffer.h"
47
48 #define R128_TIMEOUT 2048
49 #define R128_IDLE_RETRY 32
50
51
52 /* =============================================================
53 * Hardware vertex buffer handling
54 */
55
56 /* Get a new VB from the pool of vertex buffers in AGP space.
57 */
58 drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa )
59 {
60 int fd = rmesa->r128Screen->driScreen->fd;
61 int index = 0;
62 int size = 0;
63 drmDMAReq dma;
64 drmBufPtr buf = NULL;
65 int to = 0;
66 int ret;
67
68 dma.context = rmesa->hHWContext;
69 dma.send_count = 0;
70 dma.send_list = NULL;
71 dma.send_sizes = NULL;
72 dma.flags = 0;
73 dma.request_count = 1;
74 dma.request_size = R128_BUFFER_SIZE;
75 dma.request_list = &index;
76 dma.request_sizes = &size;
77 dma.granted_count = 0;
78
79 while ( !buf && ( to++ < R128_TIMEOUT ) ) {
80 ret = drmDMA( fd, &dma );
81
82 if ( ret == 0 ) {
83 buf = &rmesa->r128Screen->buffers->list[index];
84 buf->used = 0;
85 #if ENABLE_PERF_BOXES
86 /* Bump the performance counter */
87 rmesa->c_vertexBuffers++;
88 #endif
89 return buf;
90 }
91 }
92
93 if ( !buf ) {
94 drmCommandNone( fd, DRM_R128_CCE_RESET);
95 UNLOCK_HARDWARE( rmesa );
96 fprintf( stderr, "Error: Could not get new VB... exiting\n" );
97 exit( -1 );
98 }
99
100 return buf;
101 }
102
103 void r128FlushVerticesLocked( r128ContextPtr rmesa )
104 {
105 drm_clip_rect_t *pbox = rmesa->pClipRects;
106 int nbox = rmesa->numClipRects;
107 drmBufPtr buffer = rmesa->vert_buf;
108 int count = rmesa->num_verts;
109 int prim = rmesa->hw_primitive;
110 int fd = rmesa->driScreen->fd;
111 drm_r128_vertex_t vertex;
112 int i;
113
114 rmesa->num_verts = 0;
115 rmesa->vert_buf = NULL;
116
117 if ( !buffer )
118 return;
119
120 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS )
121 r128EmitHwStateLocked( rmesa );
122
123 if ( !nbox )
124 count = 0;
125
126 if ( nbox >= R128_NR_SAREA_CLIPRECTS )
127 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
128
129 if ( !count || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
130 {
131 if ( nbox < 3 ) {
132 rmesa->sarea->nbox = 0;
133 } else {
134 rmesa->sarea->nbox = nbox;
135 }
136
137 vertex.prim = prim;
138 vertex.idx = buffer->idx;
139 vertex.count = count;
140 vertex.discard = 1;
141 drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(vertex) );
142 }
143 else
144 {
145 for ( i = 0 ; i < nbox ; ) {
146 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
147 drm_clip_rect_t *b = rmesa->sarea->boxes;
148 int discard = 0;
149
150 rmesa->sarea->nbox = nr - i;
151 for ( ; i < nr ; i++ ) {
152 *b++ = pbox[i];
153 }
154
155 /* Finished with the buffer?
156 */
157 if ( nr == nbox ) {
158 discard = 1;
159 }
160
161 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
162
163 vertex.prim = prim;
164 vertex.idx = buffer->idx;
165 vertex.count = count;
166 vertex.discard = discard;
167 drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(vertex) );
168 }
169 }
170
171 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
172 }
173
174
175
176
177
178 /* ================================================================
179 * Texture uploads
180 */
181
182 void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
183 GLint offset, GLint pitch, GLint format,
184 GLint x, GLint y, GLint width, GLint height )
185 {
186 drm_r128_blit_t blit;
187 GLint ret;
188
189 blit.idx = buffer->idx;
190 blit.offset = offset;
191 blit.pitch = pitch;
192 blit.format = format;
193 blit.x = x;
194 blit.y = y;
195 blit.width = width;
196 blit.height = height;
197
198 ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT,
199 &blit, sizeof(blit) );
200
201 if ( ret ) {
202 UNLOCK_HARDWARE( rmesa );
203 fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret );
204 exit( 1 );
205 }
206 }
207
208
209 /* ================================================================
210 * SwapBuffers with client-side throttling
211 */
212
213 static void delay( void ) {
214 /* Prevent an optimizing compiler from removing a spin loop */
215 }
216
217 #define R128_MAX_OUTSTANDING 2
218
219
220 /* Throttle the frame rate -- only allow one pending swap buffers
221 * request at a time.
222 * GH: We probably don't want a timeout here, as we can wait as
223 * long as we want for a frame to complete. If it never does, then
224 * the card has locked.
225 */
226 static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
227 {
228 unsigned char *R128MMIO = rmesa->r128Screen->mmio.map;
229 int i;
230 int wait = 0;
231
232 while ( 1 ) {
233 uint32_t frame = read_MMIO_LE32( 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( __DRIdrawable *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, &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( __DRIdrawable *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, &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 /* Get ready for drawing next frame. Update the renderbuffers'
377 * flippedOffset/Pitch fields so we draw into the right place.
378 */
379 driFlipRenderbuffers(rmesa->glCtx->WinSysDrawBuffer,
380 rmesa->sarea->pfCurrentPage);
381
382 rmesa->new_state |= R128_NEW_WINDOW;
383
384 /* FIXME: Do we need this anymore? */
385 rmesa->new_state |= R128_NEW_CONTEXT;
386 rmesa->dirty |= (R128_UPLOAD_CONTEXT |
387 R128_UPLOAD_MASKS |
388 R128_UPLOAD_CLIPRECTS);
389
390 #if ENABLE_PERF_BOXES
391 /* Log the performance counters if necessary */
392 r128PerformanceCounters( rmesa );
393 #endif
394 }
395
396
397 /* ================================================================
398 * Buffer clear
399 */
400
401 static void r128Clear( GLcontext *ctx, GLbitfield mask )
402 {
403 r128ContextPtr rmesa = R128_CONTEXT(ctx);
404 __DRIdrawable *dPriv = rmesa->driDrawable;
405 drm_r128_clear_t clear;
406 GLuint flags = 0;
407 GLint i;
408 GLint ret;
409 GLuint depthmask = 0;
410 GLint cx, cy, cw, ch;
411
412 if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
413 fprintf( stderr, "%s:\n", __FUNCTION__ );
414 }
415
416 FLUSH_BATCH( rmesa );
417
418 /* The only state change we care about here is the RGBA colormask
419 * We'll just update that state, if needed. If we do more then
420 * there's some strange side-effects that the conformance tests find.
421 */
422 if ( rmesa->new_state & R128_NEW_MASKS) {
423 const GLuint save_state = rmesa->new_state;
424 rmesa->new_state = R128_NEW_MASKS;
425 r128DDUpdateHWState( ctx );
426 rmesa->new_state = save_state & ~R128_NEW_MASKS;
427 }
428
429 if ( mask & BUFFER_BIT_FRONT_LEFT ) {
430 flags |= R128_FRONT;
431 mask &= ~BUFFER_BIT_FRONT_LEFT;
432 }
433
434 if ( mask & BUFFER_BIT_BACK_LEFT ) {
435 flags |= R128_BACK;
436 mask &= ~BUFFER_BIT_BACK_LEFT;
437 }
438
439 if ( ( mask & BUFFER_BIT_DEPTH ) && ctx->Depth.Mask ) {
440 flags |= R128_DEPTH;
441 /* if we're at 16 bits, extra plane mask won't hurt */
442 depthmask |= 0x00ffffff;
443 mask &= ~BUFFER_BIT_DEPTH;
444 }
445
446 if ( mask & BUFFER_BIT_STENCIL &&
447 (ctx->Visual.stencilBits > 0 && ctx->Visual.depthBits == 24) ) {
448 flags |= R128_DEPTH;
449 depthmask |= ctx->Stencil.WriteMask[0] << 24;
450 mask &= ~BUFFER_BIT_STENCIL;
451 }
452
453 if ( flags ) {
454
455 LOCK_HARDWARE( rmesa );
456
457 /* compute region after locking: */
458 cx = ctx->DrawBuffer->_Xmin;
459 cy = ctx->DrawBuffer->_Ymin;
460 cw = ctx->DrawBuffer->_Xmax - cx;
461 ch = ctx->DrawBuffer->_Ymax - cy;
462
463 /* Flip top to bottom */
464 cx += dPriv->x;
465 cy = dPriv->y + dPriv->h - cy - ch;
466
467 /* FIXME: Do we actually need this?
468 */
469 if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
470 r128EmitHwStateLocked( rmesa );
471 }
472
473 for ( i = 0 ; i < rmesa->numClipRects ; ) {
474 GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
475 drm_clip_rect_t *box = rmesa->pClipRects;
476 drm_clip_rect_t *b = rmesa->sarea->boxes;
477 GLint n = 0;
478
479 if (cw != dPriv->w || ch != dPriv->h) {
480 /* clear subregion */
481 for ( ; i < nr ; i++ ) {
482 GLint x = box[i].x1;
483 GLint y = box[i].y1;
484 GLint w = box[i].x2 - x;
485 GLint h = box[i].y2 - y;
486
487 if ( x < cx ) w -= cx - x, x = cx;
488 if ( y < cy ) h -= cy - y, y = cy;
489 if ( x + w > cx + cw ) w = cx + cw - x;
490 if ( y + h > cy + ch ) h = cy + ch - y;
491 if ( w <= 0 ) continue;
492 if ( h <= 0 ) continue;
493
494 b->x1 = x;
495 b->y1 = y;
496 b->x2 = x + w;
497 b->y2 = y + h;
498 b++;
499 n++;
500 }
501 } else {
502 /* clear whole window */
503 for ( ; i < nr ; i++ ) {
504 *b++ = box[i];
505 n++;
506 }
507 }
508
509 rmesa->sarea->nbox = n;
510
511 if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
512 fprintf( stderr,
513 "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
514 flags,
515 (GLuint)rmesa->ClearColor,
516 (GLuint)rmesa->ClearDepth,
517 rmesa->sarea->nbox );
518 }
519
520 clear.flags = flags;
521 clear.clear_color = rmesa->ClearColor;
522 clear.clear_depth = rmesa->ClearDepth;
523 clear.color_mask = rmesa->setup.plane_3d_mask_c;
524 clear.depth_mask = depthmask;
525
526 ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
527 &clear, sizeof(clear) );
528
529 if ( ret ) {
530 UNLOCK_HARDWARE( rmesa );
531 fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
532 exit( 1 );
533 }
534 }
535
536 UNLOCK_HARDWARE( rmesa );
537
538 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
539 }
540
541 if ( mask )
542 _swrast_Clear( ctx, mask );
543 }
544
545
546 /* ================================================================
547 * Depth spans, pixels
548 */
549
550 void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
551 GLuint n, GLint x, GLint y,
552 const GLuint depth[],
553 const GLubyte mask[] )
554 {
555 drm_clip_rect_t *pbox = rmesa->pClipRects;
556 drm_r128_depth_t d;
557 int nbox = rmesa->numClipRects;
558 int fd = rmesa->driScreen->fd;
559 int i;
560
561 if ( !nbox || !n ) {
562 return;
563 }
564 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
565 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
566 }
567
568 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
569 {
570 if ( nbox < 3 ) {
571 rmesa->sarea->nbox = 0;
572 } else {
573 rmesa->sarea->nbox = nbox;
574 }
575
576 d.func = R128_WRITE_SPAN;
577 d.n = n;
578 d.x = (int*)&x;
579 d.y = (int*)&y;
580 d.buffer = (unsigned int *)depth;
581 d.mask = (unsigned char *)mask;
582
583 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
584
585 }
586 else
587 {
588 for (i = 0 ; i < nbox ; ) {
589 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
590 drm_clip_rect_t *b = rmesa->sarea->boxes;
591
592 rmesa->sarea->nbox = nr - i;
593 for ( ; i < nr ; i++) {
594 *b++ = pbox[i];
595 }
596
597 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
598
599 d.func = R128_WRITE_SPAN;
600 d.n = n;
601 d.x = (int*)&x;
602 d.y = (int*)&y;
603 d.buffer = (unsigned int *)depth;
604 d.mask = (unsigned char *)mask;
605
606 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
607 }
608 }
609
610 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
611 }
612
613 void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
614 const GLint x[], const GLint y[],
615 const GLuint depth[],
616 const GLubyte mask[] )
617 {
618 drm_clip_rect_t *pbox = rmesa->pClipRects;
619 drm_r128_depth_t d;
620 int nbox = rmesa->numClipRects;
621 int fd = rmesa->driScreen->fd;
622 int i;
623
624 if ( !nbox || !n ) {
625 return;
626 }
627 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
628 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
629 }
630
631 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
632 {
633 if ( nbox < 3 ) {
634 rmesa->sarea->nbox = 0;
635 } else {
636 rmesa->sarea->nbox = nbox;
637 }
638
639 d.func = R128_WRITE_PIXELS;
640 d.n = n;
641 d.x = (int*)&x;
642 d.y = (int*)&y;
643 d.buffer = (unsigned int *)depth;
644 d.mask = (unsigned char *)mask;
645
646 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
647 }
648 else
649 {
650 for (i = 0 ; i < nbox ; ) {
651 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
652 drm_clip_rect_t *b = rmesa->sarea->boxes;
653
654 rmesa->sarea->nbox = nr - i;
655 for ( ; i < nr ; i++) {
656 *b++ = pbox[i];
657 }
658
659 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
660
661 d.func = R128_WRITE_PIXELS;
662 d.n = n;
663 d.x = (int*)&x;
664 d.y = (int*)&y;
665 d.buffer = (unsigned int *)depth;
666 d.mask = (unsigned char *)mask;
667
668 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
669 }
670 }
671
672 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
673 }
674
675 void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
676 GLuint n, GLint x, GLint y )
677 {
678 drm_clip_rect_t *pbox = rmesa->pClipRects;
679 drm_r128_depth_t d;
680 int nbox = rmesa->numClipRects;
681 int fd = rmesa->driScreen->fd;
682 int i;
683
684 if ( !nbox || !n ) {
685 return;
686 }
687 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
688 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
689 }
690
691 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
692 {
693 if ( nbox < 3 ) {
694 rmesa->sarea->nbox = 0;
695 } else {
696 rmesa->sarea->nbox = nbox;
697 }
698
699 d.func = R128_READ_SPAN;
700 d.n = n;
701 d.x = (int*)&x;
702 d.y = (int*)&y;
703 d.buffer = NULL;
704 d.mask = NULL;
705
706 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
707 }
708 else
709 {
710 for (i = 0 ; i < nbox ; ) {
711 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
712 drm_clip_rect_t *b = rmesa->sarea->boxes;
713
714 rmesa->sarea->nbox = nr - i;
715 for ( ; i < nr ; i++) {
716 *b++ = pbox[i];
717 }
718
719 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
720
721 d.func = R128_READ_SPAN;
722 d.n = n;
723 d.x = (int*)&x;
724 d.y = (int*)&y;
725 d.buffer = NULL;
726 d.mask = NULL;
727
728 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
729 }
730 }
731
732 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
733 }
734
735 void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
736 const GLint x[], const GLint y[] )
737 {
738 drm_clip_rect_t *pbox = rmesa->pClipRects;
739 drm_r128_depth_t d;
740 int nbox = rmesa->numClipRects;
741 int fd = rmesa->driScreen->fd;
742 int i;
743
744 if ( !nbox || !n ) {
745 return;
746 }
747 if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
748 rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
749 }
750
751 if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
752 {
753 if ( nbox < 3 ) {
754 rmesa->sarea->nbox = 0;
755 } else {
756 rmesa->sarea->nbox = nbox;
757 }
758
759 d.func = R128_READ_PIXELS;
760 d.n = n;
761 d.x = (int*)&x;
762 d.y = (int*)&y;
763 d.buffer = NULL;
764 d.mask = NULL;
765
766 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
767 }
768 else
769 {
770 for (i = 0 ; i < nbox ; ) {
771 int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
772 drm_clip_rect_t *b = rmesa->sarea->boxes;
773
774 rmesa->sarea->nbox = nr - i;
775 for ( ; i < nr ; i++) {
776 *b++ = pbox[i];
777 }
778
779 rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
780
781 d.func = R128_READ_PIXELS;
782 d.n = n;
783 d.x = (int*)&x;
784 d.y = (int*)&y;
785 d.buffer = NULL;
786 d.mask = NULL;
787
788 drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(d));
789 }
790 }
791
792 rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
793 }
794
795
796 void r128WaitForIdleLocked( r128ContextPtr rmesa )
797 {
798 int fd = rmesa->r128Screen->driScreen->fd;
799 int to = 0;
800 int ret, i;
801
802 do {
803 i = 0;
804 do {
805 ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
806 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
807 } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
808
809 if ( ret < 0 ) {
810 drmCommandNone( fd, DRM_R128_CCE_RESET);
811 UNLOCK_HARDWARE( rmesa );
812 fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
813 exit( -1 );
814 }
815 }
816
817 void r128InitIoctlFuncs( struct dd_function_table *functions )
818 {
819 functions->Clear = r128Clear;
820 }