summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2001-06-16 05:48:49 +0000
committerKeith Packard <keithp@keithp.com>2001-06-16 05:48:49 +0000
commit54aea8ec0c1c3633788fd9b19636093860c75d53 (patch)
tree974db54afd6773b3fc044378c30aae6b27a7eac1
parentf386ca6c69ba10cd8c0dd60bb25cde37ecfc8bc7 (diff)
Patch DPMS support in kdrive/mach64, add preliminary (broken) Xv support
-rw-r--r--hw/kdrive/mach64/Imakefile13
-rw-r--r--hw/kdrive/mach64/mach64.c84
-rw-r--r--hw/kdrive/mach64/mach64.h88
-rw-r--r--hw/kdrive/mach64/mach64draw.c16
-rw-r--r--hw/kdrive/mach64/mach64video.c780
5 files changed, 927 insertions, 54 deletions
diff --git a/hw/kdrive/mach64/Imakefile b/hw/kdrive/mach64/Imakefile
index 067db5110..103bfb887 100644
--- a/hw/kdrive/mach64/Imakefile
+++ b/hw/kdrive/mach64/Imakefile
@@ -1,12 +1,17 @@
-XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/mach64/Imakefile,v 1.6 2000/10/20 00:19:51 keithp Exp $
+XCOMM $XFree86: xc/programs/Xserver/hw/kdrive/mach64/Imakefile,v 1.1 2001/06/03 18:48:19 keithp Exp $
KDRIVE=..
#include "../Kdrive.tmpl"
-SRCS = mach64.c mach64draw.c mach64stub.c
+#if BuildXvExt
+XVSRCS=mach64video.c
+XVOBJS=mach64video.o
+#endif
-OBJS = mach64.o mach64draw.o mach64stub.o
+SRCS = mach64.c mach64draw.c mach64stub.c $(XVSRCS)
-DEFINES = -DVESA /* -DUSE_PCI*/
+OBJS = mach64.o mach64draw.o mach64stub.o $(XVOBJS)
+
+DEFINES = XvExtensionDefines -DVESA /* -DUSE_PCI*/
INCLUDES = -I. $(KDINCS) -I$(KDRIVE)/vesa
diff --git a/hw/kdrive/mach64/mach64.c b/hw/kdrive/mach64/mach64.c
index 90f26e44e..ec49aafaa 100644
--- a/hw/kdrive/mach64/mach64.c
+++ b/hw/kdrive/mach64/mach64.c
@@ -19,7 +19,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.c,v 1.1 2001/06/03 18:48:19 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.c,v 1.2 2001/06/04 09:45:41 keithp Exp $ */
#include "mach64.h"
#include <sys/io.h>
@@ -44,6 +44,7 @@ mach64CardInit (KdCardInfo *card)
}
mach64c->reg = (Reg *) (mach64c->reg_base + MACH64_REG_OFF(card));
mach64c->media_reg = (MediaReg *) (mach64c->reg_base + MACH64_MEDIA_REG_OFF(card));
+ mach64c->lcdEnabled = FALSE;
if (!vesaInitialize (card, &mach64c->vesa))
{
@@ -77,6 +78,7 @@ mach64ScreenInit (KdScreenInfo *screen)
if (mach64s->vesa.mapping != VESA_LINEAR)
screen->dumb = TRUE;
mach64s->screen = mach64s->vesa.fb;
+ mach64s->colorKey = 1;
memory = mach64s->vesa.fb_size;
screen_size = screen->fb[0].byteStride * screen->height;
if (mach64s->screen && memory >= screen_size + 2048)
@@ -105,6 +107,9 @@ mach64ScreenInit (KdScreenInfo *screen)
Bool
mach64InitScreen (ScreenPtr pScreen)
{
+#ifdef XV
+ mach64InitVideo(pScreen);
+#endif
return vesaInitScreen (pScreen);
}
@@ -172,7 +177,7 @@ mach64Preserve (KdCardInfo *card)
vesaPreserve(card);
if (reg)
- mach64c->save.POWER_MANAGEMENT = mach64ReadLCD (reg, 0x8);
+ mach64c->save.LCD_GEN_CTRL = mach64ReadLCD (reg, 1);
}
void
@@ -216,6 +221,36 @@ const CARD8 mach64DPMSModes[4] = {
/* 0xbc, /* KD_DPMS_POWERDOWN */
};
+#define PWR_MGT_ON (1 << 0)
+#define PWR_MGT_MODE (3 << 1)
+#define PWR_MGT_MODE_PIN (0 << 1)
+#define PWR_MGT_MODE_REG (1 << 1)
+#define PWR_MGT_MODE_TIMER (2 << 1)
+#define PWR_MGR_MODE_PCI (3 << 1)
+#define AUTO_PWRUP_EN (1 << 3)
+#define ACTIVITY_PIN_ON (1 << 4)
+#define STANDBY_POL (1 << 5)
+#define SUSPEND_POL (1 << 6)
+#define SELF_REFRESH (1 << 7)
+#define ACTIVITY_PIN_EN (1 << 8)
+#define KEYBD_SNOOP (1 << 9)
+#define DONT_USE_F32KHZ (1 << 10)
+#define TRISTATE_MEM_EN (1 << 11)
+#define LCDENG_TEST_MODE (0xf << 12)
+#define STANDBY_COUNT (0xf << 16)
+#define SUSPEND_COUNT (0xf << 20)
+#define BIASON (1 << 24)
+#define BLON (1 << 25)
+#define DIGON (1 << 26)
+#define PM_D3_RST_ENB (1 << 27)
+#define STANDBY_NOW (1 << 28)
+#define SUSPEND_NOW (1 << 29)
+#define PWR_MGT_STATUS (3 << 30)
+#define PWR_MGT_STATUS_ON (0 << 30)
+#define PWR_MGT_STATUS_STANDBY (1 << 30)
+#define PWR_MGT_STATUS_SUSPEND (2 << 30)
+#define PWR_MGT_STATUS_TRANSITION (3 << 30)
+
Bool
mach64DPMS (ScreenPtr pScreen, int mode)
{
@@ -223,25 +258,15 @@ mach64DPMS (ScreenPtr pScreen, int mode)
Mach64CardInfo *mach64c = pScreenPriv->card->driver;
int hsync_off, vsync_off, blank;
CARD32 CRTC_GEN_CNTL;
- CARD32 POWER_MANAGEMENT;
+ CARD32 LCD_GEN_CTRL;
Reg *reg = mach64c->reg;
if (!reg)
return FALSE;
CRTC_GEN_CNTL = reg->CRTC_GEN_CNTL;
- POWER_MANAGEMENT = mach64ReadLCD (reg, 8);
-
- /*
- * Select register mode
- */
- POWER_MANAGEMENT = (POWER_MANAGEMENT & ~(3 << 1)) | (1 << 1);
- /*
- * Switch back to ON mode
- */
- POWER_MANAGEMENT &= ~(1 << 28);
- POWER_MANAGEMENT &= ~(1 << 29);
-
+ LCD_GEN_CTRL = mach64ReadLCD (reg, 1);
+
switch (mode) {
case KD_DPMS_NORMAL:
hsync_off = 0;
@@ -251,31 +276,18 @@ mach64DPMS (ScreenPtr pScreen, int mode)
case KD_DPMS_STANDBY:
hsync_off = 1;
vsync_off = 0;
- /*
- * Standby
- */
- POWER_MANAGEMENT |= (1 << 28);
blank = 1;
break;
case KD_DPMS_SUSPEND:
hsync_off = 0;
vsync_off = 1;
blank = 1;
- /*
- * Suspend
- */
- POWER_MANAGEMENT |= (1 << 28);
break;
case KD_DPMS_POWERDOWN:
hsync_off = 1;
vsync_off = 1;
- /*
- * Suspend
- */
- POWER_MANAGEMENT |= (1 << 28);
blank = 1;
}
-
if (hsync_off)
CRTC_GEN_CNTL |= (1 << 2);
@@ -286,10 +298,22 @@ mach64DPMS (ScreenPtr pScreen, int mode)
else
CRTC_GEN_CNTL &= ~(1 << 3);
if (blank)
+ {
+ mach64c->lcdEnabled = (LCD_GEN_CTRL & (1 << 1)) != 0;
+ LCD_GEN_CTRL &= ~(1 << 1);
CRTC_GEN_CNTL |= (1 << 6);
+
+ }
else
+ {
+ if (!(LCD_GEN_CTRL & 3) || mach64c->lcdEnabled)
+ LCD_GEN_CTRL |= (1 << 1);
CRTC_GEN_CNTL &= ~(1 << 6);
- mach64WriteLCD (reg, 8, POWER_MANAGEMENT);
+ }
+
+ KdCheckSync (pScreen);
+
+ mach64WriteLCD (reg, 1, LCD_GEN_CTRL);
reg->CRTC_GEN_CNTL = CRTC_GEN_CNTL;
return TRUE;
@@ -302,7 +326,7 @@ mach64Restore (KdCardInfo *card)
Reg *reg = mach64c->reg;
if (reg)
- mach64WriteLCD (reg, 8, mach64c->save.POWER_MANAGEMENT);
+ mach64WriteLCD (reg, 1, mach64c->save.LCD_GEN_CTRL);
mach64ResetMMIO (mach64c);
vesaRestore (card);
}
diff --git a/hw/kdrive/mach64/mach64.h b/hw/kdrive/mach64/mach64.h
index a912e2a50..dd242680b 100644
--- a/hw/kdrive/mach64/mach64.h
+++ b/hw/kdrive/mach64/mach64.h
@@ -21,11 +21,12 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.h,v 1.1 2001/06/03 18:48:19 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64.h,v 1.2 2001/06/04 09:45:42 keithp Exp $ */
#ifndef _MACH64_H_
#define _MACH64_H_
#include <vesa.h>
+#include "kxv.h"
/*
* offset from ioport beginning
@@ -331,6 +332,34 @@ typedef struct _Reg {
#define HOST_BYTE_ALIGN (1 << 28)
#define HOST_BIG_ENDIAN_EN (1 << 29)
+#define SCALE_PIX_EXPAND (1 << 0)
+#define SCALE_Y2R_TEMP (1 << 1)
+#define SCALE_HORZ_MODE (1 << 2)
+#define SCALE_VERT_MODE (1 << 3)
+#define SCALE_SIGNED_UV (1 << 4)
+#define SCALE_GAMMA_SEL (3 << 5)
+#define SCALE_GAMMA_BRIGHT (0 << 5)
+#define SCALE_GAMMA_22 (1 << 5)
+#define SCALE_GAMMA_18 (2 << 5)
+#define SCALE_GAMMA_14 (3 << 5)
+#define SCALE_DISP_SEL (1 << 7)
+#define SCALE_BANDWIDTH (1 << 26)
+#define SCALE_DIS_LIMIT (1 << 27)
+#define SCALE_CLK_FORCE_ON (1 << 29)
+#define SCALE_OVERLAY_EN (1 << 30)
+#define SCALE_EN (1 << 31)
+
+#define SCALER_IN_15bpp (0x3 << 16)
+#define SCALER_IN_16bpp (0x4 << 16)
+#define SCALER_IN_32bpp (0x6 << 16)
+#define SCALER_IN_YUV_9 (0x9 << 16)
+#define SCALER_IN_YUV_12 (0xa << 16)
+#define SCALER_IN_VYUY422 (0xb << 16)
+#define SCALER_IN_YVYU422 (0xc << 16)
+
+#define OVL_BUF_MODE (1 << 28)
+#define OVL_BUF_NEXT (1 << 29)
+
typedef struct _MediaReg {
VOL32 OVERLAY_Y_X_START; /* 0x100 */
VOL32 OVERLAY_Y_X_END;
@@ -431,10 +460,11 @@ typedef struct _MediaReg {
VOL32 dvd_subpicture[0x30]; /* 0x1d0 */
} MediaReg;
-#define TRI_XY(x,y) ((y) << 16 | (x))
+#define MACH64_XY(x,y) (((x) & 0x7fff) | (((y) & 0x7fff) << 16))
+#define MACH64_YX(x,y) (((y) & 0x7fff) | (((x) & 0x7fff) << 16))
typedef struct _mach64Save {
- CARD32 POWER_MANAGEMENT;
+ CARD32 LCD_GEN_CTRL;
} Mach64Save;
typedef struct _mach64CardInfo {
@@ -443,6 +473,7 @@ typedef struct _mach64CardInfo {
Reg *reg;
MediaReg *media_reg;
Mach64Save save;
+ Bool lcdEnabled;
} Mach64CardInfo;
#define getMach64CardInfo(kd) ((Mach64CardInfo *) ((kd)->card->driver))
@@ -459,17 +490,48 @@ typedef struct _mach64Cursor {
#define MACH64_CURSOR_WIDTH 64
#define MACH64_CURSOR_HEIGHT 64
+/*
+ * Xv information, optional
+ */
+typedef struct _mach64PortPriv {
+ CARD32 YBuf0Offset;
+ CARD32 UBuf0Offset;
+ CARD32 VBuf0Offset;
+
+ CARD32 YBuf1Offset;
+ CARD32 UBuf1Offset;
+ CARD32 VBuf1Offset;
+
+ CARD8 currentBuf;
+
+ CARD8 brightness;
+ CARD8 contrast;
+
+ RegionRec clip;
+ CARD32 colorKey;
+
+ Bool videoOn;
+ Time offTime;
+ Time freeTime;
+ CARD32 size;
+ CARD32 offset;
+} Mach64PortPrivRec, *Mach64PortPrivPtr;
+
+Bool mach64InitVideo(ScreenPtr pScreen);
+
typedef struct _mach64ScreenInfo {
- VesaScreenPrivRec vesa;
- CARD8 *cursor_base;
- CARD8 *screen;
- CARD8 *off_screen;
- int off_screen_size;
- CARD32 DP_PIX_WIDTH;
- CARD32 DP_SET_GUI_ENGINE;
- CARD32 USR1_DST_OFF_PITCH;
- Bool bpp24;
- Mach64Cursor cursor;
+ VesaScreenPrivRec vesa;
+ CARD8 *cursor_base;
+ CARD8 *screen;
+ CARD8 *off_screen;
+ int off_screen_size;
+ CARD32 DP_PIX_WIDTH;
+ CARD32 DP_SET_GUI_ENGINE;
+ CARD32 USR1_DST_OFF_PITCH;
+ Bool bpp24;
+ Mach64Cursor cursor;
+ CARD32 colorKey;
+ KdVideoAdaptorPtr pAdaptor;
} Mach64ScreenInfo;
#define getMach64ScreenInfo(kd) ((Mach64ScreenInfo *) ((kd)->screen->driver))
diff --git a/hw/kdrive/mach64/mach64draw.c b/hw/kdrive/mach64/mach64draw.c
index 5371e95b1..cdb308d22 100644
--- a/hw/kdrive/mach64/mach64draw.c
+++ b/hw/kdrive/mach64/mach64draw.c
@@ -21,7 +21,7 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c,v 1.1 2001/06/03 18:48:19 keithp Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/kdrive/mach64/mach64draw.c,v 1.2 2001/06/04 09:45:42 keithp Exp $ */
#include "mach64.h"
#include "mach64draw.h"
@@ -87,15 +87,13 @@ WAIT_IDLE (Reg *reg)
;
}
-#define MACH64_XY(x,y) (((x) & 0x7fff) | (((y) & 0x7fff) << 16))
-#define MACH64_YX(x,y) (((y) & 0x7fff) | (((x) & 0x7fff) << 16))
-
-static void
+static Bool
mach64Setup (ScreenPtr pScreen, CARD32 combo, int wait)
{
KdScreenPriv(pScreen);
mach64ScreenInfo(pScreenPriv);
mach64CardInfo(pScreenPriv);
+
reg = mach64c->reg;
triple = mach64s->bpp24;
@@ -104,6 +102,7 @@ mach64Setup (ScreenPtr pScreen, CARD32 combo, int wait)
reg->DP_PIX_WIDTH = mach64s->DP_PIX_WIDTH;
reg->USR1_DST_OFF_PITCH = mach64s->USR1_DST_OFF_PITCH;
reg->DP_SET_GUI_ENGINE = mach64s->DP_SET_GUI_ENGINE | (combo << 20);
+ return TRUE;
}
Bool
@@ -112,7 +111,8 @@ mach64PrepareSolid (DrawablePtr pDrawable,
Pixel pm,
Pixel fg)
{
- mach64Setup (pDrawable->pScreen, 1, 3);
+ if (!mach64Setup (pDrawable->pScreen, 1, 3))
+ return FALSE;
reg->DP_MIX = (mach64Rop[alu] << 16) | 0;
reg->DP_WRITE_MSK = pm;
reg->DP_FRGD_CLR = fg;
@@ -163,7 +163,9 @@ mach64PrepareCopy (DrawablePtr pSrcDrawable,
combo |= 1;
if ((copyDy = dy) > 0)
combo |= 2;
- mach64Setup (pDstDrawable->pScreen, combo, 2);
+ if (!mach64Setup (pDstDrawable->pScreen, combo, 2))
+ return FALSE;
+
reg->DP_MIX = (mach64Rop[alu] << 16) | 0;
reg->DP_WRITE_MSK = pm;
return TRUE;
diff --git a/hw/kdrive/mach64/mach64video.c b/hw/kdrive/mach64/mach64video.c
new file mode 100644
index 000000000..2566f3a5a
--- /dev/null
+++ b/hw/kdrive/mach64/mach64video.c
@@ -0,0 +1,780 @@
+/*
+ * Copyright © 2001 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#include "mach64.h"
+
+#include "Xv.h"
+#include "../../xfree86/common/fourcc.h"
+
+#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
+
+static Atom xvBrightness, xvContrast, xvColorKey;
+
+#define IMAGE_MAX_WIDTH 720
+#define IMAGE_MAX_HEIGHT 576
+#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT)
+
+static void
+mach64StopVideo(KdScreenInfo *screen, pointer data, Bool exit)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ MediaReg *media = mach64c->media_reg;
+
+ REGION_EMPTY(screen->pScreen, &pPortPriv->clip);
+
+ if(pPortPriv->videoOn)
+ {
+ pPortPriv->videoOn = FALSE;
+ }
+}
+
+static int
+mach64SetPortAttribute(KdScreenInfo *screen,
+ Atom attribute,
+ int value,
+ pointer data)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ MediaReg *media = mach64c->media_reg;
+
+ if(attribute == xvBrightness)
+ {
+ if((value < -128) || (value > 127))
+ return BadValue;
+ pPortPriv->brightness = value;
+ }
+ else if(attribute == xvContrast)
+ {
+ if((value < 0) || (value > 255))
+ return BadValue;
+ pPortPriv->contrast = value;
+ }
+ else if(attribute == xvColorKey)
+ {
+ pPortPriv->colorKey = value;
+ REGION_EMPTY(screen->pScreen, &pPortPriv->clip);
+ }
+ else
+ return BadMatch;
+
+ return Success;
+}
+
+static int
+mach64GetPortAttribute(KdScreenInfo *screen,
+ Atom attribute,
+ int *value,
+ pointer data)
+{
+ Mach64PortPrivPtr pPortPriv = (Mach64PortPrivPtr)data;
+
+ if(attribute == xvBrightness)
+ *value = pPortPriv->brightness;
+ else if(attribute == xvContrast)
+ *value = pPortPriv->contrast;
+ else if(attribute == xvColorKey)
+ *value = pPortPriv->colorKey;
+ else
+ return BadMatch;
+
+ return Success;
+}
+
+static void
+mach64QueryBestSize(KdScreenInfo *screen,
+ Bool motion,
+ short vid_w,
+ short vid_h,
+ short drw_w,
+ short drw_h,
+ unsigned int *p_w,
+ unsigned int *p_h,
+ pointer data)
+{
+ *p_w = drw_w;
+ *p_h = drw_h;
+}
+
+
+static void
+mach64CopyPackedData(KdScreenInfo *screen,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch,
+ int top,
+ int left,
+ int h,
+ int w)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ CARD8 *src, *dst;
+
+ src = buf + (top*srcPitch) + (left<<1);
+
+ if (pPortPriv->currentBuf == 0)
+ dst = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf0Offset;
+ else
+ dst = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf1Offset;
+
+ w <<= 1;
+ while(h--)
+ {
+ memcpy(dst, src, w);
+ src += srcPitch;
+ dst += dstPitch;
+ }
+}
+
+static void
+mach64CopyPlanarData(KdScreenInfo *screen,
+ unsigned char *buf,
+ int srcPitch,
+ int dstPitch, /* of chroma */
+ int srcH,
+ int top,
+ int left,
+ int h,
+ int w,
+ int id)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ int i;
+ CARD8 *src1, *src2, *src3, *dst1, *dst2, *dst3;
+
+ /* Copy Y data */
+ src1 = buf + (top*srcPitch) + left;
+ if (pPortPriv->currentBuf == 0)
+ dst1 = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf0Offset;
+ else
+ dst1 = (CARD8 *) mach64s->vesa.fb + pPortPriv->YBuf1Offset;
+
+ for (i = 0; i < h; i++)
+ {
+ memcpy(dst1, src1, w);
+ src1 += srcPitch;
+ dst1 += dstPitch << 1;
+ }
+
+ /* Copy V data for YV12, or U data for I420 */
+ src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPortPriv->currentBuf == 0)
+ {
+ if (id == FOURCC_I420)
+ dst2 = (CARD8 *) mach64s->vesa.fb + pPortPriv->UBuf0Offset;
+ else
+ dst2 = (CARD8 *) mach64s->vesa.fb + pPortPriv->VBuf0Offset;
+ } else {
+ if (id == FOURCC_I420)
+ dst2 = (CARD8 *) mach64s->vesa.fb + pPortPriv->UBuf1Offset;
+ else
+ dst2 = (CARD8 *) mach64s->vesa.fb + pPortPriv->VBuf1Offset;
+ }
+
+ for (i = 0; i < h/2; i++)
+ {
+ memcpy(dst2, src2, w/2);
+ src2 += srcPitch>>1;
+ dst2 += dstPitch;
+ }
+
+ /* Copy U data for YV12, or V data for I420 */
+ src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1);
+ if (pPortPriv->currentBuf == 0)
+ {
+ if (id == FOURCC_I420)
+ dst3 = (CARD8 *) mach64s->vesa.fb + pPortPriv->VBuf0Offset;
+ else
+ dst3 = (CARD8 *) mach64s->vesa.fb + pPortPriv->UBuf0Offset;
+ }
+ else
+ {
+ if (id == FOURCC_I420)
+ dst3 = (CARD8 *) mach64s->vesa.fb + pPortPriv->VBuf1Offset;
+ else
+ dst3 = (CARD8 *) mach64s->vesa.fb + pPortPriv->UBuf1Offset;
+ }
+
+ for (i = 0; i < h/2; i++)
+ {
+ memcpy(dst3, src3, w/2);
+ src3 += srcPitch>>1;
+ dst3 += dstPitch;
+ }
+}
+
+/* Mach64ClipVideo -
+
+ Takes the dst box in standard X BoxRec form (top and left
+ edges inclusive, bottom and right exclusive). The new dst
+ box is returned. The source boundaries are given (x1, y1
+ inclusive, x2, y2 exclusive) and returned are the new source
+ boundaries in 16.16 fixed point.
+*/
+
+static void
+Mach64ClipVideo(BoxPtr dst,
+ INT32 *x1,
+ INT32 *x2,
+ INT32 *y1,
+ INT32 *y2,
+ BoxPtr extents, /* extents of the clip region */
+ INT32 width,
+ INT32 height)
+{
+ INT32 vscale, hscale, delta;
+ int diff;
+
+ hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1);
+ vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1);
+
+ *x1 <<= 16; *x2 <<= 16;
+ *y1 <<= 16; *y2 <<= 16;
+
+ diff = extents->x1 - dst->x1;
+ if(diff > 0) {
+ dst->x1 = extents->x1;
+ *x1 += diff * hscale;
+ }
+ diff = dst->x2 - extents->x2;
+ if(diff > 0) {
+ dst->x2 = extents->x2;
+ *x2 -= diff * hscale;
+ }
+ diff = extents->y1 - dst->y1;
+ if(diff > 0) {
+ dst->y1 = extents->y1;
+ *y1 += diff * vscale;
+ }
+ diff = dst->y2 - extents->y2;
+ if(diff > 0) {
+ dst->y2 = extents->y2;
+ *y2 -= diff * vscale;
+ }
+
+ if(*x1 < 0) {
+ diff = (- *x1 + hscale - 1)/ hscale;
+ dst->x1 += diff;
+ *x1 += diff * hscale;
+ }
+ delta = *x2 - (width << 16);
+ if(delta > 0) {
+ diff = (delta + hscale - 1)/ hscale;
+ dst->x2 -= diff;
+ *x2 -= diff * hscale;
+ }
+ if(*y1 < 0) {
+ diff = (- *y1 + vscale - 1)/ vscale;
+ dst->y1 += diff;
+ *y1 += diff * vscale;
+ }
+ delta = *y2 - (height << 16);
+ if(delta > 0) {
+ diff = (delta + vscale - 1)/ vscale;
+ dst->y2 -= diff;
+ *y2 -= diff * vscale;
+ }
+}
+
+static void
+mach64DisplayVideo(KdScreenInfo *screen,
+ int id,
+ short width,
+ short height,
+ int dstPitch, /* of chroma for 4:2:0 */
+ int x1,
+ int y1,
+ int x2,
+ int y2,
+ BoxPtr dstBox,
+ short src_w,
+ short src_h,
+ short drw_w,
+ short drw_h)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ MediaReg *media = mach64c->media_reg;
+ int xscaleInt, xscaleFract, yscaleInt, yscaleFract;
+ int xscaleIntUV = 0, xscaleFractUV = 0;
+ int yscaleIntUV = 0, yscaleFractUV = 0;
+ int HORZ_INC, VERT_INC;
+ unsigned int swidth;
+ CARD32 SCALER_IN;
+
+ /* lock registers to prevent non-atomic update */
+ media->OVERLAY_Y_X_START = 0x80000000;
+ /* ending screen coordinate */
+ media->OVERLAY_Y_X_END = MACH64_YX (x2, y2);
+ /* color key */
+ media->OVERLAY_GRAPHICS_KEY_CLR = mach64s->colorKey;
+ media->OVERLAY_GRAPHICS_KEY_MSK = (1 << screen->fb[0].depth) - 1;
+ /* XXX always display video for now */
+ media->OVERLAY_KEY_CNTL = 1;
+ /* no exclusive video region */
+ media->OVERLAY_EXCLUSIVE_HORZ = 0;
+
+ VERT_INC = (src_h << 12) / drw_h;
+ HORZ_INC = (src_w << 12) / drw_w;
+
+ media->OVERLAY_SCALE_INC = MACH64_YX(HORZ_INC, VERT_INC);
+
+ media->OVERLAY_SCALE_CNTL = (SCALE_PIX_EXPAND |
+ SCALE_GAMMA_22 |
+ SCALE_EN);
+ media->SCALER_BUF0_OFFSET = pPortPriv->YBuf0Offset;
+ media->SCALER_BUF1_OFFSET = pPortPriv->YBuf0Offset;
+ media->SCALER_BUF0_OFFSET_U = pPortPriv->UBuf0Offset;
+ media->SCALER_BUF1_OFFSET_U = pPortPriv->UBuf1Offset;
+ media->SCALER_BUF0_OFFSET_V = pPortPriv->VBuf0Offset;
+ media->SCALER_BUF1_OFFSET_V = pPortPriv->VBuf1Offset;
+ media->SCALER_BUF_PITCH = src_w;
+ media->SCALER_HEIGHT_WIDTH = MACH64_YX(src_w, src_h);
+ media->SCALER_TEST + 0;
+
+ media->SCALER_COLOUR_CNTL = ((0 << 0) | /* BRIGHTNESS */
+ (0x10 << 8) | /* SATURATION_U */
+ (0x10 << 16) | /* SATURATION_V */
+ (0 << 21) | /* SCALER_VERT_ADJ_UV */
+ (0 << 28)); /* SCALER_HORZ_ADJ_UV */
+
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ SCALER_IN = SCALER_IN_YUV_12;
+ swidth = (width + 7) & ~7;
+ break;
+ break;
+ case FOURCC_UYVY:
+ SCALER_IN = SCALER_IN_VYUY422;
+ break;
+ case FOURCC_YUY2:
+ SCALER_IN = SCALER_IN_YVYU422;
+ break;
+ }
+
+ media->VIDEO_FORMAT = SCALER_IN;
+ media->CAPTURE_CONFIG = (OVL_BUF_MODE |
+ (pPortPriv->currentBuf == 0 ?
+ 0 : OVL_BUF_NEXT));
+
+#if 0
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16);
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_420;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ overlay->OV0STRIDE = dstPitch;
+ overlay->OV0CMD &= ~SOURCE_FORMAT;
+ overlay->OV0CMD |= YUV_422;
+ overlay->OV0CMD &= ~OV_BYTE_ORDER;
+ if (id == FOURCC_UYVY)
+ overlay->OV0CMD |= Y_SWAP;
+ break;
+ }
+
+ overlay->OV0CMD &= ~BUFFER_AND_FIELD;
+ if (pPriv->currentBuf == 0)
+ overlay->OV0CMD |= BUFFER0_FIELD0;
+ else
+ overlay->OV0CMD |= BUFFER1_FIELD0;
+
+ OVERLAY_UPDATE(i810c->OverlayPhysical);
+#endif
+
+ /* set XY location and unlock */
+ media->OVERLAY_Y_X_START = MACH64_YX (x1, y1);
+}
+
+static int
+mach64PutImage(KdScreenInfo *screen,
+ short src_x,
+ short src_y,
+ short drw_x,
+ short drw_y,
+ short src_w,
+ short src_h,
+ short drw_w,
+ short drw_h,
+ int id,
+ unsigned char *buf,
+ short width,
+ short height,
+ Bool sync,
+ RegionPtr clipBoxes,
+ pointer data)
+{
+ KdCardInfo *card = screen->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64PortPrivPtr pPortPriv = (Mach64PortPrivPtr)data;
+ INT32 x1, x2, y1, y2;
+ int srcPitch, dstPitch;
+ int top, left, npixels, nlines, size;
+ BoxRec dstBox;
+
+ /* Clip */
+ x1 = src_x;
+ x2 = src_x + src_w;
+ y1 = src_y;
+ y2 = src_y + src_h;
+
+ dstBox.x1 = drw_x;
+ dstBox.x2 = drw_x + drw_w;
+ dstBox.y1 = drw_y;
+ dstBox.y2 = drw_y + drw_h;
+
+ Mach64ClipVideo(&dstBox, &x1, &x2, &y1, &y2,
+ REGION_EXTENTS(pScreen, clipBoxes), width, height);
+
+ if((x1 >= x2) || (y1 >= y2))
+ return Success;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ srcPitch = (width + 3) & ~3;
+ dstPitch = ((width >> 1) + 7) & ~7; /* of chroma */
+ size = dstPitch * height * 3;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ srcPitch = (width << 1);
+ dstPitch = (srcPitch + 7) & ~7;
+ size = dstPitch * height;
+ break;
+ }
+
+ pPortPriv->offset = mach64s->off_screen - (CARD8 *) mach64s->vesa.fb;
+ /* fixup pointers */
+ pPortPriv->YBuf0Offset = pPortPriv->offset;
+ pPortPriv->UBuf0Offset = pPortPriv->YBuf0Offset + (dstPitch * 2 * height);
+ pPortPriv->VBuf0Offset = pPortPriv->UBuf0Offset + (dstPitch * height >> 1);
+
+ pPortPriv->YBuf1Offset = pPortPriv->offset + size;
+ pPortPriv->UBuf1Offset = pPortPriv->YBuf1Offset + (dstPitch * 2 * height);
+ pPortPriv->VBuf1Offset = pPortPriv->UBuf1Offset + (dstPitch * height >> 1);
+
+#if 0
+ /* wait for the last rendered buffer to be flipped in */
+ while (((INREG(DOV0STA)&0x00100000)>>20) != pPortPriv->currentBuf);
+#endif
+
+ /* buffer swap */
+ if (pPortPriv->currentBuf == 0)
+ pPortPriv->currentBuf = 1;
+ else
+ pPortPriv->currentBuf = 0;
+
+ /* copy data */
+ top = y1 >> 16;
+ left = (x1 >> 16) & ~1;
+ npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ top &= ~1;
+ nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;
+ mach64CopyPlanarData(screen, buf, srcPitch, dstPitch, height, top, left,
+ nlines, npixels, id);
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ nlines = ((y2 + 0xffff) >> 16) - top;
+ mach64CopyPackedData(screen, buf, srcPitch, dstPitch, top, left, nlines,
+ npixels);
+ break;
+ }
+
+#if 0
+ /* update cliplist */
+ if(!RegionsEqual(&pPortPriv->clip, clipBoxes)) {
+ REGION_COPY(pScreen, &pPortPriv->clip, clipBoxes);
+ mach64FillBoxSolid(screen, REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes),
+ pPortPriv->colorKey, GXcopy, ~0);
+ /*
+ XAAFillSolidRects(screen, pPortPriv->colorKey, GXcopy, ~0,
+ REGION_NUM_RECTS(clipBoxes),
+ REGION_RECTS(clipBoxes));
+ */
+ }
+#endif
+
+ mach64DisplayVideo(screen, id, width, height, dstPitch,
+ x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);
+
+ pPortPriv->videoOn = TRUE;
+
+ return Success;
+}
+
+static int
+mach64QueryImageAttributes(KdScreenInfo *screen,
+ int id,
+ unsigned short *w,
+ unsigned short *h,
+ int *pitches,
+ int *offsets)
+{
+ int size, tmp;
+
+ if(*w > IMAGE_MAX_WIDTH)
+ *w = IMAGE_MAX_WIDTH;
+ if(*h > IMAGE_MAX_HEIGHT)
+ *h = IMAGE_MAX_HEIGHT;
+
+ *w = (*w + 1) & ~1;
+ if(offsets) offsets[0] = 0;
+
+ switch(id) {
+ case FOURCC_YV12:
+ case FOURCC_I420:
+ *h = (*h + 1) & ~1;
+ size = (*w + 3) & ~3;
+ if(pitches)
+ pitches[0] = size;
+ size *= *h;
+ if(offsets)
+ offsets[1] = size;
+ tmp = ((*w >> 1) + 3) & ~3;
+ if(pitches)
+ pitches[1] = pitches[2] = tmp;
+ tmp *= (*h >> 1);
+ size += tmp;
+ if(offsets)
+ offsets[2] = size;
+ size += tmp;
+ break;
+ case FOURCC_UYVY:
+ case FOURCC_YUY2:
+ default:
+ size = *w << 1;
+ if(pitches)
+ pitches[0] = size;
+ size *= *h;
+ break;
+ }
+
+ return size;
+}
+
+
+/* client libraries expect an encoding */
+static KdVideoEncodingRec DummyEncoding[1] =
+{
+ {
+ 0,
+ "XV_IMAGE",
+ IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
+ {1, 1}
+ }
+};
+
+#define NUM_FORMATS 3
+
+static KdVideoFormatRec Formats[NUM_FORMATS] =
+{
+ {15, TrueColor}, {16, TrueColor}, {24, TrueColor}
+};
+
+#define NUM_ATTRIBUTES 3
+
+static KdAttributeRec Attributes[NUM_ATTRIBUTES] =
+{
+ {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
+ {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"},
+ {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}
+};
+
+#define NUM_IMAGES 4
+
+static KdImageRec Images[NUM_IMAGES] =
+{
+ XVIMAGE_YUY2,
+ XVIMAGE_YV12,
+ XVIMAGE_I420,
+ XVIMAGE_UYVY
+};
+
+static void mach64ResetVideo(KdScreenInfo *screen)
+{
+ ScreenPtr pScreen = screen->pScreen;
+ KdScreenPriv(pScreen);
+ KdCardInfo *card = pScreenPriv->card;
+ Mach64ScreenInfo *mach64s = (Mach64ScreenInfo *) screen->driver;
+ Mach64CardInfo *mach64c = (Mach64CardInfo *) card->driver;
+ Mach64PortPrivPtr pPortPriv = mach64s->pAdaptor->pPortPrivates[0].ptr;
+ MediaReg *media = mach64c->media_reg;
+
+ /*
+ * Default to maximum image size in YV12
+ */
+
+#if 0
+ media->OVERLAY_Y_X_START = MACH64_YX(0,0);
+ media->OVERLAY_Y_X_END = MACH64_YX(320,240);
+ media->OVERLAY_VIDEO_KEY_CLR = mach64s->colorKey;
+ media->OVERLAY_VIDEO_KEY_MSK = 0xffffffff;
+ media->OVERLAY_KEY_CNTL = 0;
+#endif
+}
+
+static KdVideoAdaptorPtr
+mach64SetupImageVideo(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ mach64CardInfo(pScreenPriv);
+ mach64ScreenInfo(pScreenPriv);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdCardInfo *card = pScreenPriv->card;
+ KdVideoAdaptorPtr adapt;
+ Mach64PortPrivPtr pPortPriv;
+
+ fprintf(stderr,"mach64SetupImageVideo\n");
+
+ if(!(adapt = xcalloc(1, sizeof(KdVideoAdaptorRec) +
+ sizeof(Mach64PortPrivRec) +
+ sizeof(DevUnion))))
+ return NULL;
+
+ adapt->type = XvWindowMask | XvInputMask | XvImageMask;
+ adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
+ adapt->name = "Mach64 Video Overlay";
+ adapt->nEncodings = 1;
+ adapt->pEncodings = DummyEncoding;
+ adapt->nFormats = NUM_FORMATS;
+ adapt->pFormats = Formats;
+ adapt->nPorts = 1;
+ adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
+
+ pPortPriv = (Mach64PortPrivPtr)(&adapt->pPortPrivates[1]);
+
+ adapt->pPortPrivates[0].ptr = (pointer)(pPortPriv);
+ adapt->pAttributes = Attributes;
+ adapt->nImages = NUM_IMAGES;
+ adapt->nAttributes = NUM_ATTRIBUTES;
+ adapt->pImages = Images;
+ adapt->PutVideo = NULL;
+ adapt->PutStill = NULL;
+ adapt->GetVideo = NULL;
+ adapt->GetStill = NULL;
+ adapt->StopVideo = mach64StopVideo;
+ adapt->SetPortAttribute = mach64SetPortAttribute;
+ adapt->GetPortAttribute = mach64GetPortAttribute;
+ adapt->QueryBestSize = mach64QueryBestSize;
+ adapt->PutImage = mach64PutImage;
+ adapt->QueryImageAttributes = mach64QueryImageAttributes;
+
+ pPortPriv->colorKey = mach64s->colorKey & ((1 << screen->fb[0].depth) - 1);
+ pPortPriv->videoOn = FALSE;
+ pPortPriv->brightness = 0;
+ pPortPriv->contrast = 128;
+ pPortPriv->currentBuf = 0;
+
+ /* gotta uninit this someplace */
+ REGION_INIT(pScreen, &pPortPriv->clip, NullBox, 0);
+
+ mach64s->pAdaptor = adapt;
+
+ xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
+ xvContrast = MAKE_ATOM("XV_CONTRAST");
+ xvColorKey = MAKE_ATOM("XV_COLORKEY");
+
+ mach64ResetVideo(screen);
+
+ return adapt;
+}
+
+Bool mach64InitVideo(ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ KdScreenInfo *screen = pScreenPriv->screen;
+ KdVideoAdaptorPtr *adaptors, *newAdaptors = NULL;
+ KdVideoAdaptorPtr newAdaptor = NULL;
+ int num_adaptors;
+
+ fprintf(stderr,"mach64InitVideo\n");
+
+ newAdaptor = mach64SetupImageVideo(pScreen);
+
+ num_adaptors = KdXVListGenericAdaptors(screen, &adaptors);
+
+ if(newAdaptor)
+ {
+ if(!num_adaptors)
+ {
+ num_adaptors = 1;
+ adaptors = &newAdaptor;
+ }
+ else
+ {
+ newAdaptors = xalloc((num_adaptors + 1) *
+ sizeof(KdVideoAdaptorPtr*));
+ if(newAdaptors)
+ {
+ memcpy(newAdaptors, adaptors,
+ num_adaptors * sizeof(KdVideoAdaptorPtr));
+ newAdaptors[num_adaptors] = newAdaptor;
+ adaptors = newAdaptors;
+ num_adaptors++;
+ }
+ }
+ }
+
+ if(num_adaptors)
+ KdXVScreenInit(pScreen, adaptors, num_adaptors);
+
+ if(newAdaptors)
+ xfree(newAdaptors);
+ return TRUE;
+}