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