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 + -
显示快捷键?