Initial mach64 driver import for DRI mach64-0-0-6 branch,
[mesa.git] / src / mesa / drivers / dri / mach64 / mach64_ioctl.c
1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
2 /*
3 * Copyright 2000 Gareth Hughes
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Authors:
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
30 */
31
32 #include "mach64_context.h"
33 #include "mach64_state.h"
34 #include "mach64_ioctl.h"
35 #include "mach64_tex.h"
36
37 #include "imports.h"
38 #include "macros.h"
39
40 #include "swrast/swrast.h"
41
42 #include "vblank.h"
43
44 #define MACH64_TIMEOUT 10 /* the DRM already has a timeout, so keep this small */
45
46
47 /* =============================================================
48 * Hardware vertex buffer handling
49 */
50
51 /* Get a new VB from the pool of vertex buffers in AGP space.
52 */
53 drmBufPtr mach64GetBufferLocked( mach64ContextPtr mmesa )
54 {
55 int fd = mmesa->mach64Screen->driScreen->fd;
56 int index = 0;
57 int size = 0;
58 drmDMAReq dma;
59 drmBufPtr buf = NULL;
60 int to = 0;
61 int ret;
62
63 dma.context = mmesa->hHWContext;
64 dma.send_count = 0;
65 dma.send_list = NULL;
66 dma.send_sizes = NULL;
67 dma.flags = 0;
68 dma.request_count = 1;
69 dma.request_size = MACH64_BUFFER_SIZE;
70 dma.request_list = &index;
71 dma.request_sizes = &size;
72 dma.granted_count = 0;
73
74 while ( !buf && ( to++ < MACH64_TIMEOUT ) ) {
75 ret = drmDMA( fd, &dma );
76
77 if ( ret == 0 ) {
78 buf = &mmesa->mach64Screen->buffers->list[index];
79 buf->used = 0;
80 #if ENABLE_PERF_BOXES
81 /* Bump the performance counter */
82 mmesa->c_vertexBuffers++;
83 #endif
84 return buf;
85 }
86 }
87
88 if ( !buf ) {
89 drmCommandNone( fd, DRM_MACH64_RESET );
90 UNLOCK_HARDWARE( mmesa );
91 fprintf( stderr, "Error: Could not get new VB... exiting\n" );
92 exit( -1 );
93 }
94
95 return buf;
96 }
97
98 void mach64FlushVerticesLocked( mach64ContextPtr mmesa )
99 {
100 XF86DRIClipRectPtr pbox = mmesa->pClipRects;
101 int nbox = mmesa->numClipRects;
102 void *buffer = mmesa->vert_buf;
103 int count = mmesa->vert_used;
104 int prim = mmesa->hw_primitive;
105 int fd = mmesa->driScreen->fd;
106 drmMach64Vertex vertex;
107 int i, ret;
108
109 mmesa->num_verts = 0;
110 mmesa->vert_used = 0;
111
112 if ( !count )
113 return;
114
115 if ( mmesa->dirty & ~MACH64_UPLOAD_CLIPRECTS )
116 mach64EmitHwStateLocked( mmesa );
117
118 if ( !nbox )
119 count = 0;
120
121 if ( nbox > MACH64_NR_SAREA_CLIPRECTS )
122 mmesa->dirty |= MACH64_UPLOAD_CLIPRECTS;
123
124 if ( !count || !(mmesa->dirty & MACH64_UPLOAD_CLIPRECTS) ) {
125 /* FIXME: Is this really necessary */
126 if ( nbox == 1 )
127 mmesa->sarea->nbox = 0;
128 else
129 mmesa->sarea->nbox = nbox;
130
131 vertex.prim = prim;
132 vertex.buf = buffer;
133 vertex.used = count;
134 vertex.discard = 1;
135 ret = drmCommandWrite( fd, DRM_MACH64_VERTEX, &vertex, sizeof(drmMach64Vertex) );
136 if ( ret ) {
137 UNLOCK_HARDWARE( mmesa );
138 fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );
139 exit( -1 );
140 }
141
142 } else {
143
144 for ( i = 0 ; i < nbox ; ) {
145 int nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS, nbox );
146 XF86DRIClipRectPtr b = mmesa->sarea->boxes;
147 int discard = 0;
148
149 mmesa->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 mmesa->sarea->dirty |= MACH64_UPLOAD_CLIPRECTS;
161
162 vertex.prim = prim;
163 vertex.buf = buffer;
164 vertex.used = count;
165 vertex.discard = discard;
166 ret = drmCommandWrite( fd, DRM_MACH64_VERTEX, &vertex, sizeof(drmMach64Vertex) );
167 if ( ret ) {
168 UNLOCK_HARDWARE( mmesa );
169 fprintf( stderr, "Error flushing vertex buffer: return = %d\n", ret );
170 exit( -1 );
171 }
172 }
173 }
174
175 mmesa->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
176 }
177
178 /* ================================================================
179 * Texture uploads
180 */
181
182 void mach64FireBlitLocked( mach64ContextPtr mmesa, drmBufPtr buffer,
183 GLint offset, GLint pitch, GLint format,
184 GLint x, GLint y, GLint width, GLint height )
185 {
186 drmMach64Blit 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( mmesa->driFd, DRM_MACH64_BLIT,
199 &blit, sizeof(drmMach64Blit) );
200
201 if ( ret ) {
202 UNLOCK_HARDWARE( mmesa );
203 fprintf( stderr, "DRM_MACH64_BLIT: return = %d\n", ret );
204 exit( -1 );
205 }
206 }
207
208
209 /* ================================================================
210 * SwapBuffers with client-side throttling
211 */
212 static void delay( void ) {
213 /* Prevent an optimizing compiler from removing a spin loop */
214 }
215
216 /* Throttle the frame rate -- only allow MACH64_MAX_QUEUED_FRAMES
217 * pending swap buffers requests at a time.
218 *
219 * GH: We probably don't want a timeout here, as we can wait as
220 * long as we want for a frame to complete. If it never does, then
221 * the card has locked.
222 */
223 static int mach64WaitForFrameCompletion( mach64ContextPtr mmesa )
224 {
225 int fd = mmesa->driFd;
226 int i;
227 int wait = 0;
228 int frames;
229
230 while ( 1 ) {
231 drmMach64GetParam gp;
232 int ret;
233
234 if ( mmesa->sarea->frames_queued < MACH64_MAX_QUEUED_FRAMES ) {
235 break;
236 }
237
238 if (MACH64_DEBUG & DEBUG_NOWAIT) {
239 return 1;
240 }
241
242 gp.param = MACH64_PARAM_FRAMES_QUEUED;
243 gp.value = &frames; /* also copied into sarea->frames_queued by DRM */
244
245 ret = drmCommandWriteRead( fd, DRM_MACH64_GETPARAM, &gp, sizeof(gp) );
246
247 if ( ret ) {
248 UNLOCK_HARDWARE( mmesa );
249 fprintf( stderr, "DRM_MACH64_GETPARAM: return = %d\n", ret );
250 exit( -1 );
251 }
252
253 /* Spin in place a bit so we aren't hammering the register */
254 wait++;
255
256 for ( i = 0 ; i < 1024 ; i++ ) {
257 delay();
258 }
259
260 }
261
262 return wait;
263 }
264
265 /* Copy the back color buffer to the front color buffer.
266 */
267 void mach64CopyBuffer( const __DRIdrawablePrivate *dPriv )
268 {
269 mach64ContextPtr mmesa;
270 GLint nbox, i, ret;
271 XF86DRIClipRectPtr pbox;
272 GLboolean missed_target;
273
274 assert(dPriv);
275 assert(dPriv->driContextPriv);
276 assert(dPriv->driContextPriv->driverPrivate);
277
278 mmesa = (mach64ContextPtr) dPriv->driContextPriv->driverPrivate;
279
280 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
281 fprintf( stderr, "\n********************************\n" );
282 fprintf( stderr, "\n%s( %p )\n\n",
283 __FUNCTION__, mmesa->glCtx );
284 fflush( stderr );
285 }
286
287 /* Flush any outstanding vertex buffers */
288 FLUSH_BATCH( mmesa );
289
290 LOCK_HARDWARE( mmesa );
291
292 /* Throttle the frame rate -- only allow one pending swap buffers
293 * request at a time.
294 */
295 if ( !mach64WaitForFrameCompletion( mmesa ) ) {
296 mmesa->hardwareWentIdle = 1;
297 } else {
298 mmesa->hardwareWentIdle = 0;
299 }
300
301 #if ENABLE_PERF_BOXES
302 if ( mmesa->boxes ) {
303 mach64PerformanceBoxesLocked( mmesa );
304 }
305 #endif
306
307 UNLOCK_HARDWARE( mmesa );
308 driWaitForVBlank( dPriv, &mmesa->vbl_seq, mmesa->vblank_flags, &missed_target );
309 LOCK_HARDWARE( mmesa );
310
311 /* use front buffer cliprects */
312 nbox = dPriv->numClipRects;
313 pbox = dPriv->pClipRects;
314
315 for ( i = 0 ; i < nbox ; ) {
316 GLint nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS , nbox );
317 XF86DRIClipRectPtr b = mmesa->sarea->boxes;
318 GLint n = 0;
319
320 for ( ; i < nr ; i++ ) {
321 *b++ = pbox[i];
322 n++;
323 }
324 mmesa->sarea->nbox = n;
325
326 ret = drmCommandNone( mmesa->driFd, DRM_MACH64_SWAP );
327
328 if ( ret ) {
329 UNLOCK_HARDWARE( mmesa );
330 fprintf( stderr, "DRM_MACH64_SWAP: return = %d\n", ret );
331 exit( -1 );
332 }
333 }
334
335 if ( MACH64_DEBUG & DEBUG_ALWAYS_SYNC ) {
336 mach64WaitForIdleLocked( mmesa );
337 }
338
339 UNLOCK_HARDWARE( mmesa );
340
341 mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
342 MACH64_UPLOAD_MISC |
343 MACH64_UPLOAD_CLIPRECTS);
344
345 #if ENABLE_PERF_BOXES
346 /* Log the performance counters if necessary */
347 mach64PerformanceCounters( mmesa );
348 #endif
349 }
350
351 #if ENABLE_PERF_BOXES
352 /* ================================================================
353 * Performance monitoring
354 */
355
356 void mach64PerformanceCounters( mach64ContextPtr mmesa )
357 {
358
359 if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {
360 /* report performance counters */
361 fprintf( stderr, "mach64CopyBuffer: vertexBuffers:%i drawWaits:%i clears:%i\n",
362 mmesa->c_vertexBuffers, mmesa->c_drawWaits, mmesa->c_clears );
363 }
364
365 mmesa->c_vertexBuffers = 0;
366 mmesa->c_drawWaits = 0;
367 mmesa->c_clears = 0;
368
369 if ( mmesa->c_textureSwaps || mmesa->c_textureBytes || mmesa->c_agpTextureBytes ) {
370 if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT) {
371 fprintf( stderr, " textureSwaps:%i textureBytes:%i agpTextureBytes:%i\n",
372 mmesa->c_textureSwaps, mmesa->c_textureBytes, mmesa->c_agpTextureBytes );
373 }
374 mmesa->c_textureSwaps = 0;
375 mmesa->c_textureBytes = 0;
376 mmesa->c_agpTextureBytes = 0;
377 }
378
379 mmesa->c_texsrc_agp = 0;
380 mmesa->c_texsrc_card = 0;
381
382 if (MACH64_DEBUG & DEBUG_VERBOSE_COUNT)
383 fprintf( stderr, "---------------------------------------------------------\n" );
384 }
385
386
387 void mach64PerformanceBoxesLocked( mach64ContextPtr mmesa )
388 {
389 GLint ret;
390 drmMach64Clear clear;
391 GLint x, y, w, h;
392 GLuint color;
393 GLint nbox;
394 GLint x1, y1, x2, y2;
395 XF86DRIClipRectPtr b = mmesa->sarea->boxes;
396
397 /* save cliprects */
398 nbox = mmesa->sarea->nbox;
399 x1 = b[0].x1;
400 y1 = b[0].y1;
401 x2 = b[0].x2;
402 y2 = b[0].y2;
403
404 /* setup a single cliprect and call the clear ioctl for each box */
405 mmesa->sarea->nbox = 1;
406
407 w = h = 8;
408 x = mmesa->drawX;
409 y = mmesa->drawY;
410 b[0].x1 = x;
411 b[0].x2 = x + w;
412 b[0].y1 = y;
413 b[0].y2 = y + h;
414
415 clear.flags = MACH64_BACK;
416 clear.clear_depth = 0;
417
418 /* Red box if DDFinish was called to wait for rendering to complete */
419 if ( mmesa->c_drawWaits ) {
420 color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 0, 0 );
421
422 clear.x = x;
423 clear.y = y;
424 clear.w = w;
425 clear.h = h;
426 clear.clear_color = color;
427
428 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
429 &clear, sizeof(drmMach64Clear) );
430
431 if (ret < 0) {
432 UNLOCK_HARDWARE( mmesa );
433 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
434 exit( -1 );
435 }
436
437 }
438
439 x += w;
440 b[0].x1 = x;
441 b[0].x2 = x + w;
442
443 /* draw a green box if we had to wait for previous frame(s) to complete */
444 if ( !mmesa->hardwareWentIdle ) {
445 color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 255, 0, 0 );
446
447 clear.x = x;
448 clear.y = y;
449 clear.w = w;
450 clear.h = h;
451 clear.clear_color = color;
452
453 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
454 &clear, sizeof(drmMach64Clear) );
455
456 if (ret < 0) {
457 UNLOCK_HARDWARE( mmesa );
458 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
459 exit( -1 );
460 }
461
462 }
463
464 x += w;
465 w = 20;
466 b[0].x1 = x;
467
468 /* show approx. ratio of AGP/card textures used - Blue = AGP, Purple = Card */
469 if ( mmesa->c_texsrc_agp || mmesa->c_texsrc_card ) {
470 color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 0, 255, 0 );
471 w = ((GLfloat)mmesa->c_texsrc_agp / (GLfloat)(mmesa->c_texsrc_agp + mmesa->c_texsrc_card))*20;
472 if (w > 1) {
473
474 b[0].x2 = x + w;
475
476 clear.x = x;
477 clear.y = y;
478 clear.w = w;
479 clear.h = h;
480 clear.clear_color = color;
481
482 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
483 &clear, sizeof(drmMach64Clear) );
484
485 if (ret < 0) {
486 UNLOCK_HARDWARE( mmesa );
487 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
488 exit( -1 );
489 }
490 }
491
492 x += w;
493 w = 20 - w;
494
495 if (w > 1) {
496 b[0].x1 = x;
497 b[0].x2 = x + w;
498
499 color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 255, 0 );
500
501 clear.x = x;
502 clear.y = y;
503 clear.w = w;
504 clear.h = h;
505 clear.clear_color = color;
506
507 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
508 &clear, sizeof(drmMach64Clear) );
509
510 if (ret < 0) {
511 UNLOCK_HARDWARE( mmesa );
512 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
513 exit( -1 );
514 }
515 }
516 }
517
518 x += w;
519 w = 8;
520 b[0].x1 = x;
521 b[0].x2 = x + w;
522
523 /* Yellow box if we swapped textures */
524 if ( mmesa->c_textureSwaps ) {
525 color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 255, 0, 0 );
526
527 clear.x = x;
528 clear.y = y;
529 clear.w = w;
530 clear.h = h;
531 clear.clear_color = color;
532
533 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
534 &clear, sizeof(drmMach64Clear) );
535
536 if (ret < 0) {
537 UNLOCK_HARDWARE( mmesa );
538 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
539 exit( -1 );
540 }
541
542 }
543
544 h = 4;
545 x += 8;
546 b[0].x1 = x;
547 b[0].y2 = y + h;
548
549 /* Purple bar for card memory texture blits/uploads */
550 if ( mmesa->c_textureBytes ) {
551 color = mach64PackColor( mmesa->mach64Screen->cpp, 255, 0, 255, 0 );
552 w = mmesa->c_textureBytes / 16384;
553 if ( w <= 0 )
554 w = 1;
555 if (w > (mmesa->driDrawable->w - 44))
556 w = mmesa->driDrawable->w - 44;
557
558 b[0].x2 = x + w;
559
560 clear.x = x;
561 clear.y = y;
562 clear.w = w;
563 clear.h = h;
564 clear.clear_color = color;
565
566 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
567 &clear, sizeof(drmMach64Clear) );
568
569 if (ret < 0) {
570 UNLOCK_HARDWARE( mmesa );
571 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
572 exit( -1 );
573 }
574 }
575
576 /* Blue bar for AGP memory texture blits/uploads */
577 if ( mmesa->c_agpTextureBytes ) {
578 color = mach64PackColor( mmesa->mach64Screen->cpp, 0, 0, 255, 0 );
579 w = mmesa->c_agpTextureBytes / 16384;
580 if ( w <= 0 )
581 w = 1;
582 if (w > (mmesa->driDrawable->w - 44))
583 w = mmesa->driDrawable->w - 44;
584
585 y += 4;
586 b[0].x2 = x + w;
587 b[0].y1 = y;
588 b[0].y2 = y + h;
589
590 clear.x = x;
591 clear.y = y;
592 clear.w = w;
593 clear.h = h;
594 clear.clear_color = color;
595
596 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
597 &clear, sizeof(drmMach64Clear) );
598
599 if (ret < 0) {
600 UNLOCK_HARDWARE( mmesa );
601 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
602 exit( -1 );
603 }
604 }
605
606 /* Pink bar for number of vertex buffers used */
607 if ( mmesa->c_vertexBuffers ) {
608 color = mach64PackColor( mmesa->mach64Screen->cpp, 196, 128, 128, 0 );
609
610 w = mmesa->c_vertexBuffers;
611 if (w > (mmesa->driDrawable->w))
612 w = mmesa->driDrawable->w;
613
614 h = 8;
615 x = mmesa->drawX;
616 y = mmesa->drawY + 8;
617 b[0].x1 = x;
618 b[0].x2 = x + w;
619 b[0].y1 = y;
620 b[0].y2 = y + h;
621
622 clear.x = x;
623 clear.y = y;
624 clear.w = w;
625 clear.h = h;
626 clear.clear_color = color;
627
628 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
629 &clear, sizeof(drmMach64Clear) );
630
631 if (ret < 0) {
632 UNLOCK_HARDWARE( mmesa );
633 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
634 exit( -1 );
635 }
636 }
637
638 /* restore cliprects */
639 mmesa->sarea->nbox = nbox;
640 b[0].x1 = x1;
641 b[0].y1 = y1;
642 b[0].x2 = x2;
643 b[0].y2 = y2;
644
645 }
646
647 #endif
648
649 /* ================================================================
650 * Buffer clear
651 */
652
653 static void mach64DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
654 GLint cx, GLint cy, GLint cw, GLint ch )
655 {
656 mach64ContextPtr mmesa = MACH64_CONTEXT( ctx );
657 __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
658 drmMach64Clear clear;
659 GLuint flags = 0;
660 GLint i;
661 GLint ret;
662
663 if ( MACH64_DEBUG & DEBUG_VERBOSE_API ) {
664 fprintf( stderr, "%s: all=%d %d,%d %dx%d\n",
665 __FUNCTION__, all, cx, cy, cw, ch );
666 }
667
668 #if ENABLE_PERF_BOXES
669 /* Bump the performance counter */
670 mmesa->c_clears++;
671 #endif
672
673 FLUSH_BATCH( mmesa );
674
675 /* The only state changes we care about here are the RGBA colormask
676 * and scissor/clipping. We'll just update that state, if needed.
677 */
678 if ( mmesa->new_state & (MACH64_NEW_MASKS | MACH64_NEW_CLIP) ) {
679 const GLuint save_state = mmesa->new_state;
680 mmesa->new_state &= (MACH64_NEW_MASKS | MACH64_NEW_CLIP);
681 mach64DDUpdateHWState( ctx );
682 mmesa->new_state = save_state & ~(MACH64_NEW_MASKS | MACH64_NEW_CLIP);
683 }
684
685 if ( mask & DD_FRONT_LEFT_BIT ) {
686 flags |= MACH64_FRONT;
687 mask &= ~DD_FRONT_LEFT_BIT;
688 }
689
690 if ( mask & DD_BACK_LEFT_BIT ) {
691 flags |= MACH64_BACK;
692 mask &= ~DD_BACK_LEFT_BIT;
693 }
694
695 if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
696 flags |= MACH64_DEPTH;
697 mask &= ~DD_DEPTH_BIT;
698 }
699
700 if ( mask )
701 _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
702
703 if ( !flags )
704 return;
705
706 LOCK_HARDWARE( mmesa );
707
708 /* This needs to be in the locked region, so updated drawable origin is used */
709 /* Flip top to bottom */
710 cx += mmesa->drawX;
711 cy = mmesa->drawY + dPriv->h - cy - ch;
712
713 /* HACK?
714 */
715 if ( mmesa->dirty & ~MACH64_UPLOAD_CLIPRECTS ) {
716 mach64EmitHwStateLocked( mmesa );
717 }
718
719 for ( i = 0 ; i < mmesa->numClipRects ; ) {
720 int nr = MIN2( i + MACH64_NR_SAREA_CLIPRECTS, mmesa->numClipRects );
721 XF86DRIClipRectPtr box = mmesa->pClipRects;
722 XF86DRIClipRectPtr b = mmesa->sarea->boxes;
723 GLint n = 0;
724
725 if ( !all ) {
726 for ( ; i < nr ; i++ ) {
727 GLint x = box[i].x1;
728 GLint y = box[i].y1;
729 GLint w = box[i].x2 - x;
730 GLint h = box[i].y2 - y;
731
732 if ( x < cx ) w -= cx - x, x = cx;
733 if ( y < cy ) h -= cy - y, y = cy;
734 if ( x + w > cx + cw ) w = cx + cw - x;
735 if ( y + h > cy + ch ) h = cy + ch - y;
736 if ( w <= 0 ) continue;
737 if ( h <= 0 ) continue;
738
739 b->x1 = x;
740 b->y1 = y;
741 b->x2 = x + w;
742 b->y2 = y + h;
743 b++;
744 n++;
745 }
746 } else {
747 for ( ; i < nr ; i++ ) {
748 *b++ = box[i];
749 n++;
750 }
751 }
752
753 mmesa->sarea->nbox = n;
754
755 if ( MACH64_DEBUG & DEBUG_VERBOSE_IOCTL ) {
756 fprintf( stderr,
757 "DRM_MACH64_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
758 flags,
759 (GLuint)mmesa->ClearColor,
760 (GLuint)mmesa->ClearDepth,
761 mmesa->sarea->nbox );
762 }
763
764 clear.flags = flags;
765 clear.x = cx;
766 clear.y = cy;
767 clear.w = cw;
768 clear.h = ch;
769 clear.clear_color = mmesa->ClearColor;
770 clear.clear_depth = mmesa->ClearDepth;
771
772 ret = drmCommandWrite( mmesa->driFd, DRM_MACH64_CLEAR,
773 &clear, sizeof(drmMach64Clear) );
774
775 if ( ret ) {
776 UNLOCK_HARDWARE( mmesa );
777 fprintf( stderr, "DRM_MACH64_CLEAR: return = %d\n", ret );
778 exit( -1 );
779 }
780 }
781
782 UNLOCK_HARDWARE( mmesa );
783
784 mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
785 MACH64_UPLOAD_MISC |
786 MACH64_UPLOAD_CLIPRECTS);
787
788 }
789
790
791 void mach64WaitForIdleLocked( mach64ContextPtr mmesa )
792 {
793 int fd = mmesa->driFd;
794 int to = 0;
795 int ret;
796
797 do {
798 ret = drmCommandNone( fd, DRM_MACH64_IDLE );
799 } while ( ( ret == -EBUSY ) && ( to++ < MACH64_TIMEOUT ) );
800
801 if ( ret < 0 ) {
802 drmCommandNone( fd, DRM_MACH64_RESET );
803 UNLOCK_HARDWARE( mmesa );
804 fprintf( stderr, "Error: Mach64 timed out... exiting\n" );
805 exit( -1 );
806 }
807 }
808
809 /* Flush the DMA queue to the hardware */
810 void mach64FlushDMALocked( mach64ContextPtr mmesa )
811 {
812 int fd = mmesa->driFd;
813 int ret;
814
815 ret = drmCommandNone( fd, DRM_MACH64_FLUSH );
816
817 if ( ret < 0 ) {
818 drmCommandNone( fd, DRM_MACH64_RESET );
819 UNLOCK_HARDWARE( mmesa );
820 fprintf( stderr, "Error flushing DMA... exiting\n" );
821 exit( -1 );
822 }
823
824 mmesa->dirty |= (MACH64_UPLOAD_CONTEXT |
825 MACH64_UPLOAD_MISC |
826 MACH64_UPLOAD_CLIPRECTS);
827
828 }
829
830 /* For client-side state emits - currently unused */
831 void mach64UploadHwStateLocked( mach64ContextPtr mmesa )
832 {
833 ATISAREAPrivPtr sarea = mmesa->sarea;
834
835 mach64_context_regs_t *regs = &sarea->ContextState;
836 unsigned int dirty = sarea->dirty;
837 CARD32 offset = ((regs->tex_size_pitch & 0xf0) >> 2);
838
839 DMALOCALS;
840
841 DMAGETPTR( 19*2 );
842
843 if ( dirty & MACH64_UPLOAD_MISC ) {
844 DMAOUTREG( MACH64_DP_MIX, regs->dp_mix );
845 DMAOUTREG( MACH64_DP_SRC, regs->dp_src );
846 DMAOUTREG( MACH64_CLR_CMP_CNTL, regs->clr_cmp_cntl );
847 DMAOUTREG( MACH64_GUI_TRAJ_CNTL, regs->gui_traj_cntl );
848 DMAOUTREG( MACH64_SC_LEFT_RIGHT, regs->sc_left_right );
849 DMAOUTREG( MACH64_SC_TOP_BOTTOM, regs->sc_top_bottom );
850 sarea->dirty &= ~MACH64_UPLOAD_MISC;
851 }
852
853 if ( dirty & MACH64_UPLOAD_DST_OFF_PITCH ) {
854 DMAOUTREG( MACH64_DST_OFF_PITCH, regs->dst_off_pitch );
855 sarea->dirty &= ~MACH64_UPLOAD_DST_OFF_PITCH;
856 }
857 if ( dirty & MACH64_UPLOAD_Z_OFF_PITCH ) {
858 DMAOUTREG( MACH64_Z_OFF_PITCH, regs->z_off_pitch );
859 sarea->dirty &= ~MACH64_UPLOAD_Z_OFF_PITCH;
860 }
861 if ( dirty & MACH64_UPLOAD_Z_ALPHA_CNTL ) {
862 DMAOUTREG( MACH64_Z_CNTL, regs->z_cntl );
863 DMAOUTREG( MACH64_ALPHA_TST_CNTL, regs->alpha_tst_cntl );
864 sarea->dirty &= ~MACH64_UPLOAD_Z_ALPHA_CNTL;
865 }
866 if ( dirty & MACH64_UPLOAD_SCALE_3D_CNTL ) {
867 DMAOUTREG( MACH64_SCALE_3D_CNTL, regs->scale_3d_cntl );
868 sarea->dirty &= ~MACH64_UPLOAD_SCALE_3D_CNTL;
869 }
870 if ( dirty & MACH64_UPLOAD_DP_FOG_CLR ) {
871 DMAOUTREG( MACH64_DP_FOG_CLR, regs->dp_fog_clr );
872 sarea->dirty &= ~MACH64_UPLOAD_DP_FOG_CLR;
873 }
874 if ( dirty & MACH64_UPLOAD_DP_WRITE_MASK ) {
875 DMAOUTREG( MACH64_DP_WRITE_MASK, regs->dp_write_mask );
876 sarea->dirty &= ~MACH64_UPLOAD_DP_WRITE_MASK;
877 }
878 if ( dirty & MACH64_UPLOAD_DP_PIX_WIDTH ) {
879 DMAOUTREG( MACH64_DP_PIX_WIDTH, regs->dp_pix_width );
880 sarea->dirty &= ~MACH64_UPLOAD_DP_PIX_WIDTH;
881 }
882 if ( dirty & MACH64_UPLOAD_SETUP_CNTL ) {
883 DMAOUTREG( MACH64_SETUP_CNTL, regs->setup_cntl );
884 sarea->dirty &= ~MACH64_UPLOAD_SETUP_CNTL;
885 }
886
887 if ( dirty & MACH64_UPLOAD_TEXTURE ) {
888 DMAOUTREG( MACH64_TEX_SIZE_PITCH, regs->tex_size_pitch );
889 DMAOUTREG( MACH64_TEX_CNTL, regs->tex_cntl );
890 DMAOUTREG( MACH64_SECONDARY_TEX_OFF, regs->secondary_tex_off );
891 DMAOUTREG( MACH64_TEX_0_OFF + offset, regs->tex_offset );
892 sarea->dirty &= ~MACH64_UPLOAD_TEXTURE;
893 }
894
895 #if 0
896 if ( dirty & MACH64_UPLOAD_CLIPRECTS ) {
897 DMAOUTREG( MACH64_SC_LEFT_RIGHT, regs->sc_left_right );
898 DMAOUTREG( MACH64_SC_TOP_BOTTOM, regs->sc_top_bottom );
899 sarea->dirty &= ~MACH64_UPLOAD_CLIPRECTS;
900 }
901 #endif
902
903 sarea->dirty = 0;
904
905 DMAADVANCE();
906 }
907
908 void mach64DDInitIoctlFuncs( GLcontext *ctx )
909 {
910 ctx->Driver.Clear = mach64DDClear;
911 }