/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. * History:
  26. * ================================================================
  27. * 2009-10-03 Li XianJing <xianjimli@hotmail.com> created
  28. *
  29. */
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <unistd.h>
  33. #include <fcntl.h>
  34. #include "ftk_log.h"
  35. #include <linux/fb.h>
  36. #include <linux/kd.h>
  37. #include <sys/mman.h>
  38. #include <sys/stat.h>
  39. #include <sys/types.h>
  40. #include <sys/ioctl.h>
  41. #include "ftk_display_mem.h"
  42. #include "ftk_display_fb.h"
  43. struct FbInfo
  44. {
  45. int fd;
  46. void* bits;
  47. struct fb_fix_screeninfo fix;
  48. struct fb_var_screeninfo var;
  49. };
  50. #define fb_width(fb) ((fb)->var.xres)
  51. #define fb_height(fb) ((fb)->var.yres)
  52. #define fb_size(fb) ((fb)->var.xres * (fb)->var.yres * fb->var.bits_per_pixel/8)
  53. #ifndef FBIO_WAITFORVSYNC
  54. #define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t)
  55. #endif
  56. static int fb_open(struct FbInfo *fb, const char* fbfilename)
  57. {
  58. fb->fd = open(fbfilename, O_RDWR);
  59. if (fb->fd < 0)
  60. {
  61. return -1;
  62. }
  63. if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fix) < 0)
  64. goto fail;
  65. if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->var) < 0)
  66. goto fail;
  67. fb->var.xoffset = 0;
  68. fb->var.yoffset = 0;
  69. ioctl (fb->fd, FBIOPAN_DISPLAY, &(fb->var));
  70. ftk_logi("FbInfo: %s\n", fbfilename);
  71. ftk_logi("FbInfo: xres=%d yres=%d bits_per_pixel=%d mem_size=%d\n",
  72. fb->var.xres, fb->var.yres, fb->var.bits_per_pixel, fb_size(fb));
  73. ftk_logi("FbInfo: red(%d %d) green(%d %d) blue(%d %d)\n",
  74. fb->var.red.offset, fb->var.red.length,
  75. fb->var.green.offset, fb->var.green.length,
  76. fb->var.blue.offset, fb->var.blue.length);
  77. #ifdef FTK_FB_NOMMAP
  78. //uclinux doesn't support MAP_SHARED or MAP_PRIVATE with PROT_WRITE, so no mmap at all is simpler
  79. fb->bits = fb->fix.smem_start;
  80. #else
  81. fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE, MAP_SHARED, fb->fd, 0);
  82. #endif
  83. if (fb->bits == MAP_FAILED)
  84. {
  85. ftk_logi("map framebuffer failed.\n");
  86. goto fail;
  87. }
  88. memset(fb->bits, 0xff, fb_size(fb));
  89. ftk_logi("xres_virtual =%d yres_virtual=%d xpanstep=%d ywrapstep=%d\n",
  90. fb->var.xres_virtual, fb->var.yres_virtual, fb->fix.xpanstep, fb->fix.ywrapstep);
  91. return 0;
  92. fail:
  93. ftk_logi("%s is not a framebuffer.\n", fbfilename);
  94. close(fb->fd);
  95. return -1;
  96. }
  97. static void fb_close(struct FbInfo *fb)
  98. {
  99. if(fb != NULL)
  100. {
  101. munmap(fb->bits, fb_size(fb));
  102. close(fb->fd);
  103. FTK_FREE(fb);
  104. }
  105. return;
  106. }
  107. static Ret fb_pan(struct FbInfo* info, int xoffset, int yoffset, int onsync)
  108. {
  109. struct fb_var_screeninfo *var = &info->var;
  110. return_val_if_fail(var->xres_virtual >= (xoffset + var->xres), RET_FAIL);
  111. return_val_if_fail(var->yres_virtual >= (yoffset + var->yres), RET_FAIL);
  112. if (!info->fix.xpanstep && !info->fix.ypanstep && !info->fix.ywrapstep)
  113. {
  114. return RET_OK;
  115. }
  116. if (info->fix.xpanstep)
  117. {
  118. var->xoffset = xoffset - (xoffset % info->fix.xpanstep);
  119. }
  120. else
  121. {
  122. var->xoffset = 0;
  123. }
  124. if (info->fix.ywrapstep)
  125. {
  126. var->yoffset = yoffset - (yoffset % info->fix.ywrapstep);
  127. var->vmode |= FB_VMODE_YWRAP;
  128. }
  129. else if (info->fix.ypanstep)
  130. {
  131. var->yoffset = yoffset - (yoffset % info->fix.ypanstep);
  132. var->vmode &= ~FB_VMODE_YWRAP;
  133. }
  134. else
  135. {
  136. var->yoffset = 0;
  137. }
  138. var->activate = onsync ? FB_ACTIVATE_VBL : FB_ACTIVATE_NOW;
  139. ftk_logi("%s: xoffset=%d yoffset=%d ywrapstep=%d\n", __func__,
  140. var->xoffset, var->yoffset, info->fix.ywrapstep);
  141. if (ioctl( info->fd, FBIOPAN_DISPLAY, var ) < 0)
  142. {
  143. return RET_FAIL;
  144. }
  145. return RET_OK;
  146. }
  147. static void fb_sync(void* ctx, FtkRect* rect)
  148. {
  149. int zero = 0;
  150. int ret = 0;
  151. struct FbInfo* info = ctx;
  152. //ret = ioctl(info->fd, FBIO_WAITFORVSYNC, &zero);
  153. //ret = fb_pan(info, 0, 0, 1);
  154. //ret = ioctl(info->fd, FBIO_WAITFORVSYNC, &zero);
  155. #ifdef USE_FB_ACTIVATE_ALL
  156. ret = ioctl(info->fd, FB_ACTIVATE_ALL, NULL);
  157. ftk_logi("%s: FB_ACTIVATE_ALL ret = %d\n", __func__, ret);
  158. #endif
  159. return;
  160. }
  161. FtkDisplay* ftk_display_fb_create(const char* filename)
  162. {
  163. FtkDisplay* thiz = NULL;
  164. struct FbInfo* fb = NULL;
  165. return_val_if_fail(filename != NULL, NULL);
  166. fb = FTK_ZALLOC(sizeof(struct FbInfo));
  167. return_val_if_fail(fb != NULL, NULL);
  168. if(fb_open(fb, filename) == 0)
  169. {
  170. FtkPixelFormat format = 0;
  171. int bits_per_pixel = fb->var.bits_per_pixel;
  172. if(bits_per_pixel == 16)
  173. {
  174. format = FTK_PIXEL_RGB565;
  175. }
  176. else if(bits_per_pixel == 24)
  177. {
  178. format = FTK_PIXEL_BGR24;
  179. }
  180. else if(bits_per_pixel == 32)
  181. {
  182. format = FTK_PIXEL_BGRA32;
  183. }
  184. else
  185. {
  186. assert(!"not supported framebuffer format.");
  187. }
  188. thiz = ftk_display_mem_create(format, fb->var.xres, fb->var.yres,
  189. fb->bits, fb_close, fb);
  190. ftk_display_mem_set_sync_func(thiz, fb_sync, fb);
  191. }
  192. return thiz;
  193. }