PageRenderTime 56ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/libhwcomposer/SecHWC.cpp

http://github.com/namko/device-samsung-smdkv210
C++ | 688 lines | 504 code | 116 blank | 68 comment | 99 complexity | 9b90f9f764ceaa4f10a1a44bc6cc06eb 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 = NULL;
  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. return 0;
  364. }
  365. static void hwc_registerProcs(struct hwc_composer_device* dev,
  366. hwc_procs_t const* procs)
  367. {
  368. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  369. ctx->procs = const_cast<hwc_procs_t *>(procs);
  370. }
  371. static int hwc_query(struct hwc_composer_device* dev,
  372. int what, int* value)
  373. {
  374. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  375. switch (what) {
  376. case HWC_BACKGROUND_LAYER_SUPPORTED:
  377. // we don't support the background layer yet
  378. value[0] = 0;
  379. break;
  380. case HWC_VSYNC_PERIOD:
  381. // vsync period in nanosecond
  382. value[0] = 1000000000.0 / gpsGrallocModule->psFrameBufferDevice->base.fps;
  383. break;
  384. default:
  385. // unsupported query
  386. return -EINVAL;
  387. }
  388. return 0;
  389. }
  390. static int hwc_eventControl(struct hwc_composer_device* dev,
  391. int event, int enabled)
  392. {
  393. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  394. switch (event) {
  395. case HWC_EVENT_VSYNC:
  396. int val = !!enabled;
  397. int err = ioctl(ctx->global_lcd_win.fd, S3CFB_SET_VSYNC_INT, &val);
  398. if (err < 0)
  399. return -errno;
  400. return 0;
  401. }
  402. return -EINVAL;
  403. }
  404. void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
  405. {
  406. uint64_t timestamp = 0;
  407. const char *s = buff;
  408. if(!ctx->procs || !ctx->procs->vsync)
  409. return;
  410. s += strlen(s) + 1;
  411. while(*s) {
  412. if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
  413. timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
  414. s += strlen(s) + 1;
  415. if (s - buff >= len)
  416. break;
  417. }
  418. ctx->procs->vsync(ctx->procs, 0, timestamp);
  419. }
  420. static void *hwc_vsync_thread(void *data)
  421. {
  422. hwc_context_t *ctx = (hwc_context_t *)(data);
  423. char uevent_desc[4096];
  424. memset(uevent_desc, 0, sizeof(uevent_desc));
  425. setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
  426. uevent_init();
  427. while(true) {
  428. int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
  429. bool vsync = !strcmp(uevent_desc, "change@/devices/platform/s3cfb");
  430. if(vsync)
  431. handle_vsync_uevent(ctx, uevent_desc, len);
  432. }
  433. return NULL;
  434. }
  435. static int hwc_device_close(struct hw_device_t *dev)
  436. {
  437. struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
  438. int ret = 0;
  439. int i;
  440. if (ctx) {
  441. if (destroyFimc(&ctx->fimc) < 0) {
  442. ALOGE("%s::destroyFimc fail", __func__);
  443. ret = -1;
  444. }
  445. if (window_close(&ctx->global_lcd_win) < 0) {
  446. ALOGE("%s::window_close() fail", __func__);
  447. ret = -1;
  448. }
  449. for (i = 0; i < NUM_OF_WIN; i++) {
  450. if (window_close(&ctx->win[i]) < 0) {
  451. ALOGE("%s::window_close() fail", __func__);
  452. ret = -1;
  453. }
  454. }
  455. // TODO: stop vsync_thread
  456. free(ctx);
  457. }
  458. return ret;
  459. }
  460. static const struct hwc_methods hwc_methods = {
  461. eventControl: hwc_eventControl
  462. };
  463. static int hwc_device_open(const struct hw_module_t* module, const char* name,
  464. struct hw_device_t** device)
  465. {
  466. int status = 0;
  467. int err;
  468. struct hwc_win_info_t *win;
  469. if(hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
  470. (const hw_module_t**)&gpsGrallocModule))
  471. return -EINVAL;
  472. if(strcmp(gpsGrallocModule->base.common.author, "Imagination Technologies"))
  473. return -EINVAL;
  474. if (strcmp(name, HWC_HARDWARE_COMPOSER))
  475. return -EINVAL;
  476. struct hwc_context_t *dev;
  477. dev = (hwc_context_t*)malloc(sizeof(*dev));
  478. /* initialize our state here */
  479. memset(dev, 0, sizeof(*dev));
  480. /* initialize the procs */
  481. dev->device.common.tag = HARDWARE_DEVICE_TAG;
  482. dev->device.common.version = HWC_DEVICE_API_VERSION_0_3;
  483. dev->device.common.module = const_cast<hw_module_t*>(module);
  484. dev->device.common.close = hwc_device_close;
  485. dev->device.prepare = hwc_prepare;
  486. dev->device.set = hwc_set;
  487. dev->device.registerProcs = hwc_registerProcs;
  488. dev->device.query = hwc_query;
  489. dev->device.methods = &hwc_methods;
  490. *device = &dev->device.common;
  491. /* initializing */
  492. memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
  493. dev->fimc.dev_fd = -1;
  494. /* open WIN0 & WIN1 here */
  495. for (int i = 0; i < NUM_OF_WIN; i++) {
  496. if (window_open(&(dev->win[i]), i) < 0) {
  497. ALOGE("%s:: Failed to open window %d device ", __func__, i);
  498. status = -EINVAL;
  499. goto err;
  500. }
  501. }
  502. /* open window 2, used to query global LCD info */
  503. if (window_open(&dev->global_lcd_win, 2) < 0) {
  504. ALOGE("%s:: Failed to open window 2 device ", __func__);
  505. status = -EINVAL;
  506. goto err;
  507. }
  508. /* get default window config */
  509. if (window_get_global_lcd_info(dev) < 0) {
  510. ALOGE("%s::window_get_global_lcd_info is failed : %s",
  511. __func__, strerror(errno));
  512. status = -EINVAL;
  513. goto err;
  514. }
  515. dev->lcd_info.yres_virtual = dev->lcd_info.yres * NUM_OF_WIN_BUF;
  516. /* initialize the window context */
  517. for (int i = 0; i < NUM_OF_WIN; i++) {
  518. win = &dev->win[i];
  519. memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
  520. memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
  521. win->rect_info.x = 0;
  522. win->rect_info.y = 0;
  523. win->rect_info.w = win->var_info.xres;
  524. win->rect_info.h = win->var_info.yres;
  525. if (window_set_pos(win) < 0) {
  526. ALOGE("%s::window_set_pos is failed : %s",
  527. __func__, strerror(errno));
  528. status = -EINVAL;
  529. goto err;
  530. }
  531. if (window_get_info(win) < 0) {
  532. ALOGE("%s::window_get_info is failed : %s",
  533. __func__, strerror(errno));
  534. status = -EINVAL;
  535. goto err;
  536. }
  537. win->size = win->fix_info.line_length * win->var_info.yres;
  538. if (!win->fix_info.smem_start){
  539. ALOGE("%s:: win-%d failed to get the reserved memory", __func__, i);
  540. status = -EINVAL;
  541. goto err;
  542. }
  543. for (int j = 0; j < NUM_OF_WIN_BUF; j++) {
  544. win->addr[j] = win->fix_info.smem_start + (win->size * j);
  545. ALOGI("%s::win-%d add[%d] %x ", __func__, i, j, win->addr[j]);
  546. }
  547. }
  548. /* open pp */
  549. if (createFimc(&dev->fimc) < 0) {
  550. ALOGE("%s::creatFimc() fail", __func__);
  551. status = -EINVAL;
  552. goto err;
  553. }
  554. err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
  555. if (err) {
  556. ALOGE("%s::pthread_create() failed : %s", __func__, strerror(err));
  557. status = -err;
  558. goto err;
  559. }
  560. ALOGD("%s:: success\n", __func__);
  561. return 0;
  562. err:
  563. if (destroyFimc(&dev->fimc) < 0)
  564. ALOGE("%s::destroyFimc() fail", __func__);
  565. if (window_close(&dev->global_lcd_win) < 0)
  566. ALOGE("%s::window_close() fail", __func__);
  567. for (int i = 0; i < NUM_OF_WIN; i++) {
  568. if (window_close(&dev->win[i]) < 0)
  569. ALOGE("%s::window_close() fail", __func__);
  570. }
  571. return status;
  572. }