sis_vid.c

来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 1,514 行 · 第 1/3 页

C
1,514
字号
	    setsrregmask(0x06, 0x80, 0xc0);	    setsrregmask(0x32, 0x80, 0xc0);	} else {	    setsrregmask(0x06, 0x40, 0xc0);	    setsrregmask(0x32, 0x40, 0xc0);	}	break;    case DISPMODE_MIRROR:	/* TW: CRT1 + CRT2 */    default:	if (sis_verbose > 2) {	    printf("[SiS] Setting up overlay on CRT1 AND CRT2!\n");	}	setsrregmask(0x06, 0x80, 0xc0);	setsrregmask(0x32, 0x80, 0xc0);	break;    }}static void init_overlay(void){    /* Initialize first overlay (CRT1) */    /* Write-enable video registers */    setvideoregmask(Index_VI_Control_Misc2, 0x80, 0x81);    /* Disable overlay */    setvideoregmask(Index_VI_Control_Misc0, 0x00, 0x02);    /* Disable bobEnable */    setvideoregmask(Index_VI_Control_Misc1, 0x02, 0x02);    /* Reset scale control and contrast */    setvideoregmask(Index_VI_Scale_Control, 0x60, 0x60);    setvideoregmask(Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);    setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low, 0x00);    setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);    setvideoreg(Index_VI_UV_Buf_Preset_Low, 0x00);    setvideoreg(Index_VI_UV_Buf_Preset_Middle, 0x00);    setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);    setvideoreg(Index_VI_Play_Threshold_Low, 0x00);    setvideoreg(Index_VI_Play_Threshold_High, 0x00);    /* may not want to init these here, could already be set to other       values by app? */    setvideoregmask(Index_VI_Control_Misc2, 0x00, 0x01);    setvideoregmask(Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);    setvideoreg(Index_VI_Brightness, 0x20);    if (sis_vga_engine == SIS_315_VGA) {	setvideoreg(Index_VI_Hue, 0x00);	setvideoreg(Index_VI_Saturation, 0x00);    }    /* Initialize second overlay (CRT2) */    if (sis_has_two_overlays) {	/* Write-enable video registers */	setvideoregmask(Index_VI_Control_Misc2, 0x81, 0x81);	/* Disable overlay */	setvideoregmask(Index_VI_Control_Misc0, 0x00, 0x02);	/* Disable bobEnable */	setvideoregmask(Index_VI_Control_Misc1, 0x02, 0x02);	/* Reset scale control and contrast */	setvideoregmask(Index_VI_Scale_Control, 0x60, 0x60);	setvideoregmask(Index_VI_Contrast_Enh_Ctrl, 0x04, 0x1F);	setvideoreg(Index_VI_Disp_Y_Buf_Preset_Low, 0x00);	setvideoreg(Index_VI_Disp_Y_Buf_Preset_Middle, 0x00);	setvideoreg(Index_VI_UV_Buf_Preset_Low, 0x00);	setvideoreg(Index_VI_UV_Buf_Preset_Middle, 0x00);	setvideoreg(Index_VI_Disp_Y_UV_Buf_Preset_High, 0x00);	setvideoreg(Index_VI_Play_Threshold_Low, 0x00);	setvideoreg(Index_VI_Play_Threshold_High, 0x00);	setvideoregmask(Index_VI_Control_Misc2, 0x01, 0x01);	setvideoregmask(Index_VI_Contrast_Enh_Ctrl, 0x04, 0x07);	setvideoreg(Index_VI_Brightness, 0x20);	if (sis_vga_engine == SIS_315_VGA) {	    setvideoreg(Index_VI_Hue, 0x00);	    setvideoreg(Index_VI_Saturation, 0x00);	}    }}static int sis_set_eq(const vidix_video_eq_t * eq);static int sis_config_playback(vidix_playback_t * info){    SISOverlayRec overlay;    int srcOffsetX = 0, srcOffsetY = 0;    int sx, sy;    int index = 0, iscrt2 = 0;    int total_size;    short src_w, drw_w;    short src_h, drw_h;    short src_x, drw_x;    short src_y, drw_y;    long dga_offset;    int pitch;    unsigned int i;    if (!is_supported_fourcc(info->fourcc))	return -1;    /* set chipset/engine.dependent config info */    /*  which CRT to use, etc.? */    switch (sis_vga_engine) {    case SIS_315_VGA:	sis_shift_value = 1;	sis_equal.cap |= VEQ_CAP_SATURATION | VEQ_CAP_HUE;	break;    case SIS_300_VGA:    default:	sis_shift_value = 2;	break;    }    sis_displaymode = DISPMODE_SINGLE1;	/* xV driver code in set_dispmode() */    set_dispmode();    set_disptype_regs();    init_overlay();    /* get basic dimension info */    src_x = info->src.x;    src_y = info->src.y;    src_w = info->src.w;    src_h = info->src.h;    drw_x = info->dest.x;    drw_y = info->dest.y;    drw_w = info->dest.w;    drw_h = info->dest.h;    switch (info->fourcc) {    case IMGFMT_YV12:    case IMGFMT_I420:	pitch = (src_w + 7) & ~7;	total_size = (pitch * src_h * 3) >> 1;	break;    case IMGFMT_YUY2:    case IMGFMT_UYVY:    case IMGFMT_RGB15:    case IMGFMT_RGB16:	pitch = ((src_w << 1) + 3) & ~3;	total_size = pitch * src_h;	break;    default:	return -1;    }    /* "allocate" memory for overlay! */    /* start at 8MB = sisfb's "dri reserved space" -       really shouldn't hardcode though */    /* XXX: JCP - this can use the sisfb FBIO_ALLOC ioctl to safely       allocate "video heap" memory... */    dga_offset = 0x800000;    /* use 7MB for now.  need to calc/get real info from sisfb? */    /* this can result in a LOT of frames - probably not necessary */    info->num_frames = 0x700000 / (total_size * 2);    if (info->num_frames > VID_PLAY_MAXFRAMES)	info->num_frames = VID_PLAY_MAXFRAMES;    info->dga_addr = sis_mem_base + dga_offset;    info->dest.pitch.y = 16;    info->dest.pitch.u = 16;    info->dest.pitch.v = 16;    info->offset.y = 0;    info->offset.u = 0;    info->offset.v = 0;    info->frame_size = (total_size * 2);	/* why times 2 ? */    for (i = 0; i < info->num_frames; i++) {	info->offsets[i] = info->frame_size * i;	/* save ptrs to mem buffers */	sis_frames[i] = (dga_offset + info->offsets[i]);    }    memset(&overlay, 0, sizeof(overlay));    overlay.pixelFormat = sis_format = info->fourcc;    overlay.pitch = overlay.origPitch = pitch;    overlay.keyOP = (sis_grkey.ckey.op == CKEY_TRUE ?		     VI_ROP_DestKey : VI_ROP_Always);    overlay.bobEnable = 0x00;    overlay.SCREENheight = sis_screen_height;    /* probably will not support X virtual screen > phys very well? */    overlay.dstBox.x1 = drw_x;	/* - pScrn->frameX0; */    overlay.dstBox.x2 = drw_x + drw_w;	/* - pScrn->frameX0; ??? */    overlay.dstBox.y1 = drw_y;	/*  - pScrn->frameY0; */    overlay.dstBox.y2 = drw_y + drw_h;	/* - pScrn->frameY0; ??? */    if ((overlay.dstBox.x1 > overlay.dstBox.x2) ||	(overlay.dstBox.y1 > overlay.dstBox.y2))	return -1;    if ((overlay.dstBox.x2 < 0) || (overlay.dstBox.y2 < 0))	return -1;    if (overlay.dstBox.x1 < 0) {	srcOffsetX = src_w * (-overlay.dstBox.x1) / drw_w;	overlay.dstBox.x1 = 0;    }    if (overlay.dstBox.y1 < 0) {	srcOffsetY = src_h * (-overlay.dstBox.y1) / drw_h;	overlay.dstBox.y1 = 0;    }    switch (info->fourcc) {    case IMGFMT_YV12:	info->dest.pitch.y = 16;	sx = (src_x + srcOffsetX) & ~7;	sy = (src_y + srcOffsetY) & ~1;	info->offset.y = sis_Yoff = sx + sy * pitch;	/* JCP: NOTE reversed u & v here!  Not sure why this is needed.	   maybe mplayer & sis define U & V differently?? */	info->offset.u = sis_Voff =	    src_h * pitch + ((sx + sy * pitch / 2) >> 1);	info->offset.v = sis_Uoff =	    src_h * pitch * 5 / 4 + ((sx + sy * pitch / 2) >> 1);	overlay.PSY = (sis_frames[0] + sis_Yoff) >> sis_shift_value;	overlay.PSV = (sis_frames[0] + sis_Voff) >> sis_shift_value;	overlay.PSU = (sis_frames[0] + sis_Uoff) >> sis_shift_value;	break;    case IMGFMT_I420:	sx = (src_x + srcOffsetX) & ~7;	sy = (src_y + srcOffsetY) & ~1;	info->offset.y = sis_Yoff = sx + sy * pitch;	/* JCP: see above... */	info->offset.u = sis_Voff =	    src_h * pitch * 5 / 4 + ((sx + sy * pitch / 2) >> 1);	info->offset.v = sis_Uoff =	    src_h * pitch + ((sx + sy * pitch / 2) >> 1);	overlay.PSY = (sis_frames[0] + sis_Yoff) >> sis_shift_value;	overlay.PSV = (sis_frames[0] + sis_Voff) >> sis_shift_value;	overlay.PSU = (sis_frames[0] + sis_Uoff) >> sis_shift_value;	break;    case IMGFMT_YUY2:    case IMGFMT_UYVY:    case IMGFMT_RGB16:    case IMGFMT_RGB15:    default:	sx = (src_x + srcOffsetX) & ~1;	sy = (src_y + srcOffsetY);	info->offset.y = sis_Yoff = sx * 2 + sy * pitch;	overlay.PSY = (sis_frames[0] + sis_Yoff) >> sis_shift_value;	break;    }    /* FIXME: is it possible that srcW < 0? */    overlay.srcW = src_w - (sx - src_x);    overlay.srcH = src_h - (sy - src_y);    /* set merge line buffer */    merge_line_buf(overlay.srcW > 384);    /* calculate line buffer length */    set_line_buf_size(&overlay);    if (sis_displaymode == DISPMODE_SINGLE2) {	if (sis_has_two_overlays) {	    /* TW: On chips with two overlays we use	     * overlay 2 for CRT2 */	    index = 1;	    iscrt2 = 1;	} else {	    /* TW: On chips with only one overlay we	     * use that only overlay for CRT2 */	    index = 0;	    iscrt2 = 1;	}	overlay.VBlankActiveFunc = vblank_active_CRT2;	/* overlay.GetScanLineFunc = get_scanline_CRT2; */    } else {	index = 0;	iscrt2 = 0;	overlay.VBlankActiveFunc = vblank_active_CRT1;	/* overlay.GetScanLineFunc = get_scanline_CRT1; */    }    /* calc scale factor (to use below) */    calc_scale_factor(&overlay, index, iscrt2);    /* Select video1 (used for CRT1) or video2 (used for CRT2) */    setvideoregmask(Index_VI_Control_Misc2, index, 0x01);    set_format(&overlay);    set_colorkey();    sis_set_eq(&sis_equal);    /* set up video overlay registers */    set_overlay(&overlay, index);    /* prevent badness if bits are not at default setting */    setvideoregmask(Index_VI_Control_Misc1, 0x00, 0x01);    setvideoregmask(Index_VI_Control_Misc2, 0x00, 0x04);    /* JCP:  Xv driver implementation loops back over above code to       setup mirror CRT2 */    return 0;}static int sis_playback_on(void){    setvideoregmask(Index_VI_Control_Misc0, 0x02, 0x02);    return 0;}static int sis_playback_off(void){    unsigned char sridx, cridx;    sridx = inSISREG(SISSR);    cridx = inSISREG(SISCR);    close_overlay();    outSISREG(SISSR, sridx);    outSISREG(SISCR, cridx);    return 0;}static int sis_frame_select(unsigned int frame){    uint8_t data;    int index = 0;    uint32_t PSY;    if (sis_displaymode == DISPMODE_SINGLE2 && sis_has_two_overlays) {	index = 1;    }    PSY = (sis_frames[frame] + sis_Yoff) >> sis_shift_value;    /* Unlock address registers */    data = getvideoreg(Index_VI_Control_Misc1);    setvideoreg(Index_VI_Control_Misc1, data | 0x20);    /* TEST: Is this required? */    setvideoreg(Index_VI_Control_Misc1, data | 0x20);    /* TEST end */    /* TEST: Is this required? */    if (sis_vga_engine == SIS_315_VGA)	setvideoreg(Index_VI_Control_Misc3, 0x00);    /* TEST end */    /* set Y start address */    setvideoreg(Index_VI_Disp_Y_Buf_Start_Low, (uint8_t) (PSY));    setvideoreg(Index_VI_Disp_Y_Buf_Start_Middle, (uint8_t) ((PSY) >> 8));    setvideoreg(Index_VI_Disp_Y_Buf_Start_High, (uint8_t) ((PSY) >> 16));    /* set 310/325 series overflow bits for Y plane */    if (sis_vga_engine == SIS_315_VGA) {	setvideoreg(Index_VI_Y_Buf_Start_Over,		    ((uint8_t) ((PSY) >> 24) & 0x01));    }    /* Set U/V data if using plane formats */    if ((sis_format == IMGFMT_YV12) || (sis_format == IMGFMT_I420)) {	uint32_t PSU, PSV;	PSU = (sis_frames[frame] + sis_Uoff) >> sis_shift_value;	PSV = (sis_frames[frame] + sis_Voff) >> sis_shift_value;	/* set U/V start address */	setvideoreg(Index_VI_U_Buf_Start_Low, (uint8_t) PSU);	setvideoreg(Index_VI_U_Buf_Start_Middle, (uint8_t) (PSU >> 8));	setvideoreg(Index_VI_U_Buf_Start_High, (uint8_t) (PSU >> 16));	setvideoreg(Index_VI_V_Buf_Start_Low, (uint8_t) PSV);	setvideoreg(Index_VI_V_Buf_Start_Middle, (uint8_t) (PSV >> 8));	setvideoreg(Index_VI_V_Buf_Start_High, (uint8_t) (PSV >> 16));	/* 310/325 series overflow bits */	if (sis_vga_engine == SIS_315_VGA) {	    setvideoreg(Index_VI_U_Buf_Start_Over,			((uint8_t) (PSU >> 24) & 0x01));	    setvideoreg(Index_VI_V_Buf_Start_Over,			((uint8_t) (PSV >> 24) & 0x01));	}    }    if (sis_vga_engine == SIS_315_VGA) {	/* Trigger register copy for 310 series */	setvideoreg(Index_VI_Control_Misc3, 1 << index);    }    /* Lock the address registers */    setvideoregmask(Index_VI_Control_Misc1, 0x00, 0x20);    return 0;}static int sis_get_gkeys(vidix_grkey_t * grkey){    memcpy(grkey, &sis_grkey, sizeof(vidix_grkey_t));    return 0;}static int sis_set_gkeys(const vidix_grkey_t * grkey){    memcpy(&sis_grkey, grkey, sizeof(vidix_grkey_t));    set_colorkey();    return 0;}static int sis_get_eq(vidix_video_eq_t * eq){    memcpy(eq, &sis_equal, sizeof(vidix_video_eq_t));    return 0;}static int sis_set_eq(const vidix_video_eq_t * eq){    int br, sat, cr, hue;    if (eq->cap & VEQ_CAP_BRIGHTNESS)	sis_equal.brightness = eq->brightness;    if (eq->cap & VEQ_CAP_CONTRAST)	sis_equal.contrast = eq->contrast;    if (eq->cap & VEQ_CAP_SATURATION)	sis_equal.saturation = eq->saturation;    if (eq->cap & VEQ_CAP_HUE)	sis_equal.hue = eq->hue;    if (eq->cap & VEQ_CAP_RGB_INTENSITY) {	sis_equal.red_intensity = eq->red_intensity;	sis_equal.green_intensity = eq->green_intensity;	sis_equal.blue_intensity = eq->blue_intensity;    }    sis_equal.flags = eq->flags;    cr = (sis_equal.contrast + 1000) * 7 / 2000;    if (cr < 0)	cr = 0;    if (cr > 7)	cr = 7;    br = sis_equal.brightness * 127 / 1000;    if (br < -128)	br = -128;    if (br > 127)	br = 127;    sat = (sis_equal.saturation * 7) / 1000;    if (sat < -7)	sat = -7;    if (sat > 7)	sat = 7;    hue = sis_equal.hue * 7 / 1000;    if (hue < -8)	hue = -8;    if (hue > 7)	hue = 7;    set_brightness(br);    set_contrast(cr);    if (sis_vga_engine == SIS_315_VGA) {	set_saturation(sat);	set_hue(hue);    }    return 0;}static void set_overlay(SISOverlayPtr pOverlay, int index){    uint16_t pitch = 0;    uint8_t h_over = 0, v_over = 0;    uint16_t top, bottom, left, right;    uint16_t screenX = sis_screen_width;    uint16_t screenY = sis_screen_height;    uint8_t data;    uint32_t watchdog;    top = pOverlay->dstBox.y1;    bottom = pOverlay->dstBox.y2;    if (bottom > screenY) {	bottom = screenY;    }    left = pOverlay->dstBox.x1;    right = pOverlay->dstBox.x2;    if (right > screenX) {	right = screenX;    }    /* JCP: these aren't really tested... */    /* TW: DoubleScan modes require Y coordinates * 2 */    if (sis_vmode & VMODE_DOUBLESCAN) {	top <<= 1;	bottom <<= 1;    }    /* TW: Interlace modes require Y coordinates / 2 */    if (sis_vmode & VMODE_INTERLACED) {

⌨️ 快捷键说明

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