PageRenderTime 601ms CodeModel.GetById 317ms app.highlight 15ms RepoModel.GetById 266ms app.codeStats 0ms

/src/backend/native/ftk_display_fb.c

http://ftk.googlecode.com/
C | 226 lines | 160 code | 33 blank | 33 comment | 28 complexity | 2d0987a3a1ade6888cffdcfccd14931e MD5 | raw file
  1/*
  2 * File: ftk_display_fb.c	 
  3 * Author:	Li XianJing <xianjimli@hotmail.com>
  4 * Brief:	framebuffer implemented display.
  5 *
  6 * Copyright (c) 2009 - 2010  Li XianJing <xianjimli@hotmail.com>
  7 *
  8 * Licensed under the Academic Free License version 2.1
  9 *
 10 * This program is free software; you can redistribute it and/or modify
 11 * it under the terms of the GNU General Public License as published by
 12 * the Free Software Foundation; either version 2 of the License, or
 13 * (at your option) any later version.
 14 *
 15 * This program is distributed in the hope that it will be useful,
 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18 * GNU General Public License for more details.
 19 *
 20 * You should have received a copy of the GNU General Public License
 21 * along with this program; if not, write to the Free Software
 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23 */
 24
 25/*
 26 * History:
 27 * ================================================================
 28 * 2009-10-03 Li XianJing <xianjimli@hotmail.com> created
 29 *
 30 */
 31
 32#include <stdio.h>
 33#include <stdlib.h>
 34#include <unistd.h>
 35#include <fcntl.h>
 36#include "ftk_log.h"
 37#include <linux/fb.h>
 38#include <linux/kd.h>
 39#include <sys/mman.h>
 40#include <sys/stat.h>
 41#include <sys/types.h>
 42#include <sys/ioctl.h>
 43#include "ftk_display_mem.h"
 44#include "ftk_display_fb.h"
 45
 46struct FbInfo 
 47{
 48	int fd;
 49	void* bits;
 50	struct fb_fix_screeninfo fix;
 51	struct fb_var_screeninfo var;
 52};
 53
 54#define fb_width(fb) ((fb)->var.xres)
 55#define fb_height(fb) ((fb)->var.yres)
 56#define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * fb->var.bits_per_pixel/8)
 57#ifndef FBIO_WAITFORVSYNC
 58#define FBIO_WAITFORVSYNC   _IOW('F', 0x20, u_int32_t)
 59#endif
 60
 61static int fb_open(struct FbInfo *fb, const char* fbfilename)
 62{
 63	fb->fd = open(fbfilename, O_RDWR);
 64	if (fb->fd < 0)
 65	{
 66		return -1;
 67	}
 68	
 69	if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fix) < 0)
 70		goto fail;
 71	if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->var) < 0)
 72		goto fail;
 73	
 74	fb->var.xoffset = 0; 
 75	fb->var.yoffset = 0; 
 76	ioctl (fb->fd, FBIOPAN_DISPLAY, &(fb->var)); 
 77
 78	ftk_logi("FbInfo: %s\n", fbfilename);
 79	ftk_logi("FbInfo: xres=%d yres=%d bits_per_pixel=%d mem_size=%d\n", 
 80		fb->var.xres, fb->var.yres, fb->var.bits_per_pixel, fb_size(fb));
 81	ftk_logi("FbInfo: red(%d %d) green(%d %d) blue(%d %d)\n", 
 82		fb->var.red.offset, fb->var.red.length,
 83		fb->var.green.offset, fb->var.green.length,
 84		fb->var.blue.offset, fb->var.blue.length);
 85
 86#ifdef FTK_FB_NOMMAP
 87	//uclinux doesn't support MAP_SHARED or MAP_PRIVATE with PROT_WRITE, so no mmap at all is simpler
 88	fb->bits = fb->fix.smem_start;
 89#else
 90	fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
 91#endif
 92
 93	if (fb->bits == MAP_FAILED)
 94	{
 95		ftk_logi("map framebuffer failed.\n");
 96		goto fail;
 97	}
 98
 99	memset(fb->bits, 0xff, fb_size(fb));
100	
101	ftk_logi("xres_virtual =%d yres_virtual=%d xpanstep=%d ywrapstep=%d\n",
102		fb->var.xres_virtual, fb->var.yres_virtual, fb->fix.xpanstep, fb->fix.ywrapstep);
103
104	return 0;
105fail:
106	ftk_logi("%s is not a framebuffer.\n", fbfilename);
107	close(fb->fd);
108
109	return -1;
110}
111
112static void fb_close(struct FbInfo *fb)
113{
114	if(fb != NULL)
115	{
116		munmap(fb->bits, fb_size(fb));
117		close(fb->fd);
118		FTK_FREE(fb);
119	}
120
121	return;
122}
123
124static Ret fb_pan(struct FbInfo* info, int xoffset, int yoffset, int onsync)
125{
126	struct fb_var_screeninfo *var = &info->var;
127
128	return_val_if_fail(var->xres_virtual >= (xoffset + var->xres), RET_FAIL);
129	return_val_if_fail(var->yres_virtual >= (yoffset + var->yres), RET_FAIL);
130
131	if (!info->fix.xpanstep && !info->fix.ypanstep && !info->fix.ywrapstep)
132	{
133		return RET_OK;
134	}
135
136	if (info->fix.xpanstep)
137	{
138		var->xoffset = xoffset - (xoffset % info->fix.xpanstep);
139	}
140	else
141	{
142		var->xoffset = 0;
143	}
144
145	if (info->fix.ywrapstep) 
146	{
147		var->yoffset = yoffset - (yoffset % info->fix.ywrapstep);
148		var->vmode |= FB_VMODE_YWRAP;
149	}
150	else if (info->fix.ypanstep) 
151	{
152		var->yoffset = yoffset - (yoffset % info->fix.ypanstep);
153		var->vmode &= ~FB_VMODE_YWRAP;
154	}
155	else 
156	{
157		 var->yoffset = 0;
158	}
159
160	var->activate = onsync ? FB_ACTIVATE_VBL : FB_ACTIVATE_NOW;
161
162	ftk_logi("%s: xoffset=%d yoffset=%d ywrapstep=%d\n", __func__,
163		var->xoffset, var->yoffset, info->fix.ywrapstep);
164	if (ioctl( info->fd, FBIOPAN_DISPLAY, var ) < 0)
165	{
166		return RET_FAIL;
167	}
168
169	return RET_OK;
170}
171
172static void fb_sync(void* ctx, FtkRect* rect)
173{
174	int zero = 0;
175	int ret = 0;
176	struct FbInfo* info = ctx;
177
178	//ret = ioctl(info->fd, FBIO_WAITFORVSYNC, &zero);
179	//ret = fb_pan(info, 0, 0, 1);
180	//ret = ioctl(info->fd, FBIO_WAITFORVSYNC, &zero);
181#ifdef USE_FB_ACTIVATE_ALL
182	ret = ioctl(info->fd, FB_ACTIVATE_ALL, NULL);
183	ftk_logi("%s: FB_ACTIVATE_ALL ret = %d\n", __func__, ret);
184#endif	
185	return;
186}
187
188FtkDisplay* ftk_display_fb_create(const char* filename)
189{
190	FtkDisplay* thiz = NULL;
191	struct FbInfo* fb = NULL;
192	return_val_if_fail(filename != NULL, NULL);
193
194	fb = FTK_ZALLOC(sizeof(struct FbInfo));
195	return_val_if_fail(fb != NULL, NULL);
196
197	if(fb_open(fb, filename) == 0)
198	{
199		FtkPixelFormat format = 0;
200		int bits_per_pixel = fb->var.bits_per_pixel;
201		
202		if(bits_per_pixel == 16)
203		{
204			format = FTK_PIXEL_RGB565;
205		}
206		else if(bits_per_pixel == 24)
207		{
208			format = FTK_PIXEL_BGR24;
209		}
210		else if(bits_per_pixel == 32)
211		{
212			format = FTK_PIXEL_BGRA32;
213		}
214		else
215		{
216			assert(!"not supported framebuffer format.");
217		}
218	
219		thiz = ftk_display_mem_create(format, fb->var.xres, fb->var.yres, 
220			fb->bits, fb_close, fb);
221		ftk_display_mem_set_sync_func(thiz, fb_sync, fb);
222	}
223		
224	return thiz;
225}
226