* Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
-v * copy of this software and associated documentation files (the "Software"),
+ * copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sub license,
* and/or sell copies of the Software, and to permit persons to whom the
#include <stdio.h>
#include <unistd.h>
-#include "glheader.h"
-#include "mtypes.h"
-#include "macros.h"
-#include "dd.h"
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/dd.h"
#include "swrast/swrast.h"
-#include "mm.h"
+#include "main/mm.h"
#include "via_context.h"
+#include "via_tris.h"
#include "via_ioctl.h"
#include "via_state.h"
+#include "via_fb.h"
+#include "via_3d_reg.h"
#include "vblank.h"
#include "drm.h"
#define VIA_BLIT_FILL 0xF0
#define VIA_BLIT_SET 0xFF
-
-#define DEPTH_SCALE ((1 << 16) - 1)
+static void dump_dma( struct via_context *vmesa )
+{
+ GLuint i;
+ GLuint *data = (GLuint *)vmesa->dma;
+ for (i = 0; i < vmesa->dmaLow; i += 16) {
+ fprintf(stderr, "%04x: ", i);
+ fprintf(stderr, "%08x ", *data++);
+ fprintf(stderr, "%08x ", *data++);
+ fprintf(stderr, "%08x ", *data++);
+ fprintf(stderr, "%08x\n", *data++);
+ }
+ fprintf(stderr, "******************************************\n");
+}
-void viaCheckDma(viaContextPtr vmesa, GLuint bytes)
+
+
+void viaCheckDma(struct via_context *vmesa, GLuint bytes)
{
VIA_FINISH_PRIM( vmesa );
if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
- viaFlushPrims(vmesa);
+ viaFlushDma(vmesa);
}
}
-static void viaClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
- GLint cx, GLint cy, GLint cw, GLint ch)
+#define SetReg2DAGP(nReg, nData) do { \
+ OUT_RING( ((nReg) >> 2) | 0xF0000000 ); \
+ OUT_RING( nData ); \
+} while (0)
+
+
+static void viaBlit(struct via_context *vmesa, GLuint bpp,
+ GLuint srcBase, GLuint srcPitch,
+ GLuint dstBase, GLuint dstPitch,
+ GLuint w, GLuint h,
+ GLuint blitMode,
+ GLuint color, GLuint nMask )
{
- viaContextPtr vmesa = VIA_CONTEXT(ctx);
+
+ GLuint dwGEMode, srcX, dstX, cmd;
+ RING_VARS;
+
+ if (VIA_DEBUG & DEBUG_2D)
+ fprintf(stderr,
+ "%s bpp %d src %x/%x dst %x/%x w %d h %d "
+ " mode: %x color: 0x%08x mask 0x%08x\n",
+ __FUNCTION__, bpp, srcBase, srcPitch, dstBase,
+ dstPitch, w,h, blitMode, color, nMask);
+
+
+ if (!w || !h)
+ return;
+
+ switch (bpp) {
+ case 16:
+ dwGEMode = VIA_GEM_16bpp;
+ srcX = (srcBase & 0x1f) >> 1;
+ dstX = (dstBase & 0x1f) >> 1;
+ break;
+ case 32:
+ dwGEMode = VIA_GEM_32bpp;
+ srcX = (srcBase & 0x1f) >> 2;
+ dstX = (dstBase & 0x1f) >> 2;
+ break;
+ default:
+ return;
+ }
+
+ switch(blitMode) {
+ case VIA_BLIT_FILL:
+ cmd = VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
+ break;
+ case VIA_BLIT_COPY:
+ cmd = VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
+ break;
+ default:
+ return;
+ }
+
+ BEGIN_RING(22);
+ SetReg2DAGP( VIA_REG_GEMODE, dwGEMode);
+ SetReg2DAGP( VIA_REG_FGCOLOR, color);
+ SetReg2DAGP( 0x2C, nMask);
+ SetReg2DAGP( VIA_REG_SRCBASE, (srcBase & ~0x1f) >> 3);
+ SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~0x1f) >> 3);
+ SetReg2DAGP( VIA_REG_PITCH, VIA_PITCH_ENABLE |
+ (srcPitch >> 3) | ((dstPitch >> 3) << 16));
+ SetReg2DAGP( VIA_REG_SRCPOS, srcX);
+ SetReg2DAGP( VIA_REG_DSTPOS, dstX);
+ SetReg2DAGP( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)));
+ SetReg2DAGP( VIA_REG_GECMD, cmd);
+ SetReg2DAGP( 0x2C, 0x00000000);
+ ADVANCE_RING();
+}
+
+static void viaFillBuffer(struct via_context *vmesa,
+ struct via_renderbuffer *buffer,
+ drm_clip_rect_t *pbox,
+ int nboxes,
+ GLuint pixel,
+ GLuint mask)
+{
+ GLuint bytePerPixel = buffer->bpp >> 3;
+ GLuint i;
+
+ for (i = 0; i < nboxes ; i++) {
+ int x = pbox[i].x1 - buffer->drawX;
+ int y = pbox[i].y1 - buffer->drawY;
+ int w = pbox[i].x2 - pbox[i].x1;
+ int h = pbox[i].y2 - pbox[i].y1;
+
+ int offset = (buffer->offset +
+ y * buffer->pitch +
+ x * bytePerPixel);
+
+ viaBlit(vmesa,
+ buffer->bpp,
+ offset, buffer->pitch,
+ offset, buffer->pitch,
+ w, h,
+ VIA_BLIT_FILL, pixel, mask);
+ }
+}
+
+
+
+static void viaClear(GLcontext *ctx, GLbitfield mask)
+{
+ struct via_context *vmesa = VIA_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = vmesa->driDrawable;
- const GLuint colorMask = *((GLuint *)&ctx->Color.ColorMask);
+ struct via_renderbuffer *const vrb =
+ (struct via_renderbuffer *) dPriv->driverPrivate;
int flag = 0;
GLuint i = 0;
GLuint clear_depth_mask = 0xf << 28;
VIA_FLUSH_DMA(vmesa);
- if ((mask & DD_FRONT_LEFT_BIT) && colorMask == ~0) {
+ if (mask & BUFFER_BIT_FRONT_LEFT) {
flag |= VIA_FRONT;
- mask &= ~DD_FRONT_LEFT_BIT;
+ mask &= ~BUFFER_BIT_FRONT_LEFT;
}
- if ((mask & DD_BACK_LEFT_BIT) && colorMask == ~0) {
+ if (mask & BUFFER_BIT_BACK_LEFT) {
flag |= VIA_BACK;
- mask &= ~DD_BACK_LEFT_BIT;
+ mask &= ~BUFFER_BIT_BACK_LEFT;
}
- if (mask & DD_DEPTH_BIT) {
+ if (mask & BUFFER_BIT_DEPTH) {
flag |= VIA_DEPTH;
clear_depth = (GLuint)(ctx->Depth.Clear * vmesa->ClearDepth);
clear_depth_mask &= ~vmesa->depth_clear_mask;
- mask &= ~DD_DEPTH_BIT;
+ mask &= ~BUFFER_BIT_DEPTH;
}
- if (mask & DD_STENCIL_BIT) {
+ if (mask & BUFFER_BIT_STENCIL) {
if (vmesa->have_hw_stencil) {
- if (ctx->Stencil.WriteMask[0] == 0xff) {
+ if ((ctx->Stencil.WriteMask[0] & 0xff) == 0xff) {
flag |= VIA_DEPTH;
clear_depth &= ~0xff;
clear_depth |= (ctx->Stencil.Clear & 0xff);
clear_depth_mask &= ~vmesa->stencil_clear_mask;
- mask &= ~DD_STENCIL_BIT;
+ mask &= ~BUFFER_BIT_STENCIL;
}
else {
- fprintf(stderr, "XXX: Clear stencil writemask %x -- need triangles (or a ROP?)\n",
- ctx->Stencil.WriteMask[0]);
- /* Fixme - clear with triangles */
+ if (VIA_DEBUG & DEBUG_2D)
+ fprintf(stderr, "Clear stencil writemask %x\n",
+ ctx->Stencil.WriteMask[0]);
}
}
}
+
+ /* 16bpp doesn't support masked clears */
+ if (vmesa->viaScreen->bytesPerPixel == 2 &&
+ vmesa->ClearMask & 0xf0000000) {
+ if (flag & VIA_FRONT)
+ mask |= BUFFER_BIT_FRONT_LEFT;
+ if (flag & VIA_BACK)
+ mask |= BUFFER_BIT_BACK_LEFT;
+ flag &= ~(VIA_FRONT | VIA_BACK);
+ }
if (flag) {
+ drm_clip_rect_t *boxes, *tmp_boxes = 0;
+ int nr = 0;
+ GLint cx, cy, cw, ch;
+ GLboolean all;
+
LOCK_HARDWARE(vmesa);
+
+ /* get region after locking: */
+ cx = ctx->DrawBuffer->_Xmin;
+ cy = ctx->DrawBuffer->_Ymin;
+ cw = ctx->DrawBuffer->_Xmax - cx;
+ ch = ctx->DrawBuffer->_Ymax - cy;
+ all = (cw == ctx->DrawBuffer->Width && ch == ctx->DrawBuffer->Height);
+
/* flip top to bottom */
cy = dPriv->h - cy - ch;
- cx += vmesa->drawX;
- cy += vmesa->drawY;
+ cx += vrb->drawX;
+ cy += vrb->drawY;
- if (vmesa->numClipRects) {
- int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, vmesa->numClipRects);
- drm_clip_rect_t *box = vmesa->pClipRects;
- drm_clip_rect_t *b = vmesa->sarea->boxes;
- int n = 0;
-
- if (!all) {
- for (; i < nr; i++) {
- GLint x = box[i].x1;
- GLint y = box[i].y1;
- GLint w = box[i].x2 - x;
- GLint h = box[i].y2 - y;
-
- if (x < cx) w -= cx - x, x = cx;
- if (y < cy) h -= cy - y, y = cy;
- if (x + w > cx + cw) w = cx + cw - x;
- if (y + h > cy + ch) h = cy + ch - y;
- if (w <= 0) continue;
- if (h <= 0) continue;
-
- b->x1 = x;
- b->y1 = y;
- b->x2 = x + w;
- b->y2 = y + h;
- b++;
- n++;
- }
- }
- else {
- for (; i < nr; i++) {
- *b++ = *(drm_clip_rect_t *)&box[i];
- n++;
- }
+ if (!all) {
+ drm_clip_rect_t *b = vmesa->pClipRects;
+
+ boxes = tmp_boxes =
+ (drm_clip_rect_t *)malloc(vmesa->numClipRects *
+ sizeof(drm_clip_rect_t));
+ if (!boxes) {
+ UNLOCK_HARDWARE(vmesa);
+ return;
}
- vmesa->sarea->nbox = n;
+ for (; i < vmesa->numClipRects; i++) {
+ GLint x = b[i].x1;
+ GLint y = b[i].y1;
+ GLint w = b[i].x2 - x;
+ GLint h = b[i].y2 - y;
+
+ if (x < cx) w -= cx - x, x = cx;
+ if (y < cy) h -= cy - y, y = cy;
+ if (x + w > cx + cw) w = cx + cw - x;
+ if (y + h > cy + ch) h = cy + ch - y;
+ if (w <= 0) continue;
+ if (h <= 0) continue;
+
+ boxes[nr].x1 = x;
+ boxes[nr].y1 = y;
+ boxes[nr].x2 = x + w;
+ boxes[nr].y2 = y + h;
+ nr++;
+ }
+ }
+ else {
+ boxes = vmesa->pClipRects;
+ nr = vmesa->numClipRects;
}
if (flag & VIA_FRONT) {
- if (vmesa->drawType == GLX_PBUFFER_BIT)
- viaFillFrontPBuffer(vmesa);
- else
- viaFillFrontBuffer(vmesa);
+ viaFillBuffer(vmesa, &vmesa->front, boxes, nr, vmesa->ClearColor,
+ vmesa->ClearMask);
}
if (flag & VIA_BACK) {
- viaFillBackBuffer(vmesa);
+ viaFillBuffer(vmesa, &vmesa->back, boxes, nr, vmesa->ClearColor,
+ vmesa->ClearMask);
}
if (flag & VIA_DEPTH) {
- viaFillDepthBuffer(vmesa, clear_depth, clear_depth_mask);
+ viaFillBuffer(vmesa, &vmesa->depth, boxes, nr, clear_depth,
+ clear_depth_mask);
}
+ viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS);
UNLOCK_HARDWARE(vmesa);
+
+ if (tmp_boxes)
+ free(tmp_boxes);
}
if (mask)
- _swrast_Clear(ctx, mask, all, cx, cy, cw, ch);
- if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);
+ _swrast_Clear(ctx, mask);
}
-/*
- * Copy the back buffer to the front buffer.
- */
-void viaCopyBuffer(const __DRIdrawablePrivate *dPriv)
+
+
+
+static void viaDoSwapBuffers(struct via_context *vmesa,
+ drm_clip_rect_t *b,
+ GLuint nbox)
+{
+ GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
+ struct via_renderbuffer *front = &vmesa->front;
+ struct via_renderbuffer *back = &vmesa->back;
+ GLuint i;
+
+ for (i = 0; i < nbox; i++, b++) {
+ GLint x = b->x1 - back->drawX;
+ GLint y = b->y1 - back->drawY;
+ GLint w = b->x2 - b->x1;
+ GLint h = b->y2 - b->y1;
+
+ GLuint src = back->offset + y * back->pitch + x * bytePerPixel;
+ GLuint dest = front->offset + y * front->pitch + x * bytePerPixel;
+
+ viaBlit(vmesa,
+ bytePerPixel << 3,
+ src, back->pitch,
+ dest, front->pitch,
+ w, h,
+ VIA_BLIT_COPY, 0, 0);
+ }
+
+ viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* redundant */
+}
+
+
+static void viaEmitBreadcrumbLocked( struct via_context *vmesa )
{
- viaContextPtr vmesa;
- drm_clip_rect_t *pbox;
- int nbox, i;
- GLboolean missed_target;
- int64_t ust;
+ struct via_renderbuffer *buffer = &vmesa->breadcrumb;
+ GLuint value = vmesa->lastBreadcrumbWrite + 1;
- if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, value);
- vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
-
+ assert(!vmesa->dmaLow);
+
+ viaBlit(vmesa,
+ buffer->bpp,
+ buffer->offset, buffer->pitch,
+ buffer->offset, buffer->pitch,
+ 1, 1,
+ VIA_BLIT_FILL, value, 0);
+
+ viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */
+ vmesa->lastBreadcrumbWrite = value;
+}
+
+void viaEmitBreadcrumb( struct via_context *vmesa )
+{
+ LOCK_HARDWARE(vmesa);
+ if (vmesa->dmaLow)
+ viaFlushDmaLocked(vmesa, 0);
+
+ viaEmitBreadcrumbLocked( vmesa );
+ UNLOCK_HARDWARE(vmesa);
+}
+
+static GLboolean viaCheckIdle( struct via_context *vmesa )
+{
+ if ((vmesa->regEngineStatus[0] & 0xFFFEFFFF) == 0x00020000) {
+ return GL_TRUE;
+ }
+ return GL_FALSE;
+}
+
+
+GLboolean viaCheckBreadcrumb( struct via_context *vmesa, GLuint value )
+{
+ GLuint *buf = (GLuint *)vmesa->breadcrumb.map;
+ vmesa->lastBreadcrumbRead = *buf;
+
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d < %d: %d\n", __FUNCTION__, value,
+ vmesa->lastBreadcrumbRead,
+ !VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbRead));
+
+ return !VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbRead);
+}
+
+static void viaWaitBreadcrumb( struct via_context *vmesa, GLuint value )
+{
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s %d\n", __FUNCTION__, value);
+
+ assert(!VIA_GEQ_WRAP(value, vmesa->lastBreadcrumbWrite));
+
+ while (!viaCheckBreadcrumb( vmesa, value )) {
+ viaSwapOutWork( vmesa );
+ via_release_pending_textures( vmesa );
+ }
+}
+
+
+void viaWaitIdle( struct via_context *vmesa, GLboolean light )
+{
VIA_FLUSH_DMA(vmesa);
- driWaitForVBlank( dPriv, & vmesa->vbl_seq, vmesa->vblank_flags, & missed_target );
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s lastDma %d lastBreadcrumbWrite %d\n",
+ __FUNCTION__, vmesa->lastDma, vmesa->lastBreadcrumbWrite);
+
+ /* Need to emit a new breadcrumb?
+ */
+ if (vmesa->lastDma == vmesa->lastBreadcrumbWrite) {
+ LOCK_HARDWARE(vmesa);
+ viaEmitBreadcrumbLocked( vmesa );
+ UNLOCK_HARDWARE(vmesa);
+ }
+
+ /* Need to wait?
+ */
+ if (VIA_GEQ_WRAP(vmesa->lastDma, vmesa->lastBreadcrumbRead))
+ viaWaitBreadcrumb( vmesa, vmesa->lastDma );
+
+ if (light) return;
+
LOCK_HARDWARE(vmesa);
-
- pbox = vmesa->pClipRects;
- nbox = vmesa->numClipRects;
+ while(!viaCheckIdle(vmesa))
+ ;
+ UNLOCK_HARDWARE(vmesa);
+ via_release_pending_textures(vmesa);
+}
- if (VIA_DEBUG) fprintf(stderr, "%s %d cliprects (%d)\n",
- __FUNCTION__, nbox, vmesa->drawType);
-
-
- if (vmesa->drawType == GLX_PBUFFER_BIT) {
- viaDoSwapPBuffers(vmesa);
- if (VIA_DEBUG) fprintf(stderr, "%s SwapPBuffers\n", __FUNCTION__);
+
+void viaWaitIdleLocked( struct via_context *vmesa, GLboolean light )
+{
+ if (vmesa->dmaLow)
+ viaFlushDmaLocked(vmesa, 0);
+
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr, "%s lastDma %d lastBreadcrumbWrite %d\n",
+ __FUNCTION__, vmesa->lastDma, vmesa->lastBreadcrumbWrite);
+
+ /* Need to emit a new breadcrumb?
+ */
+ if (vmesa->lastDma == vmesa->lastBreadcrumbWrite) {
+ viaEmitBreadcrumbLocked( vmesa );
}
- else {
- for (i = 0; i < nbox; ) {
- int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, dPriv->numClipRects);
- drm_clip_rect_t *b = (drm_clip_rect_t *)vmesa->sarea->boxes;
- vmesa->sarea->nbox = nr - i;
+ /* Need to wait?
+ */
+ if (vmesa->lastDma >= vmesa->lastBreadcrumbRead)
+ viaWaitBreadcrumb( vmesa, vmesa->lastDma );
+
+ if (light) return;
+
+ while(!viaCheckIdle(vmesa))
+ ;
+
+ via_release_pending_textures(vmesa);
+}
+
+
+
+/* Wait for command stream to be processed *and* the next vblank to
+ * occur. Equivalent to calling WAIT_IDLE() and then WaitVBlank,
+ * except that WAIT_IDLE() will spin the CPU polling, while this is
+ * IRQ driven.
+ */
+static void viaWaitIdleVBlank( __DRIdrawablePrivate *dPriv,
+ struct via_context *vmesa,
+ GLuint value )
+{
+ GLboolean missed_target;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+ VIA_FLUSH_DMA(vmesa);
- for (; i < nr; i++)
- *b++ = pbox[i];
- viaDoSwapBuffers(vmesa);
- if (VIA_DEBUG) fprintf(stderr, "%s SwapBuffers\n", __FUNCTION__);
+ if (!value)
+ return;
+
+ do {
+ if (value < vmesa->lastBreadcrumbRead ||
+ vmesa->thrashing)
+ viaSwapOutWork(vmesa);
+
+ driWaitForVBlank( dPriv, & missed_target );
+ if ( missed_target ) {
+ vmesa->swap_missed_count++;
+ (*psp->systemTime->getUST)( &vmesa->swap_missed_ust );
}
+ }
+ while (!viaCheckBreadcrumb(vmesa, value));
+
+ vmesa->thrashing = 0; /* reset flag on swap */
+ vmesa->swap_count++;
+ via_release_pending_textures( vmesa );
+}
+
+
+
+static void viaDoPageFlipLocked(struct via_context *vmesa, GLuint offset)
+{
+ RING_VARS;
+
+ if (VIA_DEBUG & DEBUG_2D)
+ fprintf(stderr, "%s %x\n", __FUNCTION__, offset);
+
+ if (!vmesa->nDoneFirstFlip) {
+ vmesa->nDoneFirstFlip = GL_TRUE;
+ BEGIN_RING(4);
+ OUT_RING(HALCYON_HEADER2);
+ OUT_RING(0x00fe0000);
+ OUT_RING(0x0000000e);
+ OUT_RING(0x0000000e);
+ ADVANCE_RING();
}
- UNLOCK_HARDWARE(vmesa);
- vmesa->swap_count++;
- (*vmesa->get_ust)( & ust );
- if ( missed_target ) {
- vmesa->swap_missed_count++;
- vmesa->swap_missed_ust = ust - vmesa->swap_ust;
+ BEGIN_RING(4);
+ OUT_RING( HALCYON_HEADER2 );
+ OUT_RING( 0x00fe0000 );
+ OUT_RING((HC_SubA_HFBBasL << 24) | (offset & 0xFFFFF8) | 0x2);
+ OUT_RING((HC_SubA_HFBDrawFirst << 24) |
+ ((offset & 0xFF000000) >> 24) | 0x0100);
+ ADVANCE_RING();
+
+ vmesa->pfCurrentOffset = vmesa->sarea->pfCurrentOffset = offset;
+
+ viaFlushDmaLocked(vmesa, VIA_NO_CLIPRECTS); /* often redundant */
+}
+
+void viaResetPageFlippingLocked(struct via_context *vmesa)
+{
+ if (VIA_DEBUG & DEBUG_2D)
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
+ viaDoPageFlipLocked( vmesa, 0 );
+
+ if (vmesa->front.offset != 0) {
+ struct via_renderbuffer buffer_tmp;
+ memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer));
+ memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer));
+ memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer));
}
-
- vmesa->swap_ust = ust;
- if (VIA_DEBUG) fprintf(stderr, "%s out\n", __FUNCTION__);
+ assert(vmesa->front.offset == 0);
+ vmesa->doPageFlip = vmesa->allowPageFlip = 0;
}
+
/*
- * XXX implement when full-screen extension is done.
+ * Copy the back buffer to the front buffer.
*/
-void viaPageFlip(const __DRIdrawablePrivate *dPriv)
+void viaCopyBuffer(__DRIdrawablePrivate *dPriv)
{
- /*=* John Sheng [2003.5.31] flip *=*/
- viaContextPtr vmesa = (viaContextPtr)dPriv->driContextPriv->driverPrivate;
- GLcontext *ctx = vmesa->glCtx;
- GLuint nBackBase;
- viaBuffer buffer_tmp;
- GLboolean missed_target;
- int retcode;
+ struct via_context *vmesa =
+ (struct via_context *)dPriv->driContextPriv->driverPrivate;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+ if (VIA_DEBUG & DEBUG_IOCTL)
+ fprintf(stderr,
+ "%s: lastSwap[1] %d lastSwap[0] %d lastWrite %d lastRead %d\n",
+ __FUNCTION__,
+ vmesa->lastSwap[1],
+ vmesa->lastSwap[0],
+ vmesa->lastBreadcrumbWrite,
+ vmesa->lastBreadcrumbRead);
- if (VIA_DEBUG) fprintf(stderr, "%s - in\n", __FUNCTION__);
- assert(dPriv);
- assert(dPriv->driContextPriv);
- assert(dPriv->driContextPriv->driverPrivate);
+ VIA_FLUSH_DMA(vmesa);
+ if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
+ vmesa->lastBreadcrumbWrite > 1)
+ viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite-1);
+ else
+ viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[1]);
- VIA_FLUSH_DMA(vmesa);
+ LOCK_HARDWARE(vmesa);
- /* Now wait for the vblank:
- */
- retcode = driWaitForVBlank( dPriv, &vmesa->vbl_seq,
- vmesa->vblank_flags, &missed_target );
- if ( missed_target ) {
- vmesa->swap_missed_count++;
- (void) (*vmesa->get_ust)( &vmesa->swap_missed_ust );
- }
+ /* Catch and cleanup situation where we were pageflipping but have
+ * stopped.
+ */
+ if (dPriv->numClipRects && vmesa->sarea->pfCurrentOffset != 0) {
+ viaResetPageFlippingLocked(vmesa);
+ UNLOCK_HARDWARE(vmesa);
+ return;
+ }
- LOCK_HARDWARE(vmesa);
+ viaDoSwapBuffers(vmesa, dPriv->pClipRects, dPriv->numClipRects);
+ vmesa->lastSwap[1] = vmesa->lastSwap[0];
+ vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite;
+ viaEmitBreadcrumbLocked(vmesa);
+ UNLOCK_HARDWARE(vmesa);
- {
- RING_VARS;
-
- if (!vmesa->nDoneFirstFlip) {
- vmesa->nDoneFirstFlip = GL_FALSE; /* XXX: FIXME LATER!!! */
- BEGIN_RING(4);
- OUT_RING(HALCYON_HEADER2);
- OUT_RING(0x00fe0000);
- OUT_RING(0x0000000e);
- OUT_RING(0x0000000e);
- ADVANCE_RING();
- }
- nBackBase = (vmesa->back.offset );
-
- BEGIN_RING(4);
- OUT_RING( HALCYON_HEADER2 );
- OUT_RING( 0x00fe0000 );
- OUT_RING((HC_SubA_HFBBasL << 24) | (nBackBase & 0xFFFFF8) | 0x2);
- OUT_RING((HC_SubA_HFBDrawFirst << 24) |
- ((nBackBase & 0xFF000000) >> 24) | 0x0100);
- ADVANCE_RING();
-
- viaFlushPrimsLocked(vmesa);
- }
-
+ (*psp->systemTime->getUST)( &vmesa->swap_ust );
+}
+
+
+void viaPageFlip(__DRIdrawablePrivate *dPriv)
+{
+ struct via_context *vmesa =
+ (struct via_context *)dPriv->driContextPriv->driverPrivate;
+ struct via_renderbuffer buffer_tmp;
+ __DRIscreenPrivate *psp = dPriv->driScreenPriv;
+
+ VIA_FLUSH_DMA(vmesa);
+ if (dPriv->vblFlags == VBLANK_FLAG_SYNC &&
+ vmesa->lastBreadcrumbWrite > 1)
+ viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastBreadcrumbWrite - 1);
+ else
+ viaWaitIdleVBlank(dPriv, vmesa, vmesa->lastSwap[0]);
+
+ LOCK_HARDWARE(vmesa);
+ viaDoPageFlipLocked(vmesa, vmesa->back.offset);
+ vmesa->lastSwap[1] = vmesa->lastSwap[0];
+ vmesa->lastSwap[0] = vmesa->lastBreadcrumbWrite;
+ viaEmitBreadcrumbLocked(vmesa);
UNLOCK_HARDWARE(vmesa);
- vmesa->swap_count++;
- (void) (*vmesa->get_ust)( &vmesa->swap_ust );
-
- memcpy(&buffer_tmp, &vmesa->back, sizeof(viaBuffer));
- memcpy(&vmesa->back, &vmesa->front, sizeof(viaBuffer));
- memcpy(&vmesa->front, &buffer_tmp, sizeof(viaBuffer));
-
- /* KW: BOGUS BOGUS BOGUS: The first time an app calls glDrawBuffer
- * while pageflipping, this will blow up: FIXME
+ (*psp->systemTime->getUST)( &vmesa->swap_ust );
+
+
+ /* KW: FIXME: When buffers are freed, could free frontbuffer by
+ * accident:
*/
- if(vmesa->currentPage) {
- vmesa->currentPage = 0;
- if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
- ctx->Driver.DrawBuffer(ctx, GL_BACK);
- }
- else {
- ctx->Driver.DrawBuffer(ctx, GL_FRONT);
- }
- }
- else {
- vmesa->currentPage = 1;
- if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
- ctx->Driver.DrawBuffer(ctx, GL_BACK);
- }
- else {
- ctx->Driver.DrawBuffer(ctx, GL_FRONT);
- }
- }
- if (VIA_DEBUG) fprintf(stderr, "%s - out\n", __FUNCTION__);
+ memcpy(&buffer_tmp, &vmesa->back, sizeof(struct via_renderbuffer));
+ memcpy(&vmesa->back, &vmesa->front, sizeof(struct via_renderbuffer));
+ memcpy(&vmesa->front, &buffer_tmp, sizeof(struct via_renderbuffer));
}
#define VIA_CMDBUF_MAX_LAG 50000
-static int fire_buffer(viaContextPtr vmesa, drm_via_flush_sys_t *buf)
+static int fire_buffer(struct via_context *vmesa)
{
- drmVIACommandBuffer bufI;
+ drm_via_cmdbuffer_t bufI;
int ret;
- bufI.buf = (char *) (buf->index + buf->offset);
- bufI.size = buf->size;
+ bufI.buf = (char *)vmesa->dma;
+ bufI.size = vmesa->dmaLow;
if (vmesa->useAgp) {
- drmVIACmdBufSize bSiz;
+ drm_via_cmdbuf_size_t bSiz;
/* Do the CMDBUF_SIZE ioctl:
*/
&bSiz, sizeof(bSiz));
} while (ret == -EAGAIN);
if (ret) {
- fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n", __FUNCTION__, ret);
+ UNLOCK_HARDWARE(vmesa);
+ fprintf(stderr, "%s: DRM_VIA_CMDBUF_SIZE returned %d\n",
+ __FUNCTION__, ret);
abort();
return ret;
}
- /* Acutally fire the buffer:
+ /* Actually fire the buffer:
*/
do {
ret = drmCommandWrite(vmesa->driFd, DRM_VIA_CMDBUFFER,
&bufI, sizeof(bufI));
} while (ret == -EAGAIN);
if (ret) {
- fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n", __FUNCTION__, ret);
+ UNLOCK_HARDWARE(vmesa);
+ fprintf(stderr, "%s: DRM_VIA_CMDBUFFER returned %d\n",
+ __FUNCTION__, ret);
abort();
/* If this fails, the original code fell back to the PCI path.
*/
/* Fall through to PCI handling?!?
*/
- WAIT_IDLE(vmesa);
+ viaWaitIdleLocked(vmesa, GL_FALSE);
}
ret = drmCommandWrite(vmesa->driFd, DRM_VIA_PCICMD, &bufI, sizeof(bufI));
if (ret) {
- fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);
+ UNLOCK_HARDWARE(vmesa);
+ dump_dma(vmesa);
+ fprintf(stderr, "%s: DRM_VIA_PCICMD returned %d\n", __FUNCTION__, ret);
abort();
}
* into the head of the DMA buffer being flushed. Fires the buffer
* for each cliprect.
*/
-static int via_flush_sys(viaContextPtr vmesa, drm_via_flush_sys_t* buf)
+static void via_emit_cliprect(struct via_context *vmesa,
+ drm_clip_rect_t *b)
{
- GLuint *vb = (GLuint *)vmesa->dmaAddr;
+ struct via_renderbuffer *buffer = vmesa->drawBuffer;
+ GLuint *vb = (GLuint *)(vmesa->dma + vmesa->dmaCliprectAddr);
+
GLuint format = (vmesa->viaScreen->bitsPerPixel == 0x20
? HC_HDBFM_ARGB8888
: HC_HDBFM_RGB565);
- if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
- GLuint offset = vmesa->back.offset;
- GLuint pitch = vmesa->back.pitch;
+ GLuint pitch = buffer->pitch;
+ GLuint offset = buffer->offset;
- vb[0] = HC_HEADER2;
- vb[1] = HC_ParaType_NotTex << 16;
-
- if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
- vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
- vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
- }
- else {
- vb[2] = (HC_SubA_HClipTB << 24) | vmesa->driDrawable->h;
- vb[3] = (HC_SubA_HClipLR << 24) | vmesa->driDrawable->w;
- }
-
- vb[4] = ((HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF));
- vb[5] = ((HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000)) >> 24);
- vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
- vb[7] = 0xcccccccc;
+ if (0)
+ fprintf(stderr, "emit cliprect for box %d,%d %d,%d\n",
+ b->x1, b->y1, b->x2, b->y2);
- return fire_buffer( vmesa, buf );
+ vb[0] = HC_HEADER2;
+ vb[1] = (HC_ParaType_NotTex << 16);
+
+ if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
+ vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
+ vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
}
else {
- GLuint i, ret;
- drm_clip_rect_t *b = vmesa->sarea->boxes;
-
- for (i = 0; i < vmesa->sarea->nbox; i++, b++) {
- GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
- GLuint pitch = vmesa->front.pitch;
- GLuint offset = (vmesa->viaScreen->fbOffset + (vmesa->drawY * pitch + vmesa->drawX * bytePerPixel)) & ~0x1f;
-
- GLuint clipL = b->x1 + vmesa->drawXoff;
- GLuint clipR = b->x2 + vmesa->drawXoff;
- GLuint clipT = b->y1;
- GLuint clipB = b->y2;
-
- vb[0] = HC_HEADER2;
- vb[1] = (HC_ParaType_NotTex << 16);
-
- if (vmesa->driDrawable->w == 0 || vmesa->driDrawable->h == 0) {
- vb[2] = (HC_SubA_HClipTB << 24) | 0x0;
- vb[3] = (HC_SubA_HClipLR << 24) | 0x0;
- }
- else {
- vb[2] = (HC_SubA_HClipTB << 24) | (clipT << 12) | clipB;
- vb[3] = (HC_SubA_HClipLR << 24) | (clipL << 12) | clipR;
- }
-
- vb[4] = ((HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF));
- vb[5] = ((HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000)) >> 24);
- vb[6] = ((HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch);
- vb[7] = 0xcccccccc;
-
- ret = fire_buffer( vmesa, buf );
- if (ret)
- return ret;
- }
+ vb[2] = (HC_SubA_HClipTB << 24) | (b->y1 << 12) | b->y2;
+ vb[3] = (HC_SubA_HClipLR << 24) | (b->x1 << 12) | b->x2;
}
+
+ vb[4] = (HC_SubA_HDBBasL << 24) | (offset & 0xFFFFFF);
+ vb[5] = (HC_SubA_HDBBasH << 24) | ((offset & 0xFF000000) >> 24);
- return 0;
+ vb[6] = (HC_SubA_HSPXYOS << 24);
+ vb[7] = (HC_SubA_HDBFM << 24) | HC_HDBLoc_Local | format | pitch;
}
drm_clip_rect_t *b)
{
*out = *a;
+
+ if (0)
+ fprintf(stderr, "intersect %d,%d %d,%d and %d,%d %d,%d\n",
+ a->x1, a->y1, a->x2, a->y2,
+ b->x1, b->y1, b->x2, b->y2);
if (b->x1 > out->x1) out->x1 = b->x1;
if (b->x2 < out->x2) out->x2 = b->x2;
return 1;
}
-void viaFlushPrimsLocked(viaContextPtr vmesa)
+void viaFlushDmaLocked(struct via_context *vmesa, GLuint flags)
{
- drm_clip_rect_t *pbox = (drm_clip_rect_t *)vmesa->pClipRects;
- int nbox = vmesa->numClipRects;
- drm_via_sarea_t *sarea = vmesa->sarea;
- drm_via_flush_sys_t sysCmd;
int i;
RING_VARS;
+ if (VIA_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
+ fprintf(stderr, "%s\n", __FUNCTION__);
+
if (*(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|vmesa->hHWContext) &&
- *(GLuint *)vmesa->driHwLock != (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
+ *(GLuint *)vmesa->driHwLock !=
+ (DRM_LOCK_HELD|DRM_LOCK_CONT|vmesa->hHWContext)) {
fprintf(stderr, "%s called without lock held\n", __FUNCTION__);
abort();
}
- if (vmesa->dmaLow == DMA_OFFSET) {
+ if (vmesa->dmaLow == 0) {
return;
}
case 0:
break;
default:
- if (VIA_DEBUG)
+ if (VIA_DEBUG & DEBUG_IOCTL)
fprintf(stderr, "%s: unaligned value for vmesa->dmaLow: %x\n",
__FUNCTION__, vmesa->dmaLow);
-/* abort(); */
-/* goto done; */
}
-/* assert((vmesa->dmaLow & 0x1f) == 0); */
+ vmesa->lastDma = vmesa->lastBreadcrumbWrite;
- sysCmd.offset = 0x0;
- sysCmd.size = vmesa->dmaLow;
- sysCmd.index = (GLuint)vmesa->dma;
- sysCmd.discard = 0;
-
- if (!nbox) {
- sysCmd.size = 0; /* KW: FIXME bogus if we ever start emitting partial state */
- sarea->nbox = 0;
- sysCmd.discard = 1;
- via_flush_sys(vmesa, &sysCmd);
+ if (VIA_DEBUG & DEBUG_DMA)
+ dump_dma( vmesa );
+
+ if (flags & VIA_NO_CLIPRECTS) {
+ if (0) fprintf(stderr, "%s VIA_NO_CLIPRECTS\n", __FUNCTION__);
+ assert(vmesa->dmaCliprectAddr == ~0);
+ fire_buffer( vmesa );
}
- else {
- for (i = 0; i < nbox; ) {
- int nr = MIN2(i + VIA_NR_SAREA_CLIPRECTS, nbox);
- drm_clip_rect_t *b = sarea->boxes;
-
- if (vmesa->glCtx->Scissor.Enabled) {
- sarea->nbox = 0;
-
- for (; i < nr; i++) {
- b->x1 = pbox[i].x1 - vmesa->drawX;
- b->y1 = pbox[i].y1 - vmesa->drawY;
- b->x2 = pbox[i].x2 - vmesa->drawX;
- b->y2 = pbox[i].y2 - vmesa->drawY;
- if (intersect_rect(b, b, &vmesa->scissorRect)) {
- sarea->nbox++;
- b++;
- }
- }
- if (!sarea->nbox) {
- if (nr < nbox) continue;
- sysCmd.size = 0;
- }
- }
- else {
- sarea->nbox = nr - i;
- for (; i < nr; i++, b++) {
- b->x1 = pbox[i].x1 - vmesa->drawX;
- b->y1 = pbox[i].y1 - vmesa->drawY;
- b->x2 = pbox[i].x2 - vmesa->drawX;
- b->y2 = pbox[i].y2 - vmesa->drawY;
- }
- }
+ else if (vmesa->dmaCliprectAddr == ~0) {
+ /* Contains only state. Could just dump the packet?
+ */
+ if (0) fprintf(stderr, "%s: no dmaCliprectAddr\n", __FUNCTION__);
+ if (0) fire_buffer( vmesa );
+ }
+ else if (vmesa->numClipRects) {
+ drm_clip_rect_t *pbox = vmesa->pClipRects;
+ __DRIdrawablePrivate *dPriv = vmesa->driDrawable;
+ struct via_renderbuffer *const vrb =
+ (struct via_renderbuffer *) dPriv->driverPrivate;
- if (nr == nbox) {
- sysCmd.discard = 1;
- }
+ for (i = 0; i < vmesa->numClipRects; i++) {
+ drm_clip_rect_t b;
- via_flush_sys(vmesa, &sysCmd);
- }
- }
+ b.x1 = pbox[i].x1;
+ b.x2 = pbox[i].x2;
+ b.y1 = pbox[i].y1;
+ b.y2 = pbox[i].y2;
+
+ if (vmesa->scissor &&
+ !intersect_rect(&b, &b, &vmesa->scissorRect))
+ continue;
- if (VIA_DEBUG) {
- GLuint i;
- GLuint *data = (GLuint *)vmesa->dmaAddr;
- for (i = 0; i < vmesa->dmaLow; i += 16) {
- fprintf(stderr, "%04x: ", i);
- fprintf(stderr, "%08x ", *data++);
- fprintf(stderr, "%08x ", *data++);
- fprintf(stderr, "%08x ", *data++);
- fprintf(stderr, "%08x\n", *data++);
+ via_emit_cliprect(vmesa, &b);
+
+ if (fire_buffer(vmesa) != 0) {
+ dump_dma( vmesa );
+ goto done;
+ }
}
- fprintf(stderr, "******************************************\n");
- }
+ } else {
+ if (0) fprintf(stderr, "%s: no cliprects\n", __FUNCTION__);
+ UNLOCK_HARDWARE(vmesa);
+ sched_yield();
+ LOCK_HARDWARE(vmesa);
+ }
done:
/* Reset vmesa vars:
*/
- vmesa->dmaLow = DMA_OFFSET;
- vmesa->dmaAddr = (unsigned char *)vmesa->dma;
+ vmesa->dmaLow = 0;
+ vmesa->dmaCliprectAddr = ~0;
+ vmesa->newEmitState = ~0;
}
-void viaFlushPrims(viaContextPtr vmesa)
+void viaWrapPrimitive( struct via_context *vmesa )
{
- if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
+ GLenum renderPrimitive = vmesa->renderPrimitive;
+ GLenum hwPrimitive = vmesa->hwPrimitive;
+
+ if (VIA_DEBUG & DEBUG_PRIMS) fprintf(stderr, "%s\n", __FUNCTION__);
+
+ if (vmesa->dmaLastPrim)
+ viaFinishPrimitive( vmesa );
+
+ viaFlushDma(vmesa);
+
+ if (renderPrimitive != GL_POLYGON + 1)
+ viaRasterPrimitive( vmesa->glCtx,
+ renderPrimitive,
+ hwPrimitive );
+
+}
+
+void viaFlushDma(struct via_context *vmesa)
+{
+ if (vmesa->dmaLow) {
+ assert(!vmesa->dmaLastPrim);
- if (vmesa->dmaLow != DMA_OFFSET) {
LOCK_HARDWARE(vmesa);
- viaFlushPrimsLocked(vmesa);
+ viaFlushDmaLocked(vmesa, 0);
UNLOCK_HARDWARE(vmesa);
}
- if (VIA_DEBUG) fprintf(stderr, "%s in\n", __FUNCTION__);
}
static void viaFlush(GLcontext *ctx)
{
- viaContextPtr vmesa = VIA_CONTEXT(ctx);
+ struct via_context *vmesa = VIA_CONTEXT(ctx);
VIA_FLUSH_DMA(vmesa);
}
static void viaFinish(GLcontext *ctx)
{
- viaContextPtr vmesa = VIA_CONTEXT(ctx);
+ struct via_context *vmesa = VIA_CONTEXT(ctx);
VIA_FLUSH_DMA(vmesa);
- WAIT_IDLE(vmesa);
+ viaWaitIdle(vmesa, GL_FALSE);
}
static void viaClearStencil(GLcontext *ctx, int s)
}
-#define SetReg2DAGP(nReg, nData) do { \
- OUT_RING( ((nReg) >> 2) | 0xF0000000 ); \
- OUT_RING( nData ); \
-} while (0)
-
-
-static void viaBlit(viaContextPtr vmesa, GLuint bpp,GLuint srcBase,
- GLuint srcPitch,GLuint dstBase,GLuint dstPitch,
- GLuint w,GLuint h,int xdir,int ydir, GLuint blitMode,
- GLuint color, GLuint nMask )
-{
-
- GLuint dwGEMode = 0, srcY=0, srcX, dstY=0, dstX;
- GLuint cmd;
- RING_VARS;
-
- if (VIA_DEBUG)
- fprintf(stderr, "%s bpp %d src %x/%x dst %x/%x w %d h %d dir %d,%d mode: %x color: 0x%08x mask 0x%08x\n",
- __FUNCTION__, bpp, srcBase, srcPitch, dstBase, dstPitch, w,h, xdir, ydir, blitMode, color, nMask);
-
-
- if (!w || !h)
- return;
-
- srcX = srcBase & 31;
- dstX = dstBase & 31;
- switch (bpp) {
- case 16:
- dwGEMode |= VIA_GEM_16bpp;
- srcX >>= 1;
- dstX >>= 1;
- break;
- case 32:
- dwGEMode |= VIA_GEM_32bpp;
- srcX >>= 2;
- dstX >>= 2;
- break;
- default:
- dwGEMode |= VIA_GEM_8bpp;
- break;
- }
-
-
- cmd = 0;
-
- if (xdir < 0) {
- cmd |= VIA_GEC_DECX;
- srcX += (w - 1);
- dstX += (w - 1);
- }
- if (ydir < 0) {
- cmd |= VIA_GEC_DECY;
- srcY += (h - 1);
- dstY += (h - 1);
- }
-
- switch(blitMode) {
- case VIA_BLIT_FILL:
- BEGIN_RING((2 + 9) * 2);
- SetReg2DAGP(VIA_REG_GEMODE, dwGEMode);
- SetReg2DAGP( VIA_REG_FGCOLOR, color);
- cmd |= VIA_GEC_BLT | VIA_GEC_FIXCOLOR_PAT | (VIA_BLIT_FILL << 24);
- break;
- case VIA_BLIT_COPY:
- BEGIN_RING((2 + 9) * 2);
- SetReg2DAGP(VIA_REG_GEMODE, dwGEMode);
- SetReg2DAGP( VIA_REG_KEYCONTROL, 0x0);
- cmd |= VIA_GEC_BLT | (VIA_BLIT_COPY << 24);
- }
-
- SetReg2DAGP( 0x2C, nMask);
- SetReg2DAGP( VIA_REG_SRCBASE, (srcBase & ~31) >> 3);
- SetReg2DAGP( VIA_REG_DSTBASE, (dstBase & ~31) >> 3);
- SetReg2DAGP( VIA_REG_PITCH, VIA_PITCH_ENABLE |
- (srcPitch >> 3) | (((dstPitch) >> 3) << 16));
- SetReg2DAGP( VIA_REG_SRCPOS, ((srcY << 16) | srcX));
- SetReg2DAGP( VIA_REG_DSTPOS, ((dstY << 16) | dstX));
- SetReg2DAGP( VIA_REG_DIMENSION, (((h - 1) << 16) | (w - 1)));
- SetReg2DAGP( VIA_REG_GECMD, cmd);
- SetReg2DAGP( 0x2C, 0x00000000);
- ADVANCE_RING();
-}
-
-void viaFillFrontBuffer(viaContextPtr vmesa)
-{
- GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight,i;
- drm_clip_rect_t *b = vmesa->sarea->boxes;
- GLuint pixel = (GLuint)vmesa->ClearColor;
- GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
- nDestPitch = vmesa->front.pitch;
-
- for (i = 0; i < vmesa->sarea->nbox ; i++) {
- nDestWidth = b->x2 - b->x1;
- nDestHeight = b->y2 - b->y1;
- nDestBase = vmesa->viaScreen->fbOffset +
- (b->y1* nDestPitch + b->x1 * bytePerPixel);
- viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
- nDestBase , nDestPitch, nDestWidth, nDestHeight,
- 0,0,VIA_BLIT_FILL, pixel, 0x0);
- b++;
- }
-
- viaFlushPrimsLocked(vmesa);
-}
-
-void viaFillFrontPBuffer(viaContextPtr vmesa)
-{
- GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offset;
- GLuint pixel = (GLuint)vmesa->ClearColor;
-
- offset = vmesa->front.offset;
- if (VIA_DEBUG) fprintf(stderr, "Fill PFront offset = %08x\n", offset);
- nDestBase = offset;
- nDestPitch = vmesa->front.pitch;
-
- nDestWidth = vmesa->driDrawable->w;
- nDestHeight = vmesa->driDrawable->h;
-
- viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
- nDestBase , nDestPitch, nDestWidth, nDestHeight,
- 0,0,VIA_BLIT_FILL, pixel, 0x0);
-
- viaFlushPrimsLocked(vmesa);
-}
-
-void viaFillBackBuffer(viaContextPtr vmesa)
-{
- GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offset;
- GLcontext *ctx = vmesa->glCtx;
- GLuint pixel = (GLuint)vmesa->ClearColor;
- GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
-
- offset = vmesa->back.offset;
- if (VIA_DEBUG) fprintf(stderr, "Fill Back offset = %08x\n", offset);
- nDestBase = offset;
- nDestPitch = vmesa->back.pitch;
-
- if (!ctx->Scissor.Enabled) {
- nDestWidth = (vmesa->back.pitch / bytePerPixel);
- nDestHeight = vmesa->driDrawable->h;
- viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
- nDestBase , nDestPitch, nDestWidth, nDestHeight,
- 0,0,VIA_BLIT_FILL, pixel, 0x0);
-
- }
- /*=* John Sheng [2003.7.18] texenv *=*/
- else {
- int i;
- drm_clip_rect_t *b = vmesa->sarea->boxes;
- for (i = 0; i < vmesa->sarea->nbox ; i++) {
- nDestWidth = b->x2 - b->x1;
- nDestHeight = b->y2 - b->y1;
- nDestBase = offset + ((b->y1 - vmesa->drawY) * nDestPitch) +
- (b->x1 - vmesa->drawX + vmesa->drawXoff) * bytePerPixel;
- viaBlit(vmesa,vmesa->viaScreen->bitsPerPixel, nDestBase, nDestPitch,
- nDestBase , nDestPitch, nDestWidth, nDestHeight,
- 0,0,VIA_BLIT_FILL, pixel, 0x0);
- b++;
- }
- }
- if (VIA_DEBUG) {
- fprintf(stderr," width = %08x\n", nDestWidth);
- fprintf(stderr," height = %08x\n", nDestHeight);
- }
-}
-
-
-void viaFillDepthBuffer(viaContextPtr vmesa, GLuint pixel, GLuint mask)
-{
- GLuint nDestBase, nDestPitch, nDestWidth, nDestHeight, offsetX, offset;
-
- offset = vmesa->depth.offset;
- if (VIA_DEBUG)
- fprintf(stderr, "Fill Depth offset = %08x, pixel %x, mask %x\n", offset, pixel, mask);
- nDestBase = offset;
- nDestPitch = vmesa->depth.pitch;
-
- offsetX = vmesa->drawXoff;
- nDestWidth = (vmesa->depth.pitch / vmesa->depth.bpp * 8) - offsetX;
- nDestHeight = vmesa->driDrawable->h;
-
- viaBlit(vmesa, vmesa->depth.bpp , nDestBase, nDestPitch,
- nDestBase , nDestPitch, nDestWidth, nDestHeight,
- 0,0,VIA_BLIT_FILL, pixel, mask);
-
-
- if (vmesa->glCtx->Color._DrawDestMask[0] == DD_BACK_LEFT_BIT) {
- viaFlushPrimsLocked(vmesa);
- }
-}
-
-void viaDoSwapBuffers(viaContextPtr vmesa)
-{
- GLuint nFrontPitch;
- GLuint nBackPitch;
- GLuint nFrontWidth, nFrontHeight;
- GLuint nFrontBase, nBackBase;
- drm_clip_rect_t *b = vmesa->sarea->boxes;
- GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
- GLuint i;
-
- nFrontPitch = vmesa->front.pitch;
- nBackPitch = vmesa->back.pitch;
-
- for (i = 0; i < vmesa->sarea->nbox; i++) {
-
- /* Width, Height */
- nFrontWidth = b->x2 - b->x1;
- nFrontHeight = b->y2 - b->y1;
-
- nFrontBase = vmesa->viaScreen->fbOffset + (b->y1* nFrontPitch +
- b->x1 * bytePerPixel);
- nBackBase = vmesa->back.offset + ((b->y1 - vmesa->drawY) * nBackPitch) +
- (b->x1 - vmesa->drawX + vmesa->drawXoff) * bytePerPixel;
-
- viaBlit(vmesa, bytePerPixel << 3 , nBackBase, nBackPitch,
- nFrontBase , nFrontPitch, nFrontWidth, nFrontHeight,
- 0,0,VIA_BLIT_COPY, 0, 0);
- b++;
- }
-
- viaFlushPrimsLocked(vmesa);
- if (VIA_DEBUG) fprintf(stderr, "Do Swap Buffer\n");
-}
-
-
-void viaDoSwapPBuffers(viaContextPtr vmesa)
-{
- GLuint nFrontPitch;
- GLuint nBackPitch;
- GLuint nFrontWidth, nFrontHeight;
- GLuint nFrontBase, nBackBase;
- GLuint nFrontOffsetX, nFrontOffsetY, nBackOffsetX, nBackOffsetY;
- GLuint bytePerPixel = vmesa->viaScreen->bitsPerPixel >> 3;
- GLuint EngStatus = *(vmesa->pnGEMode);
- GLuint blitMode;
- RING_VARS;
-
- switch(bytePerPixel) {
- case 4:
- blitMode = 0x300;
- break;
- case 2:
- blitMode = 0x100;
- break;
- default:
- blitMode = 0x000;
- break;
- }
-
- nFrontPitch = vmesa->front.pitch;
- nBackPitch = vmesa->back.pitch;
-
- /* Caculate Base */
- nFrontBase = vmesa->front.offset;
- nBackBase = vmesa->back.offset;
-
- /* Width, Height */
- nFrontWidth = nFrontPitch / bytePerPixel;
- nFrontHeight = nBackPitch / bytePerPixel;
-
- /* Offset */
- nFrontOffsetX = 0;
- nFrontOffsetY = 0;
- nBackOffsetX = nFrontOffsetX;
- nBackOffsetY = nFrontOffsetY;
-
- BEGIN_RING(8 * 2);
- /* Restore mode */
- SetReg2DAGP(0x04, (EngStatus & 0xFFFFFCFF) | blitMode);
- /* GEWD */
- SetReg2DAGP(0x10, nFrontWidth | (nFrontHeight << 16));
- /* GEDST */
- SetReg2DAGP(0x0C, nFrontOffsetX | (nFrontOffsetY << 16));
- /* GESRC */
- SetReg2DAGP(0x08, nBackOffsetX | (nBackOffsetY << 16));
- /* GEDSTBASE */
- SetReg2DAGP(0x34, (nFrontBase >> 3));
- /* GESCRBASE */
- SetReg2DAGP(0x30, (nBackBase >> 3));
- /* GEPITCH */
- SetReg2DAGP(0x38, (((nFrontPitch >> 3) << 16) & 0x7FF0000) | 0x80000000 |
- ((nBackPitch >> 3) & 0x7FF));
- /* BITBLT */
- SetReg2DAGP(0x0, 0x1 | 0xCC000000);
- ADVANCE_RING();
-
- viaFlushPrimsLocked(vmesa);
- if (VIA_DEBUG) fprintf(stderr, "Do Swap PBuffer\n");
-}
-
-
-
-
-GLuint *viaAllocDmaFunc(viaContextPtr vmesa, int bytes, const char *func, int line)
-{
- if (vmesa->dmaLow + bytes > VIA_DMA_HIGHWATER) {
- if (VIA_DEBUG) fprintf(stderr, "buffer overflow in check dma = %d + %d = %d\n",
- vmesa->dmaLow, bytes, vmesa->dmaLow + bytes);
- viaFlushPrims(vmesa);
- }
-
- {
- GLuint *start = (GLuint *)(vmesa->dmaAddr + vmesa->dmaLow);
- vmesa->dmaLow += bytes;
- if (VIA_DEBUG && (vmesa->dmaLow & 0x4))
- fprintf(stderr, "%s/%d: alloc 0x%x --> dmaLow 0x%x\n", func, line, bytes, vmesa->dmaLow);
- return start;
- }
-}
-