PageRenderTime 414ms CodeModel.GetById 2ms RepoModel.GetById 1ms app.codeStats 0ms

/exynos3/s5pc110/libhwcomposer/SecHWC.cpp

https://bitbucket.org/cyanogenmod/android_hardware_samsung
C++ | 793 lines | 587 code | 122 blank | 84 comment | 121 complexity | 4b0bb309f15d2fbcbec8928deceb8a9c MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 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. /*
  17. *
  18. * @author Rama, Meka(v.meka@samsung.com)
  19. Sangwoo, Park(sw5771.park@samsung.com)
  20. Jamie Oh (jung-min.oh@samsung.com)
  21. * @date 2011-07-28
  22. *
  23. */
  24. #include <sys/resource.h>
  25. #include <cutils/log.h>
  26. #include <cutils/atomic.h>
  27. #include <EGL/egl.h>
  28. #include <GLES/gl.h>
  29. #include <hardware_legacy/uevent.h>
  30. #include "SecHWCUtils.h"
  31. static IMG_gralloc_module_public_t *gpsGrallocModule;
  32. static int hwc_device_open(const struct hw_module_t* module, const char* name,
  33. struct hw_device_t** device);
  34. static struct hw_module_methods_t hwc_module_methods = {
  35. open: hwc_device_open
  36. };
  37. hwc_module_t HAL_MODULE_INFO_SYM = {
  38. common: {
  39. tag: HARDWARE_MODULE_TAG,
  40. module_api_version: HWC_MODULE_API_VERSION_0_1,
  41. hal_api_version: HARDWARE_HAL_API_VERSION,
  42. id: HWC_HARDWARE_MODULE_ID,
  43. name: "Samsung S5PC11X hwcomposer module",
  44. author: "SAMSUNG",
  45. methods: &hwc_module_methods,
  46. }
  47. };
  48. static void dump_layer(hwc_layer_t const* l) {
  49. ALOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}",
  50. l->compositionType, l->flags, l->handle, l->transform, l->blending,
  51. l->sourceCrop.left,
  52. l->sourceCrop.top,
  53. l->sourceCrop.right,
  54. l->sourceCrop.bottom,
  55. l->displayFrame.left,
  56. l->displayFrame.top,
  57. l->displayFrame.right,
  58. l->displayFrame.bottom);
  59. }
  60. static int set_src_dst_info(hwc_layer_t *cur,
  61. struct hwc_win_info_t *win,
  62. struct sec_img *src_img,
  63. struct sec_img *dst_img,
  64. struct sec_rect *src_rect,
  65. struct sec_rect *dst_rect,
  66. int win_idx)
  67. {
  68. IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
  69. // set src image
  70. src_img->w = prev_handle->iWidth;
  71. src_img->h = prev_handle->iHeight;
  72. src_img->format = prev_handle->iFormat;
  73. src_img->base = 0;
  74. src_img->offset = 0;
  75. src_img->mem_id = 0;
  76. src_img->mem_type = HWC_PHYS_MEM_TYPE;
  77. src_img->w = (src_img->w + 15) & (~15);
  78. src_img->h = (src_img->h + 1) & (~1) ;
  79. //set src rect
  80. src_rect->x = SEC_MAX(cur->sourceCrop.left, 0);
  81. src_rect->y = SEC_MAX(cur->sourceCrop.top, 0);
  82. src_rect->w = SEC_MAX(cur->sourceCrop.right - cur->sourceCrop.left, 0);
  83. src_rect->w = SEC_MIN(src_rect->w, src_img->w - src_rect->x);
  84. src_rect->h = SEC_MAX(cur->sourceCrop.bottom - cur->sourceCrop.top, 0);
  85. src_rect->h = SEC_MIN(src_rect->h, src_img->h - src_rect->y);
  86. //set dst image
  87. dst_img->w = win->lcd_info.xres;
  88. dst_img->h = win->lcd_info.yres;
  89. switch (win->lcd_info.bits_per_pixel) {
  90. case 32:
  91. dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
  92. break;
  93. default:
  94. dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
  95. break;
  96. }
  97. dst_img->base = win->addr[win->buf_index];
  98. dst_img->offset = 0;
  99. dst_img->mem_id = 0;
  100. dst_img->mem_type = HWC_PHYS_MEM_TYPE;
  101. //set dst rect
  102. //fimc dst image will be stored from left top corner
  103. dst_rect->x = 0;
  104. dst_rect->y = 0;
  105. dst_rect->w = win->rect_info.w;
  106. dst_rect->h = win->rect_info.h;
  107. ALOGV("%s::sr_x %d sr_y %d sr_w %d sr_h %d dr_x %d dr_y %d dr_w %d dr_h %d ",
  108. __func__, src_rect->x, src_rect->y, src_rect->w, src_rect->h,
  109. dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
  110. return 0;
  111. }
  112. static int get_hwc_compos_decision(hwc_layer_t* cur)
  113. {
  114. if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
  115. ALOGV("%s::is_skip_layer %d cur->handle %x",
  116. __func__, cur->flags & HWC_SKIP_LAYER, (uint32_t)cur->handle);
  117. return HWC_FRAMEBUFFER;
  118. }
  119. IMG_native_handle_t *prev_handle = (IMG_native_handle_t *)(cur->handle);
  120. int compositionType = HWC_FRAMEBUFFER;
  121. /* check here....if we have any resolution constraints */
  122. if (((cur->sourceCrop.right - cur->sourceCrop.left) < 16) ||
  123. ((cur->sourceCrop.bottom - cur->sourceCrop.top) < 8))
  124. return compositionType;
  125. if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
  126. (cur->transform == HAL_TRANSFORM_ROT_270)) {
  127. if(((cur->displayFrame.right - cur->displayFrame.left) < 4)||
  128. ((cur->displayFrame.bottom - cur->displayFrame.top) < 8))
  129. return compositionType;
  130. } else if (((cur->displayFrame.right - cur->displayFrame.left) < 8) ||
  131. ((cur->displayFrame.bottom - cur->displayFrame.top) < 4))
  132. return compositionType;
  133. if((prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG) &&
  134. (cur->blending == HWC_BLENDING_NONE))
  135. compositionType = HWC_OVERLAY;
  136. else
  137. compositionType = HWC_FRAMEBUFFER;
  138. ALOGV("%s::compositionType %d bpp %d format %x usage %x",
  139. __func__,compositionType, prev_handle->uiBpp, prev_handle->iFormat,
  140. prev_handle->usage & GRALLOC_USAGE_PHYS_CONTIG);
  141. return compositionType;
  142. }
  143. static int assign_overlay_window(struct hwc_context_t *ctx,
  144. hwc_layer_t *cur,
  145. int win_idx,
  146. int layer_idx)
  147. {
  148. struct hwc_win_info_t *win;
  149. sec_rect rect;
  150. int ret = 0;
  151. if(NUM_OF_WIN <= win_idx)
  152. return -1;
  153. win = &ctx->win[win_idx];
  154. rect.x = SEC_MAX(cur->displayFrame.left, 0);
  155. rect.y = SEC_MAX(cur->displayFrame.top, 0);
  156. rect.w = SEC_MIN(cur->displayFrame.right - rect.x, win->lcd_info.xres - rect.x);
  157. rect.h = SEC_MIN(cur->displayFrame.bottom - rect.y, win->lcd_info.yres - rect.y);
  158. win->set_win_flag = 0;
  159. if((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
  160. (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
  161. win->rect_info.x = rect.x;
  162. win->rect_info.y = rect.y;
  163. win->rect_info.w = rect.w;
  164. win->rect_info.h = rect.h;
  165. win->set_win_flag = 1;
  166. win->layer_prev_buf = 0;
  167. }
  168. win->layer_index = layer_idx;
  169. win->status = HWC_WIN_RESERVED;
  170. ALOGV("%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d",
  171. __func__, win->rect_info.x, win->rect_info.y, win->rect_info.w,
  172. win->rect_info.h, win->layer_index, win_idx );
  173. return 0;
  174. }
  175. static void reset_win_rect_info(hwc_win_info_t *win)
  176. {
  177. win->rect_info.x = 0;
  178. win->rect_info.y = 0;
  179. win->rect_info.w = 0;
  180. win->rect_info.h = 0;
  181. return;
  182. }
  183. static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
  184. {
  185. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  186. int overlay_win_cnt = 0;
  187. int compositionType = 0;
  188. int ret;
  189. //if geometry is not changed, there is no need to do any work here
  190. if( !list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
  191. return 0;
  192. //all the windows are free here....
  193. for (int i = 0; i < NUM_OF_WIN; i++) {
  194. ctx->win[i].status = HWC_WIN_FREE;
  195. ctx->win[i].buf_index = 0;
  196. }
  197. ctx->num_of_hwc_layer = 0;
  198. ctx->num_of_fb_layer = 0;
  199. ALOGV("%s:: hwc_prepare list->numHwLayers %d", __func__, list->numHwLayers);
  200. for (int i = 0; i < list->numHwLayers ; i++) {
  201. hwc_layer_t* cur = &list->hwLayers[i];
  202. if (overlay_win_cnt < NUM_OF_WIN) {
  203. compositionType = get_hwc_compos_decision(cur);
  204. if (compositionType == HWC_FRAMEBUFFER) {
  205. cur->compositionType = HWC_FRAMEBUFFER;
  206. ctx->num_of_fb_layer++;
  207. } else {
  208. ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
  209. if (ret != 0) {
  210. cur->compositionType = HWC_FRAMEBUFFER;
  211. ctx->num_of_fb_layer++;
  212. continue;
  213. }
  214. cur->compositionType = HWC_OVERLAY;
  215. cur->hints = HWC_HINT_CLEAR_FB;
  216. overlay_win_cnt++;
  217. ctx->num_of_hwc_layer++;
  218. }
  219. } else {
  220. cur->compositionType = HWC_FRAMEBUFFER;
  221. ctx->num_of_fb_layer++;
  222. }
  223. }
  224. if(list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
  225. ALOGV("%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
  226. __func__, list->numHwLayers, ctx->num_of_fb_layer,
  227. ctx->num_of_hwc_layer);
  228. if (overlay_win_cnt < NUM_OF_WIN) {
  229. //turn off the free windows
  230. for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
  231. window_hide(&ctx->win[i]);
  232. reset_win_rect_info(&ctx->win[i]);
  233. }
  234. }
  235. return 0;
  236. }
  237. static int hwc_set(hwc_composer_device_t *dev,
  238. hwc_display_t dpy,
  239. hwc_surface_t sur,
  240. hwc_layer_list_t* list)
  241. {
  242. struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
  243. unsigned int phyAddr[MAX_NUM_PLANES];
  244. int skipped_window_mask = 0;
  245. hwc_layer_t* cur;
  246. struct hwc_win_info_t *win;
  247. int ret;
  248. struct sec_img src_img;
  249. struct sec_img dst_img;
  250. struct sec_rect src_rect;
  251. struct sec_rect dst_rect;
  252. if (dpy == NULL && sur == NULL && list == NULL) {
  253. // release our resources, the screen is turning off
  254. // in our case, there is nothing to do.
  255. ctx->num_of_fb_layer_prev = 0;
  256. return 0;
  257. }
  258. bool need_swap_buffers = ctx->num_of_fb_layer > 0;
  259. /*
  260. * H/W composer documentation states:
  261. * There is an implicit layer containing opaque black
  262. * pixels behind all the layers in the list.
  263. * It is the responsibility of the hwcomposer module to make
  264. * sure black pixels are output (or blended from).
  265. *
  266. * Since we're using a blitter, we need to erase the frame-buffer when
  267. * switching to all-overlay mode.
  268. *
  269. */
  270. if (ctx->num_of_hwc_layer &&
  271. ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
  272. /* we're clearing the screen using GLES here, this is very
  273. * hack-ish, ideal we would use the fimc (if it can do it) */
  274. glDisable(GL_SCISSOR_TEST);
  275. glClearColor(0, 0, 0, 0);
  276. glClear(GL_COLOR_BUFFER_BIT);
  277. glEnable(GL_SCISSOR_TEST);
  278. need_swap_buffers = true;
  279. }
  280. ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
  281. if (need_swap_buffers || !list) {
  282. EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
  283. if (!sucess) {
  284. return HWC_EGL_ERROR;
  285. }
  286. }
  287. if (!list) {
  288. /* turn off the all windows */
  289. for (int i = 0; i < NUM_OF_WIN; i++) {
  290. window_hide(&ctx->win[i]);
  291. reset_win_rect_info(&ctx->win[i]);
  292. ctx->win[i].status = HWC_WIN_FREE;
  293. }
  294. ctx->num_of_hwc_layer = 0;
  295. return 0;
  296. }
  297. if(ctx->num_of_hwc_layer > NUM_OF_WIN)
  298. ctx->num_of_hwc_layer = NUM_OF_WIN;
  299. /* compose hardware layers here */
  300. for (uint32_t i = 0; i < ctx->num_of_hwc_layer; i++) {
  301. win = &ctx->win[i];
  302. if (win->status == HWC_WIN_RESERVED) {
  303. cur = &list->hwLayers[win->layer_index];
  304. if (cur->compositionType == HWC_OVERLAY) {
  305. ret = gpsGrallocModule->GetPhyAddrs(gpsGrallocModule,
  306. cur->handle, phyAddr);
  307. if (ret) {
  308. ALOGE("%s::GetPhyAddrs fail : ret=%d\n", __func__, ret);
  309. skipped_window_mask |= (1 << i);
  310. continue;
  311. }
  312. /* initialize the src & dist context for fimc */
  313. set_src_dst_info (cur, win, &src_img, &dst_img, &src_rect,
  314. &dst_rect, i);
  315. ret = runFimc(ctx, &src_img, &src_rect, &dst_img, &dst_rect,
  316. phyAddr, cur->transform);
  317. if (ret < 0){
  318. ALOGE("%s::runFimc fail : ret=%d\n", __func__, ret);
  319. skipped_window_mask |= (1 << i);
  320. continue;
  321. }
  322. if (win->set_win_flag == 1) {
  323. /* turnoff the window and set the window position with new conf... */
  324. if (window_set_pos(win) < 0) {
  325. ALOGE("%s::window_set_pos is failed : %s", __func__,
  326. strerror(errno));
  327. skipped_window_mask |= (1 << i);
  328. continue;
  329. }
  330. win->set_win_flag = 0;
  331. }
  332. /* is the frame didn't change, it needs to be composited
  333. * because something else below it could have changed, however
  334. * it doesn't need to be swapped.
  335. */
  336. if (win->layer_prev_buf != (uint32_t)cur->handle) {
  337. win->layer_prev_buf = (uint32_t)cur->handle;
  338. window_pan_display(win);
  339. win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
  340. }
  341. if(win->power_state == 0)
  342. window_show(win);
  343. } else {
  344. ALOGE("%s:: error : layer %d compositionType should have been \
  345. HWC_OVERLAY", __func__, win->layer_index);
  346. skipped_window_mask |= (1 << i);
  347. continue;
  348. }
  349. } else {
  350. ALOGE("%s:: error : window status should have been HWC_WIN_RESERVED \
  351. by now... ", __func__);
  352. skipped_window_mask |= (1 << i);
  353. continue;
  354. }
  355. }
  356. if (skipped_window_mask) {
  357. //turn off the free windows
  358. for (int i = 0; i < NUM_OF_WIN; i++) {
  359. if (skipped_window_mask & (1 << i))
  360. window_hide(&ctx->win[i]);
  361. }
  362. }
  363. #if defined(BOARD_USES_HDMI)
  364. hdmi_device_t* hdmi = ctx->hdmi;
  365. if (ctx->num_of_hwc_layer == 1 && hdmi) {
  366. if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
  367. (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
  368. ADDRS * addr = (ADDRS *)(src_img.base);
  369. hdmi->blit(hdmi,
  370. src_img.w,
  371. src_img.h,
  372. src_img.format,
  373. (unsigned int)addr->addr_y,
  374. (unsigned int)addr->addr_cbcr,
  375. (unsigned int)addr->addr_cbcr,
  376. 0, 0,
  377. HDMI_MODE_VIDEO,
  378. ctx->num_of_hwc_layer);
  379. } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
  380. (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
  381. (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
  382. (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
  383. hdmi->blit(hdmi,
  384. src_img.w,
  385. src_img.h,
  386. src_img.format,
  387. (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
  388. (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
  389. (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
  390. 0, 0,
  391. HDMI_MODE_VIDEO,
  392. ctx->num_of_hwc_layer);
  393. } else {
  394. ALOGE("%s: Unsupported format = %d for hdmi", __func__, src_img.format);
  395. }
  396. }
  397. #endif
  398. return 0;
  399. }
  400. static void hwc_registerProcs(struct hwc_composer_device* dev,
  401. hwc_procs_t const* procs)
  402. {
  403. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  404. ctx->procs = const_cast<hwc_procs_t *>(procs);
  405. }
  406. static int hwc_query(struct hwc_composer_device* dev,
  407. int what, int* value)
  408. {
  409. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  410. switch (what) {
  411. case HWC_BACKGROUND_LAYER_SUPPORTED:
  412. // we don't support the background layer yet
  413. value[0] = 0;
  414. break;
  415. case HWC_VSYNC_PERIOD:
  416. // vsync period in nanosecond
  417. value[0] = 1000000000.0 / gpsGrallocModule->psFrameBufferDevice->base.fps;
  418. break;
  419. default:
  420. // unsupported query
  421. return -EINVAL;
  422. }
  423. return 0;
  424. }
  425. #ifdef VSYNC_IOCTL
  426. // Linux version of a manual reset event to control when
  427. // and when not to ask the video card for a VSYNC. This
  428. // stops the worker thread from asking for a VSYNC when
  429. // there is nothing useful to do with it and more closely
  430. // mimicks the original uevent mechanism
  431. int vsync_enable = 0;
  432. pthread_mutex_t vsync_mutex = PTHREAD_MUTEX_INITIALIZER;
  433. pthread_cond_t vsync_condition = PTHREAD_COND_INITIALIZER;
  434. #endif
  435. static int hwc_eventControl(struct hwc_composer_device* dev,
  436. int event, int enabled)
  437. {
  438. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  439. switch (event) {
  440. case HWC_EVENT_VSYNC:
  441. int val = !!enabled;
  442. int err = ioctl(ctx->global_lcd_win.fd, S3CFB_SET_VSYNC_INT, &val);
  443. if (err < 0)
  444. return -errno;
  445. #if VSYNC_IOCTL
  446. // Enable or disable the ability for the worker thread
  447. // to ask for VSYNC events from the video driver
  448. pthread_mutex_lock(&vsync_mutex);
  449. if(enabled) {
  450. vsync_enable = 1;
  451. pthread_cond_broadcast(&vsync_condition);
  452. }
  453. else vsync_enable = 0;
  454. pthread_mutex_unlock(&vsync_mutex);
  455. #endif
  456. return 0;
  457. }
  458. return -EINVAL;
  459. }
  460. void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
  461. {
  462. uint64_t timestamp = 0;
  463. const char *s = buff;
  464. if(!ctx->procs || !ctx->procs->vsync)
  465. return;
  466. s += strlen(s) + 1;
  467. while(*s) {
  468. if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
  469. timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
  470. s += strlen(s) + 1;
  471. if (s - buff >= len)
  472. break;
  473. }
  474. ctx->procs->vsync(ctx->procs, 0, timestamp);
  475. }
  476. static void *hwc_vsync_thread(void *data)
  477. {
  478. hwc_context_t *ctx = (hwc_context_t *)(data);
  479. #ifdef VSYNC_IOCTL
  480. uint64_t timestamp = 0;
  481. #else
  482. char uevent_desc[4096];
  483. memset(uevent_desc, 0, sizeof(uevent_desc));
  484. #endif
  485. setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
  486. #ifndef VSYNC_IOCTL
  487. uevent_init();
  488. #endif
  489. while(true) {
  490. #ifdef VSYNC_IOCTL
  491. // Only continue if hwc_eventControl is enabled, otherwise
  492. // just sit here and wait until it is. This stops the code
  493. // from constantly looking for the VSYNC event with the screen
  494. // turned off.
  495. pthread_mutex_lock(&vsync_mutex);
  496. if(!vsync_enable) pthread_cond_wait(&vsync_condition, &vsync_mutex);
  497. pthread_mutex_unlock(&vsync_mutex);
  498. timestamp = 0; // Reset the timestamp value
  499. // S3CFB_WAIT_FOR_VSYNC is a custom IOCTL I added to wait for
  500. // the VSYNC interrupt, and then return the timestamp that was
  501. // originally being communicated via a uevent. The uevent was
  502. // spamming the UEventObserver and events/0 process with more
  503. // information than this device could really deal with every 18ms
  504. int res = ioctl(ctx->global_lcd_win.fd, S3CFB_WAIT_FOR_VSYNC, &timestamp);
  505. if(res > 0) {
  506. if(!ctx->procs || !ctx->procs->vsync) continue;
  507. ctx->procs->vsync(ctx->procs, 0, timestamp);
  508. }
  509. #else
  510. int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
  511. bool vsync = !strcmp(uevent_desc, "change@/devices/platform/s3cfb");
  512. if(vsync)
  513. handle_vsync_uevent(ctx, uevent_desc, len);
  514. #endif
  515. }
  516. return NULL;
  517. }
  518. static int hwc_device_close(struct hw_device_t *dev)
  519. {
  520. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  521. int ret = 0;
  522. int i;
  523. if (ctx) {
  524. if (destroyFimc(&ctx->fimc) < 0) {
  525. ALOGE("%s::destroyFimc fail", __func__);
  526. ret = -1;
  527. }
  528. if (window_close(&ctx->global_lcd_win) < 0) {
  529. ALOGE("%s::window_close() fail", __func__);
  530. ret = -1;
  531. }
  532. for (i = 0; i < NUM_OF_WIN; i++) {
  533. if (window_close(&ctx->win[i]) < 0) {
  534. ALOGE("%s::window_close() fail", __func__);
  535. ret = -1;
  536. }
  537. }
  538. // TODO: stop vsync_thread
  539. free(ctx);
  540. }
  541. return ret;
  542. }
  543. static const struct hwc_methods hwc_methods = {
  544. eventControl: hwc_eventControl
  545. };
  546. static int hwc_device_open(const struct hw_module_t* module, const char* name,
  547. struct hw_device_t** device)
  548. {
  549. int status = 0;
  550. int err;
  551. struct hwc_win_info_t *win;
  552. #if defined(BOARD_USES_HDMI)
  553. struct hw_module_t *hdmi_module;
  554. #endif
  555. if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
  556. (const hw_module_t**)&gpsGrallocModule))
  557. return -EINVAL;
  558. if(strcmp(gpsGrallocModule->base.common.author, "Imagination Technologies"))
  559. return -EINVAL;
  560. if (strcmp(name, HWC_HARDWARE_COMPOSER))
  561. return -EINVAL;
  562. struct hwc_context_t *dev;
  563. dev = (hwc_context_t*)malloc(sizeof(*dev));
  564. /* initialize our state here */
  565. memset(dev, 0, sizeof(*dev));
  566. /* initialize the procs */
  567. dev->device.common.tag = HARDWARE_DEVICE_TAG;
  568. dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
  569. dev->device.common.module = const_cast<hw_module_t*>(module);
  570. dev->device.common.close = hwc_device_close;
  571. dev->device.prepare = hwc_prepare;
  572. dev->device.set = hwc_set;
  573. dev->device.registerProcs = hwc_registerProcs;
  574. dev->device.query = hwc_query;
  575. dev->device.methods = &hwc_methods;
  576. *device = &dev->device.common;
  577. #if defined(BOARD_USES_HDMI)
  578. dev->hdmi = NULL;
  579. if(hw_get_module(HDMI_HARDWARE_MODULE_ID,
  580. (const hw_module_t**)&hdmi_module)) {
  581. ALOGE("%s:: HDMI device not present", __func__);
  582. } else {
  583. int ret = module->methods->open(hdmi_module, "hdmi-composer",
  584. (hw_device_t **)&dev->hdmi);
  585. if(ret < 0) {
  586. ALOGE("%s:: Failed to open hdmi device : %s", __func__, strerror(ret));
  587. }
  588. }
  589. #endif
  590. /* initializing */
  591. memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
  592. dev->fimc.dev_fd = -1;
  593. /* open WIN0 & WIN1 here */
  594. for (int i = 0; i < NUM_OF_WIN; i++) {
  595. if (window_open(&(dev->win[i]), i) < 0) {
  596. ALOGE("%s:: Failed to open window %d device ", __func__, i);
  597. status = -EINVAL;
  598. goto err;
  599. }
  600. }
  601. /* open window 2, used to query global LCD info */
  602. if (window_open(&dev->global_lcd_win, 2) < 0) {
  603. ALOGE("%s:: Failed to open window 2 device ", __func__);
  604. status = -EINVAL;
  605. goto err;
  606. }
  607. /* get default window config */
  608. if (window_get_global_lcd_info(dev) < 0) {
  609. ALOGE("%s::window_get_global_lcd_info is failed : %s",
  610. __func__, strerror(errno));
  611. status = -EINVAL;
  612. goto err;
  613. }
  614. dev->lcd_info.yres_virtual = dev->lcd_info.yres * NUM_OF_WIN_BUF;
  615. /* initialize the window context */
  616. for (int i = 0; i < NUM_OF_WIN; i++) {
  617. win = &dev->win[i];
  618. memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
  619. memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
  620. win->rect_info.x = 0;
  621. win->rect_info.y = 0;
  622. win->rect_info.w = win->var_info.xres;
  623. win->rect_info.h = win->var_info.yres;
  624. if (window_set_pos(win) < 0) {
  625. ALOGE("%s::window_set_pos is failed : %s",
  626. __func__, strerror(errno));
  627. status = -EINVAL;
  628. goto err;
  629. }
  630. if (window_get_info(win) < 0) {
  631. ALOGE("%s::window_get_info is failed : %s",
  632. __func__, strerror(errno));
  633. status = -EINVAL;
  634. goto err;
  635. }
  636. win->size = win->fix_info.line_length * win->var_info.yres;
  637. if (!win->fix_info.smem_start){
  638. ALOGE("%s:: win-%d failed to get the reserved memory", __func__, i);
  639. status = -EINVAL;
  640. goto err;
  641. }
  642. for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
  643. win->addr[j] = win->fix_info.smem_start + (win->size * j);
  644. ALOGI("%s::win-%d add[%d] %x ", __func__, i, j, win->addr[j]);
  645. }
  646. }
  647. /* open pp */
  648. if (createFimc(&dev->fimc) < 0) {
  649. ALOGE("%s::creatFimc() fail", __func__);
  650. status = -EINVAL;
  651. goto err;
  652. }
  653. err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
  654. if (err) {
  655. ALOGE("%s::pthread_create() failed : %s", __func__, strerror(err));
  656. status = -err;
  657. goto err;
  658. }
  659. ALOGD("%s:: success\n", __func__);
  660. return 0;
  661. err:
  662. if (destroyFimc(&dev->fimc) < 0)
  663. ALOGE("%s::destroyFimc() fail", __func__);
  664. if (window_close(&dev->global_lcd_win) < 0)
  665. ALOGE("%s::window_close() fail", __func__);
  666. for (int i = 0; i < NUM_OF_WIN; i++) {
  667. if (window_close(&dev->win[i]) < 0)
  668. ALOGE("%s::window_close() fail", __func__);
  669. }
  670. return status;
  671. }