📄 atimach64xv.c
字号:
pATI->pXVBuffer = NULL; outf(OVERLAY_SCALE_CNTL, SCALE_EN);}#endif /* USE_XAA *//* * ATIMach64StopVideo -- * * This is called to stop displaying a video. Note that, to prevent jittering * this doesn't actually turn off the overlay unless 'Cleanup' is TRUE, i.e. * when the video is to be actually stopped rather than temporarily disabled. */static voidATIMach64StopVideo( ScrnInfoPtr pScreenInfo, pointer Data, Bool Cleanup){ ScreenPtr pScreen = pScreenInfo->pScreen; ATIPtr pATI = Data; if (pATI->ActiveSurface) return; REGION_EMPTY(pScreen, &pATI->VideoClip);#ifdef USE_XAA if (!pATI->useEXA && !Cleanup) { /* * Free offscreen buffer if/when its allocation is needed by XAA's * pixmap cache. */ FBLinearPtr linear = (FBLinearPtr)pATI->pXVBuffer; if (linear) linear->RemoveLinearCallback = ATIMach64RemoveLinearCallback; return; }#endif /* USE_XAA */ ATIMach64XVMemFree(pScreen, pATI->pXVBuffer, pATI); pATI->pXVBuffer = NULL; outf(OVERLAY_SCALE_CNTL, SCALE_EN);}/* * ATIMach64QueryBestSize -- * * Quoting XVideo docs: * * This function provides the client with a way to query what the destination * dimensions would end up being if they were to request that an area * VideoWidth by VideoHeight from the video stream be scaled to rectangle of * DrawableWidth by DrawableHeight on the screen. Since it is not expected * that all hardware will be able to get the target dimensions exactly, it is * important that the driver provide this function. */static voidATIMach64QueryBestSize( ScrnInfoPtr pScreenInfo, Bool Motion, short VideoWidth, short VideoHeight, short DrawableWidth, short DrawableHeight, unsigned int *Width, unsigned int *Height, pointer pATI){ *Width = DrawableWidth; *Height = DrawableHeight;}/* * ATIMach64QueryImageAttributes -- * * Quoting XVideo docs: * * This function is called to let the driver specify how data for a particular * image of size Width by Height should be stored. Sometimes only the size and * corrected width and height are needed. In that case pitches and offsets are * NULL. The size of the memory required for the image is returned by this * function. The width and height of the requested image can be altered by the * driver to reflect format limitations (such as component sampling periods * that are larger than one). If pPitch and pOffset are not NULL, these will * be arrays with as many elements in them as there are planes in the image * format. The driver should specify the pitch (in bytes) of each scanline in * the particular plane as well as the offset to that plane (in bytes) from the * beginning of the image. */static intATIMach64QueryImageAttributes( ScrnInfoPtr pScreenInfo, int ImageID, unsigned short *Width, unsigned short *Height, int *pPitch, int *pOffset){ int Size, tmp; if (!Width || !Height) return 0; if (*Width > 2048) *Width = 2048; else *Width = (*Width + 1) & ~1; if (*Height > 2048) *Height = 2048; if (pOffset) pOffset[0] = 0; switch (ImageID) { case FOURCC_YV12: case FOURCC_I420: *Height = (*Height + 1) & ~1; Size = (*Width + 3) & ~3; if (pPitch) pPitch[0] = Size; Size *= *Height; if (pOffset) pOffset[1] = Size; tmp = ((*Width >> 1) + 3) & ~3; if (pPitch) pPitch[1] = pPitch[2] = tmp; tmp *= (*Height >> 1); Size += tmp; if (pOffset) pOffset[2] = Size; Size += tmp; break; case FOURCC_UYVY: case FOURCC_YUY2: Size = *Width << 1; if (pPitch) pPitch[0] = Size; Size *= *Height; break; default: Size = 0; break; } return Size;}/* * ATIMach64ScaleVideo -- * * This function is called to calculate overlay scaling factors. */static voidATIMach64ScaleVideo( ATIPtr pATI, DisplayModePtr pMode, int SrcW, int SrcH, int DstW, int DstH, CARD32 *pHScale, CARD32 *pVScale){ int Shift; *pHScale = ATIDivide(SrcW, DstW, GetBits(pATI->NewHW.pll_vclk_cntl, PLL_ECP_DIV) + 12, 0); Shift = 12; if (pMode->Flags & V_INTERLACE) Shift++; if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0)) { if (pMode->VDisplay < pATI->LCDVertical) { SrcH *= pMode->VDisplay; DstH *= pATI->LCDVertical; } } else { if (pMode->Flags & V_DBLSCAN) Shift--; if (pMode->VScan > 1) DstH *= pMode->VScan; } *pVScale = ATIDivide(SrcH, DstH, Shift, 0);}/* * ATIMach64ClipVideo -- * * Clip the video (both source and destination) and make various other * adjustments. */static BoolATIMach64ClipVideo( ScrnInfoPtr pScreenInfo, ATIPtr pATI, int ImageID, short SrcX, short SrcY, short SrcW, short SrcH, short DstX, short DstY, short *DstW, short *DstH, short Width, short Height, RegionPtr pClip, BoxPtr pDstBox, INT32 *SrcX1, INT32 *SrcX2, INT32 *SrcY1, INT32 *SrcY2, int *SrcLeft, int *SrcTop){ CARD32 HScale, VScale; /* Check hardware limits */ if ((Height <= 0) || (Height > 2048) || (Width <= 0) || (Width > 720) || ((Width > 384) && (pATI->Chip < ATI_CHIP_264VTB))) return FALSE; ATIMach64ScaleVideo(pATI, pScreenInfo->currentMode, SrcW, SrcH, *DstW, *DstH, &HScale, &VScale); if (!HScale || !VScale) return FALSE; if (HScale > MaxScale) *DstW = (*DstW * HScale) / MaxScale; if (VScale > MaxScale) *DstH = (*DstH * HScale) / MaxScale; /* Clip both the source and the destination */ *SrcX1 = SrcX; *SrcX2 = SrcX + SrcW; *SrcY1 = SrcY; *SrcY2 = SrcY + SrcH; pDstBox->x1 = DstX; pDstBox->x2 = DstX + *DstW; pDstBox->y1 = DstY; pDstBox->y2 = DstY + *DstH; if (!xf86XVClipVideoHelper(pDstBox, SrcX1, SrcX2, SrcY1, SrcY2, pClip, Width, Height)) return FALSE; /* * Reset overlay scaler origin. This prevents jittering during * viewport panning or while the video is being moved or gradually * obscured/unobscured. */ pDstBox->x1 = DstX; pDstBox->y1 = DstY; /* Translate to the current viewport */ pDstBox->x1 -= pScreenInfo->frameX0; pDstBox->x2 -= pScreenInfo->frameX0; pDstBox->y1 -= pScreenInfo->frameY0; pDstBox->y2 -= pScreenInfo->frameY0; *SrcLeft = *SrcTop = 0; /* * If the overlay scaler origin ends up outside the current viewport, move * it to the viewport's top left corner. This unavoidably causes a slight * jittering in the image (even with double-buffering). */ if (pDstBox->x1 < 0) { *SrcLeft = ((-pDstBox->x1 * SrcW) / *DstW) & ~1; pDstBox->x1 = 0; } if (pDstBox->y1 < 0) { *SrcTop = (-pDstBox->y1 * SrcH) / *DstH; pDstBox->y1 = 0; switch (ImageID) { case FOURCC_YV12: case FOURCC_I420: *SrcTop = (*SrcTop + 1) & ~1; break; default: break; } } return TRUE;}#ifdef ATIMove32/* A faster intercept */#undef xf86XVCopyPacked#define xf86XVCopyPacked ATIMach64XVCopyPackedstatic voidATIMach64XVCopyPacked( const CARD8 *pSrc, CARD8 *pDst, int SrcPitch, int DstPitch, int Height, int Width){ Width >>= 1; while (--Height >= 0) { ATIMove32(pDst, pSrc, Width); pSrc += SrcPitch; pDst += DstPitch; }}#endif/* * ATIMach64DisplayVideo -- * * This function programmes Mach64 registers needed to display a video. */static voidATIMach64DisplayVideo( ScrnInfoPtr pScreenInfo, ATIPtr pATI, BoxPtr pDstBox, int ImageID, int Offset, int Pitch, short SrcW, short SrcH, short DstW, short DstH, short Width, short Height){ DisplayModePtr pMode = pScreenInfo->currentMode; CARD32 HScale, VScale; if (pMode->VScan > 1) { pDstBox->y1 *= pMode->VScan; pDstBox->y2 *= pMode->VScan; } if (pMode->Flags & V_DBLSCAN) { pDstBox->y1 <<= 1; pDstBox->y2 <<= 1; } /* Recalculate overlay scale factors */ ATIMach64ScaleVideo(pATI, pMode, SrcW, SrcH, DstW, DstH, &HScale, &VScale); pATI->NewHW.video_format &= ~SCALER_IN; if (ImageID == FOURCC_UYVY) pATI->NewHW.video_format |= SCALER_IN_YVYU422; else pATI->NewHW.video_format |= SCALER_IN_VYUY422; ATIMach64WaitForFIFO(pATI, 8); outq(OVERLAY_Y_X_START, OVERLAY_Y_X_END, OVERLAY_LOCK_START | SetWord(pDstBox->x1, 1) | SetWord(pDstBox->y1, 0), SetWord(pDstBox->x2 - 1, 1) | SetWord(pDstBox->y2 - 1, 0)); outf(OVERLAY_SCALE_INC, SetWord(HScale, 1) | SetWord(VScale, 0)); outf(SCALER_HEIGHT_WIDTH, SetWord(Width, 1) | SetWord(Height, 0)); outf(VIDEO_FORMAT, pATI->NewHW.video_format); if (pATI->Chip < ATI_CHIP_264VTB) { outf(BUF0_OFFSET, Offset); outf(BUF0_PITCH, Pitch); } else { outf(SCALER_BUF0_OFFSET, Offset); outf(SCALER_BUF_PITCH, Pitch); } outf(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);}/* * ATIMach64PutImage -- * * This function is called to put a video image on the screen. */static intATIMach64PutImage( ScrnInfoPtr pScreenInfo, short SrcX, short SrcY, short DstX, short DstY, short SrcW, short SrcH, short DstW, short DstH, int ImageID, unsigned char *Buffer, short Width, short Height, Bool Synchronise, RegionPtr pClip, pointer Data, DrawablePtr pDraw){ ATIPtr pATI = Data; ScreenPtr pScreen; INT32 SrcX1, SrcX2, SrcY1, SrcY2; BoxRec DstBox; int SrcPitch, SrcPitchUV, DstPitch, DstSize; int SrcTop, SrcLeft, DstWidth, DstHeight; int Top, Bottom, Left, Right, nLine, nPixel, Offset; int OffsetV, OffsetU; int XVOffset; int tmp; CARD8 *pDst; if (pATI->ActiveSurface) return Success; if (!ATIMach64ClipVideo(pScreenInfo, pATI, ImageID, SrcX, SrcY, SrcW, SrcH, DstX, DstY, &DstW, &DstH, Width, Height, pClip, &DstBox, &SrcX1, &SrcX2, &SrcY1, &SrcY2, &SrcLeft, &SrcTop)) return Success; pScreen = pScreenInfo->pScreen; DstWidth = Width - SrcLeft; DstHeight = Height - SrcTop; /* * Allocate an offscreen buffer for the entire source, even though only a * subset of the source will be copied into it. */ DstPitch = /* bytes */ (DstWidth + DstWidth + 15) & ~15; DstSize = /* bytes */ (DstPitch * DstHeight); pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, (pATI->DoubleBuffer + 1) * DstSize, &XVOffset, pATI); if (!pATI->pXVBuffer) { if (!pATI->DoubleBuffer) return BadAlloc; pATI->pXVBuffer = ATIMach64XVMemAlloc(pScreen, pATI->pXVBuffer, DstSize, &XVOffset, pATI); if (!pATI->pXVBuffer) return BadAlloc; xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING, "Video image double-buffering downgraded to single-buffering\n due" " to insufficient video memory.\n"); pATI->DoubleBuffer = pATI->CurrentBuffer = 0; } else { /* Possibly switch buffers */ pATI->CurrentBuffer = pATI->DoubleBuffer - pATI->CurrentBuffer; } /* Synchronise video memory accesses */ ATIMach64Sync(pScreenInfo); Offset = XVOffset + pATI->CurrentBuffer * DstSize; pDst = pATI->pMemoryLE; pDst += Offset; switch (ImageID) { case FOURCC_YV12: case FOURCC_I420: Left = (SrcX1 >> 16) & ~1; Right = ((SrcX2 + 0x1FFFF) >> 16) & ~1; Top = (SrcY1 >> 16) & ~1; Bottom = ((SrcY2 + 0x1FFFF) >> 16) & ~1; if ((Right < Width) && ((SrcX1 & 0x1FFFF) <= (SrcX2 & 0x1FFFF))) Right += 2; if ((Bottom < Height) && ((SrcY1 & 0x1FFFF) <= (SrcY2 & 0x1FFFF))) Bottom += 2; nPixel = Right - Left; nLine = Bottom - Top; SrcPitch = (Width + 3) & ~3; OffsetV = SrcPitch * Height; SrcPitchUV = ((Width >> 1) + 3) & ~3; OffsetU = ((Height >> 1) * SrcPitchUV) + OffsetV; tmp = ((Top >> 1) * SrcPitchUV) + (Left >> 1); OffsetV += tmp; OffsetU += tmp; if (ImageID == FOURCC_I420) { tmp = OffsetV;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -