#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86Resources.h"
#include "xf86_ansic.h"
#include "compiler.h"
#include "xf86PciInfo.h"
#include "xf86Pci.h"
#include "xf86fbman.h"
#include "regionstr.h"
#include "i810.h"
#include "i810_dri.h"
#include "xf86xv.h"
#include "xf86xvmc.h"
#include "Xv.h"
#include "XvMC.h"
#include "xaa.h"
#include "xaalocal.h"
#include "dixstruct.h"
#include "fourcc.h"
int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
int *num_priv, long **priv );
void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext);
int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
int *num_priv, long **priv );
void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf);
int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf,
int *num_priv, long **priv );
void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf);
typedef struct {
drmContext drmcontext;
unsigned int fbBase;
unsigned int OverlayOffset;
unsigned int OverlaySize;
unsigned int SurfacesOffset;
unsigned int SurfacesSize;
char busIdString[10];
char pad[2];
} I810XvMCCreateContextRec;
static int yv12_subpicture_index_list[2] =
{
FOURCC_IA44,
FOURCC_AI44
};
static XF86MCImageIDList yv12_subpicture_list =
{
2,
yv12_subpicture_index_list
};
static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface =
{
FOURCC_YV12,
XVMC_CHROMA_FORMAT_420,
0,
720,
576,
720,
576,
XVMC_MPEG_2,
XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
XVMC_INTRA_UNSIGNED,
&yv12_subpicture_list
};
static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface =
{
FOURCC_YV12,
XVMC_CHROMA_FORMAT_420,
0,
720,
576,
720,
576,
XVMC_MPEG_1,
XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING |
XVMC_INTRA_UNSIGNED,
&yv12_subpicture_list
};
static XF86MCSurfaceInfoPtr ppSI[2] =
{
(XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface,
(XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface
};
static XF86ImageRec ia44_subpicture = XVIMAGE_IA44;
static XF86ImageRec ai44_subpicture = XVIMAGE_AI44;
static XF86ImagePtr i810_subpicture_list[2] =
{
(XF86ImagePtr)&ia44_subpicture,
(XF86ImagePtr)&ai44_subpicture
};
static XF86MCAdaptorRec pAdapt =
{
"I810 Video Overlay",
2,
ppSI,
2,
i810_subpicture_list,
(xf86XvMCCreateContextProcPtr)I810XvMCCreateContext,
(xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext,
(xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface,
(xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface,
(xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture,
(xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture
};
static XF86MCAdaptorPtr ppAdapt[1] =
{
(XF86MCAdaptorPtr)&pAdapt
};
void I810InitMC(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
I810Ptr pI810 = I810PTR(pScrn);
int i;
for(i=0; i<I810_MAX_SURFACES; i++) {
pI810->surfaceAllocation[i] = 0;
}
if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->CursorStart,
4096, DRM_AGP, 0, &pI810->overlay_map) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n");
return;
}
if (drmAddMap(pI810->drmSubFD, (drmHandle)pI810->MC.Start,
pI810->MC.Size, DRM_AGP, 0, &pI810->mc_map) < 0) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n");
return;
}
xf86XvMCScreenInit(pScreen, 1, ppAdapt);
}
int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext,
int *num_priv, long **priv )
{
I810Ptr pI810 = I810PTR(pScrn);
DRIInfoPtr pDRIInfo = pI810->pDRIInfo;
I810XvMCCreateContextRec *contextRec;
if(!pI810->directRenderingEnabled) {
xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
"I810XvMCCreateContext: Cannot use XvMC without DRI!\n");
return BadAlloc;
}
if(pI810->xvmcContext) {
xf86DrvMsg(X_WARNING, pScrn->scrnIndex,
"I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n");
return BadAlloc;
}
*priv = xcalloc(1,sizeof(I810XvMCCreateContextRec));
contextRec = (I810XvMCCreateContextRec *)*priv;
if(!*priv) {
*num_priv = 0;
return BadAlloc;
}
*num_priv = sizeof(I810XvMCCreateContextRec) >> 2;
if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) {
xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
"I810XvMCCreateContext: Unable to create DRMContext!\n");
xfree(*priv);
return BadAlloc;
}
drmAuthMagic(pI810->drmSubFD, pContext->flags);
pI810->xvmcContext = contextRec->drmcontext;
contextRec->fbBase = pScrn->memPhysBase;
contextRec->OverlayOffset = pI810->CursorStart;
contextRec->OverlaySize = 4096;
contextRec->SurfacesOffset = pI810->MC.Start;
contextRec->SurfacesSize = pI810->MC.Size;
strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9);
return Success;
}
int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf,
int *num_priv, long **priv )
{
I810Ptr pI810 = I810PTR(pScrn);
int i;
*priv = (long *)xcalloc(2,sizeof(long));
if(!*priv) {
xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
"I810XvMCCreateSurface: Unable to allocate memory!\n");
*num_priv = 0;
return BadAlloc;
}
*num_priv = 2;
if(pI810->numSurfaces == 6) {
for(i=0; i<pI810->numSurfaces; i++) {
if(!pI810->surfaceAllocation[i]) {
pI810->surfaceAllocation[i] = pSurf->surface_id;
(*priv)[0] = (2*1024*1024 + 576*1024 * i);
(*priv)[1] = (576*512 * i);
return Success;
}
}
}
if(pI810->numSurfaces == 7) {
for(i=0; i<pI810->numSurfaces; i++) {
if(!pI810->surfaceAllocation[i]) {
pI810->surfaceAllocation[i] = pSurf->surface_id;
(*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
(*priv)[1] = (576*512 * i);
return Success;
}
}
}
(*priv)[0] = 0;
(*priv)[1] = 0;
return BadAlloc;
}
int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp,
int *num_priv, long **priv )
{
I810Ptr pI810 = I810PTR(pScrn);
int i;
*priv = (long *)xcalloc(1,sizeof(long));
if(!*priv) {
xf86DrvMsg(X_ERROR, pScrn->scrnIndex,
"I810XvMCCreateSubpicture: Unable to allocate memory!\n");
*num_priv = 0;
return BadAlloc;
}
*num_priv = 1;
if(pI810->numSurfaces == 6) {
for(i=6; i<8; i++) {
if(!pI810->surfaceAllocation[i]) {
pI810->surfaceAllocation[i] = pSubp->subpicture_id;
(*priv)[0] = (2*1024*1024 + 576*1024 * i);
return Success;
}
}
}
if(pI810->numSurfaces == 7) {
for(i=7; i<9; i++) {
if(!pI810->surfaceAllocation[i]) {
pI810->surfaceAllocation[i] = pSubp->subpicture_id;
(*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i);
return Success;
}
}
}
(*priv)[0] = 0;
return BadAlloc;
}
void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext)
{
I810Ptr pI810 = I810PTR(pScrn);
drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext);
pI810->xvmcContext = 0;
}
void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf)
{
I810Ptr pI810 = I810PTR(pScrn);
int i;
for(i=0; i<I810_MAX_SURFACES; i++) {
if(pI810->surfaceAllocation[i] == pSurf->surface_id) {
pI810->surfaceAllocation[i] = 0;
return;
}
}
return;
}
void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp)
{
I810Ptr pI810 = I810PTR(pScrn);
int i;
for(i=pI810->numSurfaces; i<I810_MAX_SURFACES + I810_MAX_SUBPICTURES; i++) {
if(pI810->surfaceAllocation[i] == pSubp->subpicture_id) {
pI810->surfaceAllocation[i] = 0;
return;
}
}
return;
}