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
- vmesa
->drawX
;
186 int y
= pbox
[i
].y1
- vmesa
->drawY
;
187 int w
= pbox
[i
].x2
- pbox
[i
].x1
;
188 int h
= pbox
[i
].y2
- pbox
[i
].y1
;
190 int offset
= (buffer
->orig
+
196 offset
, buffer
->pitch
,
197 offset
, buffer
->pitch
,
199 VIA_BLIT_FILL
, pixel
, mask
);
205 static void viaClear(GLcontext
*ctx
, GLbitfield mask
, GLboolean all
,
206 GLint cx
, GLint cy
, GLint cw
, GLint ch
)
208 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
209 __DRIdrawablePrivate
*dPriv
= vmesa
->driDrawable
;
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) {
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;
265 LOCK_HARDWARE(vmesa
);
267 /* flip top to bottom */
268 cy
= dPriv
->h
- cy
- ch
;
269 cx
+= vmesa
->drawX
+ vmesa
->drawXoff
;
273 drm_clip_rect_t
*b
= vmesa
->pClipRects
;
276 (drm_clip_rect_t
*)malloc(vmesa
->numClipRects
*
277 sizeof(drm_clip_rect_t
));
279 UNLOCK_HARDWARE(vmesa
);
283 for (; i
< vmesa
->numClipRects
; i
++) {
286 GLint w
= b
[i
].x2
- x
;
287 GLint h
= b
[i
].y2
- y
;
289 if (x
< cx
) w
-= cx
- x
, x
= cx
;
290 if (y
< cy
) h
-= cy
- y
, y
= cy
;
291 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
292 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
293 if (w
<= 0) continue;
294 if (h
<= 0) continue;
298 boxes
[nr
].x2
= x
+ w
;
299 boxes
[nr
].y2
= y
+ h
;
304 boxes
= vmesa
->pClipRects
;
305 nr
= vmesa
->numClipRects
;
308 if (flag
& VIA_FRONT
) {
309 viaFillBuffer(vmesa
, &vmesa
->front
, boxes
, nr
, vmesa
->ClearColor
,
313 if (flag
& VIA_BACK
) {
314 viaFillBuffer(vmesa
, &vmesa
->back
, boxes
, nr
, vmesa
->ClearColor
,
318 if (flag
& VIA_DEPTH
) {
319 viaFillBuffer(vmesa
, &vmesa
->depth
, boxes
, nr
, clear_depth
,
323 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
);
324 UNLOCK_HARDWARE(vmesa
);
331 _swrast_Clear(ctx
, mask
, all
, cx
, cy
, cw
, ch
);
337 static void viaDoSwapBuffers(struct via_context
*vmesa
,
341 GLuint bytePerPixel
= vmesa
->viaScreen
->bitsPerPixel
>> 3;
342 struct via_renderbuffer
*front
= &vmesa
->front
;
343 struct via_renderbuffer
*back
= &vmesa
->back
;
346 for (i
= 0; i
< nbox
; i
++, b
++) {
347 GLint x
= b
->x1
- vmesa
->drawX
;
348 GLint y
= b
->y1
- vmesa
->drawY
;
349 GLint w
= b
->x2
- b
->x1
;
350 GLint h
= b
->y2
- b
->y1
;
352 GLuint src
= back
->orig
+ y
* back
->pitch
+ x
* bytePerPixel
;
353 GLuint dest
= front
->orig
+ y
* front
->pitch
+ x
* bytePerPixel
;
360 VIA_BLIT_COPY
, 0, 0);
363 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* redundant */
367 static void viaEmitBreadcrumbLocked( struct via_context
*vmesa
)
369 struct via_renderbuffer
*buffer
= &vmesa
->breadcrumb
;
370 GLuint value
= vmesa
->lastBreadcrumbWrite
+ 1;
372 if (VIA_DEBUG
& DEBUG_IOCTL
)
373 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
375 assert(!vmesa
->dmaLow
);
379 buffer
->offset
, buffer
->pitch
,
380 buffer
->offset
, buffer
->pitch
,
382 VIA_BLIT_FILL
, value
, 0);
384 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
385 vmesa
->lastBreadcrumbWrite
= value
;
388 void viaEmitBreadcrumb( struct via_context
*vmesa
)
390 LOCK_HARDWARE(vmesa
);
392 viaFlushDmaLocked(vmesa
, 0);
394 viaEmitBreadcrumbLocked( vmesa
);
395 UNLOCK_HARDWARE(vmesa
);
398 static GLboolean
viaCheckIdle( struct via_context
*vmesa
)
400 if ((vmesa
->regEngineStatus
[0] & 0xFFFEFFFF) == 0x00020000) {
407 GLboolean
viaCheckBreadcrumb( struct via_context
*vmesa
, GLuint value
)
409 GLuint
*buf
= (GLuint
*)vmesa
->breadcrumb
.map
;
410 vmesa
->lastBreadcrumbRead
= *buf
;
412 if (VIA_DEBUG
& DEBUG_IOCTL
)
413 fprintf(stderr
, "%s %d < %d: %d\n", __FUNCTION__
, value
,
414 vmesa
->lastBreadcrumbRead
,
415 !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
));
417 return !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
);
420 static void viaWaitBreadcrumb( struct via_context
*vmesa
, GLuint value
)
422 if (VIA_DEBUG
& DEBUG_IOCTL
)
423 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
425 assert(!VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbWrite
));
427 while (!viaCheckBreadcrumb( vmesa
, value
)) {
428 viaSwapOutWork( vmesa
);
429 via_release_pending_textures( vmesa
);
434 void viaWaitIdle( struct via_context
*vmesa
, GLboolean light
)
436 VIA_FLUSH_DMA(vmesa
);
438 if (VIA_DEBUG
& DEBUG_IOCTL
)
439 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
440 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
442 /* Need to emit a new breadcrumb?
444 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
445 LOCK_HARDWARE(vmesa
);
446 viaEmitBreadcrumbLocked( vmesa
);
447 UNLOCK_HARDWARE(vmesa
);
452 if (VIA_GEQ_WRAP(vmesa
->lastDma
, vmesa
->lastBreadcrumbRead
))
453 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
457 LOCK_HARDWARE(vmesa
);
458 while(!viaCheckIdle(vmesa
))
460 UNLOCK_HARDWARE(vmesa
);
461 via_release_pending_textures(vmesa
);
465 void viaWaitIdleLocked( struct via_context
*vmesa
, GLboolean light
)
468 viaFlushDmaLocked(vmesa
, 0);
470 if (VIA_DEBUG
& DEBUG_IOCTL
)
471 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
472 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
474 /* Need to emit a new breadcrumb?
476 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
477 viaEmitBreadcrumbLocked( vmesa
);
482 if (vmesa
->lastDma
>= vmesa
->lastBreadcrumbRead
)
483 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
487 while(!viaCheckIdle(vmesa
))
490 via_release_pending_textures(vmesa
);
495 /* Wait for command stream to be processed *and* the next vblank to
496 * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank,
497 * except that WAIT_IDLE() will spin the CPU polling, while this is
500 static void viaWaitIdleVBlank( const __DRIdrawablePrivate
*dPriv
,
501 struct via_context
*vmesa
,
504 GLboolean missed_target
;
506 VIA_FLUSH_DMA(vmesa
);
512 if (value
< vmesa
->lastBreadcrumbRead
||
514 viaSwapOutWork(vmesa
);
516 driWaitForVBlank( dPriv
, & vmesa
->vbl_seq
,
517 vmesa
->vblank_flags
, & missed_target
);
518 if ( missed_target
) {
519 vmesa
->swap_missed_count
++;
520 (*dri_interface
->getUST
)( &vmesa
->swap_missed_ust
);
523 while (!viaCheckBreadcrumb(vmesa
, value
));
525 vmesa
->thrashing
= 0; /* reset flag on swap */
527 via_release_pending_textures( vmesa
);
532 static void viaDoPageFlipLocked(struct via_context
*vmesa
, GLuint offset
)
536 if (VIA_DEBUG
& DEBUG_2D
)
537 fprintf(stderr
, "%s %x\n", __FUNCTION__
, offset
);
539 if (!vmesa
->nDoneFirstFlip
) {
540 vmesa
->nDoneFirstFlip
= GL_TRUE
;
542 OUT_RING(HALCYON_HEADER2
);
543 OUT_RING(0x00fe0000);
544 OUT_RING(0x0000000e);
545 OUT_RING(0x0000000e);
550 OUT_RING( HALCYON_HEADER2
);
551 OUT_RING( 0x00fe0000 );
552 OUT_RING((HC_SubA_HFBBasL
<< 24) | (offset
& 0xFFFFF8) | 0x2);
553 OUT_RING((HC_SubA_HFBDrawFirst
<< 24) |
554 ((offset
& 0xFF000000) >> 24) | 0x0100);
557 vmesa
->pfCurrentOffset
= vmesa
->sarea
->pfCurrentOffset
= offset
;
559 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
562 void viaResetPageFlippingLocked(struct via_context
*vmesa
)
564 if (VIA_DEBUG
& DEBUG_2D
)
565 fprintf(stderr
, "%s\n", __FUNCTION__
);
567 viaDoPageFlipLocked( vmesa
, 0 );
569 if (vmesa
->front
.offset
!= 0) {
570 struct via_renderbuffer buffer_tmp
;
571 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
572 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
573 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
576 assert(vmesa
->front
.offset
== 0);
577 vmesa
->doPageFlip
= vmesa
->allowPageFlip
= 0;
582 * Copy the back buffer to the front buffer.
584 void viaCopyBuffer(const __DRIdrawablePrivate
*dPriv
)
586 struct via_context
*vmesa
=
587 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
589 if (VIA_DEBUG
& DEBUG_IOCTL
)
591 "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
595 vmesa
->lastBreadcrumbWrite
,
596 vmesa
->lastBreadcrumbRead
);
598 VIA_FLUSH_DMA(vmesa
);
600 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
601 vmesa
->lastBreadcrumbWrite
> 1)
602 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
-1);
604 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[1]);
606 LOCK_HARDWARE(vmesa
);
608 /* Catch and cleanup situation where we were pageflipping but have
611 if (dPriv
->numClipRects
&& vmesa
->sarea
->pfCurrentOffset
!= 0) {
612 viaResetPageFlippingLocked(vmesa
);
613 UNLOCK_HARDWARE(vmesa
);
617 viaDoSwapBuffers(vmesa
, dPriv
->pClipRects
, dPriv
->numClipRects
);
618 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
619 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
620 viaEmitBreadcrumbLocked(vmesa
);
621 UNLOCK_HARDWARE(vmesa
);
623 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
627 void viaPageFlip(const __DRIdrawablePrivate
*dPriv
)
629 struct via_context
*vmesa
=
630 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
631 struct via_renderbuffer buffer_tmp
;
633 VIA_FLUSH_DMA(vmesa
);
634 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
635 vmesa
->lastBreadcrumbWrite
> 1)
636 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
- 1);
638 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[0]);
640 LOCK_HARDWARE(vmesa
);
641 viaDoPageFlipLocked(vmesa
, vmesa
->back
.offset
);
642 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
643 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
644 viaEmitBreadcrumbLocked(vmesa
);
645 UNLOCK_HARDWARE(vmesa
);
647 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
650 /* KW: FIXME: When buffers are freed, could free frontbuffer by
653 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
654 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
655 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
661 #define VIA_CMDBUF_MAX_LAG 50000
663 static int fire_buffer(struct via_context
*vmesa
)
665 drm_via_cmdbuffer_t bufI
;
668 bufI
.buf
= (char *)vmesa
->dma
;
669 bufI
.size
= vmesa
->dmaLow
;
672 drm_via_cmdbuf_size_t bSiz
;
674 /* Do the CMDBUF_SIZE ioctl:
676 bSiz
.func
= VIA_CMDBUF_LAG
;
678 bSiz
.size
= VIA_CMDBUF_MAX_LAG
;
680 ret
= drmCommandWriteRead(vmesa
->driFd
, DRM_VIA_CMDBUF_SIZE
,
681 &bSiz
, sizeof(bSiz
));
682 } while (ret
== -EAGAIN
);
684 UNLOCK_HARDWARE(vmesa
);
685 fprintf(stderr
, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
691 /* Actually fire the buffer:
694 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_CMDBUFFER
,
695 &bufI
, sizeof(bufI
));
696 } while (ret
== -EAGAIN
);
698 UNLOCK_HARDWARE(vmesa
);
699 fprintf(stderr
, "%s: DRM_VIA_CMDBUFFER returned %d\n",
702 /* If this fails, the original code fell back to the PCI path.
708 /* Fall through to PCI handling?!?
710 viaWaitIdleLocked(vmesa
, GL_FALSE
);
713 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_PCICMD
, &bufI
, sizeof(bufI
));
715 UNLOCK_HARDWARE(vmesa
);
717 fprintf(stderr
, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__
, ret
);
725 /* Inserts the surface addresss and active cliprects one at a time
726 * into the head of the DMA buffer being flushed. Fires the buffer
729 static void via_emit_cliprect(struct via_context
*vmesa
,
732 struct via_renderbuffer
*buffer
= vmesa
->drawBuffer
;
733 GLuint
*vb
= (GLuint
*)(vmesa
->dma
+ vmesa
->dmaCliprectAddr
);
735 GLuint format
= (vmesa
->viaScreen
->bitsPerPixel
== 0x20
739 GLuint pitch
= buffer
->pitch
;
740 GLuint offset
= buffer
->orig
;
743 fprintf(stderr
, "emit cliprect for box %d,%d %d,%d\n",
744 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
747 vb
[1] = (HC_ParaType_NotTex
<< 16);
749 if (vmesa
->driDrawable
->w
== 0 || vmesa
->driDrawable
->h
== 0) {
750 vb
[2] = (HC_SubA_HClipTB
<< 24) | 0x0;
751 vb
[3] = (HC_SubA_HClipLR
<< 24) | 0x0;
754 vb
[2] = (HC_SubA_HClipTB
<< 24) | (b
->y1
<< 12) | b
->y2
;
755 vb
[3] = (HC_SubA_HClipLR
<< 24) | (b
->x1
<< 12) | b
->x2
;
758 vb
[4] = (HC_SubA_HDBBasL
<< 24) | (offset
& 0xFFFFFF);
759 vb
[5] = (HC_SubA_HDBBasH
<< 24) | ((offset
& 0xFF000000) >> 24);
761 vb
[6] = (HC_SubA_HSPXYOS
<< 24) | ((31-vmesa
->drawXoff
) << HC_HSPXOS_SHIFT
);
762 vb
[7] = (HC_SubA_HDBFM
<< 24) | HC_HDBLoc_Local
| format
| pitch
;
767 static int intersect_rect(drm_clip_rect_t
*out
,
774 fprintf(stderr
, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
775 a
->x1
, a
->y1
, a
->x2
, a
->y2
,
776 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
778 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
779 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
780 if (out
->x1
>= out
->x2
) return 0;
782 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
783 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
784 if (out
->y1
>= out
->y2
) return 0;
789 void viaFlushDmaLocked(struct via_context
*vmesa
, GLuint flags
)
794 if (VIA_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
795 fprintf(stderr
, "%s\n", __FUNCTION__
);
797 if (*(GLuint
*)vmesa
->driHwLock
!= (DRM_LOCK_HELD
|vmesa
->hHWContext
) &&
798 *(GLuint
*)vmesa
->driHwLock
!=
799 (DRM_LOCK_HELD
|DRM_LOCK_CONT
|vmesa
->hHWContext
)) {
800 fprintf(stderr
, "%s called without lock held\n", __FUNCTION__
);
804 if (vmesa
->dmaLow
== 0) {
808 assert(vmesa
->dmaLastPrim
== 0);
810 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
812 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
+ 8) {
813 fprintf(stderr
, "buffer overflow in Flush Prims = %d\n",vmesa
->dmaLow
);
817 switch (vmesa
->dmaLow
& 0x1F) {
819 BEGIN_RING_NOCHECK( 6 );
820 OUT_RING( HC_HEADER2
);
821 OUT_RING( (HC_ParaType_NotTex
<< 16) );
822 OUT_RING( HC_DUMMY
);
823 OUT_RING( HC_DUMMY
);
824 OUT_RING( HC_DUMMY
);
825 OUT_RING( HC_DUMMY
);
829 BEGIN_RING_NOCHECK( 4 );
830 OUT_RING( HC_HEADER2
);
831 OUT_RING( (HC_ParaType_NotTex
<< 16) );
832 OUT_RING( HC_DUMMY
);
833 OUT_RING( HC_DUMMY
);
837 BEGIN_RING_NOCHECK( 10 );
838 OUT_RING( HC_HEADER2
);
839 OUT_RING( (HC_ParaType_NotTex
<< 16) );
840 OUT_RING( HC_DUMMY
);
841 OUT_RING( HC_DUMMY
);
842 OUT_RING( HC_DUMMY
);
843 OUT_RING( HC_DUMMY
);
844 OUT_RING( HC_DUMMY
);
845 OUT_RING( HC_DUMMY
);
846 OUT_RING( HC_DUMMY
);
847 OUT_RING( HC_DUMMY
);
853 if (VIA_DEBUG
& DEBUG_IOCTL
)
854 fprintf(stderr
, "%s: unaligned value for vmesa->dmaLow: %x\n",
855 __FUNCTION__
, vmesa
->dmaLow
);
858 vmesa
->lastDma
= vmesa
->lastBreadcrumbWrite
;
860 if (VIA_DEBUG
& DEBUG_DMA
)
863 if (flags
& VIA_NO_CLIPRECTS
) {
864 if (0) fprintf(stderr
, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__
);
865 assert(vmesa
->dmaCliprectAddr
== ~0);
866 fire_buffer( vmesa
);
868 else if (vmesa
->dmaCliprectAddr
== ~0) {
869 /* Contains only state. Could just dump the packet?
871 if (0) fprintf(stderr
, "%s: no dmaCliprectAddr\n", __FUNCTION__
);
872 if (0) fire_buffer( vmesa
);
874 else if (vmesa
->numClipRects
) {
875 drm_clip_rect_t
*pbox
= vmesa
->pClipRects
;
877 for (i
= 0; i
< vmesa
->numClipRects
; i
++) {
880 b
.x1
= pbox
[i
].x1
- (vmesa
->drawX
+ vmesa
->drawXoff
);
881 b
.x2
= pbox
[i
].x2
- (vmesa
->drawX
+ vmesa
->drawXoff
);
882 b
.y1
= pbox
[i
].y1
- vmesa
->drawY
;
883 b
.y2
= pbox
[i
].y2
- vmesa
->drawY
;
885 if (vmesa
->scissor
&&
886 !intersect_rect(&b
, &b
, &vmesa
->scissorRect
))
889 b
.x1
+= vmesa
->drawXoff
;
890 b
.x2
+= vmesa
->drawXoff
;
892 via_emit_cliprect(vmesa
, &b
);
894 if (fire_buffer(vmesa
) != 0) {
900 if (0) fprintf(stderr
, "%s: no cliprects\n", __FUNCTION__
);
901 UNLOCK_HARDWARE(vmesa
);
903 LOCK_HARDWARE(vmesa
);
910 vmesa
->dmaCliprectAddr
= ~0;
911 vmesa
->newEmitState
= ~0;
914 void viaWrapPrimitive( struct via_context
*vmesa
)
916 GLenum renderPrimitive
= vmesa
->renderPrimitive
;
917 GLenum hwPrimitive
= vmesa
->hwPrimitive
;
919 if (VIA_DEBUG
& DEBUG_PRIMS
) fprintf(stderr
, "%s\n", __FUNCTION__
);
921 if (vmesa
->dmaLastPrim
)
922 viaFinishPrimitive( vmesa
);
926 if (renderPrimitive
!= GL_POLYGON
+ 1)
927 viaRasterPrimitive( vmesa
->glCtx
,
933 void viaFlushDma(struct via_context
*vmesa
)
936 assert(!vmesa
->dmaLastPrim
);
938 LOCK_HARDWARE(vmesa
);
939 viaFlushDmaLocked(vmesa
, 0);
940 UNLOCK_HARDWARE(vmesa
);
944 static void viaFlush(GLcontext
*ctx
)
946 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
947 VIA_FLUSH_DMA(vmesa
);
950 static void viaFinish(GLcontext
*ctx
)
952 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
953 VIA_FLUSH_DMA(vmesa
);
954 viaWaitIdle(vmesa
, GL_FALSE
);
957 static void viaClearStencil(GLcontext
*ctx
, int s
)
962 void viaInitIoctlFuncs(GLcontext
*ctx
)
964 ctx
->Driver
.Flush
= viaFlush
;
965 ctx
->Driver
.Clear
= viaClear
;
966 ctx
->Driver
.Finish
= viaFinish
;
967 ctx
->Driver
.ClearStencil
= viaClearStencil
;