mirror of
https://github.com/X11Libre/xf86-video-nv.git
synced 2026-03-24 01:24:21 +00:00
1512 lines
38 KiB
C
1512 lines
38 KiB
C
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "xf86.h"
|
|
#include "xf86_OSproc.h"
|
|
#include "compiler.h"
|
|
#include "xf86PciInfo.h"
|
|
#include "xf86Pci.h"
|
|
#include "xf86fbman.h"
|
|
#include "regionstr.h"
|
|
|
|
#include "xf86xv.h"
|
|
#include <X11/extensions/Xv.h>
|
|
#include "xaa.h"
|
|
#include "xaalocal.h"
|
|
#include "dixstruct.h"
|
|
#include "fourcc.h"
|
|
|
|
#include "nv_include.h"
|
|
#include "nv_dma.h"
|
|
|
|
#define OFF_DELAY 500 /* milliseconds */
|
|
#define FREE_DELAY 5000
|
|
|
|
#define OFF_TIMER 0x01
|
|
#define FREE_TIMER 0x02
|
|
#define CLIENT_VIDEO_ON 0x04
|
|
|
|
#define TIMER_MASK (OFF_TIMER | FREE_TIMER)
|
|
|
|
#define NUM_BLIT_PORTS 32
|
|
|
|
typedef struct _NVPortPrivRec {
|
|
short brightness;
|
|
short contrast;
|
|
short saturation;
|
|
short hue;
|
|
RegionRec clip;
|
|
CARD32 colorKey;
|
|
Bool autopaintColorKey;
|
|
Bool doubleBuffer;
|
|
CARD32 videoStatus;
|
|
int currentBuffer;
|
|
Time videoTime;
|
|
Bool grabbedByV4L;
|
|
Bool iturbt_709;
|
|
Bool blitter;
|
|
Bool SyncToVBlank;
|
|
FBLinearPtr linear;
|
|
int pitch;
|
|
int offset;
|
|
} NVPortPrivRec, *NVPortPrivPtr;
|
|
|
|
|
|
static XF86VideoAdaptorPtr NVSetupOverlayVideo(ScreenPtr);
|
|
static XF86VideoAdaptorPtr NVSetupBlitVideo(ScreenPtr);
|
|
|
|
static void NVStopOverlay (ScrnInfoPtr);
|
|
static void NVPutOverlayImage(ScrnInfoPtr pScrnInfo,
|
|
int offset,
|
|
int id,
|
|
int dstPitch,
|
|
BoxPtr dstBox,
|
|
int x1, int y1, int x2, int y2,
|
|
short width, short height,
|
|
short src_w, short src_h,
|
|
short dst_w, short dst_h,
|
|
RegionPtr cliplist);
|
|
|
|
static int NVSetOverlayPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
|
|
static int NVGetOverlayPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
|
|
static int NVSetBlitPortAttribute(ScrnInfoPtr, Atom, INT32, pointer);
|
|
static int NVGetBlitPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer);
|
|
|
|
|
|
static void NVStopOverlayVideo(ScrnInfoPtr, pointer, Bool);
|
|
static void NVStopBlitVideo(ScrnInfoPtr, pointer, Bool);
|
|
|
|
static int NVPutImage( ScrnInfoPtr, short, short, short, short, short, short, short, short, int, unsigned char*, short, short, Bool, RegionPtr, pointer, DrawablePtr);
|
|
|
|
static void NVQueryBestSize(ScrnInfoPtr, Bool, short, short, short, short, unsigned int *, unsigned int *, pointer);
|
|
static int NVQueryImageAttributes(ScrnInfoPtr, int, unsigned short *, unsigned short *, int *, int *);
|
|
|
|
static void NVVideoTimerCallback(ScrnInfoPtr, Time);
|
|
|
|
static void NVInitOffscreenImages (ScreenPtr pScreen);
|
|
|
|
|
|
#define GET_OVERLAY_PRIVATE(pNv) \
|
|
(NVPortPrivPtr)((pNv)->overlayAdaptor->pPortPrivates[0].ptr)
|
|
|
|
#define GET_BLIT_PRIVATE(pNv) \
|
|
(NVPortPrivPtr)((pNv)->blitAdaptor->pPortPrivates[0].ptr)
|
|
|
|
#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE)
|
|
|
|
static Atom xvBrightness, xvContrast, xvColorKey, xvSaturation,
|
|
xvHue, xvAutopaintColorKey, xvSetDefaults, xvDoubleBuffer,
|
|
xvITURBT709, xvSyncToVBlank;
|
|
|
|
/* client libraries expect an encoding */
|
|
static XF86VideoEncodingRec DummyEncoding =
|
|
{
|
|
0,
|
|
"XV_IMAGE",
|
|
2046, 2046,
|
|
{1, 1}
|
|
};
|
|
|
|
#define NUM_FORMATS_ALL 6
|
|
|
|
XF86VideoFormatRec NVFormats[NUM_FORMATS_ALL] =
|
|
{
|
|
{15, TrueColor}, {16, TrueColor}, {24, TrueColor},
|
|
{15, DirectColor}, {16, DirectColor}, {24, DirectColor}
|
|
};
|
|
|
|
#define NUM_OVERLAY_ATTRIBUTES 9
|
|
XF86AttributeRec NVOverlayAttributes[NUM_OVERLAY_ATTRIBUTES] =
|
|
{
|
|
{XvSettable | XvGettable, 0, 1, "XV_DOUBLE_BUFFER"},
|
|
{XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"},
|
|
{XvSettable | XvGettable, 0, 1, "XV_AUTOPAINT_COLORKEY"},
|
|
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
|
|
{XvSettable | XvGettable, -512, 511, "XV_BRIGHTNESS"},
|
|
{XvSettable | XvGettable, 0, 8191, "XV_CONTRAST"},
|
|
{XvSettable | XvGettable, 0, 8191, "XV_SATURATION"},
|
|
{XvSettable | XvGettable, 0, 360, "XV_HUE"},
|
|
{XvSettable | XvGettable, 0, 1, "XV_ITURBT_709"}
|
|
};
|
|
|
|
#define NUM_BLIT_ATTRIBUTES 2
|
|
XF86AttributeRec NVBlitAttributes[NUM_BLIT_ATTRIBUTES] =
|
|
{
|
|
{XvSettable , 0, 0, "XV_SET_DEFAULTS"},
|
|
{XvSettable | XvGettable, 0, 1, "XV_SYNC_TO_VBLANK"}
|
|
};
|
|
|
|
|
|
#define NUM_IMAGES_YUV 4
|
|
#define NUM_IMAGES_ALL 5
|
|
|
|
#define FOURCC_RGB 0x0000003
|
|
#define XVIMAGE_RGB \
|
|
{ \
|
|
FOURCC_RGB, \
|
|
XvRGB, \
|
|
LSBFirst, \
|
|
{ 0x03, 0x00, 0x00, 0x00, \
|
|
0x00,0x00,0x00,0x10,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71}, \
|
|
32, \
|
|
XvPacked, \
|
|
1, \
|
|
24, 0x00ff0000, 0x0000ff00, 0x000000ff, \
|
|
0, 0, 0, \
|
|
0, 0, 0, \
|
|
0, 0, 0, \
|
|
{'B','G','R','X',\
|
|
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, \
|
|
XvTopToBottom \
|
|
}
|
|
|
|
static XF86ImageRec NVImages[NUM_IMAGES_ALL] =
|
|
{
|
|
XVIMAGE_YUY2,
|
|
XVIMAGE_YV12,
|
|
XVIMAGE_UYVY,
|
|
XVIMAGE_I420,
|
|
XVIMAGE_RGB
|
|
};
|
|
|
|
static void
|
|
NVSetPortDefaults (ScrnInfoPtr pScrnInfo, NVPortPrivPtr pPriv)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
|
|
pPriv->brightness = 0;
|
|
pPriv->contrast = 4096;
|
|
pPriv->saturation = 4096;
|
|
pPriv->hue = 0;
|
|
pPriv->colorKey = pNv->videoKey;
|
|
pPriv->autopaintColorKey = TRUE;
|
|
pPriv->doubleBuffer = TRUE;
|
|
pPriv->iturbt_709 = FALSE;
|
|
}
|
|
|
|
|
|
void
|
|
NVResetVideo (ScrnInfoPtr pScrnInfo)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
int satSine, satCosine;
|
|
double angle;
|
|
|
|
angle = (double)pPriv->hue * 3.1415927 / 180.0;
|
|
|
|
satSine = pPriv->saturation * sin(angle);
|
|
if (satSine < -1024)
|
|
satSine = -1024;
|
|
satCosine = pPriv->saturation * cos(angle);
|
|
if (satCosine < -1024)
|
|
satCosine = -1024;
|
|
|
|
pNv->PMC[0x8910/4] = (pPriv->brightness << 16) | pPriv->contrast;
|
|
pNv->PMC[0x8914/4] = (pPriv->brightness << 16) | pPriv->contrast;
|
|
pNv->PMC[0x8918/4] = (satSine << 16) | (satCosine & 0xffff);
|
|
pNv->PMC[0x891C/4] = (satSine << 16) | (satCosine & 0xffff);
|
|
pNv->PMC[0x8b00/4] = pPriv->colorKey;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
NVStopOverlay (ScrnInfoPtr pScrnInfo)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
|
|
pNv->PMC[0x00008704/4] = 1;
|
|
}
|
|
|
|
static FBLinearPtr
|
|
NVAllocateOverlayMemory(
|
|
ScrnInfoPtr pScrn,
|
|
FBLinearPtr linear,
|
|
int size
|
|
){
|
|
ScreenPtr pScreen;
|
|
FBLinearPtr new_linear;
|
|
|
|
if(linear) {
|
|
if(linear->size >= size)
|
|
return linear;
|
|
|
|
if(xf86ResizeOffscreenLinear(linear, size))
|
|
return linear;
|
|
|
|
xf86FreeOffscreenLinear(linear);
|
|
}
|
|
|
|
pScreen = screenInfo.screens[pScrn->scrnIndex];
|
|
|
|
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
|
|
NULL, NULL, NULL);
|
|
|
|
if(!new_linear) {
|
|
int max_size;
|
|
|
|
xf86QueryLargestOffscreenLinear(pScreen, &max_size, 32,
|
|
PRIORITY_EXTREME);
|
|
|
|
if(max_size < size)
|
|
return NULL;
|
|
|
|
xf86PurgeUnlockedOffscreenAreas(pScreen);
|
|
new_linear = xf86AllocateOffscreenLinear(pScreen, size, 32,
|
|
NULL, NULL, NULL);
|
|
}
|
|
|
|
return new_linear;
|
|
}
|
|
|
|
static void NVFreeOverlayMemory(ScrnInfoPtr pScrnInfo)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
|
|
if(pPriv->linear) {
|
|
xf86FreeOffscreenLinear(pPriv->linear);
|
|
pPriv->linear = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
static void NVFreeBlitMemory(ScrnInfoPtr pScrnInfo)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
|
|
|
|
if(pPriv->linear) {
|
|
xf86FreeOffscreenLinear(pPriv->linear);
|
|
pPriv->linear = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void NVInitVideo (ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
|
|
XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL;
|
|
XF86VideoAdaptorPtr overlayAdaptor = NULL;
|
|
XF86VideoAdaptorPtr blitAdaptor = NULL;
|
|
NVPtr pNv = NVPTR(pScrn);
|
|
int num_adaptors;
|
|
|
|
if((pScrn->bitsPerPixel != 8) && (pNv->Architecture >= NV_ARCH_10) &&
|
|
((pNv->Architecture <= NV_ARCH_30) ||
|
|
((pNv->Chipset & 0xfff0) == 0x0040)))
|
|
{
|
|
overlayAdaptor = NVSetupOverlayVideo(pScreen);
|
|
|
|
if(overlayAdaptor)
|
|
NVInitOffscreenImages(pScreen);
|
|
}
|
|
|
|
if((pScrn->bitsPerPixel != 8) && !pNv->NoAccel)
|
|
blitAdaptor = NVSetupBlitVideo(pScreen);
|
|
|
|
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
|
|
|
|
if(blitAdaptor || overlayAdaptor) {
|
|
int size = num_adaptors;
|
|
|
|
if(overlayAdaptor) size++;
|
|
if(blitAdaptor) size++;
|
|
|
|
if((newAdaptors = malloc(size * sizeof(XF86VideoAdaptorPtr*)))) {
|
|
if(num_adaptors) {
|
|
memcpy(newAdaptors, adaptors,
|
|
num_adaptors * sizeof(XF86VideoAdaptorPtr));
|
|
}
|
|
if(overlayAdaptor) {
|
|
newAdaptors[num_adaptors] = overlayAdaptor;
|
|
num_adaptors++;
|
|
}
|
|
if(blitAdaptor) {
|
|
newAdaptors[num_adaptors] = blitAdaptor;
|
|
num_adaptors++;
|
|
}
|
|
adaptors = newAdaptors;
|
|
}
|
|
}
|
|
|
|
if (num_adaptors)
|
|
xf86XVScreenInit(pScreen, adaptors, num_adaptors);
|
|
|
|
if (newAdaptors)
|
|
free(newAdaptors);
|
|
}
|
|
|
|
|
|
static XF86VideoAdaptorPtr
|
|
NVSetupBlitVideo (ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
XF86VideoAdaptorPtr adapt;
|
|
NVPortPrivPtr pPriv;
|
|
int i;
|
|
|
|
if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
|
|
sizeof(NVPortPrivRec) +
|
|
(sizeof(DevUnion) * NUM_BLIT_PORTS))))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
|
|
adapt->flags = 0;
|
|
adapt->name = "NV Video Blitter";
|
|
adapt->nEncodings = 1;
|
|
adapt->pEncodings = &DummyEncoding;
|
|
adapt->nFormats = NUM_FORMATS_ALL;
|
|
adapt->pFormats = NVFormats;
|
|
adapt->nPorts = NUM_BLIT_PORTS;
|
|
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
|
|
|
|
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[NUM_BLIT_PORTS]);
|
|
for(i = 0; i < NUM_BLIT_PORTS; i++)
|
|
adapt->pPortPrivates[i].ptr = (pointer)(pPriv);
|
|
|
|
if(pNv->WaitVSyncPossible) {
|
|
adapt->pAttributes = NVBlitAttributes;
|
|
adapt->nAttributes = NUM_BLIT_ATTRIBUTES;
|
|
} else {
|
|
adapt->pAttributes = NULL;
|
|
adapt->nAttributes = 0;
|
|
}
|
|
adapt->pImages = NVImages;
|
|
adapt->nImages = NUM_IMAGES_ALL;
|
|
adapt->PutVideo = NULL;
|
|
adapt->PutStill = NULL;
|
|
adapt->GetVideo = NULL;
|
|
adapt->GetStill = NULL;
|
|
adapt->StopVideo = NVStopBlitVideo;
|
|
adapt->SetPortAttribute = NVSetBlitPortAttribute;
|
|
adapt->GetPortAttribute = NVGetBlitPortAttribute;
|
|
adapt->QueryBestSize = NVQueryBestSize;
|
|
adapt->PutImage = NVPutImage;
|
|
adapt->QueryImageAttributes = NVQueryImageAttributes;
|
|
|
|
pPriv->videoStatus = 0;
|
|
pPriv->grabbedByV4L = FALSE;
|
|
pPriv->blitter = TRUE;
|
|
pPriv->doubleBuffer = FALSE;
|
|
pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
|
|
|
|
pNv->blitAdaptor = adapt;
|
|
|
|
xvSyncToVBlank = MAKE_ATOM("XV_SYNC_TO_VBLANK");
|
|
|
|
return adapt;
|
|
}
|
|
|
|
static XF86VideoAdaptorPtr
|
|
NVSetupOverlayVideo (ScreenPtr pScreen)
|
|
{
|
|
ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
XF86VideoAdaptorPtr adapt;
|
|
NVPortPrivPtr pPriv;
|
|
|
|
if (!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) +
|
|
sizeof(NVPortPrivRec) +
|
|
sizeof(DevUnion))))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
adapt->type = XvWindowMask | XvInputMask | XvImageMask;
|
|
adapt->flags = VIDEO_OVERLAID_IMAGES|VIDEO_CLIP_TO_VIEWPORT;
|
|
adapt->name = "NV Video Overlay";
|
|
adapt->nEncodings = 1;
|
|
adapt->pEncodings = &DummyEncoding;
|
|
adapt->nFormats = NUM_FORMATS_ALL;
|
|
adapt->pFormats = NVFormats;
|
|
adapt->nPorts = 1;
|
|
adapt->pPortPrivates = (DevUnion*)(&adapt[1]);
|
|
pPriv = (NVPortPrivPtr)(&adapt->pPortPrivates[1]);
|
|
adapt->pPortPrivates[0].ptr = (pointer)(pPriv);
|
|
adapt->pAttributes = NVOverlayAttributes;
|
|
adapt->nAttributes = NUM_OVERLAY_ATTRIBUTES;
|
|
adapt->pImages = NVImages;
|
|
adapt->nImages = NUM_IMAGES_YUV;
|
|
adapt->PutVideo = NULL;
|
|
adapt->PutStill = NULL;
|
|
adapt->GetVideo = NULL;
|
|
adapt->GetStill = NULL;
|
|
adapt->StopVideo = NVStopOverlayVideo;
|
|
adapt->SetPortAttribute = NVSetOverlayPortAttribute;
|
|
adapt->GetPortAttribute = NVGetOverlayPortAttribute;
|
|
adapt->QueryBestSize = NVQueryBestSize;
|
|
adapt->PutImage = NVPutImage;
|
|
adapt->QueryImageAttributes = NVQueryImageAttributes;
|
|
|
|
pPriv->videoStatus = 0;
|
|
pPriv->currentBuffer = 0;
|
|
pPriv->grabbedByV4L = FALSE;
|
|
pPriv->blitter = FALSE;
|
|
|
|
NVSetPortDefaults (pScrnInfo, pPriv);
|
|
|
|
/* gotta uninit this someplace */
|
|
REGION_NULL(pScreen, &pPriv->clip);
|
|
|
|
pNv->overlayAdaptor = adapt;
|
|
|
|
xvBrightness = MAKE_ATOM("XV_BRIGHTNESS");
|
|
xvDoubleBuffer = MAKE_ATOM("XV_DOUBLE_BUFFER");
|
|
xvContrast = MAKE_ATOM("XV_CONTRAST");
|
|
xvColorKey = MAKE_ATOM("XV_COLORKEY");
|
|
xvSaturation = MAKE_ATOM("XV_SATURATION");
|
|
xvHue = MAKE_ATOM("XV_HUE");
|
|
xvAutopaintColorKey = MAKE_ATOM("XV_AUTOPAINT_COLORKEY");
|
|
xvSetDefaults = MAKE_ATOM("XV_SET_DEFAULTS");
|
|
xvITURBT709 = MAKE_ATOM("XV_ITURBT_709");
|
|
|
|
NVResetVideo(pScrnInfo);
|
|
|
|
return adapt;
|
|
}
|
|
|
|
static void
|
|
NVPutOverlayImage (
|
|
ScrnInfoPtr pScrnInfo,
|
|
int offset,
|
|
int id,
|
|
int dstPitch,
|
|
BoxPtr dstBox,
|
|
int x1,
|
|
int y1,
|
|
int x2,
|
|
int y2,
|
|
short width,
|
|
short height,
|
|
short src_w,
|
|
short src_h,
|
|
short drw_w,
|
|
short drw_h,
|
|
RegionPtr clipBoxes
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
int buffer = pPriv->currentBuffer;
|
|
|
|
/* paint the color key */
|
|
if(pPriv->autopaintColorKey &&
|
|
(pPriv->grabbedByV4L ||
|
|
!REGION_EQUAL(pScrnInfo->pScreen, &pPriv->clip, clipBoxes)))
|
|
{
|
|
/* we always paint V4L's color key */
|
|
if(!pPriv->grabbedByV4L)
|
|
REGION_COPY(pScrnInfo->pScreen, &pPriv->clip, clipBoxes);
|
|
xf86XVFillKeyHelper(pScrnInfo->pScreen, pPriv->colorKey, clipBoxes);
|
|
}
|
|
|
|
if(pNv->CurrentLayout.mode->Flags & V_DBLSCAN) {
|
|
dstBox->y1 <<= 1;
|
|
dstBox->y2 <<= 1;
|
|
drw_h <<= 1;
|
|
}
|
|
|
|
pNv->PMC[(0x8900/4) + buffer] = offset;
|
|
pNv->PMC[(0x8928/4) + buffer] = (height << 16) | width;
|
|
pNv->PMC[(0x8930/4) + buffer] = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
|
|
pNv->PMC[(0x8938/4) + buffer] = (src_w << 20) / drw_w;
|
|
pNv->PMC[(0x8940/4) + buffer] = (src_h << 20) / drw_h;
|
|
pNv->PMC[(0x8948/4) + buffer] = (dstBox->y1 << 16) | dstBox->x1;
|
|
pNv->PMC[(0x8950/4) + buffer] = ((dstBox->y2 - dstBox->y1) << 16) |
|
|
(dstBox->x2 - dstBox->x1);
|
|
|
|
dstPitch |= 1 << 20; /* use color key */
|
|
|
|
if(id != FOURCC_UYVY)
|
|
dstPitch |= 1 << 16;
|
|
if(pPriv->iturbt_709)
|
|
dstPitch |= 1 << 24;
|
|
|
|
pNv->PMC[(0x8958/4) + buffer] = dstPitch;
|
|
pNv->PMC[0x00008704/4] = 0;
|
|
pNv->PMC[0x8700/4] = 1 << (buffer << 2);
|
|
|
|
pPriv->videoStatus = CLIENT_VIDEO_ON;
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
NVPutBlitImage (
|
|
ScrnInfoPtr pScrnInfo,
|
|
int offset,
|
|
int id,
|
|
int dstPitch,
|
|
BoxPtr dstBox,
|
|
int x1,
|
|
int y1,
|
|
int x2,
|
|
int y2,
|
|
short width,
|
|
short height,
|
|
short src_w,
|
|
short src_h,
|
|
short drw_w,
|
|
short drw_h,
|
|
RegionPtr clipBoxes
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_BLIT_PRIVATE(pNv);
|
|
BoxPtr pbox = REGION_RECTS(clipBoxes);
|
|
int nbox = REGION_NUM_RECTS(clipBoxes);
|
|
CARD32 dsdx, dtdy, size, point, srcpoint, format;
|
|
|
|
dsdx = (src_w << 20) / drw_w;
|
|
dtdy = (src_h << 20) / drw_h;
|
|
|
|
size = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1);
|
|
point = (dstBox->y1 << 16) | dstBox->x1;
|
|
|
|
dstPitch |= (STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER << 16) |
|
|
(STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR << 24);
|
|
|
|
srcpoint = ((y1 << 4) & 0xffff0000) | (x1 >> 12);
|
|
|
|
switch(id) {
|
|
case FOURCC_RGB:
|
|
format = STRETCH_BLIT_FORMAT_X8R8G8B8;
|
|
break;
|
|
case FOURCC_UYVY:
|
|
format = STRETCH_BLIT_FORMAT_UYVY;
|
|
break;
|
|
default:
|
|
format = STRETCH_BLIT_FORMAT_YUYV;
|
|
break;
|
|
}
|
|
|
|
if(pNv->CurrentLayout.depth == 15) {
|
|
NVDmaStart(pNv, SURFACE_FORMAT, 1);
|
|
NVDmaNext (pNv, SURFACE_FORMAT_DEPTH15);
|
|
}
|
|
|
|
if(pPriv->SyncToVBlank) {
|
|
NVDmaKickoff(pNv);
|
|
NVWaitVSync(pNv);
|
|
}
|
|
|
|
if(pNv->BlendingPossible) {
|
|
NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 2);
|
|
NVDmaNext (pNv, format);
|
|
NVDmaNext (pNv, STRETCH_BLIT_OPERATION_COPY);
|
|
} else {
|
|
NVDmaStart(pNv, STRETCH_BLIT_FORMAT, 1);
|
|
NVDmaNext (pNv, format);
|
|
}
|
|
|
|
while(nbox--) {
|
|
NVDmaStart(pNv, RECT_SOLID_COLOR, 1);
|
|
NVDmaNext (pNv, 0);
|
|
|
|
NVDmaStart(pNv, STRETCH_BLIT_CLIP_POINT, 6);
|
|
NVDmaNext (pNv, (pbox->y1 << 16) | pbox->x1);
|
|
NVDmaNext (pNv, ((pbox->y2 - pbox->y1) << 16) | (pbox->x2 - pbox->x1));
|
|
NVDmaNext (pNv, point);
|
|
NVDmaNext (pNv, size);
|
|
NVDmaNext (pNv, dsdx);
|
|
NVDmaNext (pNv, dtdy);
|
|
|
|
NVDmaStart(pNv, STRETCH_BLIT_SRC_SIZE, 4);
|
|
NVDmaNext (pNv, (height << 16) | width);
|
|
NVDmaNext (pNv, dstPitch);
|
|
NVDmaNext (pNv, offset);
|
|
NVDmaNext (pNv, srcpoint);
|
|
pbox++;
|
|
}
|
|
|
|
if(pNv->CurrentLayout.depth == 15) {
|
|
NVDmaStart(pNv, SURFACE_FORMAT, 1);
|
|
NVDmaNext (pNv, SURFACE_FORMAT_DEPTH16);
|
|
}
|
|
|
|
NVDmaKickoff(pNv);
|
|
SET_SYNC_FLAG(pNv->AccelInfoRec);
|
|
|
|
pPriv->videoStatus = FREE_TIMER;
|
|
pPriv->videoTime = currentTime.milliseconds + FREE_DELAY;
|
|
pNv->VideoTimerCallback = NVVideoTimerCallback;
|
|
}
|
|
|
|
/*
|
|
* StopVideo
|
|
*/
|
|
static void NVStopOverlayVideo
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
pointer data,
|
|
Bool Exit
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
|
|
if(pPriv->grabbedByV4L) return;
|
|
|
|
REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
|
|
|
|
if(Exit) {
|
|
if(pPriv->videoStatus & CLIENT_VIDEO_ON)
|
|
NVStopOverlay(pScrnInfo);
|
|
NVFreeOverlayMemory(pScrnInfo);
|
|
pPriv->videoStatus = 0;
|
|
} else {
|
|
if(pPriv->videoStatus & CLIENT_VIDEO_ON) {
|
|
pPriv->videoStatus = OFF_TIMER | CLIENT_VIDEO_ON;
|
|
pPriv->videoTime = currentTime.milliseconds + OFF_DELAY;
|
|
pNv->VideoTimerCallback = NVVideoTimerCallback;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void NVStopBlitVideo
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
pointer data,
|
|
Bool Exit
|
|
)
|
|
{
|
|
}
|
|
|
|
static int NVSetOverlayPortAttribute
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 value,
|
|
pointer data
|
|
)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
|
|
if (attribute == xvBrightness)
|
|
{
|
|
if ((value < -512) || (value > 512))
|
|
return BadValue;
|
|
pPriv->brightness = value;
|
|
}
|
|
else if (attribute == xvDoubleBuffer)
|
|
{
|
|
if ((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->doubleBuffer = value;
|
|
}
|
|
else if (attribute == xvContrast)
|
|
{
|
|
if ((value < 0) || (value > 8191))
|
|
return BadValue;
|
|
pPriv->contrast = value;
|
|
}
|
|
else if (attribute == xvHue)
|
|
{
|
|
value %= 360;
|
|
if (value < 0)
|
|
value += 360;
|
|
pPriv->hue = value;
|
|
}
|
|
else if (attribute == xvSaturation)
|
|
{
|
|
if ((value < 0) || (value > 8191))
|
|
return BadValue;
|
|
pPriv->saturation = value;
|
|
}
|
|
else if (attribute == xvColorKey)
|
|
{
|
|
pPriv->colorKey = value;
|
|
REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
|
|
}
|
|
else if (attribute == xvAutopaintColorKey)
|
|
{
|
|
if ((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->autopaintColorKey = value;
|
|
}
|
|
else if (attribute == xvITURBT709)
|
|
{
|
|
if ((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->iturbt_709 = value;
|
|
}
|
|
else if (attribute == xvSetDefaults)
|
|
{
|
|
NVSetPortDefaults(pScrnInfo, pPriv);
|
|
}
|
|
else
|
|
return BadMatch;
|
|
|
|
NVResetVideo(pScrnInfo);
|
|
return Success;
|
|
}
|
|
|
|
|
|
static int NVGetOverlayPortAttribute
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 *value,
|
|
pointer data
|
|
)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
|
|
if (attribute == xvBrightness)
|
|
*value = pPriv->brightness;
|
|
else if (attribute == xvDoubleBuffer)
|
|
*value = (pPriv->doubleBuffer) ? 1 : 0;
|
|
else if (attribute == xvContrast)
|
|
*value = pPriv->contrast;
|
|
else if (attribute == xvSaturation)
|
|
*value = pPriv->saturation;
|
|
else if (attribute == xvHue)
|
|
*value = pPriv->hue;
|
|
else if (attribute == xvColorKey)
|
|
*value = pPriv->colorKey;
|
|
else if (attribute == xvAutopaintColorKey)
|
|
*value = (pPriv->autopaintColorKey) ? 1 : 0;
|
|
else if (attribute == xvITURBT709)
|
|
*value = (pPriv->iturbt_709) ? 1 : 0;
|
|
else
|
|
return BadMatch;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int NVSetBlitPortAttribute
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 value,
|
|
pointer data
|
|
)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
|
|
if ((attribute == xvSyncToVBlank) && pNv->WaitVSyncPossible) {
|
|
if ((value < 0) || (value > 1))
|
|
return BadValue;
|
|
pPriv->SyncToVBlank = value;
|
|
} else
|
|
if (attribute == xvSetDefaults) {
|
|
pPriv->SyncToVBlank = pNv->WaitVSyncPossible;
|
|
} else
|
|
return BadMatch;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int NVGetBlitPortAttribute
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 *value,
|
|
pointer data
|
|
)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
|
|
if(attribute == xvSyncToVBlank)
|
|
*value = (pPriv->SyncToVBlank) ? 1 : 0;
|
|
else
|
|
return BadMatch;
|
|
|
|
return Success;
|
|
}
|
|
|
|
|
|
/*
|
|
* QueryBestSize
|
|
*/
|
|
static void NVQueryBestSize
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Bool motion,
|
|
short vid_w,
|
|
short vid_h,
|
|
short drw_w,
|
|
short drw_h,
|
|
unsigned int *p_w,
|
|
unsigned int *p_h,
|
|
pointer data
|
|
)
|
|
{
|
|
if(vid_w > (drw_w << 3))
|
|
drw_w = vid_w >> 3;
|
|
if(vid_h > (drw_h << 3))
|
|
drw_h = vid_h >> 3;
|
|
|
|
*p_w = drw_w;
|
|
*p_h = drw_h;
|
|
}
|
|
|
|
static void NVCopyData420
|
|
(
|
|
unsigned char *src1,
|
|
unsigned char *src2,
|
|
unsigned char *src3,
|
|
unsigned char *dst1,
|
|
int srcPitch,
|
|
int srcPitch2,
|
|
int dstPitch,
|
|
int h,
|
|
int w
|
|
)
|
|
{
|
|
CARD32 *dst;
|
|
CARD8 *s1, *s2, *s3;
|
|
int i, j;
|
|
|
|
w >>= 1;
|
|
|
|
for(j = 0; j < h; j++) {
|
|
dst = (CARD32*)dst1;
|
|
s1 = src1; s2 = src2; s3 = src3;
|
|
i = w;
|
|
while(i > 4) {
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
|
|
dst[1] = (s1[2] << 24) | (s1[3] << 8) | (s3[1] << 16) | s2[1];
|
|
dst[2] = (s1[4] << 24) | (s1[5] << 8) | (s3[2] << 16) | s2[2];
|
|
dst[3] = (s1[6] << 24) | (s1[7] << 8) | (s3[3] << 16) | s2[3];
|
|
#else
|
|
dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
|
|
dst[1] = s1[2] | (s1[3] << 16) | (s3[1] << 8) | (s2[1] << 24);
|
|
dst[2] = s1[4] | (s1[5] << 16) | (s3[2] << 8) | (s2[2] << 24);
|
|
dst[3] = s1[6] | (s1[7] << 16) | (s3[3] << 8) | (s2[3] << 24);
|
|
#endif
|
|
dst += 4; s2 += 4; s3 += 4; s1 += 8;
|
|
i -= 4;
|
|
}
|
|
|
|
while(i--) {
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
dst[0] = (s1[0] << 24) | (s1[1] << 8) | (s3[0] << 16) | s2[0];
|
|
#else
|
|
dst[0] = s1[0] | (s1[1] << 16) | (s3[0] << 8) | (s2[0] << 24);
|
|
#endif
|
|
dst++; s2++; s3++;
|
|
s1 += 2;
|
|
}
|
|
|
|
dst1 += dstPitch;
|
|
src1 += srcPitch;
|
|
if(j & 1) {
|
|
src2 += srcPitch2;
|
|
src3 += srcPitch2;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
static void NVMoveDWORDS(
|
|
CARD32* dest,
|
|
CARD32* src,
|
|
int dwords )
|
|
{
|
|
while(dwords & ~0x03) {
|
|
*dest = *src;
|
|
*(dest + 1) = *(src + 1);
|
|
*(dest + 2) = *(src + 2);
|
|
*(dest + 3) = *(src + 3);
|
|
src += 4;
|
|
dest += 4;
|
|
dwords -= 4;
|
|
}
|
|
if(!dwords) return;
|
|
*dest = *src;
|
|
if(dwords == 1) return;
|
|
*(dest + 1) = *(src + 1);
|
|
if(dwords == 2) return;
|
|
*(dest + 2) = *(src + 2);
|
|
}
|
|
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
static void NVMoveDWORDSSwapped(
|
|
CARD32* dest,
|
|
CARD8* src,
|
|
int dwords )
|
|
{
|
|
while(dwords--) {
|
|
*dest++ = (src[3] << 24) | (src[2] << 16) | (src[1] << 8) | src[0];
|
|
src += 4;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
static void NVCopyData422
|
|
(
|
|
unsigned char *src,
|
|
unsigned char *dst,
|
|
int srcPitch,
|
|
int dstPitch,
|
|
int h,
|
|
int w
|
|
)
|
|
{
|
|
w >>= 1; /* pixels to DWORDS */
|
|
while(h--) {
|
|
NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
|
|
src += srcPitch;
|
|
dst += dstPitch;
|
|
}
|
|
}
|
|
|
|
static void NVCopyDataRGB
|
|
(
|
|
unsigned char *src,
|
|
unsigned char *dst,
|
|
int srcPitch,
|
|
int dstPitch,
|
|
int h,
|
|
int w
|
|
)
|
|
{
|
|
while(h--) {
|
|
#if X_BYTE_ORDER == X_BIG_ENDIAN
|
|
NVMoveDWORDSSwapped((CARD32*)dst, (CARD8*)src, w);
|
|
#else
|
|
NVMoveDWORDS((CARD32*)dst, (CARD32*)src, w);
|
|
#endif
|
|
src += srcPitch;
|
|
dst += dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* PutImage
|
|
*/
|
|
static int NVPutImage
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
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,
|
|
DrawablePtr pDraw
|
|
)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)data;
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
INT32 xa, xb, ya, yb;
|
|
unsigned char *dst_start;
|
|
int newSize, offset, s2offset, s3offset;
|
|
int srcPitch, srcPitch2, dstPitch;
|
|
int top, left, right, bottom, npixels, nlines, bpp;
|
|
Bool skip = FALSE;
|
|
BoxRec dstBox;
|
|
CARD32 tmp;
|
|
|
|
/*
|
|
* s2offset, s3offset - byte offsets into U and V plane of the
|
|
* source where copying starts. Y plane is
|
|
* done by editing "buf".
|
|
*
|
|
* offset - byte offset to the first line of the destination.
|
|
*
|
|
* dst_start - byte address to the first displayed pel.
|
|
*
|
|
*/
|
|
|
|
if(pPriv->grabbedByV4L) return Success;
|
|
|
|
/* make the compiler happy */
|
|
s2offset = s3offset = srcPitch2 = 0;
|
|
|
|
if(!pPriv->blitter) {
|
|
if(src_w > (drw_w << 3))
|
|
drw_w = src_w >> 3;
|
|
if(src_h > (drw_h << 3))
|
|
drw_h = src_h >> 3;
|
|
}
|
|
|
|
/* Clip */
|
|
xa = src_x;
|
|
xb = src_x + src_w;
|
|
ya = src_y;
|
|
yb = src_y + src_h;
|
|
|
|
dstBox.x1 = drw_x;
|
|
dstBox.x2 = drw_x + drw_w;
|
|
dstBox.y1 = drw_y;
|
|
dstBox.y2 = drw_y + drw_h;
|
|
|
|
if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
|
|
width, height))
|
|
return Success;
|
|
|
|
if(!pPriv->blitter) {
|
|
dstBox.x1 -= pScrnInfo->frameX0;
|
|
dstBox.x2 -= pScrnInfo->frameX0;
|
|
dstBox.y1 -= pScrnInfo->frameY0;
|
|
dstBox.y2 -= pScrnInfo->frameY0;
|
|
}
|
|
|
|
bpp = pScrnInfo->bitsPerPixel >> 3;
|
|
|
|
switch(id) {
|
|
case FOURCC_YV12:
|
|
case FOURCC_I420:
|
|
srcPitch = (width + 3) & ~3; /* of luma */
|
|
s2offset = srcPitch * height;
|
|
srcPitch2 = ((width >> 1) + 3) & ~3;
|
|
s3offset = (srcPitch2 * (height >> 1)) + s2offset;
|
|
dstPitch = ((width << 1) + 63) & ~63;
|
|
break;
|
|
case FOURCC_UYVY:
|
|
case FOURCC_YUY2:
|
|
srcPitch = width << 1;
|
|
dstPitch = ((width << 1) + 63) & ~63;
|
|
break;
|
|
case FOURCC_RGB:
|
|
srcPitch = width << 2;
|
|
dstPitch = ((width << 2) + 63) & ~63;
|
|
break;
|
|
default:
|
|
return BadImplementation;
|
|
}
|
|
|
|
newSize = height * dstPitch / bpp;
|
|
|
|
if(pPriv->doubleBuffer)
|
|
newSize <<= 1;
|
|
|
|
pPriv->linear = NVAllocateOverlayMemory(pScrnInfo,
|
|
pPriv->linear,
|
|
newSize);
|
|
|
|
if(!pPriv->linear) return BadAlloc;
|
|
|
|
offset = pPriv->linear->offset * bpp;
|
|
|
|
if(pPriv->doubleBuffer) {
|
|
int mask = 1 << (pPriv->currentBuffer << 2);
|
|
|
|
#if 0
|
|
/* burn the CPU until the next buffer is available */
|
|
while(pNv->PMC[0x00008700/4] & mask);
|
|
#else
|
|
/* overwrite the newest buffer if there's not one free */
|
|
if(pNv->PMC[0x00008700/4] & mask) {
|
|
if(!pPriv->currentBuffer)
|
|
offset += (newSize * bpp) >> 1;
|
|
skip = TRUE;
|
|
} else
|
|
#endif
|
|
if(pPriv->currentBuffer)
|
|
offset += (newSize * bpp) >> 1;
|
|
}
|
|
|
|
dst_start = pNv->FbStart + offset;
|
|
|
|
/* We need to enlarge the copied rectangle by a pixel so the HW
|
|
filtering doesn't pick up junk laying outside of the source */
|
|
|
|
left = (xa - 0x00010000) >> 16;
|
|
if(left < 0) left = 0;
|
|
top = (ya - 0x00010000) >> 16;
|
|
if(top < 0) top = 0;
|
|
right = (xb + 0x0001ffff) >> 16;
|
|
if(right > width) right = width;
|
|
bottom = (yb + 0x0001ffff) >> 16;
|
|
if(bottom > height) bottom = height;
|
|
|
|
if(pPriv->blitter) NVSync(pScrnInfo);
|
|
|
|
switch(id) {
|
|
case FOURCC_YV12:
|
|
case FOURCC_I420:
|
|
left &= ~1;
|
|
npixels = ((right + 1) & ~1) - left;
|
|
top &= ~1;
|
|
nlines = ((bottom + 1) & ~1) - top;
|
|
|
|
dst_start += (left << 1) + (top * dstPitch);
|
|
tmp = ((top >> 1) * srcPitch2) + (left >> 1);
|
|
s2offset += tmp;
|
|
s3offset += tmp;
|
|
if(id == FOURCC_I420) {
|
|
tmp = s2offset;
|
|
s2offset = s3offset;
|
|
s3offset = tmp;
|
|
}
|
|
NVCopyData420(buf + (top * srcPitch) + left,
|
|
buf + s2offset, buf + s3offset,
|
|
dst_start, srcPitch, srcPitch2,
|
|
dstPitch, nlines, npixels);
|
|
break;
|
|
case FOURCC_UYVY:
|
|
case FOURCC_YUY2:
|
|
left &= ~1;
|
|
npixels = ((right + 1) & ~1) - left;
|
|
nlines = bottom - top;
|
|
|
|
left <<= 1;
|
|
buf += (top * srcPitch) + left;
|
|
dst_start += left + (top * dstPitch);
|
|
|
|
NVCopyData422(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
|
|
break;
|
|
case FOURCC_RGB:
|
|
npixels = right - left;
|
|
nlines = bottom - top;
|
|
|
|
left <<= 2;
|
|
buf += (top * srcPitch) + left;
|
|
dst_start += left + (top * dstPitch);
|
|
|
|
NVCopyDataRGB(buf, dst_start, srcPitch, dstPitch, nlines, npixels);
|
|
break;
|
|
default:
|
|
return BadImplementation;
|
|
}
|
|
|
|
if(!skip) {
|
|
if(pPriv->blitter) {
|
|
NVPutBlitImage(pScrnInfo, offset, id, dstPitch, &dstBox,
|
|
xa, ya, xb, yb,
|
|
width, height, src_w, src_h, drw_w, drw_h,
|
|
clipBoxes);
|
|
} else {
|
|
NVPutOverlayImage(pScrnInfo, offset, id, dstPitch, &dstBox,
|
|
xa, ya, xb, yb,
|
|
width, height, src_w, src_h, drw_w, drw_h,
|
|
clipBoxes);
|
|
pPriv->currentBuffer ^= 1;
|
|
}
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
/*
|
|
* QueryImageAttributes
|
|
*/
|
|
static int NVQueryImageAttributes
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
int id,
|
|
unsigned short *w,
|
|
unsigned short *h,
|
|
int *pitches,
|
|
int *offsets
|
|
)
|
|
{
|
|
int size, tmp;
|
|
|
|
if(*w > 2046)
|
|
*w = 2046;
|
|
if(*h > 2046)
|
|
*h = 2046;
|
|
|
|
*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:
|
|
size = *w << 1;
|
|
if (pitches)
|
|
pitches[0] = size;
|
|
size *= *h;
|
|
break;
|
|
case FOURCC_RGB:
|
|
size = *w << 2;
|
|
if(pitches)
|
|
pitches[0] = size;
|
|
size *= *h;
|
|
break;
|
|
default:
|
|
*w = *h = size = 0;
|
|
break;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
static void NVVideoTimerCallback
|
|
(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Time currentTime
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pOverPriv = NULL;
|
|
NVPortPrivPtr pBlitPriv = NULL;
|
|
Bool needCallback = FALSE;
|
|
|
|
if(!pScrnInfo->vtSema) return;
|
|
|
|
if(pNv->overlayAdaptor) {
|
|
pOverPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
if(!pOverPriv->videoStatus)
|
|
pOverPriv = NULL;
|
|
}
|
|
|
|
if(pNv->blitAdaptor) {
|
|
pBlitPriv = GET_BLIT_PRIVATE(pNv);
|
|
if(!pBlitPriv->videoStatus)
|
|
pBlitPriv = NULL;
|
|
}
|
|
|
|
if(pOverPriv) {
|
|
if(pOverPriv->videoTime < currentTime) {
|
|
if(pOverPriv->videoStatus & OFF_TIMER) {
|
|
NVStopOverlay(pScrnInfo);
|
|
pOverPriv->videoStatus = FREE_TIMER;
|
|
pOverPriv->videoTime = currentTime + FREE_DELAY;
|
|
needCallback = TRUE;
|
|
} else
|
|
if(pOverPriv->videoStatus & FREE_TIMER) {
|
|
NVFreeOverlayMemory(pScrnInfo);
|
|
pOverPriv->videoStatus = 0;
|
|
}
|
|
} else {
|
|
needCallback = TRUE;
|
|
}
|
|
}
|
|
|
|
if(pBlitPriv) {
|
|
if(pBlitPriv->videoTime < currentTime) {
|
|
NVFreeBlitMemory(pScrnInfo);
|
|
pBlitPriv->videoStatus = 0;
|
|
} else {
|
|
needCallback = TRUE;
|
|
}
|
|
}
|
|
|
|
pNv->VideoTimerCallback = needCallback ? NVVideoTimerCallback : NULL;
|
|
}
|
|
|
|
|
|
/***** Exported offscreen surface stuff ****/
|
|
|
|
|
|
static int
|
|
NVAllocSurface (
|
|
ScrnInfoPtr pScrnInfo,
|
|
int id,
|
|
unsigned short w,
|
|
unsigned short h,
|
|
XF86SurfacePtr surface
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
int size, bpp;
|
|
|
|
bpp = pScrnInfo->bitsPerPixel >> 3;
|
|
|
|
if(pPriv->grabbedByV4L) return BadAlloc;
|
|
|
|
if((w > 2046) || (h > 2046)) return BadValue;
|
|
|
|
w = (w + 1) & ~1;
|
|
pPriv->pitch = ((w << 1) + 63) & ~63;
|
|
size = h * pPriv->pitch / bpp;
|
|
|
|
pPriv->linear = NVAllocateOverlayMemory(pScrnInfo, pPriv->linear,
|
|
size);
|
|
|
|
if(!pPriv->linear) return BadAlloc;
|
|
|
|
pPriv->offset = pPriv->linear->offset * bpp;
|
|
|
|
surface->width = w;
|
|
surface->height = h;
|
|
surface->pScrn = pScrnInfo;
|
|
surface->pitches = &pPriv->pitch;
|
|
surface->offsets = &pPriv->offset;
|
|
surface->devPrivate.ptr = (pointer)pPriv;
|
|
surface->id = id;
|
|
|
|
/* grab the video */
|
|
NVStopOverlay(pScrnInfo);
|
|
pPriv->videoStatus = 0;
|
|
REGION_EMPTY(pScrnInfo->pScreen, &pPriv->clip);
|
|
pPriv->grabbedByV4L = TRUE;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
NVStopSurface (XF86SurfacePtr surface)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
|
|
|
|
if(pPriv->grabbedByV4L && pPriv->videoStatus) {
|
|
NVStopOverlay(surface->pScrn);
|
|
pPriv->videoStatus = 0;
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
NVFreeSurface (XF86SurfacePtr surface)
|
|
{
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
|
|
|
|
if(pPriv->grabbedByV4L) {
|
|
NVStopSurface(surface);
|
|
NVFreeOverlayMemory(surface->pScrn);
|
|
pPriv->grabbedByV4L = FALSE;
|
|
}
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
NVGetSurfaceAttribute (
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 *value
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
|
|
return NVGetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
|
|
}
|
|
|
|
static int
|
|
NVSetSurfaceAttribute(
|
|
ScrnInfoPtr pScrnInfo,
|
|
Atom attribute,
|
|
INT32 value
|
|
)
|
|
{
|
|
NVPtr pNv = NVPTR(pScrnInfo);
|
|
NVPortPrivPtr pPriv = GET_OVERLAY_PRIVATE(pNv);
|
|
|
|
return NVSetOverlayPortAttribute(pScrnInfo, attribute, value, (pointer)pPriv);
|
|
}
|
|
|
|
static int
|
|
NVDisplaySurface (
|
|
XF86SurfacePtr surface,
|
|
short src_x, short src_y,
|
|
short drw_x, short drw_y,
|
|
short src_w, short src_h,
|
|
short drw_w, short drw_h,
|
|
RegionPtr clipBoxes
|
|
)
|
|
{
|
|
ScrnInfoPtr pScrnInfo = surface->pScrn;
|
|
NVPortPrivPtr pPriv = (NVPortPrivPtr)(surface->devPrivate.ptr);
|
|
INT32 xa, xb, ya, yb;
|
|
BoxRec dstBox;
|
|
|
|
if(!pPriv->grabbedByV4L) return Success;
|
|
|
|
if(src_w > (drw_w << 3))
|
|
drw_w = src_w >> 3;
|
|
if(src_h > (drw_h << 3))
|
|
drw_h = src_h >> 3;
|
|
|
|
/* Clip */
|
|
xa = src_x;
|
|
xb = src_x + src_w;
|
|
ya = src_y;
|
|
yb = src_y + src_h;
|
|
|
|
dstBox.x1 = drw_x;
|
|
dstBox.x2 = drw_x + drw_w;
|
|
dstBox.y1 = drw_y;
|
|
dstBox.y2 = drw_y + drw_h;
|
|
|
|
if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes,
|
|
surface->width, surface->height))
|
|
{
|
|
return Success;
|
|
}
|
|
|
|
dstBox.x1 -= pScrnInfo->frameX0;
|
|
dstBox.x2 -= pScrnInfo->frameX0;
|
|
dstBox.y1 -= pScrnInfo->frameY0;
|
|
dstBox.y2 -= pScrnInfo->frameY0;
|
|
|
|
pPriv->currentBuffer = 0;
|
|
|
|
NVPutOverlayImage (pScrnInfo, surface->offsets[0], surface->id,
|
|
surface->pitches[0], &dstBox, xa, ya, xb, yb,
|
|
surface->width, surface->height, src_w, src_h,
|
|
drw_w, drw_h, clipBoxes);
|
|
|
|
return Success;
|
|
}
|
|
|
|
XF86OffscreenImageRec NVOffscreenImages[2] =
|
|
{
|
|
{
|
|
&NVImages[0],
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
NVAllocSurface,
|
|
NVFreeSurface,
|
|
NVDisplaySurface,
|
|
NVStopSurface,
|
|
NVGetSurfaceAttribute,
|
|
NVSetSurfaceAttribute,
|
|
2046, 2046,
|
|
NUM_OVERLAY_ATTRIBUTES - 1,
|
|
&NVOverlayAttributes[1]
|
|
},
|
|
{
|
|
&NVImages[2],
|
|
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT,
|
|
NVAllocSurface,
|
|
NVFreeSurface,
|
|
NVDisplaySurface,
|
|
NVStopSurface,
|
|
NVGetSurfaceAttribute,
|
|
NVSetSurfaceAttribute,
|
|
2046, 2046,
|
|
NUM_OVERLAY_ATTRIBUTES - 1,
|
|
&NVOverlayAttributes[1]
|
|
},
|
|
};
|
|
|
|
static void
|
|
NVInitOffscreenImages (ScreenPtr pScreen)
|
|
{
|
|
xf86XVRegisterOffscreenImages(pScreen, NVOffscreenImages, 2);
|
|
}
|