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 cxFoo
, GLint cyFoo
, GLint cwFoo
, GLint chFoo
)
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) == 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
;
266 LOCK_HARDWARE(vmesa
);
268 /* get region after locking: */
269 cx
= ctx
->DrawBuffer
->_Xmin
;
270 cy
= ctx
->DrawBuffer
->_Ymin
;
271 cw
= ctx
->DrawBuffer
->_Xmax
- cx
;
272 ch
= ctx
->DrawBuffer
->_Ymax
- cy
;
274 /* flip top to bottom */
275 cy
= dPriv
->h
- cy
- ch
;
276 cx
+= vmesa
->drawX
+ vmesa
->drawXoff
;
280 drm_clip_rect_t
*b
= vmesa
->pClipRects
;
283 (drm_clip_rect_t
*)malloc(vmesa
->numClipRects
*
284 sizeof(drm_clip_rect_t
));
286 UNLOCK_HARDWARE(vmesa
);
290 for (; i
< vmesa
->numClipRects
; i
++) {
293 GLint w
= b
[i
].x2
- x
;
294 GLint h
= b
[i
].y2
- y
;
296 if (x
< cx
) w
-= cx
- x
, x
= cx
;
297 if (y
< cy
) h
-= cy
- y
, y
= cy
;
298 if (x
+ w
> cx
+ cw
) w
= cx
+ cw
- x
;
299 if (y
+ h
> cy
+ ch
) h
= cy
+ ch
- y
;
300 if (w
<= 0) continue;
301 if (h
<= 0) continue;
305 boxes
[nr
].x2
= x
+ w
;
306 boxes
[nr
].y2
= y
+ h
;
311 boxes
= vmesa
->pClipRects
;
312 nr
= vmesa
->numClipRects
;
315 if (flag
& VIA_FRONT
) {
316 viaFillBuffer(vmesa
, &vmesa
->front
, boxes
, nr
, vmesa
->ClearColor
,
320 if (flag
& VIA_BACK
) {
321 viaFillBuffer(vmesa
, &vmesa
->back
, boxes
, nr
, vmesa
->ClearColor
,
325 if (flag
& VIA_DEPTH
) {
326 viaFillBuffer(vmesa
, &vmesa
->depth
, boxes
, nr
, clear_depth
,
330 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
);
331 UNLOCK_HARDWARE(vmesa
);
338 _swrast_Clear(ctx
, mask
, 0, 0, 0, 0, 0);
344 static void viaDoSwapBuffers(struct via_context
*vmesa
,
348 GLuint bytePerPixel
= vmesa
->viaScreen
->bitsPerPixel
>> 3;
349 struct via_renderbuffer
*front
= &vmesa
->front
;
350 struct via_renderbuffer
*back
= &vmesa
->back
;
353 for (i
= 0; i
< nbox
; i
++, b
++) {
354 GLint x
= b
->x1
- vmesa
->drawX
;
355 GLint y
= b
->y1
- vmesa
->drawY
;
356 GLint w
= b
->x2
- b
->x1
;
357 GLint h
= b
->y2
- b
->y1
;
359 GLuint src
= back
->orig
+ y
* back
->pitch
+ x
* bytePerPixel
;
360 GLuint dest
= front
->orig
+ y
* front
->pitch
+ x
* bytePerPixel
;
367 VIA_BLIT_COPY
, 0, 0);
370 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* redundant */
374 static void viaEmitBreadcrumbLocked( struct via_context
*vmesa
)
376 struct via_renderbuffer
*buffer
= &vmesa
->breadcrumb
;
377 GLuint value
= vmesa
->lastBreadcrumbWrite
+ 1;
379 if (VIA_DEBUG
& DEBUG_IOCTL
)
380 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
382 assert(!vmesa
->dmaLow
);
386 buffer
->offset
, buffer
->pitch
,
387 buffer
->offset
, buffer
->pitch
,
389 VIA_BLIT_FILL
, value
, 0);
391 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
392 vmesa
->lastBreadcrumbWrite
= value
;
395 void viaEmitBreadcrumb( struct via_context
*vmesa
)
397 LOCK_HARDWARE(vmesa
);
399 viaFlushDmaLocked(vmesa
, 0);
401 viaEmitBreadcrumbLocked( vmesa
);
402 UNLOCK_HARDWARE(vmesa
);
405 static GLboolean
viaCheckIdle( struct via_context
*vmesa
)
407 if ((vmesa
->regEngineStatus
[0] & 0xFFFEFFFF) == 0x00020000) {
414 GLboolean
viaCheckBreadcrumb( struct via_context
*vmesa
, GLuint value
)
416 GLuint
*buf
= (GLuint
*)vmesa
->breadcrumb
.map
;
417 vmesa
->lastBreadcrumbRead
= *buf
;
419 if (VIA_DEBUG
& DEBUG_IOCTL
)
420 fprintf(stderr
, "%s %d < %d: %d\n", __FUNCTION__
, value
,
421 vmesa
->lastBreadcrumbRead
,
422 !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
));
424 return !VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbRead
);
427 static void viaWaitBreadcrumb( struct via_context
*vmesa
, GLuint value
)
429 if (VIA_DEBUG
& DEBUG_IOCTL
)
430 fprintf(stderr
, "%s %d\n", __FUNCTION__
, value
);
432 assert(!VIA_GEQ_WRAP(value
, vmesa
->lastBreadcrumbWrite
));
434 while (!viaCheckBreadcrumb( vmesa
, value
)) {
435 viaSwapOutWork( vmesa
);
436 via_release_pending_textures( vmesa
);
441 void viaWaitIdle( struct via_context
*vmesa
, GLboolean light
)
443 VIA_FLUSH_DMA(vmesa
);
445 if (VIA_DEBUG
& DEBUG_IOCTL
)
446 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
447 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
449 /* Need to emit a new breadcrumb?
451 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
452 LOCK_HARDWARE(vmesa
);
453 viaEmitBreadcrumbLocked( vmesa
);
454 UNLOCK_HARDWARE(vmesa
);
459 if (VIA_GEQ_WRAP(vmesa
->lastDma
, vmesa
->lastBreadcrumbRead
))
460 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
464 LOCK_HARDWARE(vmesa
);
465 while(!viaCheckIdle(vmesa
))
467 UNLOCK_HARDWARE(vmesa
);
468 via_release_pending_textures(vmesa
);
472 void viaWaitIdleLocked( struct via_context
*vmesa
, GLboolean light
)
475 viaFlushDmaLocked(vmesa
, 0);
477 if (VIA_DEBUG
& DEBUG_IOCTL
)
478 fprintf(stderr
, "%s lastDma %d lastBreadcrumbWrite %d\n",
479 __FUNCTION__
, vmesa
->lastDma
, vmesa
->lastBreadcrumbWrite
);
481 /* Need to emit a new breadcrumb?
483 if (vmesa
->lastDma
== vmesa
->lastBreadcrumbWrite
) {
484 viaEmitBreadcrumbLocked( vmesa
);
489 if (vmesa
->lastDma
>= vmesa
->lastBreadcrumbRead
)
490 viaWaitBreadcrumb( vmesa
, vmesa
->lastDma
);
494 while(!viaCheckIdle(vmesa
))
497 via_release_pending_textures(vmesa
);
502 /* Wait for command stream to be processed *and* the next vblank to
503 * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank,
504 * except that WAIT_IDLE() will spin the CPU polling, while this is
507 static void viaWaitIdleVBlank( const __DRIdrawablePrivate
*dPriv
,
508 struct via_context
*vmesa
,
511 GLboolean missed_target
;
513 VIA_FLUSH_DMA(vmesa
);
519 if (value
< vmesa
->lastBreadcrumbRead
||
521 viaSwapOutWork(vmesa
);
523 driWaitForVBlank( dPriv
, & vmesa
->vbl_seq
,
524 vmesa
->vblank_flags
, & missed_target
);
525 if ( missed_target
) {
526 vmesa
->swap_missed_count
++;
527 (*dri_interface
->getUST
)( &vmesa
->swap_missed_ust
);
530 while (!viaCheckBreadcrumb(vmesa
, value
));
532 vmesa
->thrashing
= 0; /* reset flag on swap */
534 via_release_pending_textures( vmesa
);
539 static void viaDoPageFlipLocked(struct via_context
*vmesa
, GLuint offset
)
543 if (VIA_DEBUG
& DEBUG_2D
)
544 fprintf(stderr
, "%s %x\n", __FUNCTION__
, offset
);
546 if (!vmesa
->nDoneFirstFlip
) {
547 vmesa
->nDoneFirstFlip
= GL_TRUE
;
549 OUT_RING(HALCYON_HEADER2
);
550 OUT_RING(0x00fe0000);
551 OUT_RING(0x0000000e);
552 OUT_RING(0x0000000e);
557 OUT_RING( HALCYON_HEADER2
);
558 OUT_RING( 0x00fe0000 );
559 OUT_RING((HC_SubA_HFBBasL
<< 24) | (offset
& 0xFFFFF8) | 0x2);
560 OUT_RING((HC_SubA_HFBDrawFirst
<< 24) |
561 ((offset
& 0xFF000000) >> 24) | 0x0100);
564 vmesa
->pfCurrentOffset
= vmesa
->sarea
->pfCurrentOffset
= offset
;
566 viaFlushDmaLocked(vmesa
, VIA_NO_CLIPRECTS
); /* often redundant */
569 void viaResetPageFlippingLocked(struct via_context
*vmesa
)
571 if (VIA_DEBUG
& DEBUG_2D
)
572 fprintf(stderr
, "%s\n", __FUNCTION__
);
574 viaDoPageFlipLocked( vmesa
, 0 );
576 if (vmesa
->front
.offset
!= 0) {
577 struct via_renderbuffer buffer_tmp
;
578 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
579 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
580 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
583 assert(vmesa
->front
.offset
== 0);
584 vmesa
->doPageFlip
= vmesa
->allowPageFlip
= 0;
589 * Copy the back buffer to the front buffer.
591 void viaCopyBuffer(const __DRIdrawablePrivate
*dPriv
)
593 struct via_context
*vmesa
=
594 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
596 if (VIA_DEBUG
& DEBUG_IOCTL
)
598 "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
602 vmesa
->lastBreadcrumbWrite
,
603 vmesa
->lastBreadcrumbRead
);
605 VIA_FLUSH_DMA(vmesa
);
607 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
608 vmesa
->lastBreadcrumbWrite
> 1)
609 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
-1);
611 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[1]);
613 LOCK_HARDWARE(vmesa
);
615 /* Catch and cleanup situation where we were pageflipping but have
618 if (dPriv
->numClipRects
&& vmesa
->sarea
->pfCurrentOffset
!= 0) {
619 viaResetPageFlippingLocked(vmesa
);
620 UNLOCK_HARDWARE(vmesa
);
624 viaDoSwapBuffers(vmesa
, dPriv
->pClipRects
, dPriv
->numClipRects
);
625 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
626 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
627 viaEmitBreadcrumbLocked(vmesa
);
628 UNLOCK_HARDWARE(vmesa
);
630 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
634 void viaPageFlip(const __DRIdrawablePrivate
*dPriv
)
636 struct via_context
*vmesa
=
637 (struct via_context
*)dPriv
->driContextPriv
->driverPrivate
;
638 struct via_renderbuffer buffer_tmp
;
640 VIA_FLUSH_DMA(vmesa
);
641 if (vmesa
->vblank_flags
== VBLANK_FLAG_SYNC
&&
642 vmesa
->lastBreadcrumbWrite
> 1)
643 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastBreadcrumbWrite
- 1);
645 viaWaitIdleVBlank(dPriv
, vmesa
, vmesa
->lastSwap
[0]);
647 LOCK_HARDWARE(vmesa
);
648 viaDoPageFlipLocked(vmesa
, vmesa
->back
.offset
);
649 vmesa
->lastSwap
[1] = vmesa
->lastSwap
[0];
650 vmesa
->lastSwap
[0] = vmesa
->lastBreadcrumbWrite
;
651 viaEmitBreadcrumbLocked(vmesa
);
652 UNLOCK_HARDWARE(vmesa
);
654 (*dri_interface
->getUST
)( &vmesa
->swap_ust
);
657 /* KW: FIXME: When buffers are freed, could free frontbuffer by
660 memcpy(&buffer_tmp
, &vmesa
->back
, sizeof(struct via_renderbuffer
));
661 memcpy(&vmesa
->back
, &vmesa
->front
, sizeof(struct via_renderbuffer
));
662 memcpy(&vmesa
->front
, &buffer_tmp
, sizeof(struct via_renderbuffer
));
668 #define VIA_CMDBUF_MAX_LAG 50000
670 static int fire_buffer(struct via_context
*vmesa
)
672 drm_via_cmdbuffer_t bufI
;
675 bufI
.buf
= (char *)vmesa
->dma
;
676 bufI
.size
= vmesa
->dmaLow
;
679 drm_via_cmdbuf_size_t bSiz
;
681 /* Do the CMDBUF_SIZE ioctl:
683 bSiz
.func
= VIA_CMDBUF_LAG
;
685 bSiz
.size
= VIA_CMDBUF_MAX_LAG
;
687 ret
= drmCommandWriteRead(vmesa
->driFd
, DRM_VIA_CMDBUF_SIZE
,
688 &bSiz
, sizeof(bSiz
));
689 } while (ret
== -EAGAIN
);
691 UNLOCK_HARDWARE(vmesa
);
692 fprintf(stderr
, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
698 /* Actually fire the buffer:
701 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_CMDBUFFER
,
702 &bufI
, sizeof(bufI
));
703 } while (ret
== -EAGAIN
);
705 UNLOCK_HARDWARE(vmesa
);
706 fprintf(stderr
, "%s: DRM_VIA_CMDBUFFER returned %d\n",
709 /* If this fails, the original code fell back to the PCI path.
715 /* Fall through to PCI handling?!?
717 viaWaitIdleLocked(vmesa
, GL_FALSE
);
720 ret
= drmCommandWrite(vmesa
->driFd
, DRM_VIA_PCICMD
, &bufI
, sizeof(bufI
));
722 UNLOCK_HARDWARE(vmesa
);
724 fprintf(stderr
, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__
, ret
);
732 /* Inserts the surface addresss and active cliprects one at a time
733 * into the head of the DMA buffer being flushed. Fires the buffer
736 static void via_emit_cliprect(struct via_context
*vmesa
,
739 struct via_renderbuffer
*buffer
= vmesa
->drawBuffer
;
740 GLuint
*vb
= (GLuint
*)(vmesa
->dma
+ vmesa
->dmaCliprectAddr
);
742 GLuint format
= (vmesa
->viaScreen
->bitsPerPixel
== 0x20
746 GLuint pitch
= buffer
->pitch
;
747 GLuint offset
= buffer
->orig
;
750 fprintf(stderr
, "emit cliprect for box %d,%d %d,%d\n",
751 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
754 vb
[1] = (HC_ParaType_NotTex
<< 16);
756 if (vmesa
->driDrawable
->w
== 0 || vmesa
->driDrawable
->h
== 0) {
757 vb
[2] = (HC_SubA_HClipTB
<< 24) | 0x0;
758 vb
[3] = (HC_SubA_HClipLR
<< 24) | 0x0;
761 vb
[2] = (HC_SubA_HClipTB
<< 24) | (b
->y1
<< 12) | b
->y2
;
762 vb
[3] = (HC_SubA_HClipLR
<< 24) | (b
->x1
<< 12) | b
->x2
;
765 vb
[4] = (HC_SubA_HDBBasL
<< 24) | (offset
& 0xFFFFFF);
766 vb
[5] = (HC_SubA_HDBBasH
<< 24) | ((offset
& 0xFF000000) >> 24);
768 vb
[6] = (HC_SubA_HSPXYOS
<< 24) | ((31-vmesa
->drawXoff
) << HC_HSPXOS_SHIFT
);
769 vb
[7] = (HC_SubA_HDBFM
<< 24) | HC_HDBLoc_Local
| format
| pitch
;
774 static int intersect_rect(drm_clip_rect_t
*out
,
781 fprintf(stderr
, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
782 a
->x1
, a
->y1
, a
->x2
, a
->y2
,
783 b
->x1
, b
->y1
, b
->x2
, b
->y2
);
785 if (b
->x1
> out
->x1
) out
->x1
= b
->x1
;
786 if (b
->x2
< out
->x2
) out
->x2
= b
->x2
;
787 if (out
->x1
>= out
->x2
) return 0;
789 if (b
->y1
> out
->y1
) out
->y1
= b
->y1
;
790 if (b
->y2
< out
->y2
) out
->y2
= b
->y2
;
791 if (out
->y1
>= out
->y2
) return 0;
796 void viaFlushDmaLocked(struct via_context
*vmesa
, GLuint flags
)
801 if (VIA_DEBUG
& (DEBUG_IOCTL
|DEBUG_DMA
))
802 fprintf(stderr
, "%s\n", __FUNCTION__
);
804 if (*(GLuint
*)vmesa
->driHwLock
!= (DRM_LOCK_HELD
|vmesa
->hHWContext
) &&
805 *(GLuint
*)vmesa
->driHwLock
!=
806 (DRM_LOCK_HELD
|DRM_LOCK_CONT
|vmesa
->hHWContext
)) {
807 fprintf(stderr
, "%s called without lock held\n", __FUNCTION__
);
811 if (vmesa
->dmaLow
== 0) {
815 assert(vmesa
->dmaLastPrim
== 0);
817 /* viaFinishPrimitive can add up to 8 bytes beyond VIA_DMA_HIGHWATER:
819 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
+ 8) {
820 fprintf(stderr
, "buffer overflow in Flush Prims = %d\n",vmesa
->dmaLow
);
824 switch (vmesa
->dmaLow
& 0x1F) {
826 BEGIN_RING_NOCHECK( 6 );
827 OUT_RING( HC_HEADER2
);
828 OUT_RING( (HC_ParaType_NotTex
<< 16) );
829 OUT_RING( HC_DUMMY
);
830 OUT_RING( HC_DUMMY
);
831 OUT_RING( HC_DUMMY
);
832 OUT_RING( HC_DUMMY
);
836 BEGIN_RING_NOCHECK( 4 );
837 OUT_RING( HC_HEADER2
);
838 OUT_RING( (HC_ParaType_NotTex
<< 16) );
839 OUT_RING( HC_DUMMY
);
840 OUT_RING( HC_DUMMY
);
844 BEGIN_RING_NOCHECK( 10 );
845 OUT_RING( HC_HEADER2
);
846 OUT_RING( (HC_ParaType_NotTex
<< 16) );
847 OUT_RING( HC_DUMMY
);
848 OUT_RING( HC_DUMMY
);
849 OUT_RING( HC_DUMMY
);
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
);
860 if (VIA_DEBUG
& DEBUG_IOCTL
)
861 fprintf(stderr
, "%s: unaligned value for vmesa->dmaLow: %x\n",
862 __FUNCTION__
, vmesa
->dmaLow
);
865 vmesa
->lastDma
= vmesa
->lastBreadcrumbWrite
;
867 if (VIA_DEBUG
& DEBUG_DMA
)
870 if (flags
& VIA_NO_CLIPRECTS
) {
871 if (0) fprintf(stderr
, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__
);
872 assert(vmesa
->dmaCliprectAddr
== ~0);
873 fire_buffer( vmesa
);
875 else if (vmesa
->dmaCliprectAddr
== ~0) {
876 /* Contains only state. Could just dump the packet?
878 if (0) fprintf(stderr
, "%s: no dmaCliprectAddr\n", __FUNCTION__
);
879 if (0) fire_buffer( vmesa
);
881 else if (vmesa
->numClipRects
) {
882 drm_clip_rect_t
*pbox
= vmesa
->pClipRects
;
884 for (i
= 0; i
< vmesa
->numClipRects
; i
++) {
887 b
.x1
= pbox
[i
].x1
- (vmesa
->drawX
+ vmesa
->drawXoff
);
888 b
.x2
= pbox
[i
].x2
- (vmesa
->drawX
+ vmesa
->drawXoff
);
889 b
.y1
= pbox
[i
].y1
- vmesa
->drawY
;
890 b
.y2
= pbox
[i
].y2
- vmesa
->drawY
;
892 if (vmesa
->scissor
&&
893 !intersect_rect(&b
, &b
, &vmesa
->scissorRect
))
896 b
.x1
+= vmesa
->drawXoff
;
897 b
.x2
+= vmesa
->drawXoff
;
899 via_emit_cliprect(vmesa
, &b
);
901 if (fire_buffer(vmesa
) != 0) {
907 if (0) fprintf(stderr
, "%s: no cliprects\n", __FUNCTION__
);
908 UNLOCK_HARDWARE(vmesa
);
910 LOCK_HARDWARE(vmesa
);
917 vmesa
->dmaCliprectAddr
= ~0;
918 vmesa
->newEmitState
= ~0;
921 void viaWrapPrimitive( struct via_context
*vmesa
)
923 GLenum renderPrimitive
= vmesa
->renderPrimitive
;
924 GLenum hwPrimitive
= vmesa
->hwPrimitive
;
926 if (VIA_DEBUG
& DEBUG_PRIMS
) fprintf(stderr
, "%s\n", __FUNCTION__
);
928 if (vmesa
->dmaLastPrim
)
929 viaFinishPrimitive( vmesa
);
933 if (renderPrimitive
!= GL_POLYGON
+ 1)
934 viaRasterPrimitive( vmesa
->glCtx
,
940 void viaFlushDma(struct via_context
*vmesa
)
943 assert(!vmesa
->dmaLastPrim
);
945 LOCK_HARDWARE(vmesa
);
946 viaFlushDmaLocked(vmesa
, 0);
947 UNLOCK_HARDWARE(vmesa
);
951 static void viaFlush(GLcontext
*ctx
)
953 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
954 VIA_FLUSH_DMA(vmesa
);
957 static void viaFinish(GLcontext
*ctx
)
959 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
960 VIA_FLUSH_DMA(vmesa
);
961 viaWaitIdle(vmesa
, GL_FALSE
);
964 static void viaClearStencil(GLcontext
*ctx
, int s
)
969 void viaInitIoctlFuncs(GLcontext
*ctx
)
971 ctx
->Driver
.Flush
= viaFlush
;
972 ctx
->Driver
.Clear
= viaClear
;
973 ctx
->Driver
.Finish
= viaFinish
;
974 ctx
->Driver
.ClearStencil
= viaClearStencil
;