i810_video.c

来自「是由intel提供的针对intel显卡915以上系列的linux驱动」· C语言 代码 · 共 1,420 行 · 第 1/3 页

C
1,420
字号
        xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, 				       PRIORITY_EXTREME);        if(max_size < size) return NULL;        xf86PurgeUnlockedOffscreenAreas(pScreen);        new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4,                                                  NULL, NULL, NULL);   }    return new_linear;}static int I810PutImage(   ScrnInfoPtr pScrn,   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){    I810Ptr pI810 = I810PTR(pScrn);    I810PortPrivPtr pPriv = (I810PortPrivPtr)data;    INT32 x1, x2, y1, y2;    int srcPitch, dstPitch;    int top, left, npixels, nlines, size, loops;    BoxRec dstBox;    /* Clip */    x1 = src_x;    x2 = src_x + src_w;    y1 = src_y;    y2 = src_y + src_h;    dstBox.x1 = drw_x;    dstBox.x2 = drw_x + drw_w;    dstBox.y1 = drw_y;    dstBox.y2 = drw_y + drw_h;    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, 		  REGION_EXTENTS(pScrn->pScreen, clipBoxes), width, height);        if((x1 >= x2) || (y1 >= y2))       return Success;    /*      * Fix for 4 pixel granularity of AdjustFrame       * unless boarder is clipped  by frame      */    dstBox.x1 -= (pScrn->frameX0 & 		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));    dstBox.x2 -= (pScrn->frameX0 & ~0x3);    dstBox.y1 -= pScrn->frameY0;     dstBox.y2 -= pScrn->frameY0;    switch(id) {    case FOURCC_YV12:    case FOURCC_I420:	 srcPitch = (width + 3) & ~3;	 dstPitch = ((width >> 1) + 7) & ~7;  /* of chroma */	 size =  dstPitch * height * 3;		 break;    case FOURCC_UYVY:    case FOURCC_YUY2:    default:	 srcPitch = (width << 1);	 dstPitch = (srcPitch + 7) & ~7;	 size = dstPitch * height;	 break;    }      if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear, 		(pScrn->bitsPerPixel == 16) ? size : (size >> 1))))	return BadAlloc;    /* fixup pointers */    pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp;    pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height);    pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1);        pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size;    pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height);    pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1);    /* Make sure this buffer isn't in use */    loops = 0;    while (loops < 1000000) {          if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) {            break;          }          loops++;    }    if(loops >= 1000000) {      pPriv->currentBuf = !pPriv->currentBuf;    }    /* buffer swap */    if (pPriv->currentBuf == 0)        pPriv->currentBuf = 1;    else        pPriv->currentBuf = 0;    /* copy data */    top = y1 >> 16;    left = (x1 >> 16) & ~1;    npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left;    switch(id) {    case FOURCC_YV12:    case FOURCC_I420:	top &= ~1;	nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top;	I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch,  height, top, left,                            nlines, npixels, id);	break;    case FOURCC_UYVY:    case FOURCC_YUY2:    default:	nlines = ((y2 + 0xffff) >> 16) - top;	I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines,                                                               npixels);        break;    }    /* update cliplist */    if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) {	REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes);	/* draw these */	xf86XVFillKeyHelper(pScrn->pScreen, pPriv->colorKey, clipBoxes);    }    I810DisplayVideo(pScrn, id, width, height, dstPitch, 	     x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h);    pPriv->videoStatus = CLIENT_VIDEO_ON;    return Success;}static int I810QueryImageAttributes(  ScrnInfoPtr pScrn,   int id,   unsigned short *w, unsigned short *h,   int *pitches, int *offsets){    int size, tmp;    if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH;    if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT;    *w = (*w + 1) & ~1;    if(offsets) offsets[0] = 0;    switch(id) {      /* IA44 is for XvMC only */    case FOURCC_IA44:    case FOURCC_AI44:	if(pitches) pitches[0] = *w;	size = *w * *h;	break;    case FOURCC_YV12:    case FOURCC_I420:	*h = (*h + 1) & ~1;	size = (*w + 3) & ~3;	if(pitches) pitches[0] = size;	size *= *h;	if(offsets) offsets[1] = size;	tmp = ((*w >> 1) + 3) & ~3;	if(pitches) pitches[1] = pitches[2] = tmp;	tmp *= (*h >> 1);	size += tmp;	if(offsets) offsets[2] = size;	size += tmp;	break;    case FOURCC_UYVY:    case FOURCC_YUY2:    default:	size = *w << 1;	if(pitches) pitches[0] = size;	size *= *h;	break;    }    return size;}static voidI810BlockHandler (    int i,    pointer     blockData,    pointer     pTimeout,    pointer     pReadmask){    ScreenPtr   pScreen = screenInfo.screens[i];    ScrnInfoPtr pScrn = xf86Screens[i];    I810Ptr      pI810 = I810PTR(pScrn);    I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn);    I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);     pScreen->BlockHandler = pI810->BlockHandler;        (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);    pScreen->BlockHandler = I810BlockHandler;    if(pPriv->videoStatus & TIMER_MASK) {	UpdateCurrentTime();	if(pPriv->videoStatus & OFF_TIMER) {	    if(pPriv->offTime < currentTime.milliseconds) {		/* Turn off the overlay */		overlay->OV0CMD &= 0xFFFFFFFE;		OVERLAY_UPDATE(pI810->OverlayPhysical);		pPriv->videoStatus = FREE_TIMER;		pPriv->freeTime = currentTime.milliseconds + FREE_DELAY;	    }	} else {  /* FREE_TIMER */	    if(pPriv->freeTime < currentTime.milliseconds) {		if(pPriv->linear) {		   xf86FreeOffscreenLinear(pPriv->linear);		   pPriv->linear = NULL;		}		pPriv->videoStatus = 0;	    }        }    }}/*************************************************************************** * Offscreen Images ***************************************************************************/typedef struct {  FBLinearPtr linear;  Bool isOn;} OffscreenPrivRec, * OffscreenPrivPtr;static int I810AllocateSurface(    ScrnInfoPtr pScrn,    int id,    unsigned short w, 	    unsigned short h,    XF86SurfacePtr surface){    FBLinearPtr linear;    int pitch, fbpitch, size, bpp;    OffscreenPrivPtr pPriv;    I810Ptr pI810 = I810PTR(pScrn);    if((w > 1024) || (h > 1024))	return BadAlloc;    w = (w + 1) & ~1;    pitch = ((w << 1) + 15) & ~15;    bpp = pScrn->bitsPerPixel >> 3;    fbpitch = bpp * pScrn->displayWidth;    size = ((pitch * h) + bpp - 1) / bpp;    if(!(linear = I810AllocateMemory(pScrn, NULL, size)))	return BadAlloc;    surface->width = w;    surface->height = h;    if(!(surface->pitches = xalloc(sizeof(int)))) {	xf86FreeOffscreenLinear(linear);	return BadAlloc;    }    if(!(surface->offsets = xalloc(sizeof(int)))) {	xfree(surface->pitches);	xf86FreeOffscreenLinear(linear);	return BadAlloc;    }    if(!(pPriv = xalloc(sizeof(OffscreenPrivRec)))) {	xfree(surface->pitches);	xfree(surface->offsets);	xf86FreeOffscreenLinear(linear);	return BadAlloc;    }    pPriv->linear = linear;    pPriv->isOn = FALSE;    surface->pScrn = pScrn;    surface->id = id;       surface->pitches[0] = pitch;    surface->offsets[0] = linear->offset * bpp;    surface->devPrivate.ptr = (pointer)pPriv;    memset(pI810->FbBase + surface->offsets[0],0,size);    return Success;}static int I810StopSurface(    XF86SurfacePtr surface){    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;    if(pPriv->isOn) {      I810Ptr pI810 = I810PTR(surface->pScrn);      I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart);       overlay->OV0CMD &= 0xFFFFFFFE;      OVERLAY_UPDATE(pI810->OverlayPhysical);      pPriv->isOn = FALSE;    }    return Success;}static int I810FreeSurface(    XF86SurfacePtr surface){    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;    if(pPriv->isOn) {	I810StopSurface(surface);    }    xf86FreeOffscreenLinear(pPriv->linear);    xfree(surface->pitches);    xfree(surface->offsets);    xfree(surface->devPrivate.ptr);    return Success;}static intI810GetSurfaceAttribute(    ScrnInfoPtr pScrn,    Atom attribute,    INT32 *value){    return I810GetPortAttribute(pScrn, attribute, value, 0);}static intI810SetSurfaceAttribute(    ScrnInfoPtr pScrn,    Atom attribute,    INT32 value){    return I810SetPortAttribute(pScrn, attribute, value, 0);}static int I810DisplaySurface(    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){    OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr;    ScrnInfoPtr pScrn = surface->pScrn;    I810Ptr      pI810 = I810PTR(pScrn);    I810PortPrivPtr pI810Priv =  GET_PORT_PRIVATE(pScrn);    INT32 x1, y1, x2, y2;    INT32 loops = 0;    BoxRec dstBox;    x1 = src_x;    x2 = src_x + src_w;    y1 = src_y;    y2 = src_y + src_h;    dstBox.x1 = drw_x;    dstBox.x2 = drw_x + drw_w;    dstBox.y1 = drw_y;    dstBox.y2 = drw_y + drw_h;    I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2,		  REGION_EXTENTS(screenInfo.screens[0], clipBoxes),		  surface->width, surface->height);    /*      * Fix for 4 pixel granularity of AdjustFrame       * unless boarder is clipped  by frame      */    dstBox.x1 -= (pScrn->frameX0 & 		  ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL));    dstBox.x2 -= (pScrn->frameX0 & ~0x3);    dstBox.y1 -= pScrn->frameY0;    dstBox.y2 -= pScrn->frameY0;    /* fixup pointers */    pI810Priv->YBuf0offset = surface->offsets[0];    pI810Priv->YBuf1offset = pI810Priv->YBuf0offset;   /* wait for the last rendered buffer to be flipped in */    while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) {      if(loops == 200000) {	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n");	break;      }      loops++;    }    /* buffer swap */    if (pI810Priv->currentBuf == 0)      pI810Priv->currentBuf = 1;    else      pI810Priv->currentBuf = 0;    I810ResetVideo(pScrn);    I810DisplayVideo(pScrn, surface->id, surface->width, surface->height,		     surface->pitches[0], x1, y1, x2, y2, &dstBox,		     src_w, src_h, drw_w, drw_h);    xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes);    pPriv->isOn = TRUE;    /* we've prempted the XvImage stream so set its free timer */    if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) {      REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip);         UpdateCurrentTime();      pI810Priv->videoStatus = FREE_TIMER;      pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY;      pScrn->pScreen->BlockHandler = I810BlockHandler;    }    return Success;}static void I810InitOffscreenImages(ScreenPtr pScreen){    XF86OffscreenImagePtr offscreenImages;    /* need to free this someplace */    if(!(offscreenImages = xalloc(sizeof(XF86OffscreenImageRec)))) {      return;    }    offscreenImages[0].image = &Images[0];    offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | 			       VIDEO_CLIP_TO_VIEWPORT;    offscreenImages[0].alloc_surface = I810AllocateSurface;    offscreenImages[0].free_surface = I810FreeSurface;    offscreenImages[0].display = I810DisplaySurface;    offscreenImages[0].stop = I810StopSurface;    offscreenImages[0].setAttribute = I810SetSurfaceAttribute;    offscreenImages[0].getAttribute = I810GetSurfaceAttribute;    offscreenImages[0].max_width = 1024;    offscreenImages[0].max_height = 1024;    offscreenImages[0].num_attributes = 1;    offscreenImages[0].attributes = Attributes;    xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?