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