PageRenderTime 27ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/libgralloc/framebuffer.cpp

https://bitbucket.org/androidarmv6/android_hardware_msm7k
C++ | 416 lines | 298 code | 77 blank | 41 comment | 39 complexity | 17dc6992f0458919f644e868677e698e MD5 | raw file
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <sys/mman.h>
  17. #include <dlfcn.h>
  18. #include <cutils/ashmem.h>
  19. #include <cutils/log.h>
  20. #include <hardware/hardware.h>
  21. #include <hardware/gralloc.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24. #include <sys/ioctl.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <cutils/log.h>
  28. #include <cutils/atomic.h>
  29. #include <linux/fb.h>
  30. #include <linux/msm_mdp.h>
  31. #include "gralloc_priv.h"
  32. #include "gr.h"
  33. /*****************************************************************************/
  34. // numbers of buffers for page flipping
  35. #define NUM_BUFFERS 2
  36. enum {
  37. PAGE_FLIP = 0x00000001,
  38. LOCKED = 0x00000002
  39. };
  40. struct fb_context_t {
  41. framebuffer_device_t device;
  42. };
  43. /*****************************************************************************/
  44. static void
  45. msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height,
  46. int x, int y, int w, int h);
  47. static int fb_setSwapInterval(struct framebuffer_device_t* dev,
  48. int interval)
  49. {
  50. fb_context_t* ctx = (fb_context_t*)dev;
  51. if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
  52. return -EINVAL;
  53. // FIXME: implement fb_setSwapInterval
  54. return 0;
  55. }
  56. static int fb_setUpdateRect(struct framebuffer_device_t* dev,
  57. int l, int t, int w, int h)
  58. {
  59. if (((w|h) <= 0) || ((l|t)<0))
  60. return -EINVAL;
  61. fb_context_t* ctx = (fb_context_t*)dev;
  62. private_module_t* m = reinterpret_cast<private_module_t*>(
  63. dev->common.module);
  64. m->info.reserved[0] = 0x54445055; // "UPDT";
  65. m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
  66. m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
  67. return 0;
  68. }
  69. static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
  70. {
  71. if (private_handle_t::validate(buffer) < 0)
  72. return -EINVAL;
  73. fb_context_t* ctx = (fb_context_t*)dev;
  74. private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
  75. private_module_t* m = reinterpret_cast<private_module_t*>(
  76. dev->common.module);
  77. if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
  78. const size_t offset = hnd->base - m->framebuffer->base;
  79. m->info.activate = FB_ACTIVATE_VBL;
  80. m->info.yoffset = offset / m->finfo.line_length;
  81. if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
  82. ALOGE("FBIOPUT_VSCREENINFO failed");
  83. m->base.unlock(&m->base, buffer);
  84. return -errno;
  85. }
  86. m->currentBuffer = buffer;
  87. } else {
  88. // If we can't do the page_flip, just copy the buffer to the front
  89. // FIXME: use copybit HAL instead of memcpy
  90. void* fb_vaddr;
  91. void* buffer_vaddr;
  92. m->base.lock(&m->base, m->framebuffer,
  93. GRALLOC_USAGE_SW_WRITE_RARELY,
  94. 0, 0, m->info.xres, m->info.yres,
  95. &fb_vaddr);
  96. m->base.lock(&m->base, buffer,
  97. GRALLOC_USAGE_SW_READ_RARELY,
  98. 0, 0, m->info.xres, m->info.yres,
  99. &buffer_vaddr);
  100. //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
  101. msm_copy_buffer(m->framebuffer, m->framebuffer->fd,
  102. m->info.xres, m->info.yres,
  103. m->info.xoffset, m->info.yoffset,
  104. m->info.width, m->info.height);
  105. m->base.unlock(&m->base, buffer);
  106. m->base.unlock(&m->base, m->framebuffer);
  107. }
  108. return 0;
  109. }
  110. /*****************************************************************************/
  111. int mapFrameBufferLocked(struct private_module_t* module)
  112. {
  113. // already initialized...
  114. if (module->framebuffer) {
  115. return 0;
  116. }
  117. char const * const device_template[] = {
  118. "/dev/graphics/fb%u",
  119. "/dev/fb%u",
  120. 0 };
  121. int fd = -1;
  122. int i=0;
  123. char name[64];
  124. while ((fd==-1) && device_template[i]) {
  125. snprintf(name, 64, device_template[i], 0);
  126. fd = open(name, O_RDWR, 0);
  127. i++;
  128. }
  129. if (fd < 0)
  130. return -errno;
  131. struct fb_fix_screeninfo finfo;
  132. if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
  133. return -errno;
  134. struct fb_var_screeninfo info;
  135. if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
  136. return -errno;
  137. info.reserved[0] = 0;
  138. info.reserved[1] = 0;
  139. info.reserved[2] = 0;
  140. info.xoffset = 0;
  141. info.yoffset = 0;
  142. info.activate = FB_ACTIVATE_NOW;
  143. /*
  144. * Explicitly request 5/6/5
  145. */
  146. info.bits_per_pixel = 16;
  147. info.red.offset = 11;
  148. info.red.length = 5;
  149. info.green.offset = 5;
  150. info.green.length = 6;
  151. info.blue.offset = 0;
  152. info.blue.length = 5;
  153. info.transp.offset = 0;
  154. info.transp.length = 0;
  155. /*
  156. * Request NUM_BUFFERS screens (at lest 2 for page flipping)
  157. */
  158. info.yres_virtual = info.yres * NUM_BUFFERS;
  159. uint32_t flags = PAGE_FLIP;
  160. if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
  161. info.yres_virtual = info.yres;
  162. flags &= ~PAGE_FLIP;
  163. ALOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
  164. }
  165. if (info.yres_virtual < info.yres * 2) {
  166. // we need at least 2 for page-flipping
  167. info.yres_virtual = info.yres;
  168. flags &= ~PAGE_FLIP;
  169. ALOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
  170. info.yres_virtual, info.yres*2);
  171. }
  172. if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
  173. return -errno;
  174. int refreshRate = 1000000000000000LLU /
  175. (
  176. uint64_t( info.upper_margin + info.lower_margin + info.yres )
  177. * ( info.left_margin + info.right_margin + info.xres )
  178. * info.pixclock
  179. );
  180. if (refreshRate == 0) {
  181. // bleagh, bad info from the driver
  182. refreshRate = 60*1000; // 60 Hz
  183. }
  184. if (int(info.width) <= 0 || int(info.height) <= 0) {
  185. // the driver doesn't return that information
  186. // default to 160 dpi
  187. info.width = ((info.xres * 25.4f)/160.0f + 0.5f);
  188. info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
  189. }
  190. float xdpi = (info.xres * 25.4f) / info.width;
  191. float ydpi = (info.yres * 25.4f) / info.height;
  192. float fps = refreshRate / 1000.0f;
  193. ALOGI( "using (fd=%d)\n"
  194. "id = %s\n"
  195. "xres = %d px\n"
  196. "yres = %d px\n"
  197. "xres_virtual = %d px\n"
  198. "yres_virtual = %d px\n"
  199. "bpp = %d\n"
  200. "r = %2u:%u\n"
  201. "g = %2u:%u\n"
  202. "b = %2u:%u\n",
  203. fd,
  204. finfo.id,
  205. info.xres,
  206. info.yres,
  207. info.xres_virtual,
  208. info.yres_virtual,
  209. info.bits_per_pixel,
  210. info.red.offset, info.red.length,
  211. info.green.offset, info.green.length,
  212. info.blue.offset, info.blue.length
  213. );
  214. ALOGI( "width = %d mm (%f dpi)\n"
  215. "height = %d mm (%f dpi)\n"
  216. "refresh rate = %.2f Hz\n",
  217. info.width, xdpi,
  218. info.height, ydpi,
  219. fps
  220. );
  221. if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
  222. return -errno;
  223. if (finfo.smem_len <= 0)
  224. return -errno;
  225. module->flags = flags;
  226. module->info = info;
  227. module->finfo = finfo;
  228. module->xdpi = xdpi;
  229. module->ydpi = ydpi;
  230. module->fps = fps;
  231. /*
  232. * map the framebuffer
  233. */
  234. int err;
  235. size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
  236. module->framebuffer = new private_handle_t(dup(fd), fbSize,
  237. private_handle_t::PRIV_FLAGS_USES_PMEM);
  238. module->numBuffers = info.yres_virtual / info.yres;
  239. module->bufferMask = 0;
  240. void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
  241. if (vaddr == MAP_FAILED) {
  242. ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
  243. return -errno;
  244. }
  245. module->framebuffer->base = intptr_t(vaddr);
  246. memset(vaddr, 0, fbSize);
  247. return 0;
  248. }
  249. static int mapFrameBuffer(struct private_module_t* module)
  250. {
  251. pthread_mutex_lock(&module->lock);
  252. int err = mapFrameBufferLocked(module);
  253. pthread_mutex_unlock(&module->lock);
  254. return err;
  255. }
  256. /*****************************************************************************/
  257. static int fb_close(struct hw_device_t *dev)
  258. {
  259. fb_context_t* ctx = (fb_context_t*)dev;
  260. if (ctx) {
  261. free(ctx);
  262. }
  263. return 0;
  264. }
  265. int fb_device_open(hw_module_t const* module, const char* name,
  266. hw_device_t** device)
  267. {
  268. int status = -EINVAL;
  269. if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
  270. alloc_device_t* gralloc_device;
  271. status = gralloc_open(module, &gralloc_device);
  272. if (status < 0)
  273. return status;
  274. /* initialize our state here */
  275. fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
  276. memset(dev, 0, sizeof(*dev));
  277. /* initialize the procs */
  278. dev->device.common.tag = HARDWARE_DEVICE_TAG;
  279. dev->device.common.version = 0;
  280. dev->device.common.module = const_cast<hw_module_t*>(module);
  281. dev->device.common.close = fb_close;
  282. dev->device.setSwapInterval = fb_setSwapInterval;
  283. dev->device.post = fb_post;
  284. dev->device.setUpdateRect = 0;
  285. private_module_t* m = (private_module_t*)module;
  286. status = mapFrameBuffer(m);
  287. if (status >= 0) {
  288. int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
  289. const_cast<uint32_t&>(dev->device.flags) = 0;
  290. const_cast<uint32_t&>(dev->device.width) = m->info.xres;
  291. const_cast<uint32_t&>(dev->device.height) = m->info.yres;
  292. const_cast<int&>(dev->device.stride) = stride;
  293. const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565;
  294. const_cast<float&>(dev->device.xdpi) = m->xdpi;
  295. const_cast<float&>(dev->device.ydpi) = m->ydpi;
  296. const_cast<float&>(dev->device.fps) = m->fps;
  297. const_cast<int&>(dev->device.minSwapInterval) = 1;
  298. const_cast<int&>(dev->device.maxSwapInterval) = 1;
  299. if (m->finfo.reserved[0] == 0x5444 &&
  300. m->finfo.reserved[1] == 0x5055) {
  301. dev->device.setUpdateRect = fb_setUpdateRect;
  302. ALOGD("UPDATE_ON_DEMAND supported");
  303. }
  304. *device = &dev->device.common;
  305. }
  306. }
  307. return status;
  308. }
  309. /* Copy a pmem buffer to the framebuffer */
  310. static void
  311. msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height,
  312. int x, int y, int w, int h)
  313. {
  314. struct {
  315. unsigned int count;
  316. mdp_blit_req req;
  317. } blit;
  318. private_handle_t *priv = (private_handle_t*) handle;
  319. memset(&blit, 0, sizeof(blit));
  320. blit.count = 1;
  321. blit.req.flags = 0;
  322. blit.req.alpha = 0xff;
  323. blit.req.transp_mask = 0xffffffff;
  324. blit.req.src.width = width;
  325. blit.req.src.height = height;
  326. blit.req.src.offset = 0;
  327. blit.req.src.memory_id = priv->fd;
  328. blit.req.dst.width = width;
  329. blit.req.dst.height = height;
  330. blit.req.dst.offset = 0;
  331. blit.req.dst.memory_id = fd;
  332. blit.req.dst.format = MDP_RGB_565;
  333. blit.req.src_rect.x = blit.req.dst_rect.x = x;
  334. blit.req.src_rect.y = blit.req.dst_rect.y = y;
  335. blit.req.src_rect.w = blit.req.dst_rect.w = w;
  336. blit.req.src_rect.h = blit.req.dst_rect.h = h;
  337. if (ioctl(fd, MSMFB_BLIT, &blit))
  338. ALOGE("MSMFB_BLIT failed = %d", -errno);
  339. }