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.
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( const __DRIdrawablePrivate
*dPriv
,
511 struct via_context
*vmesa
,
514 GLboolean missed_target
;
516 VIA_FLUSH_DMA(vmesa
);
522 if (value
< vmesa
->lastBreadcrumbRead
||
524 viaSwapOutWork(vmesa
);
526 driWaitForVBlank( dPriv
, & vmesa
->vbl_seq
,
527 vmesa
->vblank_flags
, & missed_target
);
528 if ( missed_target
) {
529 vmesa
->swap_missed_count
++;
530 (*dri_interface
->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(const __DRIdrawablePrivate
*dPriv
)
596 struct via_context
*vmesa
=
597 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
599 if (VIA_DEBUG
& DEBUG_IOCTL
)
601 "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
605 vmesa
->lastBreadcrumbWrite
,
606 vmesa
->lastBreadcrumbRead
);
608 VIA_FLUSH_DMA(vmesa
);
610 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
611 vmesa
->lastBreadcrumbWrite
> 1)
612 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
-1);
614 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[1]);
616 LOCK_HARDWARE(vmesa
);
618 /* Catch and cleanup situation where we were pageflipping but have
621 if (dPriv
->numClipRects
&& vmesa
->sarea
->pfCurrentOffset
!= 0) {
622 viaResetPageFlippingLocked(vmesa
);
623 UNLOCK_HARDWARE(vmesa
);
627 viaDoSwapBuffers(vmesa
, dPriv
->pClipRects
, dPriv
->numClipRects
);
628 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
629 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
630 viaEmitBreadcrumbLocked(vmesa
);
631 UNLOCK_HARDWARE(vmesa
);
633 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
637 void viaPageFlip(const __DRIdrawablePrivate
*dPriv
)
639 struct via_context
*vmesa
=
640 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
641 struct via_renderbuffer buffer_tmp
;
643 VIA_FLUSH_DMA(vmesa
);
644 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
645 vmesa
->lastBreadcrumbWrite
> 1)
646 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
- 1);
648 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[0]);
650 LOCK_HARDWARE(vmesa
);
651 viaDoPageFlipLocked(vmesa
, vmesa
->back
.offset
);
652 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
653 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
654 viaEmitBreadcrumbLocked(vmesa
);
655 UNLOCK_HARDWARE(vmesa
);
657 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
660 /* KW: FIXME: When buffers are freed, could free frontbuffer by
663 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
664 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
665 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
671 #define VIA_CMDBUF_MAX_LAG 50000
673 static int fire_buffer(struct via_context
*vmesa
)
675 drm_via_cmdbuffer_t bufI
;
678 bufI
.buf
= (char *)vmesa
->dma
;
679 bufI
.size
= vmesa
->dmaLow
;
682 drm_via_cmdbuf_size_t bSiz
;
684 /* Do the CMDBUF_SIZE ioctl:
686 bSiz
.func
= VIA_CMDBUF_LAG
;
688 bSiz
.size
= VIA_CMDBUF_MAX_LAG
;
690 ret
= drmCommandWriteRead(vmesa
->driFd
, DRM_VIA_CMDBUF_SIZE
,
691 &bSiz
, sizeof(bSiz
));
692 } while (ret
== -EAGAIN
);
694 UNLOCK_HARDWARE(vmesa
);
695 fprintf(stderr
, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
701 /* Actually fire the buffer:
704 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_CMDBUFFER
,
705 &bufI
, sizeof(bufI
));
706 } while (ret
== -EAGAIN
);
708 UNLOCK_HARDWARE(vmesa
);
709 fprintf(stderr
, "%s: DRM_VIA_CMDBUFFER returned %d\n",
712 /* If this fails, the original code fell back to the PCI path.
718 /* Fall through to PCI handling?!?
720 viaWaitIdleLocked(vmesa
, GL_FALSE
);
723 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_PCICMD
, &bufI
, sizeof(bufI
));
725 UNLOCK_HARDWARE(vmesa
);
727 fprintf(stderr
, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__
, ret
);
735 /* Inserts the surface addresss and active cliprects one at a time
736 * into the head of the DMA buffer being flushed. Fires the buffer
739 static void via_emit_cliprect(struct via_context
*vmesa
,
742 struct via_renderbuffer
*buffer
= vmesa
->drawBuffer
;
743 GLuint
*vb
= (GLuint
*)(vmesa
->dma
+ vmesa
->dmaCliprectAddr
);
745 GLuint format
= (vmesa
->viaScreen
->bitsPerPixel
== 0x20
749 GLuint pitch
= buffer
->pitch
;
750 GLuint offset
= buffer
->offset
;
753 fprintf(stderr
, "emit cliprect for box %d,%d %d,%d\n",
754 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
757 vb
[1] = (HC_ParaType_NotTex
<< 16);
759 if (vmesa
->driDrawable
->w
== 0 || vmesa
->driDrawable
->h
== 0) {
760 vb
[2] = (HC_SubA_HClipTB
<< 24) | 0x0;
761 vb
[3] = (HC_SubA_HClipLR
<< 24) | 0x0;
764 vb
[2] = (HC_SubA_HClipTB
<< 24) | (b
->y1
<< 12) | b
->y2
;
765 vb
[3] = (HC_SubA_HClipLR
<< 24) | (b
->x1
<< 12) | b
->x2
;
768 vb
[4] = (HC_SubA_HDBBasL
<< 24) | (offset
& 0xFFFFFF);
769 vb
[5] = (HC_SubA_HDBBasH
<< 24) | ((offset
& 0xFF000000) >> 24);
771 vb
[6] = (HC_SubA_HSPXYOS
<< 24);
772 vb
[7] = (HC_SubA_HDBFM
<< 24) | HC_HDBLoc_Local
| format
| pitch
;
777 static int intersect_rect(drm_clip_rect_t
*out
,
784 fprintf(stderr
, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
785 a
->x1
, a
->y1
, a
->x2
, a
->y2
,
786 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
788 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
789 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
790 if (out
->x1
>= out
->x2
) return 0;
792 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
793 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
794 if (out
->y1
>= out
->y2
) return 0;
799 void viaFlushDmaLocked(struct via_context
*vmesa
, GLuint flags
)
804 if (VIA_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
805 fprintf(stderr
, "%s\n", __FUNCTION__
);
807 if (*(GLuint
*)vmesa
->driHwLock
!= (DRM_LOCK_HELD
|vmesa
->hHWContext
) &&
808 *(GLuint
*)vmesa
->driHwLock
!=
809 (DRM_LOCK_HELD
|DRM_LOCK_CONT
|vmesa
->hHWContext
)) {
810 fprintf(stderr
, "%s called without lock held\n", __FUNCTION__
);
814 if (vmesa
->dmaLow
== 0) {
818 assert(vmesa
->dmaLastPrim
== 0);
820 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
822 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
+ 8) {
823 fprintf(stderr
, "buffer overflow in Flush Prims = %d\n",vmesa
->dmaLow
);
827 switch (vmesa
->dmaLow
& 0x1F) {
829 BEGIN_RING_NOCHECK( 6 );
830 OUT_RING( HC_HEADER2
);
831 OUT_RING( (HC_ParaType_NotTex
<< 16) );
832 OUT_RING( HC_DUMMY
);
833 OUT_RING( HC_DUMMY
);
834 OUT_RING( HC_DUMMY
);
835 OUT_RING( HC_DUMMY
);
839 BEGIN_RING_NOCHECK( 4 );
840 OUT_RING( HC_HEADER2
);
841 OUT_RING( (HC_ParaType_NotTex
<< 16) );
842 OUT_RING( HC_DUMMY
);
843 OUT_RING( HC_DUMMY
);
847 BEGIN_RING_NOCHECK( 10 );
848 OUT_RING( HC_HEADER2
);
849 OUT_RING( (HC_ParaType_NotTex
<< 16) );
850 OUT_RING( HC_DUMMY
);
851 OUT_RING( HC_DUMMY
);
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
);
863 if (VIA_DEBUG
& DEBUG_IOCTL
)
864 fprintf(stderr
, "%s: unaligned value for vmesa->dmaLow: %x\n",
865 __FUNCTION__
, vmesa
->dmaLow
);
868 vmesa
->lastDma
= vmesa
->lastBreadcrumbWrite
;
870 if (VIA_DEBUG
& DEBUG_DMA
)
873 if (flags
& VIA_NO_CLIPRECTS
) {
874 if (0) fprintf(stderr
, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__
);
875 assert(vmesa
->dmaCliprectAddr
== ~0);
876 fire_buffer( vmesa
);
878 else if (vmesa
->dmaCliprectAddr
== ~0) {
879 /* Contains only state. Could just dump the packet?
881 if (0) fprintf(stderr
, "%s: no dmaCliprectAddr\n", __FUNCTION__
);
882 if (0) fire_buffer( vmesa
);
884 else if (vmesa
->numClipRects
) {
885 drm_clip_rect_t
*pbox
= vmesa
->pClipRects
;
886 __DRIdrawablePrivate
*dPriv
= vmesa
->driDrawable
;
887 struct via_renderbuffer
*const vrb
=
888 (struct via_renderbuffer
*) dPriv
->driverPrivate
;
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
;