blob: 704e5b805a605723fa3e2312313159265858b2fa [file] [log] [blame]
codeworkx62f02ba2012-05-20 12:00:36 +02001/*
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 *
19 * @author Rama, Meka(v.meka@samsung.com)
20 Sangwoo, Park(sw5771.park@samsung.com)
21 Jamie Oh (jung-min.oh@samsung.com)
22 * @date 2011-03-11
23 *
24 */
25
26#include <cutils/log.h>
27#include <cutils/atomic.h>
28
29#include <EGL/egl.h>
espenfjo34f9d5d2012-12-01 18:52:36 +010030#include <sys/prctl.h>
31#include <fcntl.h>
codeworkx62f02ba2012-05-20 12:00:36 +020032
33#include "SecHWCUtils.h"
34
35#include "gralloc_priv.h"
36#ifdef HWC_HWOVERLAY
37#include <GLES/gl.h>
38#endif
39#if defined(BOARD_USES_HDMI)
40#include "SecHdmiClient.h"
41#include "SecTVOutService.h"
42
43#include "SecHdmi.h"
44
45//#define CHECK_EGL_FPS
46#ifdef CHECK_EGL_FPS
47extern void check_fps();
48#endif
49
50static int lcd_width, lcd_height;
51static int prev_usage = 0;
52
53#define CHECK_TIME_DEBUG 0
54#define SUPPORT_AUTO_UI_ROTATE
55#endif
56int testRenderNum =0;
57
58static int hwc_device_open(const struct hw_module_t* module, const char* name,
59 struct hw_device_t** device);
60
61static struct hw_module_methods_t hwc_module_methods = {
62 open: hwc_device_open
63};
64
65hwc_module_t HAL_MODULE_INFO_SYM = {
66 common: {
67 tag: HARDWARE_MODULE_TAG,
espenfjo34f9d5d2012-12-01 18:52:36 +010068 version_major: 2,
codeworkx62f02ba2012-05-20 12:00:36 +020069 version_minor: 0,
70 id: HWC_HARDWARE_MODULE_ID,
71 name: "Samsung S5PC21X hwcomposer module",
72 author: "SAMSUNG",
73 methods: &hwc_module_methods,
74 }
75};
76
77/*****************************************************************************/
78
espenfjo34f9d5d2012-12-01 18:52:36 +010079static void dump_layer(hwc_layer_1_t const* l) {
80 SEC_HWC_Log(HWC_LOG_DEBUG,"\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
codeworkx62f02ba2012-05-20 12:00:36 +020081 "{%d,%d,%d,%d}, {%d,%d,%d,%d}",
82 l->compositionType, l->flags, l->handle, l->transform, l->blending,
83 l->sourceCrop.left,
84 l->sourceCrop.top,
85 l->sourceCrop.right,
86 l->sourceCrop.bottom,
87 l->displayFrame.left,
88 l->displayFrame.top,
89 l->displayFrame.right,
90 l->displayFrame.bottom);
91}
92
espenfjo34f9d5d2012-12-01 18:52:36 +010093void calculate_rect(struct hwc_win_info_t *win, hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +020094 sec_rect *rect)
95{
96 rect->x = cur->displayFrame.left;
97 rect->y = cur->displayFrame.top;
98 rect->w = cur->displayFrame.right - cur->displayFrame.left;
99 rect->h = cur->displayFrame.bottom - cur->displayFrame.top;
100
101 if (rect->x < 0) {
102 if (rect->w + rect->x > win->lcd_info.xres)
103 rect->w = win->lcd_info.xres;
104 else
105 rect->w = rect->w + rect->x;
106 rect->x = 0;
107 } else {
108 if (rect->w + rect->x > win->lcd_info.xres)
109 rect->w = win->lcd_info.xres - rect->x;
110 }
111 if (rect->y < 0) {
112 if (rect->h + rect->y > win->lcd_info.yres)
113 rect->h = win->lcd_info.yres;
114 else
115 rect->h = rect->h + rect->y;
116 rect->y = 0;
117 } else {
118 if (rect->h + rect->y > win->lcd_info.yres)
119 rect->h = win->lcd_info.yres - rect->y;
120 }
121}
122
espenfjo34f9d5d2012-12-01 18:52:36 +0100123static int set_src_dst_img_rect(hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +0200124 struct hwc_win_info_t *win,
125 struct sec_img *src_img,
126 struct sec_img *dst_img,
127 struct sec_rect *src_rect,
128 struct sec_rect *dst_rect,
129 int win_idx)
130{
131 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
132 sec_rect rect;
133
134 /* 1. Set src_img from prev_handle */
135 src_img->f_w = prev_handle->width;
136 src_img->f_h = prev_handle->height;
137 src_img->w = prev_handle->width;
138 src_img->h = prev_handle->height;
139 src_img->format = prev_handle->format;
140 src_img->base = (uint32_t)prev_handle->base;
141 src_img->offset = prev_handle->offset;
142 src_img->mem_id = prev_handle->fd;
143 src_img->paddr = prev_handle->paddr;
144 src_img->usage = prev_handle->usage;
145 src_img->uoffset = prev_handle->uoffset;
146 src_img->voffset = prev_handle->voffset;
147
148 src_img->mem_type = HWC_VIRT_MEM_TYPE;
149
150 switch (src_img->format) {
151 case HAL_PIXEL_FORMAT_YV12: /* To support video editor */
152 case HAL_PIXEL_FORMAT_YCbCr_420_P: /* To support SW codec */
153 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
154 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
155 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
156 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
157 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
158 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
159 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
160 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
161 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
162 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
163 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
164 src_img->f_w = (src_img->f_w + 15) & ~15;
165 src_img->f_h = (src_img->f_h + 1) & ~1;
166 break;
167 default:
168 src_img->f_w = src_img->w;
169 src_img->f_h = src_img->h;
170 break;
171 }
172
173 /* 2. Set dst_img from window(lcd) */
174 calculate_rect(win, cur, &rect);
175 dst_img->f_w = win->lcd_info.xres;
176 dst_img->f_h = win->lcd_info.yres;
177 dst_img->w = rect.w;
178 dst_img->h = rect.h;
179
180 switch (win->lcd_info.bits_per_pixel) {
181 case 32:
182 dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
183 break;
184 default:
185 dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
186 break;
187 }
188
189 dst_img->base = win->addr[win->buf_index];
190 dst_img->offset = 0;
191 dst_img->mem_id = 0;
192 dst_img->mem_type = HWC_PHYS_MEM_TYPE;
193
194 /* 3. Set src_rect(crop rect) */
195 if (cur->displayFrame.left < 0) {
196 src_rect->x =
197 (0 - cur->displayFrame.left)
198 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100199 /(cur->displayFrame.right - cur->displayFrame.left);
200 if (cur->displayFrame.right > win->lcd_info.xres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200201 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100202 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200203 src_rect->x -
204 (cur->displayFrame.right - win->lcd_info.xres)
205 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100206 /(cur->displayFrame.right - cur->displayFrame.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200207 } else {
208 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100209 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200210 src_rect->x;
211 }
212 } else {
213 src_rect->x = cur->sourceCrop.left;
espenfjo34f9d5d2012-12-01 18:52:36 +0100214 if (cur->displayFrame.right > win->lcd_info.xres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200215 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100216 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200217 src_rect->x -
218 (cur->displayFrame.right - win->lcd_info.xres)
219 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100220 /(cur->displayFrame.right - cur->displayFrame.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200221 } else {
222 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100223 (cur->sourceCrop.right - cur->sourceCrop.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200224 }
225 }
226 if (cur->displayFrame.top < 0) {
227 src_rect->y =
228 (0 - cur->displayFrame.top)
229 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100230 /(cur->displayFrame.bottom - cur->displayFrame.top);
231 if (cur->displayFrame.bottom > win->lcd_info.yres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200232 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100233 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200234 src_rect->y -
235 (cur->displayFrame.bottom - win->lcd_info.yres)
236 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100237 /(cur->displayFrame.bottom - cur->displayFrame.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200238 } else {
239 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100240 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200241 src_rect->y;
242 }
243 } else {
244 src_rect->y = cur->sourceCrop.top;
espenfjo34f9d5d2012-12-01 18:52:36 +0100245 if (cur->displayFrame.bottom > win->lcd_info.yres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200246 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100247 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200248 src_rect->y -
249 (cur->displayFrame.bottom - win->lcd_info.yres)
250 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100251 /(cur->displayFrame.bottom - cur->displayFrame.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200252 } else {
253 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100254 (cur->sourceCrop.bottom - cur->sourceCrop.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200255 }
256 }
257
258 SEC_HWC_Log(HWC_LOG_DEBUG,
259 "crop information()::"
260 "sourceCrop left(%d),top(%d),right(%d),bottom(%d),"
261 "src_rect x(%d),y(%d),w(%d),h(%d),"
262 "prev_handle w(%d),h(%d)",
263 cur->sourceCrop.left,
264 cur->sourceCrop.top,
265 cur->sourceCrop.right,
266 cur->sourceCrop.bottom,
267 src_rect->x, src_rect->y, src_rect->w, src_rect->h,
268 prev_handle->width, prev_handle->height);
269
270 src_rect->x = SEC_MAX(src_rect->x, 0);
271 src_rect->y = SEC_MAX(src_rect->y, 0);
272 src_rect->w = SEC_MAX(src_rect->w, 0);
273 src_rect->w = SEC_MIN(src_rect->w, prev_handle->width);
274 src_rect->h = SEC_MAX(src_rect->h, 0);
275 src_rect->h = SEC_MIN(src_rect->h, prev_handle->height);
276
277 /* 4. Set dst_rect(fb or lcd)
278 * fimc dst image will be stored from left top corner
279 */
280 dst_rect->x = 0;
281 dst_rect->y = 0;
282 dst_rect->w = win->rect_info.w;
283 dst_rect->h = win->rect_info.h;
284
285 /* Summery */
286 SEC_HWC_Log(HWC_LOG_DEBUG,
287 "set_src_dst_img_rect()::"
288 "SRC w(%d),h(%d),f_w(%d),f_h(%d),fmt(0x%x),"
289 "base(0x%x),offset(%d),paddr(0x%X),mem_id(%d),mem_type(%d)=>\r\n"
290 " DST w(%d),h(%d),f(0x%x),base(0x%x),"
291 "offset(%d),mem_id(%d),mem_type(%d),"
292 "rot(%d),win_idx(%d)"
293 " SRC_RECT x(%d),y(%d),w(%d),h(%d)=>"
294 "DST_RECT x(%d),y(%d),w(%d),h(%d)",
295 src_img->w, src_img->h, src_img->f_w, src_img->f_h, src_img->format,
296 src_img->base, src_img->offset, src_img->paddr, src_img->mem_id, src_img->mem_type,
297 dst_img->w, dst_img->h, dst_img->format, dst_img->base,
298 dst_img->offset, dst_img->mem_id, dst_img->mem_type,
299 cur->transform, win_idx,
300 src_rect->x, src_rect->y, src_rect->w, src_rect->h,
301 dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
302
303 return 0;
304}
305
espenfjo34f9d5d2012-12-01 18:52:36 +0100306static int get_hwc_compos_decision(hwc_layer_1_t* cur, int iter, int win_cnt)
codeworkx62f02ba2012-05-20 12:00:36 +0200307{
308 if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
309 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::is_skip_layer %d cur->handle %x ",
310 __func__, cur->flags & HWC_SKIP_LAYER, cur->handle);
311
312 return HWC_FRAMEBUFFER;
313 }
314
315 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
316 int compositionType = HWC_FRAMEBUFFER;
317
318 if (iter == 0) {
319 /* check here....if we have any resolution constraints */
320 if (((cur->sourceCrop.right - cur->sourceCrop.left + 1) < 16) ||
321 ((cur->sourceCrop.bottom - cur->sourceCrop.top + 1) < 8))
322 return compositionType;
323
324 if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
325 (cur->transform == HAL_TRANSFORM_ROT_270)) {
326 if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 4) ||
327 ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 8))
328 return compositionType;
329 } else if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 8) ||
330 ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 4)) {
331 return compositionType;
332 }
333
334 switch (prev_handle->format) {
335 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
336 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
337 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
338 compositionType = HWC_OVERLAY;
339 break;
340 case HAL_PIXEL_FORMAT_YV12: /* YCrCb_420_P */
341 case HAL_PIXEL_FORMAT_YCbCr_420_P:
342 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
343 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
344 if ((prev_handle->usage & GRALLOC_USAGE_HWC_HWOVERLAY) &&
345 (cur->blending == HWC_BLENDING_NONE))
346 compositionType = HWC_OVERLAY;
347 else
348 compositionType = HWC_FRAMEBUFFER;
349 break;
350 default:
351 compositionType = HWC_FRAMEBUFFER;
352 break;
353 }
354 }
355
codeworkx62f02ba2012-05-20 12:00:36 +0200356 SEC_HWC_Log(HWC_LOG_DEBUG,
357 "%s::compositionType(%d)=>0:FB,1:OVERLAY \r\n"
358 " format(0x%x),magic(0x%x),flags(%d),size(%d),offset(%d)"
359 "b_addr(0x%x),usage(%d),w(%d),h(%d),bpp(%d)",
360 "get_hwc_compos_decision()", compositionType,
361 prev_handle->format, prev_handle->magic, prev_handle->flags,
362 prev_handle->size, prev_handle->offset, prev_handle->base,
363 prev_handle->usage, prev_handle->width, prev_handle->height,
364 prev_handle->bpp);
365
366 return compositionType;
367}
368
369static void reset_win_rect_info(hwc_win_info_t *win)
370{
371 win->rect_info.x = 0;
372 win->rect_info.y = 0;
373 win->rect_info.w = 0;
374 win->rect_info.h = 0;
375 return;
376}
377
378
espenfjo34f9d5d2012-12-01 18:52:36 +0100379static int assign_overlay_window(struct hwc_context_t *ctx, hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +0200380 int win_idx, int layer_idx)
381{
382 struct hwc_win_info_t *win;
383 sec_rect rect;
384 int ret = 0;
385
386 if (NUM_OF_WIN <= win_idx)
387 return -1;
388
389 win = &ctx->win[win_idx];
390
391 SEC_HWC_Log(HWC_LOG_DEBUG,
392 "%s:: left(%d),top(%d),right(%d),bottom(%d),transform(%d)"
393 "lcd_info.xres(%d),lcd_info.yres(%d)",
394 "++assign_overlay_window()",
395 cur->displayFrame.left, cur->displayFrame.top,
396 cur->displayFrame.right, cur->displayFrame.bottom, cur->transform,
397 win->lcd_info.xres, win->lcd_info.yres);
398
399 calculate_rect(win, cur, &rect);
400
401 if ((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
402 (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
403 win->rect_info.x = rect.x;
404 win->rect_info.y = rect.y;
405 win->rect_info.w = rect.w;
406 win->rect_info.h = rect.h;
407 //turnoff the window and set the window position with new conf...
408 if (window_set_pos(win) < 0) {
409 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
410 __func__, strerror(errno));
411 ret = -1;
412 }
413 ctx->layer_prev_buf[win_idx] = 0;
414 }
415
416 win->layer_index = layer_idx;
417 win->status = HWC_WIN_RESERVED;
418
419 SEC_HWC_Log(HWC_LOG_DEBUG,
420 "%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d\n",
421 "--assign_overlay_window()",
422 win->rect_info.x, win->rect_info.y, win->rect_info.w,
423 win->rect_info.h, win->layer_index, win_idx );
424
425 return 0;
426}
427
espenfjo34f9d5d2012-12-01 18:52:36 +0100428#ifdef SKIP_DUMMY_UI_LAY_DRAWING
429static void get_hwc_ui_lay_skipdraw_decision(struct hwc_context_t* ctx,
430 hwc_display_contents_1_t* list)
codeworkx62f02ba2012-05-20 12:00:36 +0200431{
espenfjo34f9d5d2012-12-01 18:52:36 +0100432 private_handle_t *prev_handle;
433 hwc_layer_1_t* cur;
434 int num_of_fb_lay_skip = 0;
435 int fb_lay_tot = ctx->num_of_fb_layer + ctx->num_of_fb_lay_skip;
codeworkx62f02ba2012-05-20 12:00:36 +0200436
espenfjo34f9d5d2012-12-01 18:52:36 +0100437 if (fb_lay_tot > NUM_OF_DUMMY_WIN)
438 return;
439
440 if (fb_lay_tot < 1) {
441#ifdef GL_WA_OVLY_ALL
442 ctx->ui_skip_frame_cnt++;
443 if (ctx->ui_skip_frame_cnt >= THRES_FOR_SWAP) {
444 ctx->ui_skip_frame_cnt = 0;
445 ctx->num_of_fb_layer_prev = 1;
446 }
447#endif
448 return;
449 }
450
451 if (ctx->fb_lay_skip_initialized) {
452 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
453 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
454 if (ctx->win_virt[cnt].layer_prev_buf == (uint32_t)cur->handle)
455 num_of_fb_lay_skip++;
456 }
457#ifdef GL_WA_OVLY_ALL
458 if (ctx->ui_skip_frame_cnt >= THRES_FOR_SWAP)
459 num_of_fb_lay_skip = 0;
460#endif
461 if (num_of_fb_lay_skip != fb_lay_tot) {
462 ctx->num_of_fb_layer = fb_lay_tot;
463 ctx->num_of_fb_lay_skip = 0;
464#ifdef GL_WA_OVLY_ALL
465 ctx->ui_skip_frame_cnt = 0;
466#endif
467 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
468 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
469 ctx->win_virt[cnt].layer_prev_buf = (uint32_t)cur->handle;
470 cur->compositionType = HWC_FRAMEBUFFER;
471 ctx->win_virt[cnt].status = HWC_WIN_FREE;
472 }
473 } else {
474 ctx->num_of_fb_layer = 0;
475 ctx->num_of_fb_lay_skip = fb_lay_tot;
476#ifdef GL_WA_OVLY_ALL
477 ctx->ui_skip_frame_cnt++;
478#endif
479 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
480 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
481 cur->compositionType = HWC_OVERLAY;
482 ctx->win_virt[cnt].status = HWC_WIN_RESERVED;
483 }
484 }
485 } else {
486 ctx->num_of_fb_lay_skip = 0;
487 for (int i = 0; i < list->numHwLayers ; i++) {
488 if(num_of_fb_lay_skip >= NUM_OF_DUMMY_WIN)
489 break;
490
491 cur = &list->hwLayers[i];
492 if (cur->handle) {
493 prev_handle = (private_handle_t *)(cur->handle);
494
495 switch (prev_handle->format) {
496 case HAL_PIXEL_FORMAT_RGBA_8888:
497 case HAL_PIXEL_FORMAT_BGRA_8888:
498 case HAL_PIXEL_FORMAT_RGBX_8888:
499 case HAL_PIXEL_FORMAT_RGB_565:
500 cur->compositionType = HWC_FRAMEBUFFER;
501 ctx->win_virt[num_of_fb_lay_skip].layer_prev_buf =
502 (uint32_t)cur->handle;
503 ctx->win_virt[num_of_fb_lay_skip].layer_index = i;
504 ctx->win_virt[num_of_fb_lay_skip].status = HWC_WIN_FREE;
505 num_of_fb_lay_skip++;
506 break;
507 default:
508 break;
509 }
510 } else {
511 cur->compositionType = HWC_FRAMEBUFFER;
512 }
513 }
514
515 if (num_of_fb_lay_skip == fb_lay_tot)
516 ctx->fb_lay_skip_initialized = 1;
517 }
518
519 return;
520
521}
522#endif
523
524static int hwc_prepare(hwc_composer_device_1_t *dev, size_t numDisplays, hwc_display_contents_1_t** displays)
525{
526
527 for (uint32_t i = 0; i < numDisplays; i++) {
528 hwc_display_contents_1_t *list = displays[i];
529 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
530 int overlay_win_cnt = 0;
531 int compositionType = 0;
532 int ret;
533#if defined(BOARD_USES_HDMI)
534 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
535 int hdmi_cable_status = (int)mHdmiClient->getHdmiCableStatus();
536
537 ctx->hdmi_cable_status = hdmi_cable_status;
538#endif
539
540#ifdef SKIP_DUMMY_UI_LAY_DRAWING
541 if ((list && (!(list->flags & HWC_GEOMETRY_CHANGED))) &&
542 (ctx->num_of_hwc_layer > 0)) {
543 get_hwc_ui_lay_skipdraw_decision(ctx, list);
544 return 0;
545 }
546 ctx->fb_lay_skip_initialized = 0;
547 ctx->num_of_fb_lay_skip = 0;
548#ifdef GL_WA_OVLY_ALL
549 ctx->ui_skip_frame_cnt = 0;
550#endif
551
552 for (int i = 0; i < NUM_OF_DUMMY_WIN; i++) {
553 ctx->win_virt[i].layer_prev_buf = 0;
554 ctx->win_virt[i].layer_index = -1;
555 ctx->win_virt[i].status = HWC_WIN_FREE;
556 }
557#endif
558
559 //if geometry is not changed, there is no need to do any work here
560 if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
codeworkx62f02ba2012-05-20 12:00:36 +0200561 return 0;
562
563 //all the windows are free here....
564 for (int i = 0 ; i < NUM_OF_WIN; i++) {
565 ctx->win[i].status = HWC_WIN_FREE;
566 ctx->win[i].buf_index = 0;
567 }
568
569 ctx->num_of_hwc_layer = 0;
570 ctx->num_of_fb_layer = 0;
571 ctx->num_2d_blit_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100572 ctx->num_of_ext_disp_video_layer = 0;
573
574 for (int i = 0; i < list->numHwLayers; i++) {
575 hwc_layer_1_t *cur = &list->hwLayers[i];
576 private_handle_t *prev_handle = NULL;
577 if (cur->handle) {
578 prev_handle = (private_handle_t *)(cur->handle);
579 SEC_HWC_Log(HWC_LOG_DEBUG, "prev_handle->usage = %d", prev_handle->usage);
580 if (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) {
581 ctx->num_of_ext_disp_layer++;
582 if ((prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
583 check_yuv_format((unsigned int)prev_handle->format) == 1) {
584 ctx->num_of_ext_disp_video_layer++;
585 }
586 }
587 }
588 }
codeworkx62f02ba2012-05-20 12:00:36 +0200589
590 for (int i = 0; i < list->numHwLayers ; i++) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100591 hwc_layer_1_t* cur = &list->hwLayers[i];
592 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
codeworkx62f02ba2012-05-20 12:00:36 +0200593
594 if (overlay_win_cnt < NUM_OF_WIN) {
595 compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt);
596
597 if (compositionType == HWC_FRAMEBUFFER) {
598 cur->compositionType = HWC_FRAMEBUFFER;
599 ctx->num_of_fb_layer++;
600 } else {
601 ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
602 if (ret != 0) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100603 SEC_HWC_Log(HWC_LOG_ERROR, "assign_overlay_window fail, change to frambuffer");
codeworkx62f02ba2012-05-20 12:00:36 +0200604 cur->compositionType = HWC_FRAMEBUFFER;
605 ctx->num_of_fb_layer++;
606 continue;
607 }
608
609 cur->compositionType = HWC_OVERLAY;
610 cur->hints = HWC_HINT_CLEAR_FB;
611 overlay_win_cnt++;
612 ctx->num_of_hwc_layer++;
613 }
614 } else {
615 cur->compositionType = HWC_FRAMEBUFFER;
616 ctx->num_of_fb_layer++;
617 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100618#if defined(BOARD_USES_HDMI)
619 SEC_HWC_Log(HWC_LOG_DEBUG, "ext disp vid = %d, cable status = %d, composition type = %d",
620 ctx->num_of_ext_disp_video_layer, ctx->hdmi_cable_status, compositionType);
621 if (ctx->num_of_ext_disp_video_layer >= 2) {
622 if ((ctx->hdmi_cable_status) &&
623 (compositionType == HWC_OVERLAY) &&
624 (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) {
625 cur->compositionType = HWC_FRAMEBUFFER;
626 ctx->num_of_hwc_layer--;
627 overlay_win_cnt--;
628 ctx->num_of_fb_layer++;
629 cur->hints = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200630 }
631 }
codeworkx62f02ba2012-05-20 12:00:36 +0200632#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100633 }
codeworkx62f02ba2012-05-20 12:00:36 +0200634
635#if defined(BOARD_USES_HDMI)
espenfjo34f9d5d2012-12-01 18:52:36 +0100636 mHdmiClient = android::SecHdmiClient::getInstance();
codeworkx62f02ba2012-05-20 12:00:36 +0200637 mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer);
espenfjo34f9d5d2012-12-01 18:52:36 +0100638 if (ctx->num_of_ext_disp_video_layer > 1) {
639 mHdmiClient->setExtDispLayerNum(0);
640 }
codeworkx62f02ba2012-05-20 12:00:36 +0200641#endif
642
643 if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
644 SEC_HWC_Log(HWC_LOG_DEBUG,
645 "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
646 __func__, list->numHwLayers, ctx->num_of_fb_layer,
647 ctx->num_of_hwc_layer);
648
649 if (overlay_win_cnt < NUM_OF_WIN) {
650 //turn off the free windows
651 for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
652 window_hide(&ctx->win[i]);
653 reset_win_rect_info(&ctx->win[i]);
654 }
655 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100656 }
codeworkx62f02ba2012-05-20 12:00:36 +0200657 return 0;
658}
659
espenfjo34f9d5d2012-12-01 18:52:36 +0100660static int hwc_set(hwc_composer_device_1_t *dev,
661 size_t numDisplays,
662 hwc_display_contents_1_t** displays)
codeworkx62f02ba2012-05-20 12:00:36 +0200663{
664 struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
665 int skipped_window_mask = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100666 hwc_layer_1_t* cur;
codeworkx62f02ba2012-05-20 12:00:36 +0200667 struct hwc_win_info_t *win;
668 int ret;
669 int pmem_phyaddr;
codeworkx62f02ba2012-05-20 12:00:36 +0200670 struct sec_img src_img;
671 struct sec_img dst_img;
672 struct sec_rect src_work_rect;
673 struct sec_rect dst_work_rect;
espenfjo34f9d5d2012-12-01 18:52:36 +0100674 bool need_swap_buffers = ctx->num_of_fb_layer > 0;
675 for (uint32_t i = 0; i < numDisplays; i++) {
676 hwc_display_contents_1_t* list = displays[i];
codeworkx62f02ba2012-05-20 12:00:36 +0200677
678 memset(&src_img, 0, sizeof(src_img));
679 memset(&dst_img, 0, sizeof(dst_img));
680 memset(&src_work_rect, 0, sizeof(src_work_rect));
681 memset(&dst_work_rect, 0, sizeof(dst_work_rect));
682
683#if defined(BOARD_USES_HDMI)
684 int skip_hdmi_rendering = 0;
685 int rotVal = 0;
686#endif
687
688 if (!list) {
689 //turn off the all windows
690 for (int i = 0; i < NUM_OF_WIN; i++) {
691 window_hide(&ctx->win[i]);
692 reset_win_rect_info(&ctx->win[i]);
693 ctx->win[i].status = HWC_WIN_FREE;
694 }
695 ctx->num_of_hwc_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100696 need_swap_buffers = true;
codeworkx62f02ba2012-05-20 12:00:36 +0200697
espenfjo34f9d5d2012-12-01 18:52:36 +0100698 if (list->sur == NULL && list->dpy == NULL) {
699#ifdef SKIP_DUMMY_UI_LAY_DRAWING
700 ctx->fb_lay_skip_initialized = 0;
701#endif
codeworkx62f02ba2012-05-20 12:00:36 +0200702 return HWC_EGL_ERROR;
espenfjo34f9d5d2012-12-01 18:52:36 +0100703 }
codeworkx62f02ba2012-05-20 12:00:36 +0200704 }
705
706 if(ctx->num_of_hwc_layer > NUM_OF_WIN)
707 ctx->num_of_hwc_layer = NUM_OF_WIN;
708
espenfjo34f9d5d2012-12-01 18:52:36 +0100709 /*
710 * H/W composer documentation states:
711 * There is an implicit layer containing opaque black
712 * pixels behind all the layers in the list.
713 * It is the responsibility of the hwcomposer module to make
714 * sure black pixels are output (or blended from).
715 *
716 * Since we're using a blitter, we need to erase the frame-buffer when
717 * switching to all-overlay mode.
718 *
719 */
720 if (ctx->num_of_hwc_layer &&
721 ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
722#ifdef SKIP_DUMMY_UI_LAY_DRAWING
723 if (ctx->num_of_fb_lay_skip == 0)
724#endif
725 {
726 glDisable(GL_SCISSOR_TEST);
727 glClearColor(0, 0, 0, 0);
728 glClear(GL_COLOR_BUFFER_BIT);
729 glEnable(GL_SCISSOR_TEST);
730 need_swap_buffers = true;
731 }
732 }
733 ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
734
codeworkx62f02ba2012-05-20 12:00:36 +0200735 //compose hardware layers here
736 for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) {
737 win = &ctx->win[i];
738 if (win->status == HWC_WIN_RESERVED) {
739 cur = &list->hwLayers[win->layer_index];
740
741 if (cur->compositionType == HWC_OVERLAY) {
742 if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) {
743 /*
744 * In android platform, all the graphic buffer are at least
745 * double buffered (2 or more) this buffer is already rendered.
746 * It is the redundant src buffer for FIMC rendering.
747 */
espenfjo34f9d5d2012-12-01 18:52:36 +0100748
codeworkx62f02ba2012-05-20 12:00:36 +0200749#if defined(BOARD_USES_HDMI)
750 skip_hdmi_rendering = 1;
751#endif
752 continue;
753 }
754 ctx->layer_prev_buf[i] = (uint32_t)cur->handle;
755 // initialize the src & dist context for fimc
756 set_src_dst_img_rect(cur, win, &src_img, &dst_img,
757 &src_work_rect, &dst_work_rect, i);
758
759 ret = runFimc(ctx,
760 &src_img, &src_work_rect,
761 &dst_img, &dst_work_rect,
762 cur->transform);
763
764 if (ret < 0) {
765 SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n",
766 __func__, ret);
767 skipped_window_mask |= (1 << i);
768 continue;
769 }
770
771 window_pan_display(win);
772
773 win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
774 if (win->power_state == 0)
775 window_show(win);
776 } else {
777 SEC_HWC_Log(HWC_LOG_ERROR,
778 "%s:: error : layer %d compositionType should have been"
779 " HWC_OVERLAY ", __func__, win->layer_index);
780 skipped_window_mask |= (1 << i);
781 continue;
782 }
783 } else {
784 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have "
785 "been HWC_WIN_RESERVED by now... ", __func__);
786 skipped_window_mask |= (1 << i);
787 continue;
788 }
789 }
790
codeworkx62f02ba2012-05-20 12:00:36 +0200791 if (skipped_window_mask) {
792 //turn off the free windows
793 for (int i = 0; i < NUM_OF_WIN; i++) {
794 if (skipped_window_mask & (1 << i)) {
795 window_hide(&ctx->win[i]);
796 reset_win_rect_info(&ctx->win[i]);
797 }
798 }
799 }
800
espenfjo34f9d5d2012-12-01 18:52:36 +0100801 if (need_swap_buffers) {
codeworkx62f02ba2012-05-20 12:00:36 +0200802#ifdef CHECK_EGL_FPS
803 check_fps();
804#endif
805#ifdef HWC_HWOVERLAY
806 unsigned char pixels[4];
807 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
808#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100809 EGLBoolean sucess = eglSwapBuffers((EGLDisplay)list->dpy, (EGLSurface)list->sur);
codeworkx62f02ba2012-05-20 12:00:36 +0200810 if (!sucess)
811 return HWC_EGL_ERROR;
812 }
813
814#if defined(BOARD_USES_HDMI)
815 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
816
817 if (skip_hdmi_rendering == 1)
818 return 0;
819
820 if (list == NULL) {
821 // Don't display unnecessary image
822 mHdmiClient->setHdmiEnable(0);
823 return 0;
824 } else {
825 mHdmiClient->setHdmiEnable(1);
826 }
827
828#ifdef SUPPORT_AUTO_UI_ROTATE
829 cur = &list->hwLayers[0];
830
831 if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270)
832 mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
833 else
834 mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
835#endif
836
837 // To support S3D video playback (automatic TV mode change to 3D mode)
838 if (ctx->num_of_hwc_layer == 1) {
839 if (src_img.usage != prev_usage)
espenfjo34f9d5d2012-12-01 18:52:36 +0100840 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200841
842 if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
843 (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100844 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_S3D_SBS_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_S3D_SBS); // V4L2_STD_TVOUT_720P_60_SBS_HALF
codeworkx62f02ba2012-05-20 12:00:36 +0200845 else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
846 (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100847 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_S3D_TB_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_S3D_TB); // V4L2_STD_TVOUT_1080P_24_TB
codeworkx62f02ba2012-05-20 12:00:36 +0200848
849 prev_usage = src_img.usage;
850 } else {
851 if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
852 (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) ||
853 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
854 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100855 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200856
857 prev_usage = 0;
858 }
859
860 if (ctx->num_of_hwc_layer == 1) {
861 if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
862 (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
863 ADDRS * addr = (ADDRS *)(src_img.base);
espenfjo34f9d5d2012-12-01 18:52:36 +0100864 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200865 src_img.format,
866 (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr,
867 0, 0,
868 android::SecHdmiClient::HDMI_MODE_VIDEO,
869 ctx->num_of_hwc_layer);
870 } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
871 (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
872 (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
873 (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100874 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200875 src_img.format,
876 (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
877 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
878 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
879 0, 0,
880 android::SecHdmiClient::HDMI_MODE_VIDEO,
881 ctx->num_of_hwc_layer);
882 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100883 SEC_HWC_Log(HWC_LOG_ERROR, "%s: Unsupported format = %d", __func__, src_img.format);
codeworkx62f02ba2012-05-20 12:00:36 +0200884 }
885 }
886#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100887 }
codeworkx62f02ba2012-05-20 12:00:36 +0200888 return 0;
889}
890
espenfjo34f9d5d2012-12-01 18:52:36 +0100891static void hwc_registerProcs(struct hwc_composer_device_1* dev,
892 hwc_procs_t const* procs)
893{
894 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
895 ctx->procs = const_cast<hwc_procs_t *>(procs);
896}
897
898static int hwc_query(struct hwc_composer_device_1* dev,
899 int what, int* value)
900{
901 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
902
903 switch (what) {
904 case HWC_BACKGROUND_LAYER_SUPPORTED:
905 // we don't support the background layer yet
906 value[0] = 0;
907 break;
908 case HWC_VSYNC_PERIOD:
909 // vsync period in nanosecond
910 value[0] = 1000000000.0 / 57;
911 break;
912 default:
913 // unsupported query
914 return -EINVAL;
915 }
916 return 0;
917}
918
919static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
920 int event, int enabled)
921{
922 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
923
924 switch (event) {
925 case HWC_EVENT_VSYNC:
926 int val = !!enabled;
927 int err = ioctl(ctx->win[0].fd, S3CFB_SET_VSYNC_INT, &val);
928 if (err < 0)
929 return -errno;
930
931 return 0;
932 }
933 return -EINVAL;
934}
935
936
937static void *hwc_vsync_sysfs_loop(void *data)
938{
939 static char buf[4096];
940 int vsync_timestamp_fd;
941 fd_set exceptfds;
942 int res;
943 int64_t timestamp = 0;
944 hwc_context_t * ctx = (hwc_context_t *)(data);
945
946 vsync_timestamp_fd = open("/sys/devices/platform/samsung-pd.2/s3cfb.0/vsync_time", O_RDONLY);
947 char thread_name[64] = "hwcVsyncThread";
948 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
949 setpriority(PRIO_PROCESS, 0, -20);
950 memset(buf, 0, sizeof(buf));
951
952 SEC_HWC_Log(HWC_LOG_DEBUG,"Using sysfs mechanism for VSYNC notification");
953
954 FD_ZERO(&exceptfds);
955 FD_SET(vsync_timestamp_fd, &exceptfds);
956 do {
957 ssize_t len = read(vsync_timestamp_fd, buf, sizeof(buf));
958 timestamp = strtoull(buf, NULL, 0);
959 ctx->procs->vsync(ctx->procs, 0, timestamp);
960 select(vsync_timestamp_fd + 1, NULL, NULL, &exceptfds, NULL);
961 lseek(vsync_timestamp_fd, 0, SEEK_SET);
962 } while (1);
963
964 return NULL;
965}
966
codeworkx62f02ba2012-05-20 12:00:36 +0200967static int hwc_device_close(struct hw_device_t *dev)
968{
969 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
970 int ret = 0;
971 int i;
972 if (ctx) {
973 if (destroyFimc(&ctx->fimc) < 0) {
974 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__);
975 ret = -1;
976 }
codeworkx62f02ba2012-05-20 12:00:36 +0200977
codeworkx62f02ba2012-05-20 12:00:36 +0200978 for (i = 0; i < NUM_OF_WIN; i++) {
979 if (window_close(&ctx->win[i]) < 0)
980 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
981 }
982
983 free(ctx);
984 }
985 return ret;
986}
espenfjo34f9d5d2012-12-01 18:52:36 +0100987static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank)
988{
989 // We're using an older method of screen blanking based on
990 // early_suspend in the kernel. No need to do anything here.
991 return 0;
992}
codeworkx62f02ba2012-05-20 12:00:36 +0200993static int hwc_device_open(const struct hw_module_t* module, const char* name,
994 struct hw_device_t** device)
995{
996 int status = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100997 int err = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200998 struct hwc_win_info_t *win;
999
1000 if (strcmp(name, HWC_HARDWARE_COMPOSER))
1001 return -EINVAL;
1002
1003 struct hwc_context_t *dev;
1004 dev = (hwc_context_t*)malloc(sizeof(*dev));
1005
1006 /* initialize our state here */
1007 memset(dev, 0, sizeof(*dev));
1008
1009 /* initialize the procs */
espenfjo34f9d5d2012-12-01 18:52:36 +01001010 dev->device.common.tag = HARDWARE_DEVICE_TAG;
1011 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
1012 dev->device.common.module = const_cast<hw_module_t*>(module);
1013 dev->device.common.close = hwc_device_close;
1014 dev->device.prepare = hwc_prepare;
1015 dev->device.set = hwc_set;
1016 dev->device.eventControl = hwc_eventControl;
1017 dev->device.blank = hwc_blank;
1018 dev->device.query = hwc_query;
1019 dev->device.registerProcs = hwc_registerProcs;
codeworkx62f02ba2012-05-20 12:00:36 +02001020 *device = &dev->device.common;
1021
1022 //initializing
1023 memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
espenfjo34f9d5d2012-12-01 18:52:36 +01001024
codeworkx62f02ba2012-05-20 12:00:36 +02001025 /* open WIN0 & WIN1 here */
1026 for (int i = 0; i < NUM_OF_WIN; i++) {
1027 if (window_open(&(dev->win[i]), i) < 0) {
1028 SEC_HWC_Log(HWC_LOG_ERROR,
1029 "%s:: Failed to open window %d device ", __func__, i);
1030 status = -EINVAL;
1031 goto err;
1032 }
1033 }
1034
1035 if (window_get_global_lcd_info(dev->win[0].fd, &dev->lcd_info) < 0) {
1036 SEC_HWC_Log(HWC_LOG_ERROR,
1037 "%s::window_get_global_lcd_info is failed : %s",
1038 __func__, strerror(errno));
1039 status = -EINVAL;
1040 goto err;
1041 }
1042
1043#if defined(BOARD_USES_HDMI)
1044 lcd_width = dev->lcd_info.xres;
1045 lcd_height = dev->lcd_info.yres;
1046#endif
1047
1048 /* initialize the window context */
1049 for (int i = 0; i < NUM_OF_WIN; i++) {
1050 win = &dev->win[i];
1051 memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1052 memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1053
1054 win->rect_info.x = 0;
1055 win->rect_info.y = 0;
1056 win->rect_info.w = win->var_info.xres;
1057 win->rect_info.h = win->var_info.yres;
1058
1059 if (window_set_pos(win) < 0) {
1060 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
1061 __func__, strerror(errno));
1062 status = -EINVAL;
1063 goto err;
1064 }
1065
1066 if (window_get_info(win, i) < 0) {
1067 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s",
1068 __func__, strerror(errno));
1069 status = -EINVAL;
1070 goto err;
1071 }
1072
1073 }
1074
codeworkx62f02ba2012-05-20 12:00:36 +02001075 //create PP
1076 if (createFimc(&dev->fimc) < 0) {
1077 SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__);
1078 status = -EINVAL;
1079 goto err;
1080 }
1081
espenfjo34f9d5d2012-12-01 18:52:36 +01001082 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_sysfs_loop, dev);
1083 if (err) {
1084 SEC_HWC_Log(HWC_LOG_ERROR, "%s::pthread_create() failed : %s", __func__, strerror(err));
1085 status = -err;
codeworkx62f02ba2012-05-20 12:00:36 +02001086 goto err;
1087 }
codeworkx62f02ba2012-05-20 12:00:36 +02001088
1089 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__);
1090
1091 return 0;
1092
1093err:
1094 if (destroyFimc(&dev->fimc) < 0)
1095 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001096
1097 for (int i = 0; i < NUM_OF_WIN; i++) {
1098 if (window_close(&dev->win[i]) < 0)
1099 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1100 }
1101
1102 return status;
1103}