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"
38 #include "via_3d_reg.h"
43 #include <sys/ioctl.h>
47 #define VIA_REG_STATUS 0x400
48 #define VIA_REG_GEMODE 0x004
49 #define VIA_REG_SRCBASE 0x030
50 #define VIA_REG_DSTBASE 0x034
51 #define VIA_REG_PITCH 0x038
52 #define VIA_REG_SRCCOLORKEY 0x01C
53 #define VIA_REG_KEYCONTROL 0x02C
54 #define VIA_REG_SRCPOS 0x008
55 #define VIA_REG_DSTPOS 0x00C
56 #define VIA_REG_GECMD 0x000
57 #define VIA_REG_DIMENSION 0x010 /* width and height */
58 #define VIA_REG_FGCOLOR 0x018
60 #define VIA_GEM_8bpp 0x00000000
61 #define VIA_GEM_16bpp 0x00000100
62 #define VIA_GEM_32bpp 0x00000300
63 #define VIA_GEC_BLT 0x00000001
64 #define VIA_PITCH_ENABLE 0x80000000
65 #define VIA_GEC_INCX 0x00000000
66 #define VIA_GEC_DECY 0x00004000
67 #define VIA_GEC_INCY 0x00000000
68 #define VIA_GEC_DECX 0x00008000
69 #define VIA_GEC_FIXCOLOR_PAT 0x00002000
72 #define VIA_BLIT_CLEAR 0x00
73 #define VIA_BLIT_COPY 0xCC
74 #define VIA_BLIT_FILL 0xF0
75 #define VIA_BLIT_SET 0xFF
77 static void dump_dma( struct via_context
*vmesa
)
80 GLuint
*data
= (GLuint
*)vmesa
->dma
;
81 for (i
= 0; i
< vmesa
->dmaLow
; i
+= 16) {
82 fprintf(stderr
, "%04x: ", i
);
83 fprintf(stderr
, "%08x ", *data
++);
84 fprintf(stderr
, "%08x ", *data
++);
85 fprintf(stderr
, "%08x ", *data
++);
86 fprintf(stderr
, "%08x\n", *data
++);
88 fprintf(stderr
, "******************************************\n");
93 void viaCheckDma(struct via_context
*vmesa
, GLuint bytes
)
95 VIA_FINISH_PRIM( vmesa
);
96 if (vmesa
->dmaLow
+ bytes
> VIA_DMA_HIGHWATER
) {
103 #define SetReg2DAGP(nReg, nData) do { \
104 OUT_RING( ((nReg) >> 2) | 0xF0000000 ); \
109 static void viaBlit(struct via_context
*vmesa
, GLuint bpp
,
110 GLuint srcBase
, GLuint srcPitch
,
111 GLuint dstBase
, GLuint dstPitch
,
114 GLuint color
, GLuint nMask
)
117 GLuint dwGEMode
, srcX
, dstX
, cmd
;
120 if (VIA_DEBUG
& DEBUG_2D
)
122 "%s bpp %d src %x/%x dst %x/%x w %d h %d "
123 " mode: %x color: 0x%08x mask 0x%08x\n",
124 __FUNCTION__
, bpp
, srcBase
, srcPitch
, dstBase
,
125 dstPitch
, w
,h
, blitMode
, color
, nMask
);
133 dwGEMode
= VIA_GEM_16bpp
;
134 srcX
= (srcBase
& 0x1f) >> 1;
135 dstX
= (dstBase
& 0x1f) >> 1;
138 dwGEMode
= VIA_GEM_32bpp
;
139 srcX
= (srcBase
& 0x1f) >> 2;
140 dstX
= (dstBase
& 0x1f) >> 2;
148 cmd
= VIA_GEC_BLT
| VIA_GEC_FIXCOLOR_PAT
| (VIA_BLIT_FILL
<< 24);
151 cmd
= VIA_GEC_BLT
| (VIA_BLIT_COPY
<< 24);
158 SetReg2DAGP( VIA_REG_GEMODE
, dwGEMode
);
159 SetReg2DAGP( VIA_REG_FGCOLOR
, color
);
160 SetReg2DAGP( 0x2C, nMask
);
161 SetReg2DAGP( VIA_REG_SRCBASE
, (srcBase
& ~0x1f) >> 3);
162 SetReg2DAGP( VIA_REG_DSTBASE
, (dstBase
& ~0x1f) >> 3);
163 SetReg2DAGP( VIA_REG_PITCH
, VIA_PITCH_ENABLE
|
164 (srcPitch
>> 3) | ((dstPitch
>> 3) << 16));
165 SetReg2DAGP( VIA_REG_SRCPOS
, srcX
);
166 SetReg2DAGP( VIA_REG_DSTPOS
, dstX
);
167 SetReg2DAGP( VIA_REG_DIMENSION
, (((h
- 1) << 16) | (w
- 1)));
168 SetReg2DAGP( VIA_REG_GECMD
, cmd
);
169 SetReg2DAGP( 0x2C, 0x00000000);
173 static void viaFillBuffer(struct via_context
*vmesa
,
174 struct via_renderbuffer
*buffer
,
175 drm_clip_rect_t
*pbox
,
180 GLuint bytePerPixel
= buffer
->bpp
>> 3;
183 for (i
= 0; i
< nboxes
; i
++) {
184 int x
= pbox
[i
].x1
- buffer
->drawX
;
185 int y
= pbox
[i
].y1
- buffer
->drawY
;
186 int w
= pbox
[i
].x2
- pbox
[i
].x1
;
187 int h
= pbox
[i
].y2
- pbox
[i
].y1
;
189 int offset
= (buffer
->offset
+
195 offset
, buffer
->pitch
,
196 offset
, buffer
->pitch
,
198 VIA_BLIT_FILL
, pixel
, mask
);
204 static void viaClear(struct gl_context
*ctx
, GLbitfield mask
)
206 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
207 __DRIdrawable
*dPriv
= vmesa
->driDrawable
;
208 struct via_renderbuffer
*const vrb
=
209 (struct via_renderbuffer
*) dPriv
->driverPrivate
;
212 GLuint clear_depth_mask
= 0xf << 28;
213 GLuint clear_depth
= 0;
215 VIA_FLUSH_DMA(vmesa
);
217 if (mask
& BUFFER_BIT_FRONT_LEFT
) {
219 mask
&= ~BUFFER_BIT_FRONT_LEFT
;
222 if (mask
& BUFFER_BIT_BACK_LEFT
) {
224 mask
&= ~BUFFER_BIT_BACK_LEFT
;
227 if (mask
& BUFFER_BIT_DEPTH
) {
229 clear_depth
= (GLuint
)(ctx
->Depth
.Clear
* vmesa
->ClearDepth
);
230 clear_depth_mask
&= ~vmesa
->depth_clear_mask
;
231 mask
&= ~BUFFER_BIT_DEPTH
;
234 if (mask
& BUFFER_BIT_STENCIL
) {
235 if (vmesa
->have_hw_stencil
) {
236 if ((ctx
->Stencil
.WriteMask
[0] & 0xff) == 0xff) {
238 clear_depth
&= ~0xff;
239 clear_depth
|= (ctx
->Stencil
.Clear
& 0xff);
240 clear_depth_mask
&= ~vmesa
->stencil_clear_mask
;
241 mask
&= ~BUFFER_BIT_STENCIL
;
244 if (VIA_DEBUG
& DEBUG_2D
)
245 fprintf(stderr
, "Clear stencil writemask %x\n",
246 ctx
->Stencil
.WriteMask
[0]);
251 /* 16bpp doesn't support masked clears */
252 if (vmesa
->viaScreen
->bytesPerPixel
== 2 &&
253 vmesa
->ClearMask
& 0xf0000000) {
254 if (flag
& VIA_FRONT
)
255 mask
|= BUFFER_BIT_FRONT_LEFT
;
257 mask
|= BUFFER_BIT_BACK_LEFT
;
258 flag
&= ~(VIA_FRONT
| VIA_BACK
);
262 drm_clip_rect_t
*boxes
, *tmp_boxes
= 0;
264 GLint cx
, cy
, cw
, ch
;
267 LOCK_HARDWARE(vmesa
);
269 /* get region after locking: */
270 cx
= ctx
->DrawBuffer
->_Xmin
;
271 cy
= ctx
->DrawBuffer
->_Ymin
;
272 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
273 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
274 all
= (cw
== ctx
->DrawBuffer
->Width
&& ch
== ctx
->DrawBuffer
->Height
);
276 /* flip top to bottom */
277 cy
= dPriv
->h
- cy
- ch
;
282 drm_clip_rect_t
*b
= vmesa
->pClipRects
;
285 (drm_clip_rect_t
*)malloc(vmesa
->numClipRects
*
286 sizeof(drm_clip_rect_t
));
288 UNLOCK_HARDWARE(vmesa
);
292 for (; i
< vmesa
->numClipRects
; i
++) {
295 GLint w
= b
[i
].x2
- x
;
296 GLint h
= b
[i
].y2
- y
;
298 if (x
< cx
) w
-= cx
- x
, x
= cx
;
299 if (y
< cy
) h
-= cy
- y
, y
= cy
;
300 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
301 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
302 if (w
<= 0) continue;
303 if (h
<= 0) continue;
307 boxes
[nr
].x2
= x
+ w
;
308 boxes
[nr
].y2
= y
+ h
;
313 boxes
= vmesa
->pClipRects
;
314 nr
= vmesa
->numClipRects
;
317 if (flag
& VIA_FRONT
) {
318 viaFillBuffer(vmesa
, &vmesa
->front
, boxes
, nr
, vmesa
->ClearColor
,
322 if (flag
& VIA_BACK
) {
323 viaFillBuffer(vmesa
, &vmesa
->back
, boxes
, nr
, vmesa
->ClearColor
,
327 if (flag
& VIA_DEPTH
) {
328 viaFillBuffer(vmesa
, &vmesa
->depth
, boxes
, nr
, clear_depth
,
332 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
);
333 UNLOCK_HARDWARE(vmesa
);
340 _swrast_Clear(ctx
, mask
);
346 static void viaDoSwapBuffers(struct via_context
*vmesa
,
350 GLuint bytePerPixel
= vmesa
->viaScreen
->bitsPerPixel
>> 3;
351 struct via_renderbuffer
*front
= &vmesa
->front
;
352 struct via_renderbuffer
*back
= &vmesa
->back
;
355 for (i
= 0; i
< nbox
; i
++, b
++) {
356 GLint x
= b
->x1
- back
->drawX
;
357 GLint y
= b
->y1
- back
->drawY
;
358 GLint w
= b
->x2
- b
->x1
;
359 GLint h
= b
->y2
- b
->y1
;
361 GLuint src
= back
->offset
+ y
* back
->pitch
+ x
* bytePerPixel
;
362 GLuint dest
= front
->offset
+ y
* front
->pitch
+ x
* bytePerPixel
;
369 VIA_BLIT_COPY
, 0, 0);
372 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* redundant */
376 static void viaEmitBreadcrumbLocked( struct via_context
*vmesa
)
378 struct via_renderbuffer
*buffer
= &vmesa
->breadcrumb
;
379 GLuint value
= vmesa
->lastBreadcrumbWrite
+ 1;
381 if (VIA_DEBUG
& DEBUG_IOCTL
)
382 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
384 assert(!vmesa
->dmaLow
);
388 buffer
->offset
, buffer
->pitch
,
389 buffer
->offset
, buffer
->pitch
,
391 VIA_BLIT_FILL
, value
, 0);
393 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
394 vmesa
->lastBreadcrumbWrite
= value
;
397 void viaEmitBreadcrumb( struct via_context
*vmesa
)
399 LOCK_HARDWARE(vmesa
);
401 viaFlushDmaLocked(vmesa
, 0);
403 viaEmitBreadcrumbLocked( vmesa
);
404 UNLOCK_HARDWARE(vmesa
);
407 static GLboolean
viaCheckIdle( struct via_context
*vmesa
)
409 if ((vmesa
->regEngineStatus
[0] & 0xFFFEFFFF) == 0x00020000) {
416 GLboolean
viaCheckBreadcrumb( struct via_context
*vmesa
, GLuint value
)
418 GLuint
*buf
= (GLuint
*)vmesa
->breadcrumb
.map
;
419 vmesa
->lastBreadcrumbRead
= *buf
;
421 if (VIA_DEBUG
& DEBUG_IOCTL
)
422 fprintf(stderr
, "%s %d < %d: %d\n", __FUNCTION__
, value
,
423 vmesa
->lastBreadcrumbRead
,
424 !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
));
426 return !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
);
429 static void viaWaitBreadcrumb( struct via_context
*vmesa
, GLuint value
)
431 if (VIA_DEBUG
& DEBUG_IOCTL
)
432 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
434 assert(!VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbWrite
));
436 while (!viaCheckBreadcrumb( vmesa
, value
)) {
437 viaSwapOutWork( vmesa
);
438 via_release_pending_textures( vmesa
);
443 void viaWaitIdle( struct via_context
*vmesa
, GLboolean light
)
445 VIA_FLUSH_DMA(vmesa
);
447 if (VIA_DEBUG
& DEBUG_IOCTL
)
448 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
449 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
451 /* Need to emit a new breadcrumb?
453 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
454 LOCK_HARDWARE(vmesa
);
455 viaEmitBreadcrumbLocked( vmesa
);
456 UNLOCK_HARDWARE(vmesa
);
461 if (VIA_GEQ_WRAP(vmesa
->lastDma
, vmesa
->lastBreadcrumbRead
))
462 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
466 LOCK_HARDWARE(vmesa
);
467 while(!viaCheckIdle(vmesa
))
469 UNLOCK_HARDWARE(vmesa
);
470 via_release_pending_textures(vmesa
);
474 void viaWaitIdleLocked( struct via_context
*vmesa
, GLboolean light
)
477 viaFlushDmaLocked(vmesa
, 0);
479 if (VIA_DEBUG
& DEBUG_IOCTL
)
480 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
481 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
483 /* Need to emit a new breadcrumb?
485 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
486 viaEmitBreadcrumbLocked( vmesa
);
491 if (vmesa
->lastDma
>= vmesa
->lastBreadcrumbRead
)
492 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
496 while(!viaCheckIdle(vmesa
))
499 via_release_pending_textures(vmesa
);
504 /* Wait for command stream to be processed *and* the next vblank to
505 * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank,
506 * except that WAIT_IDLE() will spin the CPU polling, while this is
509 static void viaWaitIdleVBlank( __DRIdrawable
*dPriv
,
510 struct via_context
*vmesa
,
513 GLboolean missed_target
;
514 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
516 VIA_FLUSH_DMA(vmesa
);
522 if (value
< vmesa
->lastBreadcrumbRead
||
524 viaSwapOutWork(vmesa
);
526 driWaitForVBlank( dPriv
, & missed_target
);
527 if ( missed_target
) {
528 vmesa
->swap_missed_count
++;
529 (*psp
->systemTime
->getUST
)( &vmesa
->swap_missed_ust
);
532 while (!viaCheckBreadcrumb(vmesa
, value
));
534 vmesa
->thrashing
= 0; /* reset flag on swap */
536 via_release_pending_textures( vmesa
);
541 static void viaDoPageFlipLocked(struct via_context
*vmesa
, GLuint offset
)
545 if (VIA_DEBUG
& DEBUG_2D
)
546 fprintf(stderr
, "%s %x\n", __FUNCTION__
, offset
);
548 if (!vmesa
->nDoneFirstFlip
) {
549 vmesa
->nDoneFirstFlip
= GL_TRUE
;
551 OUT_RING(HALCYON_HEADER2
);
552 OUT_RING(0x00fe0000);
553 OUT_RING(0x0000000e);
554 OUT_RING(0x0000000e);
559 OUT_RING( HALCYON_HEADER2
);
560 OUT_RING( 0x00fe0000 );
561 OUT_RING((HC_SubA_HFBBasL
<< 24) | (offset
& 0xFFFFF8) | 0x2);
562 OUT_RING((HC_SubA_HFBDrawFirst
<< 24) |
563 ((offset
& 0xFF000000) >> 24) | 0x0100);
566 vmesa
->pfCurrentOffset
= vmesa
->sarea
->pfCurrentOffset
= offset
;
568 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
571 void viaResetPageFlippingLocked(struct via_context
*vmesa
)
573 if (VIA_DEBUG
& DEBUG_2D
)
574 fprintf(stderr
, "%s\n", __FUNCTION__
);
576 viaDoPageFlipLocked( vmesa
, 0 );
578 if (vmesa
->front
.offset
!= 0) {
579 struct via_renderbuffer buffer_tmp
;
580 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
581 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
582 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
585 assert(vmesa
->front
.offset
== 0);
586 vmesa
->doPageFlip
= vmesa
->allowPageFlip
= 0;
591 * Copy the back buffer to the front buffer.
593 void viaCopyBuffer(__DRIdrawable
*dPriv
)
595 struct via_context
*vmesa
=
596 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
597 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
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 (dPriv
->vblFlags
== 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 (*psp
->systemTime
->getUST
)( &vmesa
->swap_ust
);
637 void viaPageFlip(__DRIdrawable
*dPriv
)
639 struct via_context
*vmesa
=
640 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
641 struct via_renderbuffer buffer_tmp
;
642 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
644 VIA_FLUSH_DMA(vmesa
);
645 if (dPriv
->vblFlags
== VBLANK_FLAG_SYNC
&&
646 vmesa
->lastBreadcrumbWrite
> 1)
647 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
- 1);
649 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[0]);
651 LOCK_HARDWARE(vmesa
);
652 viaDoPageFlipLocked(vmesa
, vmesa
->back
.offset
);
653 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
654 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
655 viaEmitBreadcrumbLocked(vmesa
);
656 UNLOCK_HARDWARE(vmesa
);
658 (*psp
->systemTime
->getUST
)( &vmesa
->swap_ust
);
661 /* KW: FIXME: When buffers are freed, could free frontbuffer by
664 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
665 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
666 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
672 #define VIA_CMDBUF_MAX_LAG 50000
674 static int fire_buffer(struct via_context
*vmesa
)
676 drm_via_cmdbuffer_t bufI
;
679 bufI
.buf
= (char *)vmesa
->dma
;
680 bufI
.size
= vmesa
->dmaLow
;
683 drm_via_cmdbuf_size_t bSiz
;
685 /* Do the CMDBUF_SIZE ioctl:
687 bSiz
.func
= VIA_CMDBUF_LAG
;
689 bSiz
.size
= VIA_CMDBUF_MAX_LAG
;
691 ret
= drmCommandWriteRead(vmesa
->driFd
, DRM_VIA_CMDBUF_SIZE
,
692 &bSiz
, sizeof(bSiz
));
693 } while (ret
== -EAGAIN
);
695 UNLOCK_HARDWARE(vmesa
);
696 fprintf(stderr
, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
702 /* Actually fire the buffer:
705 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_CMDBUFFER
,
706 &bufI
, sizeof(bufI
));
707 } while (ret
== -EAGAIN
);
709 UNLOCK_HARDWARE(vmesa
);
710 fprintf(stderr
, "%s: DRM_VIA_CMDBUFFER returned %d\n",
713 /* If this fails, the original code fell back to the PCI path.
719 /* Fall through to PCI handling?!?
721 viaWaitIdleLocked(vmesa
, GL_FALSE
);
724 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_PCICMD
, &bufI
, sizeof(bufI
));
726 UNLOCK_HARDWARE(vmesa
);
728 fprintf(stderr
, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__
, ret
);
736 /* Inserts the surface addresss and active cliprects one at a time
737 * into the head of the DMA buffer being flushed. Fires the buffer
740 static void via_emit_cliprect(struct via_context
*vmesa
,
743 struct via_renderbuffer
*buffer
= vmesa
->drawBuffer
;
744 GLuint
*vb
= (GLuint
*)(vmesa
->dma
+ vmesa
->dmaCliprectAddr
);
746 GLuint format
= (vmesa
->viaScreen
->bitsPerPixel
== 0x20
750 GLuint pitch
= buffer
->pitch
;
751 GLuint offset
= buffer
->offset
;
754 fprintf(stderr
, "emit cliprect for box %d,%d %d,%d\n",
755 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
758 vb
[1] = (HC_ParaType_NotTex
<< 16);
760 assert(vmesa
->driDrawable
);
762 if (vmesa
->driDrawable
->w
== 0 || vmesa
->driDrawable
->h
== 0) {
763 vb
[2] = (HC_SubA_HClipTB
<< 24) | 0x0;
764 vb
[3] = (HC_SubA_HClipLR
<< 24) | 0x0;
767 vb
[2] = (HC_SubA_HClipTB
<< 24) | (b
->y1
<< 12) | b
->y2
;
768 vb
[3] = (HC_SubA_HClipLR
<< 24) | (b
->x1
<< 12) | b
->x2
;
771 vb
[4] = (HC_SubA_HDBBasL
<< 24) | (offset
& 0xFFFFFF);
772 vb
[5] = (HC_SubA_HDBBasH
<< 24) | ((offset
& 0xFF000000) >> 24);
774 vb
[6] = (HC_SubA_HSPXYOS
<< 24);
775 vb
[7] = (HC_SubA_HDBFM
<< 24) | HC_HDBLoc_Local
| format
| pitch
;
780 static int intersect_rect(drm_clip_rect_t
*out
,
787 fprintf(stderr
, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
788 a
->x1
, a
->y1
, a
->x2
, a
->y2
,
789 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
791 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
792 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
793 if (out
->x1
>= out
->x2
) return 0;
795 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
796 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
797 if (out
->y1
>= out
->y2
) return 0;
802 void viaFlushDmaLocked(struct via_context
*vmesa
, GLuint flags
)
807 if (VIA_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
808 fprintf(stderr
, "%s\n", __FUNCTION__
);
810 if (*(GLuint
*)vmesa
->driHwLock
!= (DRM_LOCK_HELD
|vmesa
->hHWContext
) &&
811 *(GLuint
*)vmesa
->driHwLock
!=
812 (DRM_LOCK_HELD
|DRM_LOCK_CONT
|vmesa
->hHWContext
)) {
813 fprintf(stderr
, "%s called without lock held\n", __FUNCTION__
);
817 if (vmesa
->dmaLow
== 0) {
821 assert(vmesa
->dmaLastPrim
== 0);
823 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
825 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
+ 8) {
826 fprintf(stderr
, "buffer overflow in Flush Prims = %d\n",vmesa
->dmaLow
);
830 switch (vmesa
->dmaLow
& 0x1F) {
832 BEGIN_RING_NOCHECK( 6 );
833 OUT_RING( HC_HEADER2
);
834 OUT_RING( (HC_ParaType_NotTex
<< 16) );
835 OUT_RING( HC_DUMMY
);
836 OUT_RING( HC_DUMMY
);
837 OUT_RING( HC_DUMMY
);
838 OUT_RING( HC_DUMMY
);
842 BEGIN_RING_NOCHECK( 4 );
843 OUT_RING( HC_HEADER2
);
844 OUT_RING( (HC_ParaType_NotTex
<< 16) );
845 OUT_RING( HC_DUMMY
);
846 OUT_RING( HC_DUMMY
);
850 BEGIN_RING_NOCHECK( 10 );
851 OUT_RING( HC_HEADER2
);
852 OUT_RING( (HC_ParaType_NotTex
<< 16) );
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
);
860 OUT_RING( HC_DUMMY
);
866 if (VIA_DEBUG
& DEBUG_IOCTL
)
867 fprintf(stderr
, "%s: unaligned value for vmesa->dmaLow: %x\n",
868 __FUNCTION__
, vmesa
->dmaLow
);
871 vmesa
->lastDma
= vmesa
->lastBreadcrumbWrite
;
873 if (VIA_DEBUG
& DEBUG_DMA
)
876 if (flags
& VIA_NO_CLIPRECTS
) {
877 if (0) fprintf(stderr
, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__
);
878 assert(vmesa
->dmaCliprectAddr
== ~0);
879 fire_buffer( vmesa
);
881 else if (vmesa
->dmaCliprectAddr
== ~0) {
882 /* Contains only state. Could just dump the packet?
884 if (0) fprintf(stderr
, "%s: no dmaCliprectAddr\n", __FUNCTION__
);
885 if (0) fire_buffer( vmesa
);
887 else if (vmesa
->numClipRects
) {
888 drm_clip_rect_t
*pbox
= vmesa
->pClipRects
;
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(struct gl_context
*ctx
)
956 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
957 VIA_FLUSH_DMA(vmesa
);
960 static void viaFinish(struct gl_context
*ctx
)
962 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
963 VIA_FLUSH_DMA(vmesa
);
964 viaWaitIdle(vmesa
, GL_FALSE
);
967 static void viaClearStencil(struct gl_context
*ctx
, int s
)
972 void viaInitIoctlFuncs(struct gl_context
*ctx
)
974 ctx
->Driver
.Flush
= viaFlush
;
975 ctx
->Driver
.Clear
= viaClear
;
976 ctx
->Driver
.Finish
= viaFinish
;
977 ctx
->Driver
.ClearStencil
= viaClearStencil
;