2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
27 #include "main/glheader.h"
28 #include "main/mtypes.h"
29 #include "main/macros.h"
31 #include "swrast/swrast.h"
34 #include "via_context.h"
36 #include "via_ioctl.h"
37 #include "via_state.h"
39 #include "via_3d_reg.h"
44 #include <sys/ioctl.h>
48 #define VIA_REG_STATUS 0x400
49 #define VIA_REG_GEMODE 0x004
50 #define VIA_REG_SRCBASE 0x030
51 #define VIA_REG_DSTBASE 0x034
52 #define VIA_REG_PITCH 0x038
53 #define VIA_REG_SRCCOLORKEY 0x01C
54 #define VIA_REG_KEYCONTROL 0x02C
55 #define VIA_REG_SRCPOS 0x008
56 #define VIA_REG_DSTPOS 0x00C
57 #define VIA_REG_GECMD 0x000
58 #define VIA_REG_DIMENSION 0x010 /* width and height */
59 #define VIA_REG_FGCOLOR 0x018
61 #define VIA_GEM_8bpp 0x00000000
62 #define VIA_GEM_16bpp 0x00000100
63 #define VIA_GEM_32bpp 0x00000300
64 #define VIA_GEC_BLT 0x00000001
65 #define VIA_PITCH_ENABLE 0x80000000
66 #define VIA_GEC_INCX 0x00000000
67 #define VIA_GEC_DECY 0x00004000
68 #define VIA_GEC_INCY 0x00000000
69 #define VIA_GEC_DECX 0x00008000
70 #define VIA_GEC_FIXCOLOR_PAT 0x00002000
73 #define VIA_BLIT_CLEAR 0x00
74 #define VIA_BLIT_COPY 0xCC
75 #define VIA_BLIT_FILL 0xF0
76 #define VIA_BLIT_SET 0xFF
78 static void dump_dma( struct via_context
*vmesa
)
81 GLuint
*data
= (GLuint
*)vmesa
->dma
;
82 for (i
= 0; i
< vmesa
->dmaLow
; i
+= 16) {
83 fprintf(stderr
, "%04x: ", i
);
84 fprintf(stderr
, "%08x ", *data
++);
85 fprintf(stderr
, "%08x ", *data
++);
86 fprintf(stderr
, "%08x ", *data
++);
87 fprintf(stderr
, "%08x\n", *data
++);
89 fprintf(stderr
, "******************************************\n");
94 void viaCheckDma(struct via_context
*vmesa
, GLuint bytes
)
96 VIA_FINISH_PRIM( vmesa
);
97 if (vmesa
->dmaLow
+ bytes
> VIA_DMA_HIGHWATER
) {
104 #define SetReg2DAGP(nReg, nData) do { \
105 OUT_RING( ((nReg) >> 2) | 0xF0000000 ); \
110 static void viaBlit(struct via_context
*vmesa
, GLuint bpp
,
111 GLuint srcBase
, GLuint srcPitch
,
112 GLuint dstBase
, GLuint dstPitch
,
115 GLuint color
, GLuint nMask
)
118 GLuint dwGEMode
, srcX
, dstX
, cmd
;
121 if (VIA_DEBUG
& DEBUG_2D
)
123 "%s bpp %d src %x/%x dst %x/%x w %d h %d "
124 " mode: %x color: 0x%08x mask 0x%08x\n",
125 __FUNCTION__
, bpp
, srcBase
, srcPitch
, dstBase
,
126 dstPitch
, w
,h
, blitMode
, color
, nMask
);
134 dwGEMode
= VIA_GEM_16bpp
;
135 srcX
= (srcBase
& 0x1f) >> 1;
136 dstX
= (dstBase
& 0x1f) >> 1;
139 dwGEMode
= VIA_GEM_32bpp
;
140 srcX
= (srcBase
& 0x1f) >> 2;
141 dstX
= (dstBase
& 0x1f) >> 2;
149 cmd
= VIA_GEC_BLT
| VIA_GEC_FIXCOLOR_PAT
| (VIA_BLIT_FILL
<< 24);
152 cmd
= VIA_GEC_BLT
| (VIA_BLIT_COPY
<< 24);
159 SetReg2DAGP( VIA_REG_GEMODE
, dwGEMode
);
160 SetReg2DAGP( VIA_REG_FGCOLOR
, color
);
161 SetReg2DAGP( 0x2C, nMask
);
162 SetReg2DAGP( VIA_REG_SRCBASE
, (srcBase
& ~0x1f) >> 3);
163 SetReg2DAGP( VIA_REG_DSTBASE
, (dstBase
& ~0x1f) >> 3);
164 SetReg2DAGP( VIA_REG_PITCH
, VIA_PITCH_ENABLE
|
165 (srcPitch
>> 3) | ((dstPitch
>> 3) << 16));
166 SetReg2DAGP( VIA_REG_SRCPOS
, srcX
);
167 SetReg2DAGP( VIA_REG_DSTPOS
, dstX
);
168 SetReg2DAGP( VIA_REG_DIMENSION
, (((h
- 1) << 16) | (w
- 1)));
169 SetReg2DAGP( VIA_REG_GECMD
, cmd
);
170 SetReg2DAGP( 0x2C, 0x00000000);
174 static void viaFillBuffer(struct via_context
*vmesa
,
175 struct via_renderbuffer
*buffer
,
176 drm_clip_rect_t
*pbox
,
181 GLuint bytePerPixel
= buffer
->bpp
>> 3;
184 for (i
= 0; i
< nboxes
; i
++) {
185 int x
= pbox
[i
].x1
- buffer
->drawX
;
186 int y
= pbox
[i
].y1
- buffer
->drawY
;
187 int w
= pbox
[i
].x2
- pbox
[i
].x1
;
188 int h
= pbox
[i
].y2
- pbox
[i
].y1
;
190 int offset
= (buffer
->offset
+
196 offset
, buffer
->pitch
,
197 offset
, buffer
->pitch
,
199 VIA_BLIT_FILL
, pixel
, mask
);
205 static void viaClear(GLcontext
*ctx
, GLbitfield mask
)
207 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
208 __DRIdrawablePrivate
*dPriv
= vmesa
->driDrawable
;
209 struct via_renderbuffer
*const vrb
=
210 (struct via_renderbuffer
*) dPriv
->driverPrivate
;
213 GLuint clear_depth_mask
= 0xf << 28;
214 GLuint clear_depth
= 0;
216 VIA_FLUSH_DMA(vmesa
);
218 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
220 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
223 if (mask
& BUFFER_BIT_BACK_LEFT
) {
225 mask
&= ~BUFFER_BIT_BACK_LEFT
;
228 if (mask
& BUFFER_BIT_DEPTH
) {
230 clear_depth
= (GLuint
)(ctx
->Depth
.Clear
* vmesa
->ClearDepth
);
231 clear_depth_mask
&= ~vmesa
->depth_clear_mask
;
232 mask
&= ~BUFFER_BIT_DEPTH
;
235 if (mask
& BUFFER_BIT_STENCIL
) {
236 if (vmesa
->have_hw_stencil
) {
237 if ((ctx
->Stencil
.WriteMask
[0] & 0xff) == 0xff) {
239 clear_depth
&= ~0xff;
240 clear_depth
|= (ctx
->Stencil
.Clear
& 0xff);
241 clear_depth_mask
&= ~vmesa
->stencil_clear_mask
;
242 mask
&= ~BUFFER_BIT_STENCIL
;
245 if (VIA_DEBUG
& DEBUG_2D
)
246 fprintf(stderr
, "Clear stencil writemask %x\n",
247 ctx
->Stencil
.WriteMask
[0]);
252 /* 16bpp doesn't support masked clears */
253 if (vmesa
->viaScreen
->bytesPerPixel
== 2 &&
254 vmesa
->ClearMask
& 0xf0000000) {
255 if (flag
& VIA_FRONT
)
256 mask
|= BUFFER_BIT_FRONT_LEFT
;
258 mask
|= BUFFER_BIT_BACK_LEFT
;
259 flag
&= ~(VIA_FRONT
| VIA_BACK
);
263 drm_clip_rect_t
*boxes
, *tmp_boxes
= 0;
265 GLint cx
, cy
, cw
, ch
;
268 LOCK_HARDWARE(vmesa
);
270 /* get region after locking: */
271 cx
= ctx
->DrawBuffer
->_Xmin
;
272 cy
= ctx
->DrawBuffer
->_Ymin
;
273 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
274 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
275 all
= (cw
== ctx
->DrawBuffer
->Width
&& ch
== ctx
->DrawBuffer
->Height
);
277 /* flip top to bottom */
278 cy
= dPriv
->h
- cy
- ch
;
283 drm_clip_rect_t
*b
= vmesa
->pClipRects
;
286 (drm_clip_rect_t
*)malloc(vmesa
->numClipRects
*
287 sizeof(drm_clip_rect_t
));
289 UNLOCK_HARDWARE(vmesa
);
293 for (; i
< vmesa
->numClipRects
; i
++) {
296 GLint w
= b
[i
].x2
- x
;
297 GLint h
= b
[i
].y2
- y
;
299 if (x
< cx
) w
-= cx
- x
, x
= cx
;
300 if (y
< cy
) h
-= cy
- y
, y
= cy
;
301 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
302 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
303 if (w
<= 0) continue;
304 if (h
<= 0) continue;
308 boxes
[nr
].x2
= x
+ w
;
309 boxes
[nr
].y2
= y
+ h
;
314 boxes
= vmesa
->pClipRects
;
315 nr
= vmesa
->numClipRects
;
318 if (flag
& VIA_FRONT
) {
319 viaFillBuffer(vmesa
, &vmesa
->front
, boxes
, nr
, vmesa
->ClearColor
,
323 if (flag
& VIA_BACK
) {
324 viaFillBuffer(vmesa
, &vmesa
->back
, boxes
, nr
, vmesa
->ClearColor
,
328 if (flag
& VIA_DEPTH
) {
329 viaFillBuffer(vmesa
, &vmesa
->depth
, boxes
, nr
, clear_depth
,
333 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
);
334 UNLOCK_HARDWARE(vmesa
);
341 _swrast_Clear(ctx
, mask
);
347 static void viaDoSwapBuffers(struct via_context
*vmesa
,
351 GLuint bytePerPixel
= vmesa
->viaScreen
->bitsPerPixel
>> 3;
352 struct via_renderbuffer
*front
= &vmesa
->front
;
353 struct via_renderbuffer
*back
= &vmesa
->back
;
356 for (i
= 0; i
< nbox
; i
++, b
++) {
357 GLint x
= b
->x1
- back
->drawX
;
358 GLint y
= b
->y1
- back
->drawY
;
359 GLint w
= b
->x2
- b
->x1
;
360 GLint h
= b
->y2
- b
->y1
;
362 GLuint src
= back
->offset
+ y
* back
->pitch
+ x
* bytePerPixel
;
363 GLuint dest
= front
->offset
+ y
* front
->pitch
+ x
* bytePerPixel
;
370 VIA_BLIT_COPY
, 0, 0);
373 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* redundant */
377 static void viaEmitBreadcrumbLocked( struct via_context
*vmesa
)
379 struct via_renderbuffer
*buffer
= &vmesa
->breadcrumb
;
380 GLuint value
= vmesa
->lastBreadcrumbWrite
+ 1;
382 if (VIA_DEBUG
& DEBUG_IOCTL
)
383 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
385 assert(!vmesa
->dmaLow
);
389 buffer
->offset
, buffer
->pitch
,
390 buffer
->offset
, buffer
->pitch
,
392 VIA_BLIT_FILL
, value
, 0);
394 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
395 vmesa
->lastBreadcrumbWrite
= value
;
398 void viaEmitBreadcrumb( struct via_context
*vmesa
)
400 LOCK_HARDWARE(vmesa
);
402 viaFlushDmaLocked(vmesa
, 0);
404 viaEmitBreadcrumbLocked( vmesa
);
405 UNLOCK_HARDWARE(vmesa
);
408 static GLboolean
viaCheckIdle( struct via_context
*vmesa
)
410 if ((vmesa
->regEngineStatus
[0] & 0xFFFEFFFF) == 0x00020000) {
417 GLboolean
viaCheckBreadcrumb( struct via_context
*vmesa
, GLuint value
)
419 GLuint
*buf
= (GLuint
*)vmesa
->breadcrumb
.map
;
420 vmesa
->lastBreadcrumbRead
= *buf
;
422 if (VIA_DEBUG
& DEBUG_IOCTL
)
423 fprintf(stderr
, "%s %d < %d: %d\n", __FUNCTION__
, value
,
424 vmesa
->lastBreadcrumbRead
,
425 !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
));
427 return !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
);
430 static void viaWaitBreadcrumb( struct via_context
*vmesa
, GLuint value
)
432 if (VIA_DEBUG
& DEBUG_IOCTL
)
433 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
435 assert(!VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbWrite
));
437 while (!viaCheckBreadcrumb( vmesa
, value
)) {
438 viaSwapOutWork( vmesa
);
439 via_release_pending_textures( vmesa
);
444 void viaWaitIdle( struct via_context
*vmesa
, GLboolean light
)
446 VIA_FLUSH_DMA(vmesa
);
448 if (VIA_DEBUG
& DEBUG_IOCTL
)
449 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
450 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
452 /* Need to emit a new breadcrumb?
454 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
455 LOCK_HARDWARE(vmesa
);
456 viaEmitBreadcrumbLocked( vmesa
);
457 UNLOCK_HARDWARE(vmesa
);
462 if (VIA_GEQ_WRAP(vmesa
->lastDma
, vmesa
->lastBreadcrumbRead
))
463 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
467 LOCK_HARDWARE(vmesa
);
468 while(!viaCheckIdle(vmesa
))
470 UNLOCK_HARDWARE(vmesa
);
471 via_release_pending_textures(vmesa
);
475 void viaWaitIdleLocked( struct via_context
*vmesa
, GLboolean light
)
478 viaFlushDmaLocked(vmesa
, 0);
480 if (VIA_DEBUG
& DEBUG_IOCTL
)
481 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
482 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
484 /* Need to emit a new breadcrumb?
486 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
487 viaEmitBreadcrumbLocked( vmesa
);
492 if (vmesa
->lastDma
>= vmesa
->lastBreadcrumbRead
)
493 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
497 while(!viaCheckIdle(vmesa
))
500 via_release_pending_textures(vmesa
);
505 /* Wait for command stream to be processed *and* the next vblank to
506 * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank,
507 * except that WAIT_IDLE() will spin the CPU polling, while this is
510 static void viaWaitIdleVBlank( __DRIdrawablePrivate
*dPriv
,
511 struct via_context
*vmesa
,
514 GLboolean missed_target
;
515 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
517 VIA_FLUSH_DMA(vmesa
);
523 if (value
< vmesa
->lastBreadcrumbRead
||
525 viaSwapOutWork(vmesa
);
527 driWaitForVBlank( dPriv
, & missed_target
);
528 if ( missed_target
) {
529 vmesa
->swap_missed_count
++;
530 (*psp
->systemTime
->getUST
)( &vmesa
->swap_missed_ust
);
533 while (!viaCheckBreadcrumb(vmesa
, value
));
535 vmesa
->thrashing
= 0; /* reset flag on swap */
537 via_release_pending_textures( vmesa
);
542 static void viaDoPageFlipLocked(struct via_context
*vmesa
, GLuint offset
)
546 if (VIA_DEBUG
& DEBUG_2D
)
547 fprintf(stderr
, "%s %x\n", __FUNCTION__
, offset
);
549 if (!vmesa
->nDoneFirstFlip
) {
550 vmesa
->nDoneFirstFlip
= GL_TRUE
;
552 OUT_RING(HALCYON_HEADER2
);
553 OUT_RING(0x00fe0000);
554 OUT_RING(0x0000000e);
555 OUT_RING(0x0000000e);
560 OUT_RING( HALCYON_HEADER2
);
561 OUT_RING( 0x00fe0000 );
562 OUT_RING((HC_SubA_HFBBasL
<< 24) | (offset
& 0xFFFFF8) | 0x2);
563 OUT_RING((HC_SubA_HFBDrawFirst
<< 24) |
564 ((offset
& 0xFF000000) >> 24) | 0x0100);
567 vmesa
->pfCurrentOffset
= vmesa
->sarea
->pfCurrentOffset
= offset
;
569 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
572 void viaResetPageFlippingLocked(struct via_context
*vmesa
)
574 if (VIA_DEBUG
& DEBUG_2D
)
575 fprintf(stderr
, "%s\n", __FUNCTION__
);
577 viaDoPageFlipLocked( vmesa
, 0 );
579 if (vmesa
->front
.offset
!= 0) {
580 struct via_renderbuffer buffer_tmp
;
581 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
582 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
583 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
586 assert(vmesa
->front
.offset
== 0);
587 vmesa
->doPageFlip
= vmesa
->allowPageFlip
= 0;
592 * Copy the back buffer to the front buffer.
594 void viaCopyBuffer(__DRIdrawablePrivate
*dPriv
)
596 struct via_context
*vmesa
=
597 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
598 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
600 if (VIA_DEBUG
& DEBUG_IOCTL
)
602 "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
606 vmesa
->lastBreadcrumbWrite
,
607 vmesa
->lastBreadcrumbRead
);
609 VIA_FLUSH_DMA(vmesa
);
611 if (dPriv
->vblFlags
== VBLANK_FLAG_SYNC
&&
612 vmesa
->lastBreadcrumbWrite
> 1)
613 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
-1);
615 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[1]);
617 LOCK_HARDWARE(vmesa
);
619 /* Catch and cleanup situation where we were pageflipping but have
622 if (dPriv
->numClipRects
&& vmesa
->sarea
->pfCurrentOffset
!= 0) {
623 viaResetPageFlippingLocked(vmesa
);
624 UNLOCK_HARDWARE(vmesa
);
628 viaDoSwapBuffers(vmesa
, dPriv
->pClipRects
, dPriv
->numClipRects
);
629 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
630 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
631 viaEmitBreadcrumbLocked(vmesa
);
632 UNLOCK_HARDWARE(vmesa
);
634 (*psp
->systemTime
->getUST
)( &vmesa
->swap_ust
);
638 void viaPageFlip(__DRIdrawablePrivate
*dPriv
)
640 struct via_context
*vmesa
=
641 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
642 struct via_renderbuffer buffer_tmp
;
643 __DRIscreenPrivate
*psp
= dPriv
->driScreenPriv
;
645 VIA_FLUSH_DMA(vmesa
);
646 if (dPriv
->vblFlags
== VBLANK_FLAG_SYNC
&&
647 vmesa
->lastBreadcrumbWrite
> 1)
648 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
- 1);
650 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[0]);
652 LOCK_HARDWARE(vmesa
);
653 viaDoPageFlipLocked(vmesa
, vmesa
->back
.offset
);
654 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
655 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
656 viaEmitBreadcrumbLocked(vmesa
);
657 UNLOCK_HARDWARE(vmesa
);
659 (*psp
->systemTime
->getUST
)( &vmesa
->swap_ust
);
662 /* KW: FIXME: When buffers are freed, could free frontbuffer by
665 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
666 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
667 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
673 #define VIA_CMDBUF_MAX_LAG 50000
675 static int fire_buffer(struct via_context
*vmesa
)
677 drm_via_cmdbuffer_t bufI
;
680 bufI
.buf
= (char *)vmesa
->dma
;
681 bufI
.size
= vmesa
->dmaLow
;
684 drm_via_cmdbuf_size_t bSiz
;
686 /* Do the CMDBUF_SIZE ioctl:
688 bSiz
.func
= VIA_CMDBUF_LAG
;
690 bSiz
.size
= VIA_CMDBUF_MAX_LAG
;
692 ret
= drmCommandWriteRead(vmesa
->driFd
, DRM_VIA_CMDBUF_SIZE
,
693 &bSiz
, sizeof(bSiz
));
694 } while (ret
== -EAGAIN
);
696 UNLOCK_HARDWARE(vmesa
);
697 fprintf(stderr
, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
703 /* Actually fire the buffer:
706 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_CMDBUFFER
,
707 &bufI
, sizeof(bufI
));
708 } while (ret
== -EAGAIN
);
710 UNLOCK_HARDWARE(vmesa
);
711 fprintf(stderr
, "%s: DRM_VIA_CMDBUFFER returned %d\n",
714 /* If this fails, the original code fell back to the PCI path.
720 /* Fall through to PCI handling?!?
722 viaWaitIdleLocked(vmesa
, GL_FALSE
);
725 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_PCICMD
, &bufI
, sizeof(bufI
));
727 UNLOCK_HARDWARE(vmesa
);
729 fprintf(stderr
, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__
, ret
);
737 /* Inserts the surface addresss and active cliprects one at a time
738 * into the head of the DMA buffer being flushed. Fires the buffer
741 static void via_emit_cliprect(struct via_context
*vmesa
,
744 struct via_renderbuffer
*buffer
= vmesa
->drawBuffer
;
745 GLuint
*vb
= (GLuint
*)(vmesa
->dma
+ vmesa
->dmaCliprectAddr
);
747 GLuint format
= (vmesa
->viaScreen
->bitsPerPixel
== 0x20
751 GLuint pitch
= buffer
->pitch
;
752 GLuint offset
= buffer
->offset
;
755 fprintf(stderr
, "emit cliprect for box %d,%d %d,%d\n",
756 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
759 vb
[1] = (HC_ParaType_NotTex
<< 16);
761 if (vmesa
->driDrawable
->w
== 0 || vmesa
->driDrawable
->h
== 0) {
762 vb
[2] = (HC_SubA_HClipTB
<< 24) | 0x0;
763 vb
[3] = (HC_SubA_HClipLR
<< 24) | 0x0;
766 vb
[2] = (HC_SubA_HClipTB
<< 24) | (b
->y1
<< 12) | b
->y2
;
767 vb
[3] = (HC_SubA_HClipLR
<< 24) | (b
->x1
<< 12) | b
->x2
;
770 vb
[4] = (HC_SubA_HDBBasL
<< 24) | (offset
& 0xFFFFFF);
771 vb
[5] = (HC_SubA_HDBBasH
<< 24) | ((offset
& 0xFF000000) >> 24);
773 vb
[6] = (HC_SubA_HSPXYOS
<< 24);
774 vb
[7] = (HC_SubA_HDBFM
<< 24) | HC_HDBLoc_Local
| format
| pitch
;
779 static int intersect_rect(drm_clip_rect_t
*out
,
786 fprintf(stderr
, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
787 a
->x1
, a
->y1
, a
->x2
, a
->y2
,
788 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
790 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
791 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
792 if (out
->x1
>= out
->x2
) return 0;
794 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
795 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
796 if (out
->y1
>= out
->y2
) return 0;
801 void viaFlushDmaLocked(struct via_context
*vmesa
, GLuint flags
)
806 if (VIA_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
807 fprintf(stderr
, "%s\n", __FUNCTION__
);
809 if (*(GLuint
*)vmesa
->driHwLock
!= (DRM_LOCK_HELD
|vmesa
->hHWContext
) &&
810 *(GLuint
*)vmesa
->driHwLock
!=
811 (DRM_LOCK_HELD
|DRM_LOCK_CONT
|vmesa
->hHWContext
)) {
812 fprintf(stderr
, "%s called without lock held\n", __FUNCTION__
);
816 if (vmesa
->dmaLow
== 0) {
820 assert(vmesa
->dmaLastPrim
== 0);
822 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
824 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
+ 8) {
825 fprintf(stderr
, "buffer overflow in Flush Prims = %d\n",vmesa
->dmaLow
);
829 switch (vmesa
->dmaLow
& 0x1F) {
831 BEGIN_RING_NOCHECK( 6 );
832 OUT_RING( HC_HEADER2
);
833 OUT_RING( (HC_ParaType_NotTex
<< 16) );
834 OUT_RING( HC_DUMMY
);
835 OUT_RING( HC_DUMMY
);
836 OUT_RING( HC_DUMMY
);
837 OUT_RING( HC_DUMMY
);
841 BEGIN_RING_NOCHECK( 4 );
842 OUT_RING( HC_HEADER2
);
843 OUT_RING( (HC_ParaType_NotTex
<< 16) );
844 OUT_RING( HC_DUMMY
);
845 OUT_RING( HC_DUMMY
);
849 BEGIN_RING_NOCHECK( 10 );
850 OUT_RING( HC_HEADER2
);
851 OUT_RING( (HC_ParaType_NotTex
<< 16) );
852 OUT_RING( HC_DUMMY
);
853 OUT_RING( HC_DUMMY
);
854 OUT_RING( HC_DUMMY
);
855 OUT_RING( HC_DUMMY
);
856 OUT_RING( HC_DUMMY
);
857 OUT_RING( HC_DUMMY
);
858 OUT_RING( HC_DUMMY
);
859 OUT_RING( HC_DUMMY
);
865 if (VIA_DEBUG
& DEBUG_IOCTL
)
866 fprintf(stderr
, "%s: unaligned value for vmesa->dmaLow: %x\n",
867 __FUNCTION__
, vmesa
->dmaLow
);
870 vmesa
->lastDma
= vmesa
->lastBreadcrumbWrite
;
872 if (VIA_DEBUG
& DEBUG_DMA
)
875 if (flags
& VIA_NO_CLIPRECTS
) {
876 if (0) fprintf(stderr
, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__
);
877 assert(vmesa
->dmaCliprectAddr
== ~0);
878 fire_buffer( vmesa
);
880 else if (vmesa
->dmaCliprectAddr
== ~0) {
881 /* Contains only state. Could just dump the packet?
883 if (0) fprintf(stderr
, "%s: no dmaCliprectAddr\n", __FUNCTION__
);
884 if (0) fire_buffer( vmesa
);
886 else if (vmesa
->numClipRects
) {
887 drm_clip_rect_t
*pbox
= vmesa
->pClipRects
;
888 __DRIdrawablePrivate
*dPriv
= vmesa
->driDrawable
;
890 for (i
= 0; i
< vmesa
->numClipRects
; i
++) {
898 if (vmesa
->scissor
&&
899 !intersect_rect(&b
, &b
, &vmesa
->scissorRect
))
902 via_emit_cliprect(vmesa
, &b
);
904 if (fire_buffer(vmesa
) != 0) {
910 if (0) fprintf(stderr
, "%s: no cliprects\n", __FUNCTION__
);
911 UNLOCK_HARDWARE(vmesa
);
913 LOCK_HARDWARE(vmesa
);
920 vmesa
->dmaCliprectAddr
= ~0;
921 vmesa
->newEmitState
= ~0;
924 void viaWrapPrimitive( struct via_context
*vmesa
)
926 GLenum renderPrimitive
= vmesa
->renderPrimitive
;
927 GLenum hwPrimitive
= vmesa
->hwPrimitive
;
929 if (VIA_DEBUG
& DEBUG_PRIMS
) fprintf(stderr
, "%s\n", __FUNCTION__
);
931 if (vmesa
->dmaLastPrim
)
932 viaFinishPrimitive( vmesa
);
936 if (renderPrimitive
!= GL_POLYGON
+ 1)
937 viaRasterPrimitive( vmesa
->glCtx
,
943 void viaFlushDma(struct via_context
*vmesa
)
946 assert(!vmesa
->dmaLastPrim
);
948 LOCK_HARDWARE(vmesa
);
949 viaFlushDmaLocked(vmesa
, 0);
950 UNLOCK_HARDWARE(vmesa
);
954 static void viaFlush(GLcontext
*ctx
)
956 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
957 VIA_FLUSH_DMA(vmesa
);
960 static void viaFinish(GLcontext
*ctx
)
962 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
963 VIA_FLUSH_DMA(vmesa
);
964 viaWaitIdle(vmesa
, GL_FALSE
);
967 static void viaClearStencil(GLcontext
*ctx
, int s
)
972 void viaInitIoctlFuncs(GLcontext
*ctx
)
974 ctx
->Driver
.Flush
= viaFlush
;
975 ctx
->Driver
.Clear
= viaClear
;
976 ctx
->Driver
.Finish
= viaFinish
;
977 ctx
->Driver
.ClearStencil
= viaClearStencil
;