diff options
author | Keith Packard <keithp@keithp.com> | 2001-06-16 05:48:49 +0000 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2001-06-16 05:48:49 +0000 |
commit | 54aea8ec0c1c3633788fd9b19636093860c75d53 (patch) | |
tree | 974db54afd6773b3fc044378c30aae6b27a7eac1 | |
parent | f386ca6c69ba10cd8c0dd60bb25cde37ecfc8bc7 (diff) |
Patch DPMS support in kdrive/mach64, add preliminary (broken) Xv support
-rw-r--r-- | hw/kdrive/mach64/Imakefile | 13 | ||||
-rw-r--r-- | hw/kdrive/mach64/mach64.c | 84 | ||||
-rw-r--r-- | hw/kdrive/mach64/mach64.h | 88 | ||||
-rw-r--r-- | hw/kdrive/mach64/mach64draw.c | 16 | ||||
-rw-r--r-- | hw/kdrive/mach64/mach64video.c | 780 |
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; +} |