vo_fbdev.c

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

C
1,205
字号
/* * Video driver for Framebuffer device * by Szabolcs Berecz <szabi@inf.elte.hu> * (C) 2001 *  * Some idea and code borrowed from Chris Lawrence's ppmtofb-0.27 * Some fixes and small improvements by Joey Parrish <joey@nicewarrior.org> */#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <errno.h>#include <ctype.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <sys/kd.h>#include <linux/fb.h>#include "config.h"#include "video_out.h"#include "video_out_internal.h"#include "fastmemcpy.h"#include "sub.h"#ifdef CONFIG_VIDIX#include "vosub_vidix.h"#endif#include "aspect.h"#include "mp_msg.h"static vo_info_t info = {	"Framebuffer Device",	"fbdev",	"Szabolcs Berecz <szabi@inf.elte.hu>",	""};LIBVO_EXTERN(fbdev)#ifdef CONFIG_VIDIX/* Name of VIDIX driver */static const char *vidix_name = NULL;static vidix_grkey_t gr_key;#endifstatic signed int pre_init_err = -2;/*******************************	fb.modes support      *******************************/static range_t *monitor_hfreq = NULL;static range_t *monitor_vfreq = NULL;static range_t *monitor_dotclock = NULL;typedef struct {	char *name;	uint32_t xres, yres, vxres, vyres, depth;	uint32_t pixclock, left, right, upper, lower, hslen, vslen;	uint32_t sync;	uint32_t vmode;} fb_mode_t;#define MAX_NR_TOKEN	16#define MAX_LINE_LEN	1000#define RET_EOF		-1#define RET_EOL		-2static int validate_mode(fb_mode_t *m){	if (!m->xres) {		mp_msg(MSGT_VO, MSGL_V, "needs geometry ");		return 0;	}	if (!m->pixclock) {		mp_msg(MSGT_VO, MSGL_V, "needs timings ");		return 0;	}	return 1;}static FILE *fp;static int line_num = 0;static char *line;static char *token[MAX_NR_TOKEN];static int get_token(int num){	static int read_nextline = 1;	static int line_pos;	int i;	char c;	if (num >= MAX_NR_TOKEN) {		mp_msg(MSGT_VO, MSGL_V, "get_token(): max >= MAX_NR_TOKEN!\n");		goto out_eof;	}	if (read_nextline) {		if (!fgets(line, MAX_LINE_LEN, fp))			goto out_eof;		line_pos = 0;		++line_num;		read_nextline = 0;	}	for (i = 0; i < num; i++) {		while (isspace(line[line_pos]))			++line_pos;		if (line[line_pos] == '\0' || line[line_pos] == '#') {			read_nextline = 1;			goto out_eol;		}		token[i] = line + line_pos;		c = line[line_pos];		if (c == '"' || c == '\'') {			token[i]++;			while (line[++line_pos] != c && line[line_pos])				/* NOTHING */;			if (!line[line_pos])				goto out_eol;			line[line_pos] = ' ';		} else {			for (/* NOTHING */; !isspace(line[line_pos]) &&					line[line_pos]; line_pos++)				/* NOTHING */;		}		if (!line[line_pos]) {			read_nextline = 1;			if (i == num - 1)				goto out_ok;			goto out_eol;		}		line[line_pos++] = '\0';	}out_ok:	return i;out_eof:	return RET_EOF;out_eol:	return RET_EOL;}static fb_mode_t *fb_modes = NULL;static int nr_modes = 0;static int parse_fbmode_cfg(char *cfgfile){#define CHECK_IN_MODE_DEF\	if (!in_mode_def) {\		mp_msg(MSGT_VO, MSGL_V, "'needs 'mode' first");\		goto err_out_print_linenum;\	}	fb_mode_t *mode = NULL;	char *endptr;	// strtoul()...	int in_mode_def = 0;	int tmp, i;	/* If called more than once, reuse parsed data */	if (nr_modes)		return nr_modes;	mp_msg(MSGT_VO, MSGL_V, "Reading %s: ", cfgfile);	if ((fp = fopen(cfgfile, "r")) == NULL) {		mp_msg(MSGT_VO, MSGL_V, "can't open '%s': %s\n", cfgfile, strerror(errno));		return -1;	}	if ((line = (char *) malloc(MAX_LINE_LEN + 1)) == NULL) {		mp_msg(MSGT_VO, MSGL_V, "can't get memory for 'line': %s\n", strerror(errno));		return -2;	}	/*	 * check if the cfgfile starts with 'mode'	 */	while ((tmp = get_token(1)) == RET_EOL)		/* NOTHING */;	if (tmp == RET_EOF)		goto out;	if (!strcmp(token[0], "mode"))		goto loop_enter;	goto err_out_parse_error;	while ((tmp = get_token(1)) != RET_EOF) {		if (tmp == RET_EOL)			continue;		if (!strcmp(token[0], "mode")) {			if (in_mode_def) {				mp_msg(MSGT_VO, MSGL_V, "'endmode' required");				goto err_out_print_linenum;			}			if (!validate_mode(mode))				goto err_out_not_valid;		loop_enter:		        if (!(fb_modes = (fb_mode_t *) realloc(fb_modes,				sizeof(fb_mode_t) * (nr_modes + 1)))) {			    mp_msg(MSGT_VO, MSGL_V, "can't realloc 'fb_modes' (nr_modes = %d):"					    " %s\n", nr_modes, strerror(errno));			    goto err_out;		        }			mode=fb_modes + nr_modes;			++nr_modes;                        memset(mode,0,sizeof(fb_mode_t));			if (get_token(1) < 0)				goto err_out_parse_error;			for (i = 0; i < nr_modes - 1; i++) {				if (!strcmp(token[0], fb_modes[i].name)) {					mp_msg(MSGT_VO, MSGL_V, "mode name '%s' isn't unique", token[0]);					goto err_out_print_linenum;				}			}			if (!(mode->name = strdup(token[0]))) {				mp_msg(MSGT_VO, MSGL_V, "can't strdup -> 'name': %s\n", strerror(errno));				goto err_out;			}			in_mode_def = 1;		} else if (!strcmp(token[0], "geometry")) {			CHECK_IN_MODE_DEF;			if (get_token(5) < 0)				goto err_out_parse_error;			mode->xres = strtoul(token[0], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->yres = strtoul(token[1], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->vxres = strtoul(token[2], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->vyres = strtoul(token[3], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->depth = strtoul(token[4], &endptr, 0);			if (*endptr)				goto err_out_parse_error;		} else if (!strcmp(token[0], "timings")) {			CHECK_IN_MODE_DEF;			if (get_token(7) < 0)				goto err_out_parse_error;			mode->pixclock = strtoul(token[0], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->left = strtoul(token[1], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->right = strtoul(token[2], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->upper = strtoul(token[3], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->lower = strtoul(token[4], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->hslen = strtoul(token[5], &endptr, 0);			if (*endptr)				goto err_out_parse_error;			mode->vslen = strtoul(token[6], &endptr, 0);			if (*endptr)				goto err_out_parse_error;		} else if (!strcmp(token[0], "endmode")) {			CHECK_IN_MODE_DEF;			in_mode_def = 0;		} else if (!strcmp(token[0], "accel")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			/*			 * it's only used for text acceleration			 * so we just ignore it.			 */		} else if (!strcmp(token[0], "hsync")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "low"))				mode->sync &= ~FB_SYNC_HOR_HIGH_ACT;			else if(!strcmp(token[0], "high"))				mode->sync |= FB_SYNC_HOR_HIGH_ACT;			else				goto err_out_parse_error;		} else if (!strcmp(token[0], "vsync")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "low"))				mode->sync &= ~FB_SYNC_VERT_HIGH_ACT;			else if(!strcmp(token[0], "high"))				mode->sync |= FB_SYNC_VERT_HIGH_ACT;			else				goto err_out_parse_error;		} else if (!strcmp(token[0], "csync")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "low"))				mode->sync &= ~FB_SYNC_COMP_HIGH_ACT;			else if(!strcmp(token[0], "high"))				mode->sync |= FB_SYNC_COMP_HIGH_ACT;			else				goto err_out_parse_error;		} else if (!strcmp(token[0], "extsync")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "false"))				mode->sync &= ~FB_SYNC_EXT;			else if(!strcmp(token[0], "true"))				mode->sync |= FB_SYNC_EXT;			else				goto err_out_parse_error;		} else if (!strcmp(token[0], "laced")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "false"))				mode->vmode = FB_VMODE_NONINTERLACED;			else if (!strcmp(token[0], "true"))				mode->vmode = FB_VMODE_INTERLACED;			else				goto err_out_parse_error;		} else if (!strcmp(token[0], "double")) {			CHECK_IN_MODE_DEF;			if (get_token(1) < 0)				goto err_out_parse_error;			if (!strcmp(token[0], "false"))				;			else if (!strcmp(token[0], "true"))				mode->vmode = FB_VMODE_DOUBLE;			else				goto err_out_parse_error;		} else			goto err_out_parse_error;	}	if (!validate_mode(mode))		goto err_out_not_valid;out:	mp_msg(MSGT_VO, MSGL_V, "%d modes\n", nr_modes);	free(line);	fclose(fp);	return nr_modes;err_out_parse_error:	mp_msg(MSGT_VO, MSGL_V, "parse error");err_out_print_linenum:	mp_msg(MSGT_VO, MSGL_V, " at line %d\n", line_num);err_out:	if (fb_modes) {		free(fb_modes);		fb_modes = NULL;	}	nr_modes = 0;	free(line);	free(fp);	return -2;err_out_not_valid:	mp_msg(MSGT_VO, MSGL_V, "previous mode is not correct");	goto err_out_print_linenum;}static fb_mode_t *find_mode_by_name(char *name){	int i;	for (i = 0; i < nr_modes; i++)		if (!strcmp(name, fb_modes[i].name))			return fb_modes + i;	return NULL;}static float dcf(fb_mode_t *m)	//driving clock frequency{	return 1e12f / m->pixclock;}static float hsf(fb_mode_t *m)	//horizontal scan frequency{	int htotal = m->left + m->xres + m->right + m->hslen;	return dcf(m) / htotal;}static float vsf(fb_mode_t *m)	//vertical scan frequency{	int vtotal = m->upper + m->yres + m->lower + m->vslen;	return hsf(m) / vtotal;}static int mode_works(fb_mode_t *m, range_t *hfreq, range_t *vfreq,		range_t *dotclock){	float h = hsf(m);	float v = vsf(m);	float d = dcf(m);	int ret = 1;	mp_msg(MSGT_VO, MSGL_DBG2, "mode %dx%d:", m->xres, m->yres);	if (!in_range(hfreq, h)) {		ret = 0;

⌨️ 快捷键说明

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