📄 r128_video.c
字号:
static voidR128CopyData420( R128InfoPtr info, unsigned char *src1, unsigned char *src2, unsigned char *src3, unsigned char *dst1, unsigned char *dst2, unsigned char *dst3, int srcPitch, int srcPitch2, int dstPitch, int h, int w){ int count; /* Attempt data transfer with DMA and fall back to memcpy */ if (!R128DMA(info, src1, dst1, srcPitch, dstPitch, h, w)) { count = h; while(count--) { memcpy(dst1, src1, w); src1 += srcPitch; dst1 += dstPitch; } } w >>= 1; h >>= 1; dstPitch >>= 1; if (!R128DMA(info, src2, dst2, srcPitch2, dstPitch, h, w)) { count = h; while(count--) { memcpy(dst2, src2, w); src2 += srcPitch2; dst2 += dstPitch; } } if (!R128DMA(info, src3, dst3, srcPitch2, dstPitch, h, w)) { count = h; while(count--) { memcpy(dst3, src3, w); src3 += srcPitch2; dst3 += dstPitch; } }}static FBLinearPtrR128AllocateMemory( ScrnInfoPtr pScrn, FBLinearPtr linear, int size){ ScreenPtr pScreen; FBLinearPtr new_linear; if(linear) { if(linear->size >= size) return linear; if(xf86ResizeOffscreenLinear(linear, size)) return linear; xf86FreeOffscreenLinear(linear); } pScreen = screenInfo.screens[pScrn->scrnIndex]; new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); if(!new_linear) { int max_size; xf86QueryLargestOffscreenLinear(pScreen, &max_size, 8, PRIORITY_EXTREME); if(max_size < size) return NULL; xf86PurgeUnlockedOffscreenAreas(pScreen); new_linear = xf86AllocateOffscreenLinear(pScreen, size, 8, NULL, NULL, NULL); } return new_linear;}static voidR128DisplayVideo422( ScrnInfoPtr pScrn, int id, int offset, short width, short height, int pitch, int left, int right, int top, BoxPtr dstBox, short src_w, short src_h, short drw_w, short drw_h){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; int v_inc, h_inc, step_by, tmp; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init; R128ECP(pScrn, pPriv); v_inc = (src_h << 20) / drw_h; h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; step_by = 1; while(h_inc >= (2 << 12)) { step_by++; h_inc >>= 1; } /* keep everything in 16.16 */ offset += ((left >> 16) & ~7) << 1; tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); p1_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0xf0000000); tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); p23_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0x70000000); tmp = (top & 0x0000ffff) + 0x00018000; p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; left = (left >> 16) & 7; OUTREG(R128_OV0_REG_LOAD_CNTL, 1); while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); OUTREG(R128_OV0_V_INC, v_inc); OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); left >>= 1; width >>= 1; OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16)); OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16)); OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset & 0xfffffff0); OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0); OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); if(id == FOURCC_UYVY) OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8C03); else OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03); OUTREG(R128_OV0_REG_LOAD_CNTL, 0);}static voidR128DisplayVideo420( ScrnInfoPtr pScrn, short width, short height, int pitch, int offset1, int offset2, int offset3, int left, int right, int top, BoxPtr dstBox, short src_w, short src_h, short drw_w, short drw_h){ R128InfoPtr info = R128PTR(pScrn); unsigned char *R128MMIO = info->MMIO; R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; int v_inc, h_inc, step_by, tmp, leftUV; int p1_h_accum_init, p23_h_accum_init; int p1_v_accum_init, p23_v_accum_init; v_inc = (src_h << 20) / drw_h; h_inc = (src_w << (12 + pPriv->ecp_div)) / drw_w; step_by = 1; while(h_inc >= (2 << 12)) { step_by++; h_inc >>= 1; } /* keep everything in 16.16 */ offset1 += (left >> 16) & ~15; offset2 += (left >> 17) & ~15; offset3 += (left >> 17) & ~15; tmp = (left & 0x0003ffff) + 0x00028000 + (h_inc << 3); p1_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0xf0000000); tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (h_inc << 2); p23_h_accum_init = ((tmp << 4) & 0x000f8000) | ((tmp << 12) & 0x70000000); tmp = (top & 0x0000ffff) + 0x00018000; p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001; tmp = ((top >> 1) & 0x0000ffff) + 0x00018000; p23_v_accum_init = ((tmp << 4) & 0x01ff8000) | 0x00000001; leftUV = (left >> 17) & 15; left = (left >> 16) & 15; OUTREG(R128_OV0_REG_LOAD_CNTL, 1); while(!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3))); OUTREG(R128_OV0_H_INC, h_inc | ((h_inc >> 1) << 16)); OUTREG(R128_OV0_STEP_BY, step_by | (step_by << 8)); OUTREG(R128_OV0_Y_X_START, dstBox->x1 | (dstBox->y1 << 16)); OUTREG(R128_OV0_Y_X_END, dstBox->x2 | (dstBox->y2 << 16)); OUTREG(R128_OV0_V_INC, v_inc); OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP, 0x00000fff | ((src_h - 1) << 16)); src_h = (src_h + 1) >> 1; OUTREG(R128_OV0_P23_BLANK_LINES_AT_TOP, 0x000007ff | ((src_h - 1) << 16)); OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, pitch); OUTREG(R128_OV0_VID_BUF_PITCH1_VALUE, pitch >> 1); OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16)); width >>= 1; OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (leftUV << 16)); OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (leftUV << 16)); OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset1 & 0xfffffff0); OUTREG(R128_OV0_VID_BUF1_BASE_ADRS, (offset2 & 0xfffffff0) | 0x00000001); OUTREG(R128_OV0_VID_BUF2_BASE_ADRS, (offset3 & 0xfffffff0) | 0x00000001); OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init); OUTREG(R128_OV0_P23_V_ACCUM_INIT, p23_v_accum_init); OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init); OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init); OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8A03); OUTREG(R128_OV0_REG_LOAD_CNTL, 0);}static intR128PutImage( 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, DrawablePtr pDraw){ R128InfoPtr info = R128PTR(pScrn); R128PortPrivPtr pPriv = (R128PortPrivPtr)data; INT32 xa, xb, ya, yb; int new_size, offset, s1offset, s2offset, s3offset; int srcPitch, srcPitch2, dstPitch; int d1line, d2line, d3line, d1offset, d2offset, d3offset; int top, left, npixels, nlines, bpp; BoxRec dstBox; CARD32 tmp;#if X_BYTE_ORDER == X_BIG_ENDIAN unsigned char *R128MMIO = info->MMIO; CARD32 config_cntl = INREG(R128_CONFIG_CNTL); /* We need to disable byte swapping, or the data gets mangled */ OUTREG(R128_CONFIG_CNTL, config_cntl & ~(APER_0_BIG_ENDIAN_16BPP_SWAP | APER_0_BIG_ENDIAN_32BPP_SWAP));#endif /* * s1offset, s2offset, s3offset - byte offsets to the Y, U and V planes * of the source. * * d1offset, d2offset, d3offset - byte offsets to the Y, U and V planes * of the destination. * * offset - byte offset within the framebuffer to where the destination * is stored. * * d1line, d2line, d3line - byte offsets within the destination to the * first displayed scanline in each plane. * */ if(src_w > (drw_w << 4)) drw_w = src_w >> 4; if(src_h > (drw_h << 4)) drw_h = src_h >> 4; /* Clip */ xa = src_x; xb = src_x + src_w; ya = src_y; yb = src_y + src_h; dstBox.x1 = drw_x; dstBox.x2 = drw_x + drw_w; dstBox.y1 = drw_y; dstBox.y2 = drw_y + drw_h; if(!xf86XVClipVideoHelper(&dstBox, &xa, &xb, &ya, &yb, clipBoxes, width, height)) return Success; dstBox.x1 -= pScrn->frameX0; dstBox.x2 -= pScrn->frameX0; dstBox.y1 -= pScrn->frameY0; dstBox.y2 -= pScrn->frameY0; bpp = pScrn->bitsPerPixel >> 3; switch(id) { case FOURCC_YV12: case FOURCC_I420: srcPitch = (width + 3) & ~3; srcPitch2 = ((width >> 1) + 3) & ~3; dstPitch = (width + 31) & ~31; /* of luma */ new_size = ((dstPitch * (height + (height >> 1))) + bpp - 1) / bpp; s1offset = 0; s2offset = srcPitch * height; s3offset = (srcPitch2 * (height >> 1)) + s2offset; break; case FOURCC_UYVY: case FOURCC_YUY2: default: srcPitch = width << 1; srcPitch2 = 0; dstPitch = ((width << 1) + 15) & ~15; new_size = ((dstPitch * height) + bpp - 1) / bpp; s1offset = 0; s2offset = 0; s3offset = 0; break; } if(!(pPriv->linear = R128AllocateMemory(pScrn, pPriv->linear, pPriv->doubleBuffer ? (new_size << 1) : new_size))) { return BadAlloc; } pPriv->currentBuffer ^= 1; /* copy data */ top = ya >> 16; left = (xa >> 16) & ~1; npixels = ((((xb + 0xffff) >> 16) + 1) & ~1) - left; offset = pPriv->linear->offset * bpp; if(pPriv->doubleBuffer) offset += pPriv->currentBuffer * new_size * bpp; switch(id) { case FOURCC_YV12: case FOURCC_I420: d1line = top * dstPitch; d2line = (height * dstPitch) + ((top >> 1) * (dstPitch >> 1)); d3line = d2line + ((height >> 1) * (dstPitch >> 1)); top &= ~1; d1offset = (top * dstPitch) + left + offset; d2offset = d2line + (left >> 1) + offset; d3offset = d3line + (left >> 1) + offset; s1offset += (top * srcPitch) + left; tmp = ((top >> 1) * srcPitch2) + (left >> 1); s2offset += tmp; s3offset += tmp; if(id == FOURCC_YV12) { tmp = s2offset; s2offset = s3offset; s3offset = tmp; } nlines = ((((yb + 0xffff) >> 16) + 1) & ~1) - top; R128CopyData420(info, buf + s1offset, buf + s2offset, buf + s3offset, info->FB+d1offset, info->FB+d2offset, info->FB+d3offset, srcPitch, srcPitch2, dstPitch, nlines, npixels); break; case FOURCC_UYVY: case FOURCC_YUY2: default: left <<= 1; d1line = top * dstPitch; d2line = 0; d3line = 0; d1offset = d1line + left + offset; d2offset = 0; d3offset = 0; s1offset += (top * srcPitch) + left; nlines = ((yb + 0xffff) >> 16) - top; R128CopyData422(info, buf + s1offset, info->FB + d1offset, srcPitch, dstPitch, nlines, npixels); break; }#if X_BYTE_ORDER == X_BIG_ENDIAN /* restore byte swapping */ OUTREG(R128_CONFIG_CNTL, config_cntl);#endif /* 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); } switch(id) { case FOURCC_YV12: case FOURCC_I420: R128DisplayVideo420(pScrn, width, height, dstPitch, offset + d1line, offset + d2line, offset + d3line, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); break; case FOURCC_UYVY: case FOURCC_YUY2: default: R128DisplayVideo422(pScrn, id, offset + d1line, width, height, dstPitch, xa, xb, ya, &dstBox, src_w, src_h, drw_w, drw_h); break; } pPriv->videoStatus = CLIENT_VIDEO_ON; info->VideoTimerCallback = R128VideoTimerCallback; return Success;}static intR128QueryImageAttributes( ScrnInfoPtr pScrn, int id, unsigned short *w, unsigned short *h, int *pitches, int *offsets){ int size, tmp; if(*w > MAXWIDTH) *w = MAXWIDTH; if(*h > MAXHEIGHT) *h = MAXHEIGHT; *w = (*w + 1) & ~1; if(offsets) offsets[0] = 0; switch(id) { case FOURCC_YV12: case FOURCC_I420: *h = (*h + 1) & ~1; size = (*w + 3) & ~3; if(pitches) pitches[0] = size; size *= *h; if(offsets) offsets[1] = size; tmp = ((*w >> 1) + 3) & ~3; if(pitches) pitches[1] = pitches[2] = tmp; tmp *= (*h >> 1); size += tmp; if(offsets) offsets[2] = size; size += tmp; break; case FOURCC_UYVY: case FOURCC_YUY2: default: size = *w << 1; if(pitches) pitches[0] = size; size *= *h; break; } return size;}static voidR128VideoTimerCallback(ScrnInfoPtr pScrn, Time now){ R128InfoPtr info = R128PTR(pScrn); R128PortPrivPtr pPriv = info->adaptor->pPortPrivates[0].ptr; if(pPriv->videoStatus & TIMER_MASK) { if(pPriv->videoStatus & OFF_TIMER) { if(pPriv->offTime < now) { unsigned char *R128MMIO = info->MMIO; OUTREG(R128_OV0_SCALE_CNTL, 0); pPriv->videoStatus = FREE_TIMER; pPriv->freeTime = now + FREE_DELAY; } } else { /* FREE_TIMER */ if(pPriv->freeTime < now) { if(pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); pPriv->linear = NULL; } pPriv->videoStatus = 0; info->VideoTimerCallback = NULL; } } } else /* shouldn't get here */ info->VideoTimerCallback = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -