#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <sys/ioctl.h>
#include <X11/Xlibint.h>
#include <fourcc.h>
#include <Xv.h>
#include <Xvlib.h>
#include <XvMC.h>
#include <XvMClib.h>
#include "I810XvMC.h"
static int error_base;
static int event_base;
drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) {
drmI810DMA dma;
drmBufPtr buf;
dma.granted = 0;
dma.request_size = 4096;
while(!dma.granted) {
if(GET_BUFFER(pI810XvMC, dma) || !dma.granted)
FLUSH(pI810XvMC);
}
buf = &(pI810XvMC->dmabufs->list[dma.request_idx]);
buf->idx = dma.request_idx;
buf->used = 0;
buf->total = dma.request_size;
buf->address = (drmAddress)dma.virtual;
return buf;
}
void i810_free_privContext(i810XvMCContext *pI810XvMC) {
I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
pI810XvMC->ref--;
if(!pI810XvMC->ref) {
drmUnmapBufs(pI810XvMC->dmabufs);
drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size);
drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size);
drmClose(pI810XvMC->fd);
free(pI810XvMC->dmabufs->list);
free(pI810XvMC);
}
I810_UNLOCK(pI810XvMC);
}
Status XvMCCreateContext(Display *display, XvPortID port,
int surface_type_id, int width, int height, int flags,
XvMCContext *context) {
i810XvMCContext *pI810XvMC;
char busIdString[10];
int priv_count;
uint *priv_data;
uint magic;
Status ret;
int major, minor;
if(context == NULL) {
return XvMCBadContext;
}
if(!flags & XVMC_DIRECT) {
printf("Indirect Rendering not supported!\nUsing Direct.");
}
if(geteuid()) {
printf("Use of XvMC on i810 is currently limited to root\n");
return BadAccess;
}
context->surface_type_id = surface_type_id;
context->width = (unsigned short)width;
context->height = (unsigned short)height;
context->flags = flags;
context->port = port;
context->privData = (void *)malloc(sizeof(i810XvMCContext));
if(!context->privData) {
printf("Unable to allocate resources for XvMC context.\n");
return BadAlloc;
}
pI810XvMC = (i810XvMCContext *)context->privData;
if(! XvMCQueryExtension(display, &event_base,
&error_base)) {
printf("XvMC Extension is not available!\n");
return BadAlloc;
}
ret = XvMCQueryVersion(display, &major, &minor);
if(ret) {
printf("XvMCQuery Version Failed, unable to determine protocol version\n");
}
if(! drmAvailable()) {
printf("Direct Rendering is not avilable on this system!\n");
return BadAlloc;
}
pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0);
if(!pI810XvMC->xv_colorkey) {
return XvBadPort;
}
ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey,
&pI810XvMC->colorkey);
if(ret) {
return ret;
}
pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0);
pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0);
pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0);
pI810XvMC->brightness = 0;
pI810XvMC->saturation = 0x80;
pI810XvMC->contrast = 0x40;
if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) {
printf("DRM Device for i810 could not be opened.\n");
free(busIdString);
free(pI810XvMC);
return BadAccess;
}
drmGetMagic(pI810XvMC->fd,&magic);
context->flags = (unsigned long)magic;
if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) {
printf("Unable to create XvMC Context.\n");
return ret;
}
if(priv_count != 9) {
printf("_xvmc_create_context() returned incorrect data size!\n");
printf("\tExpected 9, got %d\n",priv_count);
_xvmc_destroy_context(display, context);
free(pI810XvMC);
return BadAlloc;
}
pI810XvMC->drmcontext = priv_data[0];
pI810XvMC->fb_base = priv_data[1];
pI810XvMC->overlay.offset = priv_data[2] + priv_data[1];
pI810XvMC->overlay.size = priv_data[3];
pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1];
pI810XvMC->surfaces.size = priv_data[5];
strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9);
pI810XvMC->busIdString[9] = '\0';
free(priv_data);
pI810XvMC->current = 0;
pI810XvMC->lock = 0;
pI810XvMC->last_flip = 0;
pI810XvMC->dual_prime = 0;
pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap));
if(pI810XvMC->dmabufs == NULL) {
printf("Dma Bufs could not be mapped.\n");
_xvmc_destroy_context(display, context);
free(pI810XvMC);
return BadAlloc;
}
memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap));
pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) *
I810_DMA_BUF_NR);
if(pI810XvMC->dmabufs->list == NULL) {
printf("Dma Bufs could not be mapped.\n");
_xvmc_destroy_context(display, context);
free(pI810XvMC);
return BadAlloc;
}
memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR);
if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset,
pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) {
printf("Unable to map Overlay at offset 0x%x and size 0x%x\n",
(unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size);
_xvmc_destroy_context(display, context);
free(pI810XvMC->dmabufs->list);
free(pI810XvMC);
return BadAlloc;
}
pI810XvMC->oregs = (i810OverlayRec *)
((unsigned char *)pI810XvMC->overlay.address + 1024);
if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset,
pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) {
printf("Unable to map XvMC Surfaces.\n");
_xvmc_destroy_context(display, context);
free(pI810XvMC->dmabufs->list);
free(pI810XvMC);
return BadAlloc;
}
I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
usleep(20000);
pI810XvMC->oregs->YRGB_VPH = 0;
pI810XvMC->oregs->UV_VPH = 0;
pI810XvMC->oregs->HORZ_PH = 0;
pI810XvMC->oregs->INIT_PH = 0;
pI810XvMC->oregs->DWINPOS = 0;
pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) |
I810_XVMC_MAXWIDTH;
pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15);
pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) |
(I810_XVMC_MAXWIDTH << 12);
pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT |
(I810_XVMC_MAXHEIGHT << 15);
pI810XvMC->oregs->YRGBSCALE = 0x80004000;
pI810XvMC->oregs->UVSCALE = 0x80004000;
pI810XvMC->oregs->OV0CLRC0 = 0x4000;
pI810XvMC->oregs->OV0CLRC1 = 0x80;
pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
pI810XvMC->oregs->DCLRKM = 0x80070307;
pI810XvMC->oregs->SCLRKVH = 0;
pI810XvMC->oregs->SCLRKVL = 0;
pI810XvMC->oregs->SCLRKM = 0;
pI810XvMC->oregs->OV0CONF = 0;
pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
Y_ADJUST | YUV_420;
pI810XvMC->ref = 1;
I810_UNLOCK(pI810XvMC);
return Success;
}
Status XvMCDestroyContext(Display *display, XvMCContext *context) {
i810XvMCContext *pI810XvMC;
if(context == NULL) {
return (error_base + XvMCBadContext);
}
if(context->privData == NULL) {
return (error_base + XvMCBadContext);
}
pI810XvMC = (i810XvMCContext *)context->privData;
if(pI810XvMC->last_flip) {
I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
Y_ADJUST;
pI810XvMC->current = !pI810XvMC->current;
if(pI810XvMC->current == 1) {
pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
}
else {
pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
}
OVERLAY_FLIP(pI810XvMC);
pI810XvMC->last_flip++;
BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
I810_UNLOCK(pI810XvMC);
}
_xvmc_destroy_context(display, context);
i810_free_privContext(pI810XvMC);
context->privData = NULL;
return Success;
}
Status XvMCCreateSurface( Display *display, XvMCContext *context,
XvMCSurface *surface) {
i810XvMCContext *pI810XvMC;
i810XvMCSurface *pI810Surface;
int priv_count;
uint *priv_data;
Status ret;
if((surface == NULL) || (context == NULL) || (display == NULL)){
return BadValue;
}
pI810XvMC = (i810XvMCContext *)context->privData;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadContext);
}
surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface));
if(!surface->privData) {
return BadAlloc;
}
pI810Surface = (i810XvMCSurface *)surface->privData;
pI810Surface->privContext = pI810XvMC;
pI810Surface->last_render = 0;
pI810Surface->last_flip = 0;
pI810Surface->second_field = 0;
if((ret = _xvmc_create_surface(display, context, surface,
&priv_count, &priv_data))) {
free(pI810Surface);
printf("Unable to create XvMCSurface.\n");
return ret;
}
if(priv_count != 2) {
printf("_xvmc_create_surface() return incorrect data size.\n");
printf("Expected 2 got %d\n",priv_count);
free(priv_data);
free(pI810Surface);
return BadAlloc;
}
pI810Surface->data = pI810XvMC->surfaces.address;
pI810Surface->offset = pI810XvMC->surfaces.offset;
pI810Surface->pitch = 10;
if((surface->surface_type_id == FOURCC_UYVY) ||
(surface->surface_type_id == FOURCC_YUY2)) {
pI810Surface->pitch++;
}
pI810Surface->offsets[0] = priv_data[0];
if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) {
printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n");
}
if((surface->surface_type_id == FOURCC_UYVY) ||
(surface->surface_type_id == FOURCC_YUY2)) {
pI810Surface->offsets[1] = 0;
pI810Surface->offsets[2] = 0;
}
else {
pI810Surface->offsets[1] = priv_data[1];
if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) {
printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n");
}
pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] +
(1<<(pI810Surface->pitch - 1)) * 288);
if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) {
printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n");
}
}
free(priv_data);
memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]),
0, ((1<<pI810Surface->pitch) * surface->height));
switch(surface->surface_type_id) {
case FOURCC_YV12:
case FOURCC_I420:
pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
pI810Surface->offsets[0]) & ~0xfc000fff) |
(pI810Surface->pitch - 9));
pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset +
pI810Surface->offsets[1]) & ~0xfc000fff) |
(pI810Surface->pitch - 10));
pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset +
pI810Surface->offsets[2]) & ~0xfc000fff) |
(pI810Surface->pitch - 10));
pI810Surface->dbv1 = (0x8<<20) | (0x8<<16);
pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3);
pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4);
pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) |
((unsigned int)surface->width - 1);
pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) |
(((unsigned int)surface->width - 1)>>1);
pI810Surface->mi2v = pI810Surface->mi2u;
pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
pI810Surface->offsets[0]) & ~0x0000000f;
pI810Surface->mi3u = ((unsigned int)pI810Surface->offset +
pI810Surface->offsets[1]) & ~0x0000000f;
pI810Surface->mi3v = ((unsigned int)pI810Surface->offset +
pI810Surface->offsets[2]) & ~0x0000000f;
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset +
pI810Surface->offsets[0]) & ~0xfc000fff) |
(pI810Surface->pitch - 9));
if(surface->surface_type_id == FOURCC_YUY2) {
pI810Surface->dbv1 = 0x5<<8;
pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21;
}
else {
pI810Surface->dbv1 = 0x4<<8;
pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3);
}
pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) |
((unsigned int)surface->height - 1);
pI810Surface->mi3y = ((unsigned int)pI810Surface->offset +
pI810Surface->offsets[0]) & ~0xfc000fff;
break;
}
pI810XvMC->ref++;
return Success;
}
Status XvMCDestroySurface(Display *display, XvMCSurface *surface) {
i810XvMCSurface *pI810Surface;
i810XvMCContext *pI810XvMC;
if((display == NULL) || (surface == NULL)) {
return BadValue;
}
if(surface->privData == NULL) {
return (error_base + XvMCBadSurface);
}
pI810Surface = (i810XvMCSurface *)surface->privData;
if(pI810Surface->last_flip) {
XvMCSyncSurface(display,surface);
}
pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
_xvmc_destroy_surface(display,surface);
i810_free_privContext(pI810XvMC);
free(pI810Surface);
surface->privData = NULL;
return Success;
}
Status XvMCCreateBlocks(Display *display, XvMCContext *context,
unsigned int num_blocks,
XvMCBlockArray *block) {
if((display == NULL) || (context == NULL) || (num_blocks == 0)) {
return BadValue;
}
block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short));
if(block->blocks == NULL) {
return BadAlloc;
}
block->num_blocks = num_blocks;
block->context_id = context->context_id;
block->privData = NULL;
return Success;
}
Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) {
if(display == NULL) {
return BadValue;
}
free(block->blocks);
block->num_blocks = 0;
block->context_id = 0;
block->privData = NULL;
return Success;
}
Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context,
unsigned int num_blocks,
XvMCMacroBlockArray *blocks) {
if((display == NULL) || (context == NULL) || (blocks == NULL) ||
(num_blocks == 0)) {
return BadValue;
}
memset(blocks,0,sizeof(XvMCMacroBlockArray));
blocks->context_id = context->context_id;
blocks->privData = NULL;
blocks->macro_blocks = (XvMCMacroBlock *)
malloc(num_blocks * sizeof(XvMCMacroBlock));
if(blocks->macro_blocks == NULL) {
return BadAlloc;
}
blocks->num_blocks = num_blocks;
return Success;
}
Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) {
if((display == NULL) || (block == NULL)) {
return BadValue;
}
if(block->macro_blocks) {
free(block->macro_blocks);
}
block->context_id = 0;
block->num_blocks = 0;
block->privData = NULL;
return Success;
}
void dp(unsigned int *address, unsigned int i) {
int j;
printf("DebugPrint:\n");
for(j=0; j<i; j++) {
printf("0x%8.8x ",address[j]);
if(j && !(j & 7)) { printf("\n");}
}
}
#define PACK_INTRA_DATA(d,b,n) \
do { \
char *dp = (char *)d; \
char *bp = (char *)b; \
int counter; \
for(counter = 0; counter < n; counter++) { \
*dp++ = *bp; \
bp += 2; \
} \
}while(0);
#define PACK_CORR_DATA(d,b,n) \
memcpy(d,b,n); \
d = (uint *)((unsigned long)d + n);
#define MARK_CORR_DATA(d,n) \
do { \
uint* q = (uint*)((unsigned long)d - n); \
while((unsigned long)q < (unsigned long)d) { \
*q++ += 0x00330033; \
} \
}while(0);
#define MARK_INTRA_BLOCK(d) \
do { \
int q; \
for(q=0; q<16; q++) { \
d[q] += 0x33333333; \
} \
}while(0);
#define PACK_CORR_DATA_1to0(d,top,bottom) \
do { \
short *t = top,*b = bottom; \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 16); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 16); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 16); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 16); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 16); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 16); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 16); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 16); \
}while(0);
#define PACK_CORR_DATA_0to1(d,top,bottom) \
do{ \
short *t = top,*b = bottom; \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 32); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 32); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 32); \
PACK_CORR_DATA(d,t,16); \
t = (short *)((unsigned long)t + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
}while(0);
#define PACK_CORR_DATA_SHORT(d,block) \
do { \
short *b = block; \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
PACK_CORR_DATA(d,b,16); \
b = (short *)((unsigned long)b + 32); \
}while(0);
static unsigned int drps_table[] = {2<<6,3<<6};
static unsigned int mvfs_table[] = {
0x12,
0x1a,
0x13,
0x1b
};
static unsigned int type_table[] = {
0x1<<12,
0x1<<12,
0x1<<12,
0x1<<12,
0x2<<12,
0x2<<12,
0x3<<12,
0x3<<12,
0x1<<12,
0x1<<12,
0x1<<12,
0x1<<12,
0x2<<12,
0x2<<12,
0x3<<12,
0x3<<12
};
static unsigned int y_frame_bytes[] = {
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256,
128,128,128,128,256,256,256,256,
256,256,256,256,384,384,384,384,
128,128,128,128,256,256,256,256,
256,256,256,256,384,384,384,384,
256,256,256,256,384,384,384,384,
384,384,384,384,512,512,512,512
};
static unsigned int u_frame_bytes[] = {
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128,
0,0,128,128,0,0,128,128
};
static unsigned int v_frame_bytes[] = {
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128,
0,128,0,128,0,128,0,128
};
static unsigned int y_first_field_bytes[] = {
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
128,128,128,128,128,128,128,128,
256,256,256,256,256,256,256,256,
256,256,256,256,256,256,256,256
};
static unsigned int y_second_field_bytes[] = {
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256,
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256,
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256,
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256
};
static unsigned int y_dct0_field_bytes[] = {
0,0,0,0,128,128,128,128,
128,128,128,128,256,256,256,256,
128,128,128,128,128,128,128,128,
256,256,256,256,256,256,256,256,
128,128,128,128,256,256,256,256,
128,128,128,128,256,256,256,256,
256,256,256,256,256,256,256,256,
256,256,256,256,256,256,256,256
};
static unsigned int y_dct1_frame_bytes[] = {
0,0,0,0,256,256,256,256,
256,256,256,256,512,512,512,512,
256,256,256,256,256,256,256,256,
512,512,512,512,512,512,512,512,
256,256,256,256,512,512,512,512,
256,256,256,256,512,512,512,512,
512,512,512,512,512,512,512,512,
512,512,512,512,512,512,512,512
};
static unsigned int u_field_bytes[] = {
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64,
0,0,64,64,0,0,64,64
};
static unsigned int v_field_bytes[] = {
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64,
0,64,0,64,0,64,0,64
};
static short empty_block[] = {
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,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,
0,0,0,0,0,0,0,0
};
static __inline__ void dispatchYContext(i810XvMCSurface *privTarget,
i810XvMCSurface *privPast,
i810XvMCSurface *privFuture,
i810XvMCContext *pI810XvMC) {
uint *data;
drmBufPtr pDMA;
drm_i810_mc_t mc;
pDMA = i810_get_free_buffer(pI810XvMC);
data = pDMA->address;
*data++ = CMD_FLUSH;
*data++ = BOOLEAN_ENA_2;
*data++ = CMD_FLUSH;
*data++ = DEST_BUFFER_INFO;
*data++ = privTarget->dbi1y;
*data++ = DEST_BUFFER_VAR;
*data++ = privTarget->dbv1;
*data++ = CMD_MAP_INFO;
*data++ = privPast->mi1y;
*data++ = privPast->mi2y;
*data++ = privPast->mi3y;
*data++ = CMD_MAP_INFO;
*data++ = privFuture->mi1y | 0x1<<28;
*data++ = privFuture->mi2y;
*data++ = privFuture->mi3y;
mc.idx = pDMA->idx;
mc.used = (unsigned long)data - (unsigned long)pDMA->address;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
static __inline__ void renderError(void) {
printf("Invalid Macroblock Parameters found.\n");
return;
}
static __inline__ void renderIntrainFrame(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,
short *block_ptr) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
*dy++ = GFXBLOCK + 68;
*dy++ = (1<<30) | (3<<28) | (0xf<<24);
*dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4);
*dy++ = (16<<16) | 16;
*dy++ = 0;
*dy++ = 0;
PACK_INTRA_DATA(dy,block_ptr,256);
dy += 64;
block_ptr += 256;
*du++ = GFXBLOCK + 20;
*du++ = (2<<30) | (1<<28) | (1<<23);
*du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
*du++ = (8<<16) | 8;
*du++ = 0;
*du++ = 0;
PACK_INTRA_DATA(du,block_ptr,64);
du += 16;
block_ptr += 64;
*dv++ = GFXBLOCK + 20;
*dv++ = (3<<30) | (1<<28) | (1<<22);
*dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
*dv++ = (8<<16) | 8;
*dv++ = 0;
*dv++ = 0;
PACK_INTRA_DATA(dv,block_ptr,64);
dv += 16;
block_ptr += 64;
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau,
uint **datav,XvMCMacroBlock *mb,
short *block_ptr,uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
*dy++ = GFXBLOCK + 36;
*dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6);
*dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
*dy++ = (8<<16) | 16;
*dy++ = 0;
*dy++ = 0;
PACK_INTRA_DATA(dy,block_ptr,128);
dy += 32;
block_ptr += 128;
*dy++ = GFXBLOCK + 36;
*dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6);
*dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3);
*dy++ = (8<<16) | 16;
*dy++ = 0;
*dy++ = 0;
PACK_INTRA_DATA(dy,block_ptr,128);
dy += 32;
block_ptr += 128;
*du++ = GFXBLOCK + 20;
*du++ = (2<<30) | (1<<28) | (1<<23);
*du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
*du++ = (8<<16) | 8;
*du++ = 0;
*du++ = 0;
PACK_INTRA_DATA(du,block_ptr,64);
du += 16;
block_ptr += 64;
*dv++ = GFXBLOCK + 20;
*dv++ = (3<<30) | (1<<28) | (1<<22);
*dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3);
*dv++ = (8<<16) | 8;
*dv++ = 0;
*dv++ = 0;
PACK_INTRA_DATA(dv,block_ptr,64);
dv += 16;
block_ptr += 64;
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderIntrainField(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,short *block_ptr,
uint ps) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
uint dw1 = drps_table[~ps & 0x1];
*dy++ = GFXBLOCK + 68;
*dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1;
*dy++ = xy;
*dy++ = (16<<16) | 16;
*dy++ = 0;
*dy++ = 0;
PACK_INTRA_DATA(dy,block_ptr,256);
dy += 64;
block_ptr += 256;
xy >>= 1;
*du++ = GFXBLOCK + 20;
*du++ = (2<<30) | (1<<28) | (1<<23) | dw1;
*du++ = xy;
*du++ = (8<<16) | 8;
*du++ = 0;
*du++ = 0;
PACK_INTRA_DATA(du,block_ptr,64);
du += 16;
block_ptr += 64;
*dv++ = GFXBLOCK + 20;
*dv++ = (3<<30) | (1<<28) | (1<<22) | dw1;
*dv++ = xy;
*dv++ = (8<<16) | 8;
*dv++ = 0;
*dv++ = 0;
PACK_INTRA_DATA(dv,block_ptr,64);
dv += 16;
block_ptr += 64;
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderFieldinField(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,short *block_ptr,
uint ps, uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[2];
short bmv[2];
uint dw1;
uint parity = ~ps & XVMC_TOP_FIELD;
uint ysize = y_frame_bytes[mb->coded_block_pattern];
uint usize = u_frame_bytes[mb->coded_block_pattern];
uint vsize = v_frame_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
if(flags & 0x80000000) {
if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
parity) {
dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
(((uint)mb->coded_block_pattern)<<22);
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = 0;
bmv[1] = 0;
}
else {
dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
(((uint)mb->coded_block_pattern)<<22);
bmv[0] = mb->PMV[0][0][1];
bmv[1] = mb->PMV[0][0][0];
fmv[0] = 0;
fmv[1] = 0;
}
}
else {
dw1 = type_table[mb->macroblock_type & 0xf] |
drps_table[~ps & 0x1] |
mvfs_table[mb->motion_vertical_field_select & 3] |
(((uint)mb->coded_block_pattern)<<22);
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[0][1][1];
bmv[1] = mb->PMV[0][1][0];
}
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (3<<28) | dw1;
*dy++ = xy;
*dy++ = (16<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
PACK_CORR_DATA(dy,block_ptr,ysize);
block_ptr = (short *)((unsigned long)block_ptr + ysize);
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1;
*du++ = xy;
*du++ = (8<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1;
*dv++ = xy;
*dv++ = (8<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void render16x8inField(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,short *block_ptr,
uint ps, uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
uint dw1[2];
uint y1size = y_first_field_bytes[mb->coded_block_pattern];
uint y2size = y_second_field_bytes[mb->coded_block_pattern];
uint usize = u_field_bytes[mb->coded_block_pattern];
uint vsize = v_field_bytes[mb->coded_block_pattern];
uint parity = ~ps & XVMC_TOP_FIELD;
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
if(flags & 0x80000000) {
if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) ==
parity) {
dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
(((uint)mb->coded_block_pattern)<<22);
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = 0;
bmv[1] = 0;
}
else {
dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
(((uint)mb->coded_block_pattern)<<22);
bmv[0] = mb->PMV[0][0][1];
bmv[1] = mb->PMV[0][0][0];
fmv[0] = 0;
fmv[1] = 0;
}
if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) ==
(parity<<2)) {
dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) |
((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
(((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
fmv[2] = mb->PMV[1][0][1];
fmv[3] = mb->PMV[1][0][0];
bmv[2] = 0;
bmv[3] = 0;
}
else {
dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) |
((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
(((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
bmv[2] = mb->PMV[1][0][1];
bmv[3] = mb->PMV[1][0][0];
fmv[2] = 0;
fmv[3] = 0;
}
}
else {
dw1[0] = type_table[mb->macroblock_type & 0xf] |
drps_table[~ps & 0x1] |
mvfs_table[mb->motion_vertical_field_select & 3] |
(((uint)mb->coded_block_pattern)<<22);
dw1[1] = type_table[mb->macroblock_type & 0xf] |
drps_table[~ps & 0x1] |
mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] |
((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) |
(((uint)mb->coded_block_pattern<<24) & (0x3<<26)));
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
fmv[2] = mb->PMV[1][0][1];
fmv[3] = mb->PMV[1][0][0];
bmv[0] = mb->PMV[0][1][1];
bmv[1] = mb->PMV[0][1][0];
bmv[2] = mb->PMV[1][1][1];
bmv[3] = mb->PMV[1][1][0];
}
*dy++ = GFXBLOCK + 4 + (y1size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[0];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
PACK_CORR_DATA(dy,block_ptr,y1size);
block_ptr = (short *)((unsigned long)block_ptr + y1size);
*dy++ = GFXBLOCK + 4 + (y2size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[1];
*dy++ = (xy + 8);
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[2];
*dy++ = *(uint *)&bmv[2];
PACK_CORR_DATA(dy,block_ptr,y2size);
block_ptr = (short *)((unsigned long)block_ptr + y2size);
fmv[0] /= 2;
fmv[1] /= 2;
fmv[2] /= 2;
fmv[3] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
bmv[2] /= 2;
bmv[3] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[0];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[1];
*du++ = (xy + 4);
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[2];
*du++ = *(uint *)&bmv[2];
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[0];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[1];
*dv++ = (xy + 4);
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[2];
*dv++ = *(uint *)&bmv[2];
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderDualPrimeinField(uint **datay,uint **datau,
uint **datav,XvMCMacroBlock *mb,
short *block_ptr,uint ps,
uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[2];
short bmv[2];
uint dw1;
uint ysize = y_frame_bytes[mb->coded_block_pattern];
uint usize = u_frame_bytes[mb->coded_block_pattern];
uint vsize = v_frame_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
if(ps & XVMC_TOP_FIELD) {
dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3;
}
else {
dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2;
}
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[0][1][1];
bmv[1] = mb->PMV[0][1][0];
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (3<<28) | dw1;
*dy++ = xy;
*dy++ = (16<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
PACK_CORR_DATA(dy,block_ptr,ysize);
block_ptr = (short *)((unsigned long)block_ptr + ysize);
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1;
*du++ = xy;
*du++ = (8<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1;
*dv++ = xy;
*dv++ = (8<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderFieldinFrame(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,short *block_ptr,
uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
uint dw1[2];
uint y1size = y_first_field_bytes[mb->coded_block_pattern];
uint y2size = y_second_field_bytes[mb->coded_block_pattern];
uint usize = u_field_bytes[mb->coded_block_pattern];
uint vsize = v_field_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
mvfs_table[mb->motion_vertical_field_select & 3] |
(((uint)mb->coded_block_pattern)<<22);
dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
mvfs_table[mb->motion_vertical_field_select>>2] |
(((mb->coded_block_pattern & 0x3) |
((mb->coded_block_pattern & 0xc)<<2))<<22);
fmv[0] = mb->PMV[0][0][1]/2;
fmv[1] = mb->PMV[0][0][0];
fmv[2] = mb->PMV[1][0][1]/2;
fmv[3] = mb->PMV[1][0][0];
bmv[0] = mb->PMV[0][1][1]/2;
bmv[1] = mb->PMV[0][1][0];
bmv[2] = mb->PMV[1][1][1]/2;
bmv[3] = mb->PMV[1][1][0];
*dy++ = GFXBLOCK + 4 + (y1size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[0];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[0];
*dy++ = *(uint *)&bmv[0];
PACK_CORR_DATA(dy,block_ptr,y1size);
block_ptr = (short *)((unsigned long)block_ptr + y1size);
*dy++ = GFXBLOCK + 4 + (y2size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[1];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[2];
*dy++ = *(uint *)&bmv[2];
PACK_CORR_DATA(dy,block_ptr,y2size);
block_ptr = (short *)((unsigned long)block_ptr + y2size);
fmv[0] /= 2;
fmv[1] /= 2;
fmv[2] /= 2;
fmv[3] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
bmv[2] /= 2;
bmv[3] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[0];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[0];
*du++ = *(uint *)&bmv[0];
if(usize) {
PACK_CORR_DATA_SHORT(du,block_ptr);
}
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[1];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[2];
*du++ = *(uint *)&bmv[2];
if(usize) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(du,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[0];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[0];
*dv++ = *(uint *)&bmv[0];
if(vsize) {
PACK_CORR_DATA_SHORT(dv,block_ptr);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[1];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[2];
*dv++ = *(uint *)&bmv[2];
if(vsize) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(dv,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau,
uint **datav,XvMCMacroBlock *mb,
short *block_ptr,uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
uint cbp = (uint)mb->coded_block_pattern;
uint dw1[2];
short * top_left_b = NULL;
short * top_right_b = NULL;
short * bottom_left_b = NULL;
short * bottom_right_b = NULL;
unsigned int ysize = y_dct0_field_bytes[cbp];
unsigned int usize = u_field_bytes[cbp];
unsigned int vsize = v_field_bytes[cbp];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) |
mvfs_table[mb->motion_vertical_field_select & 3] |
((cbp | ((cbp<<2) & 0x30))<<22);
dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) |
mvfs_table[mb->motion_vertical_field_select>>2] |
((cbp | ((cbp<<2) & 0x30))<<22);
fmv[0] = mb->PMV[0][0][1]/2;
fmv[1] = mb->PMV[0][0][0];
fmv[2] = mb->PMV[1][0][1]/2;
fmv[3] = mb->PMV[1][0][0];
bmv[0] = mb->PMV[0][1][1]/2;
bmv[1] = mb->PMV[0][1][0];
bmv[2] = mb->PMV[1][1][1]/2;
bmv[3] = mb->PMV[1][1][0];
top_left_b = &empty_block[0];
if(cbp & 0x20) {
top_left_b = block_ptr;
block_ptr += 64;
}
top_right_b = &empty_block[0];
if(cbp & 0x10) {
top_right_b = block_ptr;
block_ptr += 64;
}
bottom_left_b = &empty_block[0];
if(cbp & 0x8) {
bottom_left_b = block_ptr;
block_ptr += 64;
}
bottom_right_b = &empty_block[0];
if(cbp & 0x4) {
bottom_right_b = block_ptr;
block_ptr += 64;
}
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (2<<28) | dw1[0];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[0];
*dy++ = *(uint *)&bmv[0];
if(dw1[0] & (1<<27)) {
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
}
if(dw1[0] & (1<<26)) {
PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
}
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (2<<28) | dw1[1];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[2];
*dy++ = *(uint *)&bmv[2];
if(dw1[1] & (1<<27)) {
top_left_b = (short *)((unsigned long)top_left_b + 16);
bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
}
if(dw1[1] & (1<<26)) {
top_right_b = (short *)((unsigned long)top_right_b + 16);
bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
}
fmv[0] /= 2;
fmv[1] /= 2;
fmv[2] /= 2;
fmv[3] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
bmv[2] /= 2;
bmv[3] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[0];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[0];
*du++ = *(uint *)&bmv[0];
if(usize) {
PACK_CORR_DATA_SHORT(du,block_ptr);
}
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[1];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[2];
*du++ = *(uint *)&bmv[2];
if(usize) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(du,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[0];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[0];
*dv++ = *(uint *)&bmv[0];
if(vsize) {
PACK_CORR_DATA_SHORT(dv,block_ptr);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[1];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[2];
*dv++ = *(uint *)&bmv[2];
if(vsize) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(dv,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderFrameinFrame(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,short *block_ptr,
uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[2];
short bmv[2];
uint dw1;
unsigned int ysize = y_frame_bytes[mb->coded_block_pattern];
unsigned int usize = u_frame_bytes[mb->coded_block_pattern];
unsigned int vsize = v_frame_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
dw1 = type_table[mb->macroblock_type & 0xf] |
(((uint)mb->coded_block_pattern)<<22);
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[0][1][1];
bmv[1] = mb->PMV[0][1][0];
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (3<<28) | dw1;
*dy++ = xy;
*dy++ = (16<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
PACK_CORR_DATA(dy,block_ptr,ysize);
block_ptr = (short *)((unsigned long)block_ptr + ysize);
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1;
*du++ = xy;
*du++ = (8<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1;
*dv++ = xy;
*dv++ = (8<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau,
uint **datav,XvMCMacroBlock *mb,
short *block_ptr,uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
short * top_left_b = NULL;
short * top_right_b = NULL;
short * bottom_left_b = NULL;
short * bottom_right_b = NULL;
uint temp_bp = 0;
uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern];
uint usize = u_frame_bytes[mb->coded_block_pattern];
uint vsize = v_frame_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4);
uint dw1 = type_table[mb->macroblock_type & 0xf] |
(((uint)mb->coded_block_pattern)<<22);
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[0][1][1];
bmv[1] = mb->PMV[0][1][0];
top_left_b = &empty_block[0];
if(dw1 & (1<<27)) {
temp_bp |= (1<<25);
top_left_b = block_ptr;
block_ptr += 64;
}
top_right_b = &empty_block[0];
if(dw1 & (1<<26)) {
temp_bp |= (1<<24);
top_right_b = block_ptr;
block_ptr += 64;
}
bottom_left_b = &empty_block[0];
if(dw1 & (1<<25)) {
temp_bp |= (1<<27);
bottom_left_b = block_ptr;
block_ptr += 64;
}
bottom_right_b = &empty_block[0];
if(dw1 & (1<<24)) {
temp_bp |= (1<<26);
bottom_right_b = block_ptr;
block_ptr += 64;
}
dw1 |= temp_bp;
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (3<<28) | dw1;
*dy++ = xy;
*dy++ = (16<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
if(dw1 & (1<<27)) {
PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
top_left_b = (short *)((unsigned long)top_left_b + 64);
bottom_left_b = (short *)((unsigned long)bottom_left_b + 64);
}
if(dw1 & (1<<26)) {
PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
top_right_b = (short *)((unsigned long)top_right_b + 64);
bottom_right_b = (short *)((unsigned long)bottom_right_b + 64);
}
if(dw1 & (1<<27)) {
PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b);
}
if(dw1 & (1<<26)) {
PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b);
}
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1;
*du++ = xy;
*du++ = (8<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
PACK_CORR_DATA(du,block_ptr,usize);
block_ptr = (short *)((unsigned long)block_ptr + usize);
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1;
*dv++ = xy;
*dv++ = (8<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
PACK_CORR_DATA(dv,block_ptr,vsize);
block_ptr = (short *)((unsigned long)block_ptr + vsize);
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau,
uint **datav,XvMCMacroBlock *mb,
short *block_ptr,uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
uint dw1[2];
uint y1size = y_first_field_bytes[mb->coded_block_pattern];
uint y2size = y_second_field_bytes[mb->coded_block_pattern];
uint usize = u_field_bytes[mb->coded_block_pattern];
uint vsize = v_field_bytes[mb->coded_block_pattern];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
dw1[0] = (((uint)mb->coded_block_pattern)<<22) |
3<<12 | 2<<6 | 2<<3 | 3;
dw1[1] = (((mb->coded_block_pattern & 0x3) |
((mb->coded_block_pattern & 0xc)<<2))<<22) |
3<<12 | 3<<6 | 3<<3 | 2;
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[1][0][1];
bmv[1] = mb->PMV[1][0][0];
fmv[2] = mb->PMV[0][0][1];
fmv[3] = mb->PMV[0][0][0];
bmv[2] = mb->PMV[1][1][1];
bmv[3] = mb->PMV[1][1][0];
*dy++ = GFXBLOCK + 4 + (y1size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[0];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;;
PACK_CORR_DATA(dy,block_ptr,y1size);
block_ptr = (short *)((unsigned long)block_ptr + y1size);
*dy++ = GFXBLOCK + 4 + (y2size>>2);
*dy++ = (1<<30) | (2<<28) | dw1[1];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[2];
*dy++ = *(uint *)&bmv[2];
PACK_CORR_DATA(dy,block_ptr,y2size);
block_ptr = (short *)((unsigned long)block_ptr + y2size);
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
fmv[2] /= 2;
fmv[3] /= 2;
bmv[2] /= 2;
bmv[3] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[0];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
if(dw1[0] & (1<<23)) {
PACK_CORR_DATA_SHORT(du,block_ptr);
}
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[1];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[2];
*du++ = *(uint *)&bmv[2];
if(dw1[1] & (1<<23)) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(du,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[0];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
if(dw1[0] & (1<<22)) {
PACK_CORR_DATA_SHORT(dv,block_ptr);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[1];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[2];
*dv++ = *(uint *)&bmv[2];
if(dw1[1] & (1<<22)) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(dv,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*datay = dy;
*datau = du;
*datav = dv;
}
static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau,
uint **datav,
XvMCMacroBlock *mb,
short *block_ptr,
uint flags) {
register uint *dy = *datay;
register uint *du = *datau;
register uint *dv = *datav;
short fmv[4];
short bmv[4];
uint dw1[2];
short * top_left_b = NULL;
short * top_right_b = NULL;
short * bottom_left_b = NULL;
short * bottom_right_b = NULL;
uint cbp = (uint)mb->coded_block_pattern;
uint ysize = y_dct0_field_bytes[cbp];
uint usize = u_field_bytes[cbp];
uint vsize = v_field_bytes[cbp];
uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3);
dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) |
3<<12 | 2<<6 | 2<<3 | 3;
dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) |
3<<12 | 3<<6 | 3<<3 | 2;
fmv[0] = mb->PMV[0][0][1];
fmv[1] = mb->PMV[0][0][0];
bmv[0] = mb->PMV[1][0][1];
bmv[1] = mb->PMV[1][0][0];
fmv[2] = mb->PMV[0][0][1];
fmv[3] = mb->PMV[0][0][0];
bmv[2] = mb->PMV[1][1][1];
bmv[3] = mb->PMV[1][1][0];
top_left_b = &empty_block[0];
if(cbp & 0x20) {
top_left_b = block_ptr;
block_ptr += 64;
}
top_right_b = &empty_block[0];
if(cbp & 0x10) {
top_right_b = block_ptr;
block_ptr += 64;
}
bottom_left_b = &empty_block[0];
if(cbp & 0x8) {
bottom_left_b = block_ptr;
block_ptr += 64;
}
bottom_right_b = &empty_block[0];
if(cbp & 0x4) {
bottom_right_b = block_ptr;
block_ptr += 64;
}
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (2<<28) | dw1[0];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)fmv;
*dy++ = *(uint *)bmv;
if(cbp & 0x20) {
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
}
if(cbp & 0x10) {
PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
}
*dy++ = GFXBLOCK + 4 + (ysize>>2);
*dy++ = (1<<30) | (2<<28) | dw1[1];
*dy++ = xy;
*dy++ = (8<<16) | 16;
*dy++ = *(uint *)&fmv[2];
*dy++ = *(uint *)&bmv[2];
if(cbp & 0x20) {
top_left_b = (short *)((unsigned long)top_left_b + 16);
bottom_left_b = (short *)((unsigned long)bottom_left_b + 16);
PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b);
}
if(cbp & 0x10) {
top_right_b = (short *)((unsigned long)top_right_b + 16);
bottom_right_b = (short *)((unsigned long)bottom_right_b + 16);
PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b);
}
fmv[0] /= 2;
fmv[1] /= 2;
bmv[0] /= 2;
bmv[1] /= 2;
fmv[2] /= 2;
fmv[3] /= 2;
bmv[2] /= 2;
bmv[3] /= 2;
xy >>= 1;
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[0];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)fmv;
*du++ = *(uint *)bmv;
if(cbp & (1<<23)) {
PACK_CORR_DATA_SHORT(du,block_ptr);
}
*du++ = GFXBLOCK + 4 + (usize>>2);
*du++ = (2<<30) | (1<<28) | dw1[1];
*du++ = xy;
*du++ = (4<<16) | 8;
*du++ = *(uint *)&fmv[2];
*du++ = *(uint *)&bmv[2];
if(cbp & (1<<23)) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(du,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[0];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)fmv;
*dv++ = *(uint *)bmv;
if(cbp & (1<<22)) {
PACK_CORR_DATA_SHORT(dv,block_ptr);
}
*dv++ = GFXBLOCK + 4 + (vsize>>2);
*dv++ = (3<<30) | (1<<28) | dw1[1];
*dv++ = xy;
*dv++ = (4<<16) | 8;
*dv++ = *(uint *)&fmv[2];
*dv++ = *(uint *)&bmv[2];
if(cbp & (1<<22)) {
block_ptr = (short *)((unsigned long)block_ptr + 16);
PACK_CORR_DATA_SHORT(dv,block_ptr);
block_ptr = (short *)((unsigned long)block_ptr + 112);
}
*datay = dy;
*datau = du;
*datav = dv;
}
#define UV_QUEUE 14
Status XvMCRenderSurface(Display *display, XvMCContext *context,
unsigned int picture_structure,
XvMCSurface *target_surface,
XvMCSurface *past_surface,
XvMCSurface *future_surface,
unsigned int flags,
unsigned int num_macroblocks,
unsigned int first_macroblock,
XvMCMacroBlockArray *macroblock_array,
XvMCBlockArray *blocks) {
drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE];
int u_index = 0,v_index = 0;
int dirty_context = 1;
short *block_ptr;
XvMCMacroBlock *mb;
drm_i810_mc_t mc;
int i,j;
i810XvMCSurface *privTarget;
i810XvMCSurface *privFuture = NULL;
i810XvMCSurface *privPast = NULL;
i810XvMCContext *pI810XvMC;
uint *datay = NULL;
uint *datau = NULL;
uint *datav = NULL;
if((target_surface == NULL) || (context == NULL) || (display == NULL)) {
printf("Error, Invalid Target,Context, or DIsplay!\n");
return BadValue;
}
if(num_macroblocks == 0) {return Success;}
if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;}
if(context->privData == NULL) {return BadValue;}
pI810XvMC = (i810XvMCContext *)context->privData;
if(target_surface->privData == NULL) {
printf("Error, Invalid Target Surface!\n");
return BadValue;
}
privTarget = (i810XvMCSurface *)target_surface->privData;
if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) {
printf("Error, Too many macroblocks requested for MB array size.\n");
return BadValue;
}
if(context->surface_type_id != FOURCC_YV12) {
printf("Error, HWMC only possible on YV12 Surfaces\n");
return BadValue;
}
if(past_surface == NULL) {
privPast = privTarget;
}
else {
if(past_surface->privData == NULL) {
printf("Error, Invalid Past Surface!\n");
return BadValue;
}
privPast = (i810XvMCSurface *)past_surface->privData;
}
if(future_surface == NULL) {
privFuture = privTarget;
if(pI810XvMC->dual_prime) {
privFuture = privPast;
flags |= 0x40000000;
}
if(flags & XVMC_SECOND_FIELD) {
flags |= 0x80000000;
}
}
else {
if((future_surface->privData == NULL) || (past_surface == NULL)) {
printf("Error, Invalid Future Surface or No Past Surface!\n");
return BadValue;
}
privFuture = (i810XvMCSurface *)future_surface->privData;
flags &= ~0x80000000;
}
I810_LOCK(pI810XvMC,0);
for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) {
mb = ¯oblock_array->macro_blocks[i];
block_ptr = &(blocks->blocks[mb->index<<6]);
if(mb->x > target_surface->width>>4) {
mb->x = 0;
}
if(mb->y > target_surface->height>>4) {
mb->y = 0;
}
if(datay) {
pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address;
if(pDMAy->used > 3520) {
if(dirty_context) {
dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
}
dirty_context = 0;
mc.idx = pDMAy->idx;
mc.used = pDMAy->used;
datay = NULL;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
}
if(datau) {
pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
if(pDMAu[u_index]->used > 3904) {
u_index++;
datau = NULL;
if(u_index == UV_QUEUE) {
for(j=0; j<UV_QUEUE; j++) {
mc.idx = pDMAu[j]->idx;
mc.used = pDMAu[j]->used;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
u_index = 0;
dirty_context = 1;
}
}
}
if(datav) {
pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
if(pDMAv[v_index]->used > 3904) {
v_index++;
datav = NULL;
if(v_index == UV_QUEUE) {
for(j=0; j<UV_QUEUE; j++) {
mc.idx = pDMAv[j]->idx;
mc.used = pDMAv[j]->used;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
v_index = 0;
dirty_context = 1;
}
}
}
if(datay == NULL) {
pDMAy = i810_get_free_buffer(pI810XvMC);
datay = pDMAy->address;
}
if(datau == NULL) {
pDMAu[u_index] = i810_get_free_buffer(pI810XvMC);
datau = pDMAu[u_index]->address;
if(u_index == 0) {
*datau++ = CMD_FLUSH;
*datau++ = BOOLEAN_ENA_2;
*datau++ = CMD_FLUSH;
*datau++ = DEST_BUFFER_INFO;
*datau++ = privTarget->dbi1u;
*datau++ = DEST_BUFFER_VAR;
*datau++ = privTarget->dbv1;
*datau++ = CMD_MAP_INFO;
*datau++ = privPast->mi1u;
*datau++ = privPast->mi2u;
*datau++ = privPast->mi3u;
*datau++ = CMD_MAP_INFO;
*datau++ = privFuture->mi1u | 0x1<<28;
*datau++ = privFuture->mi2u;
*datau++ = privFuture->mi3u;
}
}
if(datav == NULL) {
pDMAv[v_index] = i810_get_free_buffer(pI810XvMC);
datav = pDMAv[v_index]->address;
if(v_index == 0) {
*datav++ = CMD_FLUSH;
*datav++ = BOOLEAN_ENA_2;
*datav++ = CMD_FLUSH;
*datav++ = DEST_BUFFER_INFO;
*datav++ = privTarget->dbi1v;
*datav++ = DEST_BUFFER_VAR;
*datav++ = privTarget->dbv1;
*datav++ = CMD_MAP_INFO;
*datav++ = privPast->mi1v;
*datav++ = privPast->mi2v;
*datav++ = privPast->mi3v;
*datav++ = CMD_MAP_INFO;
*datav++ = privFuture->mi1v | 0x1<<28;
*datav++ = privFuture->mi2v;
*datav++ = privFuture->mi3v;
}
}
if(!(mb->macroblock_type & 0x8)) {
mb->coded_block_pattern = 0;
}
if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) {
if(!pI810XvMC->dual_prime) {
pI810XvMC->dual_prime = 1;
privFuture = privPast;
*datay++ = CMD_MAP_INFO;
*datay++ = privFuture->mi1y | 0x1<<28;
*datay++ = privFuture->mi2y;
*datay++ = privFuture->mi3y;
*datau++ = CMD_MAP_INFO;
*datau++ = privFuture->mi1u | 0x1<<28;
*datau++ = privFuture->mi2u;
*datau++ = privFuture->mi3u;
*datav++ = CMD_MAP_INFO;
*datav++ = privFuture->mi1v | 0x1<<28;
*datav++ = privFuture->mi2v;
*datav++ = privFuture->mi3v;
}
}
if((pI810XvMC->dual_prime) &&
(mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) {
pI810XvMC->dual_prime = 0;
privFuture = privTarget;
*datay++ = CMD_MAP_INFO;
*datay++ = privFuture->mi1y | 0x1<<28;
*datay++ = privFuture->mi2y;
*datay++ = privFuture->mi3y;
*datau++ = CMD_MAP_INFO;
*datau++ = privFuture->mi1u | 0x1<<28;
*datau++ = privFuture->mi2u;
*datau++ = privFuture->mi3u;
*datav++ = CMD_MAP_INFO;
*datav++ = privFuture->mi1v | 0x1<<28;
*datav++ = privFuture->mi2v;
*datav++ = privFuture->mi3v;
}
if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) {
if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
if(mb->dct_type) {
renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
}
renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr);
continue;
}
switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) {
case 0x2:
renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
case 0x5:
renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
case 0x6:
renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
case 0x1:
renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
case 0x3:
renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
case 0x7:
renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags);
continue;
default:
renderError();
continue;
}
}
if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) {
renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure);
continue;
}
switch(mb->motion_type & 0x3) {
case 0x1:
renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
flags);
continue;
case 0x2:
render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure,
flags);
continue;
case 0x3:
renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr,
picture_structure,flags);
continue;
default:
renderError();
continue;
}
continue;
}
if(dirty_context) {
dispatchYContext(privTarget,privPast,privFuture,pI810XvMC);
}
mc.idx = pDMAy->idx;
mc.used = (unsigned long)datay - (unsigned long)pDMAy->address;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address;
for(j=0; j<=u_index; j++) {
mc.idx = pDMAu[j]->idx;
mc.used = pDMAu[j]->used;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address;
for(j=0; j<=v_index; j++) {
mc.idx = pDMAv[j]->idx;
mc.used = pDMAv[j]->used;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
}
I810_UNLOCK(pI810XvMC);
return Success;
}
Status XvMCPutSurface(Display *display,XvMCSurface *surface,
Drawable draw, short srcx, short srcy,
unsigned short srcw, unsigned short srch,
short destx, short desty,
unsigned short destw, unsigned short desth,
int flags) {
i810XvMCContext *pI810XvMC;
i810XvMCSurface *pI810Surface;
i810OverlayRecPtr pORegs;
unsigned int ysrc_offset,uvsrc_offset;
Box extents;
uint window_width,window_height;
unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0;
unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0;
unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0;
unsigned int ovcmd = 0;
uint d;
double xscale,yscale;
int diff;
int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty;
int clipped_srcw, clipped_srch, clipped_destw, clipped_desth;
uint x1,y1,root_width,root_height;
int x2 = 0, y2 = 0,unused;
uint nChilds;
int stat;
Window win,root,parent,*pChilds;
if((display == NULL) || (surface == NULL)) {
return BadValue;
}
if(surface->privData == NULL) {
return (error_base + XvMCBadSurface);
}
pI810Surface = (i810XvMCSurface *)surface->privData;
pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
pORegs = (i810OverlayRecPtr)pI810XvMC->oregs;
switch(surface->surface_type_id) {
case FOURCC_YV12:
case FOURCC_I420:
yPitch = (srcw + 7) & ~7;
uvPitch = ((srcw>>1) + 7) & ~7;
if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
srch = srch>>1;
}
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
return BadValue;
yPitch = ((srcw + 7) & ~7) << 1;
break;
}
win = draw;
XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
if(nChilds) XFree(pChilds);
XGetGeometry(display,win, &root, &x2, &y2, &window_width,
&window_height, &d, &d);
x1 = x2;
y1 = y2;
win = parent;
do {
XQueryTree(display,win,&root,&parent,&pChilds,&nChilds);
if(nChilds) XFree(pChilds);
XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d);
x1 += x2;
y1 += y2;
win = parent;
}while(win != root);
XGetGeometry(display,root, &root, &unused, &unused,
&root_width, &root_height, &d, &d);
extents.x1 = 0;
if(x1 > extents.x1) {
extents.x1 = x1;
}
extents.x2 = root_width;
if(extents.x2 > (x1 + window_width)) {
extents.x2 = x1 + window_width;
}
extents.y1 = 0;
if(y1 > extents.y1) {
extents.y1 = y1;
}
extents.y2 = root_height;
if(extents.y2 > (y1 + window_height)) {
extents.y2 = y1 + window_height;
}
destx += x1;
desty += y1;
xscale = (double)srcw / (double)destw;
yscale = (double)srch / (double)desth;
clipped_srcx = srcx;
clipped_srcy = srcy;
clipped_destx = destx;
clipped_desty = desty;
clipped_srcw = srcw;
clipped_srch = srch;
clipped_destw = destw;
clipped_desth = desth;
if(clipped_srcx < 0) {
clipped_destx += (0 - clipped_srcx) / xscale;
clipped_srcw -= clipped_srcx;
clipped_destw -= clipped_srcx / xscale;
clipped_srcx = 0;
}
if((clipped_srcw + clipped_srcx) > surface->width) {
clipped_srcw = surface->width - clipped_srcx;
clipped_destw -= (clipped_srcw - srcw) / xscale;
}
if(clipped_srcy < 0) {
clipped_desty += (0 - clipped_srcy) / yscale;
clipped_srch -= clipped_srcy;
clipped_desth -= clipped_srcy / yscale;
clipped_srcy = 0;
}
if((clipped_srch + clipped_srcy) > surface->height) {
clipped_srch = surface->height - clipped_srcy;
clipped_desth -= (clipped_srch - srch) / yscale;
}
if(clipped_destx < extents.x1) {
diff = extents.x1 - clipped_destx;
clipped_srcx += diff * xscale;
clipped_srcw -= diff * xscale;
clipped_destw -= diff;
clipped_destx = extents.x1;
}
diff = (clipped_destx + clipped_destw) - extents.x2;
if(diff > 0) {
clipped_destw -= diff;
clipped_srcw -= diff * xscale;
}
if(clipped_desty < extents.y1) {
diff = extents.y1 - clipped_desty;
clipped_srcy += diff * yscale;
clipped_srch -= diff * yscale;
clipped_desth -= diff;
clipped_desty = 0;
}
diff = (clipped_desty + clipped_desth) - extents.y2;
if(diff > 0) {
clipped_desth -= diff;
clipped_srch -= diff * yscale;
}
if((clipped_destx + clipped_destw < extents.x1) ||
(clipped_desty + clipped_desth < extents.y1) ||
(clipped_destx > extents.x2) ||
(clipped_desty > extents.y2)) {
return XvMCHideSurface(display, surface);
}
ysrc_offset = ((clipped_srcx + 1) & ~1) +
((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch);
uvsrc_offset = (clipped_srcx>>1) +
(clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1));
ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
Y_ADJUST | OVERLAY_ENABLE;
if ((clipped_destw != clipped_srcw) ||
(clipped_desth != clipped_srch)) {
xscaleInt = (clipped_srcw / clipped_destw) & 0x3;
xscaleFract = (clipped_srcw << 12) / clipped_destw;
yscaleInt = (clipped_srch / clipped_desth) & 0x3;
yscaleFract = (clipped_srch << 12) / clipped_desth;
if (clipped_destw > clipped_srcw) {
ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION);
}
if (clipped_desth > clipped_srch) {
ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION);
}
if (clipped_destw < clipped_srcw) {
ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER;
ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER;
ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION);
}
if (clipped_desth < clipped_srch) {
ovcmd &= ~VERTICAL_CHROMINANCE_FILTER;
ovcmd &= ~VERTICAL_LUMINANCE_FILTER;
ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION);
}
if (xscaleFract) {
xscaleFractUV = xscaleFract >> MINUV_SCALE;
ovcmd &= ~HC_DOWN_INTERPOLATION;
ovcmd |= HC_UP_INTERPOLATION;
}
if (xscaleInt) {
xscaleIntUV = xscaleInt >> MINUV_SCALE;
if (xscaleIntUV) {
ovcmd &= ~HC_UP_INTERPOLATION;
}
}
if (yscaleFract) {
yscaleFractUV = yscaleFract >> MINUV_SCALE;
ovcmd &= ~VC_DOWN_INTERPOLATION;
ovcmd |= VC_UP_INTERPOLATION;
}
if (yscaleInt) {
yscaleIntUV = yscaleInt >> MINUV_SCALE;
if (yscaleIntUV) {
ovcmd &= ~VC_UP_INTERPOLATION;
ovcmd |= VC_DOWN_INTERPOLATION;
}
}
}
I810_LOCK(pI810XvMC,0);
stat = XVMC_RENDERING;
while(stat & XVMC_RENDERING) {
XvMCGetSurfaceStatus(display,surface,&stat);
}
if(pI810XvMC->last_flip) {
BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
}
pI810XvMC->current = !pI810XvMC->current;
pORegs->OV0CMD = ovcmd;
if ((clipped_destw != clipped_srcw) ||
(clipped_desth != clipped_srch)) {
pORegs->YRGBSCALE = (xscaleInt << 15) |
((xscaleFract & 0xFFF) << 3) | (yscaleInt) |
((yscaleFract & 0xFFF) << 20);
pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) |
((yscaleFractUV & 0xFFF) << 20);
}
else {
pORegs->YRGBSCALE = 0x80004000;
pORegs->UVSCALE = 0x80004000;
}
pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15);
pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx;
pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw));
pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) |
(pI810XvMC->brightness & 0xff);
pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff);
pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey);
if(pI810XvMC->current) {
pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[0] + ysrc_offset;
pORegs->OBUF_1V = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
pORegs->OBUF_1U = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
}
else {
pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[0] + ysrc_offset;
pORegs->OBUF_0V = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[2] + uvsrc_offset;
pORegs->OBUF_0U = (unsigned long)pI810Surface->offset +
(unsigned long)pI810Surface->offsets[1] + uvsrc_offset;
}
switch(surface->surface_type_id) {
case FOURCC_YV12:
case FOURCC_I420:
pORegs->SWID = (uvPitch << 16) | yPitch;
pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3);
pORegs->OV0STRIDE = (1<<pI810Surface->pitch) |
((1<<pI810Surface->pitch) << 15);
pORegs->OV0CMD &= ~SOURCE_FORMAT;
pORegs->OV0CMD |= YUV_420;
if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) {
if(flags & XVMC_TOP_FIELD) {
if(pI810XvMC->current == 1) {
pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
BUFFER1_FIELD0);
}
else {
pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
BUFFER0_FIELD0);
}
pORegs->YRGB_VPH = 1<<15 | 1<<31;
pORegs->UV_VPH = 3<<14 | 3<<30;
pORegs->INIT_PH = 0x06 | 0x18;
}
else {
if(pI810XvMC->current == 1) {
pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
BUFFER1_FIELD1);
}
else {
pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD |
BUFFER0_FIELD1);
}
pORegs->YRGB_VPH = 0;
pORegs->UV_VPH = 7<<29 | 7<<13;
pORegs->INIT_PH = 0x06;
}
}
else {
if(pI810XvMC->current == 1) {
pORegs->OV0CMD |= BUFFER1_FIELD0;
}
else {
pORegs->OV0CMD |= BUFFER0_FIELD0;
}
pORegs->YRGB_VPH = 0;
pORegs->UV_VPH = 0;
pORegs->INIT_PH = 0;
}
break;
case FOURCC_UYVY:
case FOURCC_YUY2:
default:
pORegs->SWID = srcw;
pORegs->SWIDQW = srcw >> 3;
pORegs->OV0STRIDE = pI810Surface->pitch;
pORegs->OV0CMD &= ~SOURCE_FORMAT;
pORegs->OV0CMD |= YUV_422;
pORegs->OV0CMD &= ~OV_BYTE_ORDER;
if (surface->surface_type_id == FOURCC_UYVY) {
pORegs->OV0CMD |= Y_SWAP;
}
pORegs->OV0CMD &= ~BUFFER_AND_FIELD;
if(pI810XvMC->current == 1) {
pORegs->OV0CMD |= BUFFER1_FIELD0;
}
else {
pORegs->OV0CMD |= BUFFER0_FIELD0;
}
break;
}
OVERLAY_FLIP(pI810XvMC);
if(!pI810XvMC->last_flip) {
pORegs->OV0CMD &= ~0x4;
if(pI810XvMC->current == 1) {
pORegs->OV0CMD |= BUFFER1_FIELD0;
}
else {
pORegs->OV0CMD |= BUFFER0_FIELD0;
}
}
pI810Surface->last_flip = ++pI810XvMC->last_flip;
I810_UNLOCK(pI810XvMC);
return Success;
}
Status XvMCSyncSurface(Display *display,XvMCSurface *surface) {
Status ret;
int stat=0;
do {
ret = XvMCGetSurfaceStatus(display,surface,&stat);
}while(!ret && (stat & XVMC_RENDERING));
return ret;
}
Status XvMCFlushSurface(Display * display, XvMCSurface *surface) {
return Success;
}
Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface,
int *stat) {
i810XvMCSurface *privSurface;
i810XvMCContext *pI810XvMC;
int temp;
if((display == NULL) || (surface == NULL) || (stat == NULL)) {
return BadValue;
}
if(surface->privData == NULL) {
return BadValue;
}
*stat = 0;
privSurface = surface->privData;
pI810XvMC = privSurface->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSurface);
}
I810_LOCK(pI810XvMC,0);
if(privSurface->last_flip) {
if(pI810XvMC->last_flip < privSurface->last_flip) {
printf("Error: Context last flip is less than surface last flip.\n");
return BadValue;
}
if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) {
if(pI810XvMC->last_flip == privSurface->last_flip) {
*stat |= XVMC_DISPLAYING;
}
else {
temp = GET_FSTATUS(pI810XvMC);
if(((temp & (1<<20))>>20) != pI810XvMC->current) {
*stat |= XVMC_DISPLAYING;
}
}
}
}
if(privSurface->last_render &&
(privSurface->last_render > GET_RSTATUS(pI810XvMC))) {
*stat |= XVMC_RENDERING;
}
I810_UNLOCK(pI810XvMC);
return Success;
}
Status XvMCHideSurface(Display *display, XvMCSurface *surface) {
i810XvMCSurface *pI810Surface;
i810XvMCContext *pI810XvMC;
int ss, xx;
if(display == NULL) {
return BadValue;
}
if(surface == NULL) {
return (error_base + XvMCBadSurface);
}
XvMCSyncSurface(display, surface);
if(surface->privData == NULL) {
return (error_base + XvMCBadSurface);
}
pI810Surface = (i810XvMCSurface *)surface->privData;
if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) {
return xx;
}
if(! (ss & XVMC_DISPLAYING)) {
return Success;
}
pI810XvMC = (i810XvMCContext *)pI810Surface->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSurface);
}
if(pI810XvMC->last_flip) {
I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT);
BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current);
pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION |
Y_ADJUST;
pI810XvMC->current = !pI810XvMC->current;
if(pI810XvMC->current == 1) {
pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0;
}
else {
pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0;
}
OVERLAY_FLIP(pI810XvMC);
pI810XvMC->last_flip++;
BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current)
I810_UNLOCK(pI810XvMC);
}
return Success;
}
Status XvMCCreateSubpicture(Display *display, XvMCContext *context,
XvMCSubpicture *subpicture,
unsigned short width, unsigned short height,
int xvimage_id) {
i810XvMCContext *pI810XvMC;
i810XvMCSubpicture *pI810Subpicture;
int priv_count;
uint *priv_data;
Status ret;
if((subpicture == NULL) || (context == NULL) || (display == NULL)){
return BadValue;
}
pI810XvMC = (i810XvMCContext *)context->privData;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadContext);
}
subpicture->context_id = context->context_id;
subpicture->xvimage_id = xvimage_id;
subpicture->width = width;
subpicture->height = height;
subpicture->privData =
(i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture));
if(!subpicture->privData) {
return BadAlloc;
}
pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
if((ret = _xvmc_create_subpicture(display, context, subpicture,
&priv_count, &priv_data))) {
printf("Unable to create XvMCSubpicture.\n");
return ret;
}
if(priv_count != 1) {
printf("_xvmc_create_subpicture() returned incorrect data size.\n");
printf("Expected 1 got %d\n",priv_count);
free(priv_data);
return BadAlloc;
}
pI810Subpicture->data = pI810XvMC->surfaces.address;
pI810Subpicture->offset = pI810XvMC->surfaces.offset;
pI810Subpicture->privContext = pI810XvMC;
pI810Subpicture->last_render = 0;
pI810Subpicture->last_flip = 0;
subpicture->num_palette_entries = 16;
subpicture->entry_bytes = 3;
strcpy(subpicture->component_order,"YUV");
pI810Subpicture->pitch = 10;
pI810Subpicture->offsets[0] = priv_data[0];
if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) {
printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n");
}
free(priv_data);
memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]),
0, ((1<<pI810Subpicture->pitch) * subpicture->height));
switch(subpicture->xvimage_id) {
case FOURCC_IA44:
case FOURCC_AI44:
pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset +
pI810Subpicture->offsets[0]) & ~0xfc000fff) |
(pI810Subpicture->pitch - 9));
pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16);
pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) |
(pI810Subpicture->pitch - 3);
pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) |
((unsigned int)subpicture->width - 1);
pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset +
pI810Subpicture->offsets[0]) & ~0xfc00000f;
break;
default:
free(subpicture->privData);
return BadMatch;
}
pI810XvMC->ref++;
return Success;
}
Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture,
short x, short y,
unsigned short width, unsigned short height,
unsigned int color) {
i810XvMCContext *pI810XvMC;
i810XvMCSubpicture *pI810Subpicture;
int i;
if((subpicture == NULL) || (display == NULL)){
return BadValue;
}
if(!subpicture->privData) {
return (error_base + XvMCBadSubpicture);
}
pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSubpicture);
}
if((x < 0) || (x + width > subpicture->width)) {
return BadValue;
}
if((y < 0) || (y + height > subpicture->height)) {
return BadValue;
}
for(i=y; i<y + height; i++) {
memset((void *)((unsigned long)pI810Subpicture->data +
(unsigned long)pI810Subpicture->offsets[0] + x +
(1<<pI810Subpicture->pitch) * i),(char)color,width);
}
return Success;
}
Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture,
XvImage *image,
short srcx, short srcy,
unsigned short width, unsigned short height,
short dstx, short dsty) {
i810XvMCContext *pI810XvMC;
i810XvMCSubpicture *pI810Subpicture;
int i;
if((subpicture == NULL) || (display == NULL)){
return BadValue;
}
if(!subpicture->privData) {
return (error_base + XvMCBadSubpicture);
}
pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSubpicture);
}
if((srcx < 0) || (srcx + width > image->width)) {
return BadValue;
}
if((dstx < 0) || (dstx + width > subpicture->width)) {
return BadValue;
}
if((srcy < 0) || (srcy + height > image->height)) {
return BadValue;
}
if((dsty < 0) || (dsty + height > subpicture->height)) {
return BadValue;
}
for(i=0; i<height; i++) {
memcpy((void *)((unsigned long)pI810Subpicture->data +
(unsigned long)pI810Subpicture->offsets[0] + dstx +
(1<<pI810Subpicture->pitch) * (i + dsty)),
(void *)((unsigned long)image->data +
(unsigned long)image->offsets[0] + srcx +
image->pitches[0] * (i + srcy))
,width);
}
return Success;
}
Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) {
i810XvMCSubpicture *pI810Subpicture;
i810XvMCContext *pI810XvMC;
if((display == NULL) || (subpicture == NULL)) {
return BadValue;
}
if(!subpicture->privData) {
return (error_base + XvMCBadSubpicture);
}
pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData;
pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext;
if(!pI810XvMC) {
return (error_base + XvMCBadSubpicture);
}
if(pI810Subpicture->last_render) {
XvMCSyncSubpicture(display,subpicture);
}
_xvmc_destroy_subpicture(display,subpicture);
i810_free_privContext(pI810XvMC);
free(pI810Subpicture);
subpicture->privData = NULL;
return Success;
}
Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture,
unsigned char *palette) {
i810XvMCSubpicture *privSubpicture;
int i,j;
if((display == NULL) || (subpicture == NULL)) {
return BadValue;
}
if(subpicture->privData == NULL) {
return (error_base + XvMCBadSubpicture);
}
privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
j=0;
for(i=0; i<16; i++) {
privSubpicture->palette[0][i] = palette[j++];
privSubpicture->palette[1][i] = palette[j++];
privSubpicture->palette[2][i] = palette[j++];
}
return Success;
}
Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface,
XvMCSubpicture *subpicture,
short subx, short suby,
unsigned short subw, unsigned short subh,
short surfx, short surfy,
unsigned short surfw, unsigned short surfh) {
return BadMatch;
}
Status XvMCBlendSubpicture2(Display *display,
XvMCSurface *source_surface,
XvMCSurface *target_surface,
XvMCSubpicture *subpicture,
short subx, short suby,
unsigned short subw, unsigned short subh,
short surfx, short surfy,
unsigned short surfw, unsigned short surfh) {
drmBufPtr pDMA;
unsigned int *data;
i810XvMCContext *pI810XvMC;
i810XvMCSubpicture *privSubpicture;
i810XvMCSurface *privTarget;
i810XvMCSurface *privSource;
drm_i810_mc_t mc;
int i,j;
if(display == NULL) {
return BadValue;
}
if(subpicture == NULL) {
return (error_base + XvMCBadSubpicture);
}
if((target_surface == NULL) || (source_surface == NULL)) {
return (error_base + XvMCBadSurface);
}
if((subpicture->xvimage_id != FOURCC_AI44) &&
(subpicture->xvimage_id != FOURCC_IA44)) {
return (error_base + XvMCBadSubpicture);
}
if(!subpicture->privData) {
return (error_base + XvMCBadSubpicture);
}
privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSubpicture);
}
if(!target_surface->privData) {
return (error_base + XvMCBadSurface);
}
privTarget = (i810XvMCSurface *)target_surface->privData;
if(!source_surface->privData) {
return (error_base + XvMCBadSurface);
}
privSource = (i810XvMCSurface *)source_surface->privData;
if((subx + subw) > subpicture->width) {
return BadValue;
}
if((suby + subh) > subpicture->height) {
return BadValue;
}
if((surfx + surfw) > target_surface->width) {
return BadValue;
}
if((surfy + surfh) > target_surface->height) {
return BadValue;
}
if(target_surface->width != source_surface->width) {
return BadValue;
}
if(target_surface->height != source_surface->height) {
return BadValue;
}
I810_LOCK(pI810XvMC,0);
pDMA = i810_get_free_buffer(pI810XvMC);
data = pDMA->address;
*data++ = (2<<29) | (0x43<<22) | 0x4;
*data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch);
*data++ = (target_surface->height<<16) | target_surface->width;
*data++ = privTarget->offset + privTarget->offsets[0];
*data++ = (1<<privSource->pitch);
*data++ = privSource->offset + privSource->offsets[0];
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<8);
*data++ = CMD_FLUSH;
*data++ = MAP_PALETTE_LOAD;
switch(subpicture->xvimage_id) {
case FOURCC_IA44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i];
}
}
break;
case FOURCC_AI44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j];
}
}
break;
}
*data++ = CMD_FLUSH;
*data++ = DEST_BUFFER_INFO;
*data++ = privTarget->dbi1y;
*data++ = DEST_BUFFER_VAR;
*data++ = privTarget->dbv1;
*data++ = CMD_MAP_INFO;
*data++ = privSubpicture->mi1;
*data++ = privSubpicture->mi2;
*data++ = privSubpicture->mi3;
*data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
*data++ = BOOLEAN_ENA_1;
*data++ = SRC_DEST_BLEND_MONO | (0x940);
*data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224);
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<16) | 1;
*data++ = CMD_FLUSH;
*data++ = DRAWING_RECT_INFO;
*data++ = 0x0;
*data++ = 0x0;
*data++ = 0x0;
*data++ = 0x0;
*data++ = 0x0;
*data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
*(float *)data++ = (float) (surfx + surfw);
*(float *)data++ = (float) (surfy + surfh);
*(float *)data++ = (float) (subx + subw);
*(float *)data++ = (float) (suby + subh);
*(float *)data++ = (float) surfx;
*(float *)data++ = (float) (surfy + surfh);
*(float *)data++ = (float) subx;
*(float *)data++ = (float) (suby + subh);
*(float *)data++ = (float) surfx;
*(float *)data++ = (float) surfy;
*(float *)data++ = (float) subx;
*(float *)data++ = (float) suby;
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<16);
*data++ = CMD_FLUSH;
*data++ = (2<<29) | (0x43<<22) | 0x4;
*data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
*data++ = (target_surface->height<<15) | (target_surface->width>>1);
*data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1];
*data++ = (1<<(privSource->pitch - 1));
*data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1];
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<8);
*data++ = CMD_FLUSH;
*data++ = MAP_PALETTE_LOAD;
switch(subpicture->xvimage_id) {
case FOURCC_IA44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i];
}
}
break;
case FOURCC_AI44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j];
}
}
break;
}
*data++ = CMD_FLUSH;
*data++ = BOOLEAN_ENA_2;
*data++ = CMD_FLUSH;
*data++ = DEST_BUFFER_INFO;
*data++ = privTarget->dbi1u;
*data++ = DEST_BUFFER_VAR;
*data++ = privTarget->dbv1;
*data++ = CMD_MAP_INFO;
*data++ = privSubpicture->mi1;
*data++ = privSubpicture->mi2;
*data++ = privSubpicture->mi3;
*data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
*data++ = BOOLEAN_ENA_1;
*data++ = SRC_DEST_BLEND_MONO | (0x940);
*data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<16) | 1;
*data++ = CMD_FLUSH;
*data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
*(float *)data++ = (float) ((surfx + surfw)>>1);
*(float *)data++ = (float) ((surfy + surfh)>>1);
*(float *)data++ = (float) subx + subw;
*(float *)data++ = (float) suby + subh;
*(float *)data++ = (float) (surfx>>1);
*(float *)data++ = (float) ((surfy + surfh)>>1);
*(float *)data++ = (float) subx;
*(float *)data++ = (float) suby + subh;
*(float *)data++ = (float) (surfx>>1);
*(float *)data++ = (float) (surfy>>1);
*(float *)data++ = (float) subx;
*(float *)data++ = (float) suby;
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<16);
*data++ = CMD_FLUSH;
*data++ = (2<<29) | (0x43<<22) | 0x4;
*data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1));
*data++ = (target_surface->height<<15) | (target_surface->width>>1);
*data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2];
*data++ = (1<<(privSource->pitch - 1));
*data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2];
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<8);
*data++ = CMD_FLUSH;
*data++ = MAP_PALETTE_LOAD;
switch(subpicture->xvimage_id) {
case FOURCC_IA44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i];
}
}
break;
case FOURCC_AI44:
for(i=0; i<16; i++) {
for(j=0; j<16; j++) {
*data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j];
}
}
break;
}
*data++ = CMD_FLUSH;
*data++ = BOOLEAN_ENA_2;
*data++ = CMD_FLUSH;
*data++ = DEST_BUFFER_INFO;
*data++ = privTarget->dbi1v;
*data++ = DEST_BUFFER_VAR;
*data++ = privTarget->dbv1;
*data++ = CMD_MAP_INFO;
*data++ = privSubpicture->mi1;
*data++ = privSubpicture->mi2;
*data++ = privSubpicture->mi3;
*data++ = VERTEX_FORMAT | (1<<8) | (3<<1);
*data++ = BOOLEAN_ENA_1;
*data++ = SRC_DEST_BLEND_MONO | (0x940);
*data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224);
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<16) | 1;
*data++ = CMD_FLUSH;
*data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = 0;
*data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11;
*(float *)data++ = (float) ((surfx + surfw)>>1);
*(float *)data++ = (float) ((surfy + surfh)>>1);
*(float *)data++ = (float) subx + subw;
*(float *)data++ = (float) suby + subh;
*(float *)data++ = (float) (surfx>>1);
*(float *)data++ = (float) ((surfy + surfh)>>1);
*(float *)data++ = (float) subx;
*(float *)data++ = (float) suby + subh;
*(float *)data++ = (float) (surfx>>1);
*(float *)data++ = (float) (surfy>>1);
*(float *)data++ = (float) subx;
*(float *)data++ = (float) suby;
*data++ = CMD_FLUSH;
*data++ = (5<<23) | (1<<17) | (1<<16);
*data++ = CMD_FLUSH;
pDMA->used = (unsigned long)data - (unsigned long)pDMA->address;
mc.idx = pDMA->idx;
mc.used = pDMA->used;
mc.last_render = ++pI810XvMC->last_render;
privTarget->last_render = pI810XvMC->last_render;
I810_MC(pI810XvMC,mc);
I810_UNLOCK(pI810XvMC);
return Success;
}
Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) {
Status ret;
int stat=0;
do {
ret = XvMCGetSubpictureStatus(display,subpicture,&stat);
}while(!ret && (stat & XVMC_RENDERING));
return ret;
}
Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) {
if(display == NULL) {
return BadValue;
}
if(subpicture == NULL) {
return (error_base + XvMCBadSubpicture);
}
return Success;
}
Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture,
int *stat) {
i810XvMCSubpicture *privSubpicture;
i810XvMCContext *pI810XvMC;
if((display == NULL) || (stat == NULL)) {
return BadValue;
}
if((subpicture == NULL) || (subpicture->privData == NULL)) {
return (error_base + XvMCBadSubpicture);
}
*stat = 0;
privSubpicture = (i810XvMCSubpicture *)subpicture->privData;
pI810XvMC = (i810XvMCContext *)privSubpicture->privContext;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadSubpicture);
}
I810_LOCK(pI810XvMC,0);
if(privSubpicture->last_render &&
(privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) {
*stat |= XVMC_RENDERING;
}
I810_UNLOCK(pI810XvMC);
return Success;
}
#define NUM_XVMC_ATTRIBUTES 4
static XvAttribute I810_XVMC_ATTRIBUTES[] = {
{XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"},
{XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"},
{XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"},
{XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"}
};
XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context,
int *number) {
i810XvMCContext *pI810XvMC;
XvAttribute *attributes;
if(number == NULL) {
return NULL;
}
if(display == NULL) {
*number = 0;
return NULL;
}
if(context == NULL) {
*number = 0;
return NULL;
}
pI810XvMC = context->privData;
if(pI810XvMC == NULL) {
*number = 0;
return NULL;
}
attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES *
sizeof(XvAttribute));
if(attributes == NULL) {
*number = 0;
return NULL;
}
memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES *
sizeof(XvAttribute)));
*number = NUM_XVMC_ATTRIBUTES;
return attributes;
}
Status XvMCSetAttribute(Display *display, XvMCContext *context,
Atom attribute, int value) {
i810XvMCContext *pI810XvMC;
if(display == NULL) {
return BadValue;
}
if(context == NULL) {
return (error_base + XvMCBadContext);
}
pI810XvMC = context->privData;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadContext);
}
if(attribute == pI810XvMC->xv_colorkey) {
if((value < I810_XVMC_ATTRIBUTES[0].min_value) ||
(value > I810_XVMC_ATTRIBUTES[0].max_value)) {
return BadValue;
}
pI810XvMC->colorkey = value;
return Success;
}
if(attribute == pI810XvMC->xv_brightness) {
if((value < I810_XVMC_ATTRIBUTES[1].min_value) ||
(value > I810_XVMC_ATTRIBUTES[1].max_value)) {
return BadValue;
}
pI810XvMC->brightness = value;
return Success;
}
if(attribute == pI810XvMC->xv_saturation) {
if((value < I810_XVMC_ATTRIBUTES[2].min_value) ||
(value > I810_XVMC_ATTRIBUTES[2].max_value)) {
return BadValue;
}
pI810XvMC->saturation = value;
return Success;
}
if(attribute == pI810XvMC->xv_contrast) {
if((value < I810_XVMC_ATTRIBUTES[3].min_value) ||
(value > I810_XVMC_ATTRIBUTES[3].max_value)) {
return BadValue;
}
pI810XvMC->contrast = value;
return Success;
}
return BadValue;
}
Status XvMCGetAttribute(Display *display, XvMCContext *context,
Atom attribute, int *value) {
i810XvMCContext *pI810XvMC;
if(display == NULL) {
return BadValue;
}
if(context == NULL) {
return (error_base + XvMCBadContext);
}
pI810XvMC = context->privData;
if(pI810XvMC == NULL) {
return (error_base + XvMCBadContext);
}
if(value == NULL) {
return BadValue;
}
if(attribute == pI810XvMC->xv_colorkey) {
*value = pI810XvMC->colorkey;
return Success;
}
if(attribute == pI810XvMC->xv_brightness) {
*value = pI810XvMC->brightness;
return Success;
}
if(attribute == pI810XvMC->xv_saturation) {
*value = pI810XvMC->saturation;
return Success;
}
if(attribute == pI810XvMC->xv_contrast) {
*value = pI810XvMC->contrast;
return Success;
}
return BadValue;
}