blob: 9f32226e71913c9be91d0732e808a94f72cea30e [file] [log] [blame]
codeworkx62f02ba2012-05-20 12:00:36 +02001/*
2 * Copyright (C) 2010 The Android Open Source Project
codeworkxabfed772012-12-01 19:37:39 +01003 * Copyright (C) 2012 The CyanogenMod Project <http://www.cyanogenmod.org>
codeworkx62f02ba2012-05-20 12:00:36 +02004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 *
20 * @author Rama, Meka(v.meka@samsung.com)
21 Sangwoo, Park(sw5771.park@samsung.com)
22 Jamie Oh (jung-min.oh@samsung.com)
23 * @date 2011-03-11
24 *
25 */
26
27#include <cutils/log.h>
28#include <cutils/atomic.h>
29
30#include <EGL/egl.h>
espenfjo34f9d5d2012-12-01 18:52:36 +010031#include <fcntl.h>
codeworkxabfed772012-12-01 19:37:39 +010032#include <hardware_legacy/uevent.h>
33#include <sys/prctl.h>
34#include <sys/resource.h>
codeworkx62f02ba2012-05-20 12:00:36 +020035
36#include "SecHWCUtils.h"
37
38#include "gralloc_priv.h"
39#ifdef HWC_HWOVERLAY
40#include <GLES/gl.h>
41#endif
42#if defined(BOARD_USES_HDMI)
43#include "SecHdmiClient.h"
44#include "SecTVOutService.h"
45
46#include "SecHdmi.h"
47
48//#define CHECK_EGL_FPS
49#ifdef CHECK_EGL_FPS
50extern void check_fps();
51#endif
52
53static int lcd_width, lcd_height;
54static int prev_usage = 0;
55
56#define CHECK_TIME_DEBUG 0
57#define SUPPORT_AUTO_UI_ROTATE
58#endif
59int testRenderNum =0;
60
61static int hwc_device_open(const struct hw_module_t* module, const char* name,
62 struct hw_device_t** device);
63
64static struct hw_module_methods_t hwc_module_methods = {
65 open: hwc_device_open
66};
67
68hwc_module_t HAL_MODULE_INFO_SYM = {
69 common: {
70 tag: HARDWARE_MODULE_TAG,
espenfjo34f9d5d2012-12-01 18:52:36 +010071 version_major: 2,
codeworkx62f02ba2012-05-20 12:00:36 +020072 version_minor: 0,
73 id: HWC_HARDWARE_MODULE_ID,
74 name: "Samsung S5PC21X hwcomposer module",
75 author: "SAMSUNG",
76 methods: &hwc_module_methods,
77 }
78};
79
80/*****************************************************************************/
81
espenfjo34f9d5d2012-12-01 18:52:36 +010082static void dump_layer(hwc_layer_1_t const* l) {
83 SEC_HWC_Log(HWC_LOG_DEBUG,"\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, "
codeworkx62f02ba2012-05-20 12:00:36 +020084 "{%d,%d,%d,%d}, {%d,%d,%d,%d}",
85 l->compositionType, l->flags, l->handle, l->transform, l->blending,
86 l->sourceCrop.left,
87 l->sourceCrop.top,
88 l->sourceCrop.right,
89 l->sourceCrop.bottom,
90 l->displayFrame.left,
91 l->displayFrame.top,
92 l->displayFrame.right,
93 l->displayFrame.bottom);
94}
95
espenfjo34f9d5d2012-12-01 18:52:36 +010096void calculate_rect(struct hwc_win_info_t *win, hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +020097 sec_rect *rect)
98{
99 rect->x = cur->displayFrame.left;
100 rect->y = cur->displayFrame.top;
101 rect->w = cur->displayFrame.right - cur->displayFrame.left;
102 rect->h = cur->displayFrame.bottom - cur->displayFrame.top;
103
104 if (rect->x < 0) {
105 if (rect->w + rect->x > win->lcd_info.xres)
106 rect->w = win->lcd_info.xres;
107 else
108 rect->w = rect->w + rect->x;
109 rect->x = 0;
110 } else {
111 if (rect->w + rect->x > win->lcd_info.xres)
112 rect->w = win->lcd_info.xres - rect->x;
113 }
114 if (rect->y < 0) {
115 if (rect->h + rect->y > win->lcd_info.yres)
116 rect->h = win->lcd_info.yres;
117 else
118 rect->h = rect->h + rect->y;
119 rect->y = 0;
120 } else {
121 if (rect->h + rect->y > win->lcd_info.yres)
122 rect->h = win->lcd_info.yres - rect->y;
123 }
124}
125
espenfjo34f9d5d2012-12-01 18:52:36 +0100126static int set_src_dst_img_rect(hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +0200127 struct hwc_win_info_t *win,
128 struct sec_img *src_img,
129 struct sec_img *dst_img,
130 struct sec_rect *src_rect,
131 struct sec_rect *dst_rect,
132 int win_idx)
133{
134 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
135 sec_rect rect;
136
137 /* 1. Set src_img from prev_handle */
138 src_img->f_w = prev_handle->width;
139 src_img->f_h = prev_handle->height;
140 src_img->w = prev_handle->width;
141 src_img->h = prev_handle->height;
142 src_img->format = prev_handle->format;
143 src_img->base = (uint32_t)prev_handle->base;
144 src_img->offset = prev_handle->offset;
145 src_img->mem_id = prev_handle->fd;
146 src_img->paddr = prev_handle->paddr;
147 src_img->usage = prev_handle->usage;
148 src_img->uoffset = prev_handle->uoffset;
149 src_img->voffset = prev_handle->voffset;
150
151 src_img->mem_type = HWC_VIRT_MEM_TYPE;
152
153 switch (src_img->format) {
154 case HAL_PIXEL_FORMAT_YV12: /* To support video editor */
155 case HAL_PIXEL_FORMAT_YCbCr_420_P: /* To support SW codec */
156 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
157 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
158 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
159 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
160 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
161 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_SP:
162 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_SP:
163 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_422_I:
164 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_422_I:
165 case HAL_PIXEL_FORMAT_CUSTOM_CbYCrY_422_I:
166 case HAL_PIXEL_FORMAT_CUSTOM_CrYCbY_422_I:
167 src_img->f_w = (src_img->f_w + 15) & ~15;
168 src_img->f_h = (src_img->f_h + 1) & ~1;
169 break;
170 default:
171 src_img->f_w = src_img->w;
172 src_img->f_h = src_img->h;
173 break;
174 }
175
176 /* 2. Set dst_img from window(lcd) */
177 calculate_rect(win, cur, &rect);
178 dst_img->f_w = win->lcd_info.xres;
179 dst_img->f_h = win->lcd_info.yres;
180 dst_img->w = rect.w;
181 dst_img->h = rect.h;
182
183 switch (win->lcd_info.bits_per_pixel) {
184 case 32:
185 dst_img->format = HAL_PIXEL_FORMAT_RGBX_8888;
186 break;
187 default:
188 dst_img->format = HAL_PIXEL_FORMAT_RGB_565;
189 break;
190 }
191
192 dst_img->base = win->addr[win->buf_index];
193 dst_img->offset = 0;
194 dst_img->mem_id = 0;
195 dst_img->mem_type = HWC_PHYS_MEM_TYPE;
196
197 /* 3. Set src_rect(crop rect) */
198 if (cur->displayFrame.left < 0) {
199 src_rect->x =
200 (0 - cur->displayFrame.left)
201 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100202 /(cur->displayFrame.right - cur->displayFrame.left);
203 if (cur->displayFrame.right > win->lcd_info.xres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200204 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100205 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200206 src_rect->x -
207 (cur->displayFrame.right - win->lcd_info.xres)
208 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100209 /(cur->displayFrame.right - cur->displayFrame.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200210 } else {
211 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100212 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200213 src_rect->x;
214 }
215 } else {
216 src_rect->x = cur->sourceCrop.left;
espenfjo34f9d5d2012-12-01 18:52:36 +0100217 if (cur->displayFrame.right > win->lcd_info.xres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200218 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100219 (cur->sourceCrop.right - cur->sourceCrop.left) -
codeworkx62f02ba2012-05-20 12:00:36 +0200220 src_rect->x -
221 (cur->displayFrame.right - win->lcd_info.xres)
222 *(src_img->w)
espenfjo34f9d5d2012-12-01 18:52:36 +0100223 /(cur->displayFrame.right - cur->displayFrame.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200224 } else {
225 src_rect->w =
espenfjo34f9d5d2012-12-01 18:52:36 +0100226 (cur->sourceCrop.right - cur->sourceCrop.left);
codeworkx62f02ba2012-05-20 12:00:36 +0200227 }
228 }
229 if (cur->displayFrame.top < 0) {
230 src_rect->y =
231 (0 - cur->displayFrame.top)
232 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100233 /(cur->displayFrame.bottom - cur->displayFrame.top);
234 if (cur->displayFrame.bottom > win->lcd_info.yres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200235 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100236 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200237 src_rect->y -
238 (cur->displayFrame.bottom - win->lcd_info.yres)
239 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100240 /(cur->displayFrame.bottom - cur->displayFrame.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200241 } else {
242 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100243 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200244 src_rect->y;
245 }
246 } else {
247 src_rect->y = cur->sourceCrop.top;
espenfjo34f9d5d2012-12-01 18:52:36 +0100248 if (cur->displayFrame.bottom > win->lcd_info.yres) {
codeworkx62f02ba2012-05-20 12:00:36 +0200249 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100250 (cur->sourceCrop.bottom - cur->sourceCrop.top) -
codeworkx62f02ba2012-05-20 12:00:36 +0200251 src_rect->y -
252 (cur->displayFrame.bottom - win->lcd_info.yres)
253 *(src_img->h)
espenfjo34f9d5d2012-12-01 18:52:36 +0100254 /(cur->displayFrame.bottom - cur->displayFrame.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200255 } else {
256 src_rect->h =
espenfjo34f9d5d2012-12-01 18:52:36 +0100257 (cur->sourceCrop.bottom - cur->sourceCrop.top);
codeworkx62f02ba2012-05-20 12:00:36 +0200258 }
259 }
260
261 SEC_HWC_Log(HWC_LOG_DEBUG,
262 "crop information()::"
263 "sourceCrop left(%d),top(%d),right(%d),bottom(%d),"
264 "src_rect x(%d),y(%d),w(%d),h(%d),"
265 "prev_handle w(%d),h(%d)",
266 cur->sourceCrop.left,
267 cur->sourceCrop.top,
268 cur->sourceCrop.right,
269 cur->sourceCrop.bottom,
270 src_rect->x, src_rect->y, src_rect->w, src_rect->h,
271 prev_handle->width, prev_handle->height);
272
273 src_rect->x = SEC_MAX(src_rect->x, 0);
274 src_rect->y = SEC_MAX(src_rect->y, 0);
275 src_rect->w = SEC_MAX(src_rect->w, 0);
276 src_rect->w = SEC_MIN(src_rect->w, prev_handle->width);
277 src_rect->h = SEC_MAX(src_rect->h, 0);
278 src_rect->h = SEC_MIN(src_rect->h, prev_handle->height);
279
280 /* 4. Set dst_rect(fb or lcd)
281 * fimc dst image will be stored from left top corner
282 */
283 dst_rect->x = 0;
284 dst_rect->y = 0;
285 dst_rect->w = win->rect_info.w;
286 dst_rect->h = win->rect_info.h;
287
288 /* Summery */
289 SEC_HWC_Log(HWC_LOG_DEBUG,
290 "set_src_dst_img_rect()::"
291 "SRC w(%d),h(%d),f_w(%d),f_h(%d),fmt(0x%x),"
292 "base(0x%x),offset(%d),paddr(0x%X),mem_id(%d),mem_type(%d)=>\r\n"
293 " DST w(%d),h(%d),f(0x%x),base(0x%x),"
294 "offset(%d),mem_id(%d),mem_type(%d),"
295 "rot(%d),win_idx(%d)"
296 " SRC_RECT x(%d),y(%d),w(%d),h(%d)=>"
297 "DST_RECT x(%d),y(%d),w(%d),h(%d)",
298 src_img->w, src_img->h, src_img->f_w, src_img->f_h, src_img->format,
299 src_img->base, src_img->offset, src_img->paddr, src_img->mem_id, src_img->mem_type,
300 dst_img->w, dst_img->h, dst_img->format, dst_img->base,
301 dst_img->offset, dst_img->mem_id, dst_img->mem_type,
302 cur->transform, win_idx,
303 src_rect->x, src_rect->y, src_rect->w, src_rect->h,
304 dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
305
306 return 0;
307}
308
espenfjo34f9d5d2012-12-01 18:52:36 +0100309static int get_hwc_compos_decision(hwc_layer_1_t* cur, int iter, int win_cnt)
codeworkx62f02ba2012-05-20 12:00:36 +0200310{
311 if(cur->flags & HWC_SKIP_LAYER || !cur->handle) {
312 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::is_skip_layer %d cur->handle %x ",
313 __func__, cur->flags & HWC_SKIP_LAYER, cur->handle);
314
315 return HWC_FRAMEBUFFER;
316 }
317
318 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
319 int compositionType = HWC_FRAMEBUFFER;
320
321 if (iter == 0) {
322 /* check here....if we have any resolution constraints */
323 if (((cur->sourceCrop.right - cur->sourceCrop.left + 1) < 16) ||
324 ((cur->sourceCrop.bottom - cur->sourceCrop.top + 1) < 8))
325 return compositionType;
326
327 if ((cur->transform == HAL_TRANSFORM_ROT_90) ||
328 (cur->transform == HAL_TRANSFORM_ROT_270)) {
329 if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 4) ||
330 ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 8))
331 return compositionType;
332 } else if (((cur->displayFrame.right - cur->displayFrame.left + 1) < 8) ||
333 ((cur->displayFrame.bottom - cur->displayFrame.top + 1) < 4)) {
334 return compositionType;
335 }
336
337 switch (prev_handle->format) {
338 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP:
339 case HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP:
340 case HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED:
341 compositionType = HWC_OVERLAY;
342 break;
343 case HAL_PIXEL_FORMAT_YV12: /* YCrCb_420_P */
344 case HAL_PIXEL_FORMAT_YCbCr_420_P:
345 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
346 case HAL_PIXEL_FORMAT_YCbCr_420_SP:
347 if ((prev_handle->usage & GRALLOC_USAGE_HWC_HWOVERLAY) &&
348 (cur->blending == HWC_BLENDING_NONE))
349 compositionType = HWC_OVERLAY;
350 else
351 compositionType = HWC_FRAMEBUFFER;
352 break;
353 default:
354 compositionType = HWC_FRAMEBUFFER;
355 break;
356 }
357 }
358
codeworkx62f02ba2012-05-20 12:00:36 +0200359 SEC_HWC_Log(HWC_LOG_DEBUG,
360 "%s::compositionType(%d)=>0:FB,1:OVERLAY \r\n"
361 " format(0x%x),magic(0x%x),flags(%d),size(%d),offset(%d)"
362 "b_addr(0x%x),usage(%d),w(%d),h(%d),bpp(%d)",
363 "get_hwc_compos_decision()", compositionType,
364 prev_handle->format, prev_handle->magic, prev_handle->flags,
365 prev_handle->size, prev_handle->offset, prev_handle->base,
366 prev_handle->usage, prev_handle->width, prev_handle->height,
367 prev_handle->bpp);
368
369 return compositionType;
370}
371
372static void reset_win_rect_info(hwc_win_info_t *win)
373{
374 win->rect_info.x = 0;
375 win->rect_info.y = 0;
376 win->rect_info.w = 0;
377 win->rect_info.h = 0;
378 return;
379}
380
381
espenfjo34f9d5d2012-12-01 18:52:36 +0100382static int assign_overlay_window(struct hwc_context_t *ctx, hwc_layer_1_t *cur,
codeworkx62f02ba2012-05-20 12:00:36 +0200383 int win_idx, int layer_idx)
384{
385 struct hwc_win_info_t *win;
386 sec_rect rect;
387 int ret = 0;
388
389 if (NUM_OF_WIN <= win_idx)
390 return -1;
391
392 win = &ctx->win[win_idx];
393
394 SEC_HWC_Log(HWC_LOG_DEBUG,
395 "%s:: left(%d),top(%d),right(%d),bottom(%d),transform(%d)"
396 "lcd_info.xres(%d),lcd_info.yres(%d)",
397 "++assign_overlay_window()",
398 cur->displayFrame.left, cur->displayFrame.top,
399 cur->displayFrame.right, cur->displayFrame.bottom, cur->transform,
400 win->lcd_info.xres, win->lcd_info.yres);
401
402 calculate_rect(win, cur, &rect);
403
404 if ((rect.x != win->rect_info.x) || (rect.y != win->rect_info.y) ||
405 (rect.w != win->rect_info.w) || (rect.h != win->rect_info.h)){
406 win->rect_info.x = rect.x;
407 win->rect_info.y = rect.y;
408 win->rect_info.w = rect.w;
409 win->rect_info.h = rect.h;
410 //turnoff the window and set the window position with new conf...
411 if (window_set_pos(win) < 0) {
412 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
413 __func__, strerror(errno));
414 ret = -1;
415 }
416 ctx->layer_prev_buf[win_idx] = 0;
417 }
418
419 win->layer_index = layer_idx;
420 win->status = HWC_WIN_RESERVED;
421
422 SEC_HWC_Log(HWC_LOG_DEBUG,
423 "%s:: win_x %d win_y %d win_w %d win_h %d lay_idx %d win_idx %d\n",
424 "--assign_overlay_window()",
425 win->rect_info.x, win->rect_info.y, win->rect_info.w,
426 win->rect_info.h, win->layer_index, win_idx );
427
428 return 0;
429}
430
espenfjo34f9d5d2012-12-01 18:52:36 +0100431#ifdef SKIP_DUMMY_UI_LAY_DRAWING
432static void get_hwc_ui_lay_skipdraw_decision(struct hwc_context_t* ctx,
433 hwc_display_contents_1_t* list)
codeworkx62f02ba2012-05-20 12:00:36 +0200434{
espenfjo34f9d5d2012-12-01 18:52:36 +0100435 private_handle_t *prev_handle;
436 hwc_layer_1_t* cur;
437 int num_of_fb_lay_skip = 0;
438 int fb_lay_tot = ctx->num_of_fb_layer + ctx->num_of_fb_lay_skip;
codeworkx62f02ba2012-05-20 12:00:36 +0200439
espenfjo34f9d5d2012-12-01 18:52:36 +0100440 if (fb_lay_tot > NUM_OF_DUMMY_WIN)
441 return;
442
443 if (fb_lay_tot < 1) {
444#ifdef GL_WA_OVLY_ALL
445 ctx->ui_skip_frame_cnt++;
446 if (ctx->ui_skip_frame_cnt >= THRES_FOR_SWAP) {
447 ctx->ui_skip_frame_cnt = 0;
448 ctx->num_of_fb_layer_prev = 1;
449 }
450#endif
451 return;
452 }
453
454 if (ctx->fb_lay_skip_initialized) {
455 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
456 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
457 if (ctx->win_virt[cnt].layer_prev_buf == (uint32_t)cur->handle)
458 num_of_fb_lay_skip++;
459 }
460#ifdef GL_WA_OVLY_ALL
461 if (ctx->ui_skip_frame_cnt >= THRES_FOR_SWAP)
462 num_of_fb_lay_skip = 0;
463#endif
464 if (num_of_fb_lay_skip != fb_lay_tot) {
465 ctx->num_of_fb_layer = fb_lay_tot;
466 ctx->num_of_fb_lay_skip = 0;
467#ifdef GL_WA_OVLY_ALL
468 ctx->ui_skip_frame_cnt = 0;
469#endif
470 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
471 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
472 ctx->win_virt[cnt].layer_prev_buf = (uint32_t)cur->handle;
473 cur->compositionType = HWC_FRAMEBUFFER;
474 ctx->win_virt[cnt].status = HWC_WIN_FREE;
475 }
476 } else {
477 ctx->num_of_fb_layer = 0;
478 ctx->num_of_fb_lay_skip = fb_lay_tot;
479#ifdef GL_WA_OVLY_ALL
480 ctx->ui_skip_frame_cnt++;
481#endif
482 for (int cnt = 0; cnt < fb_lay_tot; cnt++) {
483 cur = &list->hwLayers[ctx->win_virt[cnt].layer_index];
484 cur->compositionType = HWC_OVERLAY;
485 ctx->win_virt[cnt].status = HWC_WIN_RESERVED;
486 }
487 }
488 } else {
489 ctx->num_of_fb_lay_skip = 0;
490 for (int i = 0; i < list->numHwLayers ; i++) {
491 if(num_of_fb_lay_skip >= NUM_OF_DUMMY_WIN)
492 break;
493
494 cur = &list->hwLayers[i];
495 if (cur->handle) {
496 prev_handle = (private_handle_t *)(cur->handle);
497
498 switch (prev_handle->format) {
499 case HAL_PIXEL_FORMAT_RGBA_8888:
500 case HAL_PIXEL_FORMAT_BGRA_8888:
501 case HAL_PIXEL_FORMAT_RGBX_8888:
502 case HAL_PIXEL_FORMAT_RGB_565:
503 cur->compositionType = HWC_FRAMEBUFFER;
504 ctx->win_virt[num_of_fb_lay_skip].layer_prev_buf =
505 (uint32_t)cur->handle;
506 ctx->win_virt[num_of_fb_lay_skip].layer_index = i;
507 ctx->win_virt[num_of_fb_lay_skip].status = HWC_WIN_FREE;
508 num_of_fb_lay_skip++;
509 break;
510 default:
511 break;
512 }
513 } else {
514 cur->compositionType = HWC_FRAMEBUFFER;
515 }
516 }
517
518 if (num_of_fb_lay_skip == fb_lay_tot)
519 ctx->fb_lay_skip_initialized = 1;
520 }
521
522 return;
523
524}
525#endif
526
527static int hwc_prepare(hwc_composer_device_1_t *dev, size_t numDisplays, hwc_display_contents_1_t** displays)
528{
529
530 for (uint32_t i = 0; i < numDisplays; i++) {
531 hwc_display_contents_1_t *list = displays[i];
532 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
533 int overlay_win_cnt = 0;
534 int compositionType = 0;
535 int ret;
536#if defined(BOARD_USES_HDMI)
537 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
538 int hdmi_cable_status = (int)mHdmiClient->getHdmiCableStatus();
539
540 ctx->hdmi_cable_status = hdmi_cable_status;
541#endif
542
543#ifdef SKIP_DUMMY_UI_LAY_DRAWING
544 if ((list && (!(list->flags & HWC_GEOMETRY_CHANGED))) &&
545 (ctx->num_of_hwc_layer > 0)) {
546 get_hwc_ui_lay_skipdraw_decision(ctx, list);
547 return 0;
548 }
549 ctx->fb_lay_skip_initialized = 0;
550 ctx->num_of_fb_lay_skip = 0;
551#ifdef GL_WA_OVLY_ALL
552 ctx->ui_skip_frame_cnt = 0;
553#endif
554
555 for (int i = 0; i < NUM_OF_DUMMY_WIN; i++) {
556 ctx->win_virt[i].layer_prev_buf = 0;
557 ctx->win_virt[i].layer_index = -1;
558 ctx->win_virt[i].status = HWC_WIN_FREE;
559 }
560#endif
561
562 //if geometry is not changed, there is no need to do any work here
563 if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
codeworkx62f02ba2012-05-20 12:00:36 +0200564 return 0;
565
566 //all the windows are free here....
567 for (int i = 0 ; i < NUM_OF_WIN; i++) {
568 ctx->win[i].status = HWC_WIN_FREE;
569 ctx->win[i].buf_index = 0;
570 }
571
572 ctx->num_of_hwc_layer = 0;
573 ctx->num_of_fb_layer = 0;
574 ctx->num_2d_blit_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100575 ctx->num_of_ext_disp_video_layer = 0;
576
577 for (int i = 0; i < list->numHwLayers; i++) {
578 hwc_layer_1_t *cur = &list->hwLayers[i];
579 private_handle_t *prev_handle = NULL;
580 if (cur->handle) {
581 prev_handle = (private_handle_t *)(cur->handle);
582 SEC_HWC_Log(HWC_LOG_DEBUG, "prev_handle->usage = %d", prev_handle->usage);
583 if (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) {
584 ctx->num_of_ext_disp_layer++;
585 if ((prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
586 check_yuv_format((unsigned int)prev_handle->format) == 1) {
587 ctx->num_of_ext_disp_video_layer++;
588 }
589 }
590 }
591 }
codeworkx62f02ba2012-05-20 12:00:36 +0200592
593 for (int i = 0; i < list->numHwLayers ; i++) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100594 hwc_layer_1_t* cur = &list->hwLayers[i];
595 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
codeworkx62f02ba2012-05-20 12:00:36 +0200596
597 if (overlay_win_cnt < NUM_OF_WIN) {
598 compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt);
599
600 if (compositionType == HWC_FRAMEBUFFER) {
601 cur->compositionType = HWC_FRAMEBUFFER;
602 ctx->num_of_fb_layer++;
603 } else {
604 ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
605 if (ret != 0) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100606 SEC_HWC_Log(HWC_LOG_ERROR, "assign_overlay_window fail, change to frambuffer");
codeworkx62f02ba2012-05-20 12:00:36 +0200607 cur->compositionType = HWC_FRAMEBUFFER;
608 ctx->num_of_fb_layer++;
609 continue;
610 }
611
612 cur->compositionType = HWC_OVERLAY;
613 cur->hints = HWC_HINT_CLEAR_FB;
614 overlay_win_cnt++;
615 ctx->num_of_hwc_layer++;
616 }
617 } else {
618 cur->compositionType = HWC_FRAMEBUFFER;
619 ctx->num_of_fb_layer++;
620 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100621#if defined(BOARD_USES_HDMI)
622 SEC_HWC_Log(HWC_LOG_DEBUG, "ext disp vid = %d, cable status = %d, composition type = %d",
623 ctx->num_of_ext_disp_video_layer, ctx->hdmi_cable_status, compositionType);
624 if (ctx->num_of_ext_disp_video_layer >= 2) {
625 if ((ctx->hdmi_cable_status) &&
626 (compositionType == HWC_OVERLAY) &&
627 (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) {
628 cur->compositionType = HWC_FRAMEBUFFER;
629 ctx->num_of_hwc_layer--;
630 overlay_win_cnt--;
631 ctx->num_of_fb_layer++;
632 cur->hints = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200633 }
634 }
codeworkx62f02ba2012-05-20 12:00:36 +0200635#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100636 }
codeworkx62f02ba2012-05-20 12:00:36 +0200637
638#if defined(BOARD_USES_HDMI)
espenfjo34f9d5d2012-12-01 18:52:36 +0100639 mHdmiClient = android::SecHdmiClient::getInstance();
codeworkx62f02ba2012-05-20 12:00:36 +0200640 mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer);
espenfjo34f9d5d2012-12-01 18:52:36 +0100641 if (ctx->num_of_ext_disp_video_layer > 1) {
642 mHdmiClient->setExtDispLayerNum(0);
643 }
codeworkx62f02ba2012-05-20 12:00:36 +0200644#endif
645
646 if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
647 SEC_HWC_Log(HWC_LOG_DEBUG,
648 "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
649 __func__, list->numHwLayers, ctx->num_of_fb_layer,
650 ctx->num_of_hwc_layer);
651
652 if (overlay_win_cnt < NUM_OF_WIN) {
653 //turn off the free windows
654 for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
655 window_hide(&ctx->win[i]);
656 reset_win_rect_info(&ctx->win[i]);
657 }
658 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100659 }
codeworkx62f02ba2012-05-20 12:00:36 +0200660 return 0;
661}
662
espenfjo34f9d5d2012-12-01 18:52:36 +0100663static int hwc_set(hwc_composer_device_1_t *dev,
664 size_t numDisplays,
665 hwc_display_contents_1_t** displays)
codeworkx62f02ba2012-05-20 12:00:36 +0200666{
667 struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
668 int skipped_window_mask = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100669 hwc_layer_1_t* cur;
codeworkx62f02ba2012-05-20 12:00:36 +0200670 struct hwc_win_info_t *win;
671 int ret;
672 int pmem_phyaddr;
codeworkx62f02ba2012-05-20 12:00:36 +0200673 struct sec_img src_img;
674 struct sec_img dst_img;
675 struct sec_rect src_work_rect;
676 struct sec_rect dst_work_rect;
espenfjo34f9d5d2012-12-01 18:52:36 +0100677 bool need_swap_buffers = ctx->num_of_fb_layer > 0;
678 for (uint32_t i = 0; i < numDisplays; i++) {
679 hwc_display_contents_1_t* list = displays[i];
codeworkx62f02ba2012-05-20 12:00:36 +0200680
681 memset(&src_img, 0, sizeof(src_img));
682 memset(&dst_img, 0, sizeof(dst_img));
683 memset(&src_work_rect, 0, sizeof(src_work_rect));
684 memset(&dst_work_rect, 0, sizeof(dst_work_rect));
685
686#if defined(BOARD_USES_HDMI)
687 int skip_hdmi_rendering = 0;
688 int rotVal = 0;
689#endif
690
691 if (!list) {
692 //turn off the all windows
693 for (int i = 0; i < NUM_OF_WIN; i++) {
694 window_hide(&ctx->win[i]);
695 reset_win_rect_info(&ctx->win[i]);
696 ctx->win[i].status = HWC_WIN_FREE;
697 }
698 ctx->num_of_hwc_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100699 need_swap_buffers = true;
codeworkx62f02ba2012-05-20 12:00:36 +0200700
espenfjo34f9d5d2012-12-01 18:52:36 +0100701 if (list->sur == NULL && list->dpy == NULL) {
702#ifdef SKIP_DUMMY_UI_LAY_DRAWING
703 ctx->fb_lay_skip_initialized = 0;
704#endif
codeworkx62f02ba2012-05-20 12:00:36 +0200705 return HWC_EGL_ERROR;
espenfjo34f9d5d2012-12-01 18:52:36 +0100706 }
codeworkx62f02ba2012-05-20 12:00:36 +0200707 }
708
709 if(ctx->num_of_hwc_layer > NUM_OF_WIN)
710 ctx->num_of_hwc_layer = NUM_OF_WIN;
711
espenfjo34f9d5d2012-12-01 18:52:36 +0100712 /*
713 * H/W composer documentation states:
714 * There is an implicit layer containing opaque black
715 * pixels behind all the layers in the list.
716 * It is the responsibility of the hwcomposer module to make
717 * sure black pixels are output (or blended from).
718 *
719 * Since we're using a blitter, we need to erase the frame-buffer when
720 * switching to all-overlay mode.
721 *
722 */
723 if (ctx->num_of_hwc_layer &&
724 ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
725#ifdef SKIP_DUMMY_UI_LAY_DRAWING
726 if (ctx->num_of_fb_lay_skip == 0)
727#endif
728 {
729 glDisable(GL_SCISSOR_TEST);
730 glClearColor(0, 0, 0, 0);
731 glClear(GL_COLOR_BUFFER_BIT);
732 glEnable(GL_SCISSOR_TEST);
733 need_swap_buffers = true;
734 }
735 }
736 ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
737
codeworkx62f02ba2012-05-20 12:00:36 +0200738 //compose hardware layers here
739 for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) {
740 win = &ctx->win[i];
741 if (win->status == HWC_WIN_RESERVED) {
742 cur = &list->hwLayers[win->layer_index];
743
744 if (cur->compositionType == HWC_OVERLAY) {
745 if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) {
746 /*
747 * In android platform, all the graphic buffer are at least
748 * double buffered (2 or more) this buffer is already rendered.
749 * It is the redundant src buffer for FIMC rendering.
750 */
espenfjo34f9d5d2012-12-01 18:52:36 +0100751
codeworkx62f02ba2012-05-20 12:00:36 +0200752#if defined(BOARD_USES_HDMI)
753 skip_hdmi_rendering = 1;
754#endif
755 continue;
756 }
757 ctx->layer_prev_buf[i] = (uint32_t)cur->handle;
758 // initialize the src & dist context for fimc
759 set_src_dst_img_rect(cur, win, &src_img, &dst_img,
760 &src_work_rect, &dst_work_rect, i);
761
762 ret = runFimc(ctx,
763 &src_img, &src_work_rect,
764 &dst_img, &dst_work_rect,
765 cur->transform);
766
767 if (ret < 0) {
768 SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n",
769 __func__, ret);
770 skipped_window_mask |= (1 << i);
771 continue;
772 }
773
774 window_pan_display(win);
775
776 win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
777 if (win->power_state == 0)
778 window_show(win);
779 } else {
780 SEC_HWC_Log(HWC_LOG_ERROR,
781 "%s:: error : layer %d compositionType should have been"
782 " HWC_OVERLAY ", __func__, win->layer_index);
783 skipped_window_mask |= (1 << i);
784 continue;
785 }
786 } else {
787 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have "
788 "been HWC_WIN_RESERVED by now... ", __func__);
789 skipped_window_mask |= (1 << i);
790 continue;
791 }
792 }
793
codeworkx62f02ba2012-05-20 12:00:36 +0200794 if (skipped_window_mask) {
795 //turn off the free windows
796 for (int i = 0; i < NUM_OF_WIN; i++) {
797 if (skipped_window_mask & (1 << i)) {
798 window_hide(&ctx->win[i]);
799 reset_win_rect_info(&ctx->win[i]);
800 }
801 }
802 }
803
espenfjo34f9d5d2012-12-01 18:52:36 +0100804 if (need_swap_buffers) {
codeworkx62f02ba2012-05-20 12:00:36 +0200805#ifdef CHECK_EGL_FPS
806 check_fps();
807#endif
808#ifdef HWC_HWOVERLAY
809 unsigned char pixels[4];
810 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
811#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100812 EGLBoolean sucess = eglSwapBuffers((EGLDisplay)list->dpy, (EGLSurface)list->sur);
codeworkx62f02ba2012-05-20 12:00:36 +0200813 if (!sucess)
814 return HWC_EGL_ERROR;
815 }
816
817#if defined(BOARD_USES_HDMI)
818 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
819
820 if (skip_hdmi_rendering == 1)
821 return 0;
822
823 if (list == NULL) {
824 // Don't display unnecessary image
825 mHdmiClient->setHdmiEnable(0);
826 return 0;
827 } else {
828 mHdmiClient->setHdmiEnable(1);
829 }
830
831#ifdef SUPPORT_AUTO_UI_ROTATE
832 cur = &list->hwLayers[0];
833
834 if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270)
835 mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
836 else
837 mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
838#endif
839
840 // To support S3D video playback (automatic TV mode change to 3D mode)
841 if (ctx->num_of_hwc_layer == 1) {
842 if (src_img.usage != prev_usage)
espenfjo34f9d5d2012-12-01 18:52:36 +0100843 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200844
845 if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
846 (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100847 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 +0200848 else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
849 (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100850 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 +0200851
852 prev_usage = src_img.usage;
853 } else {
854 if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
855 (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) ||
856 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
857 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100858 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200859
860 prev_usage = 0;
861 }
862
863 if (ctx->num_of_hwc_layer == 1) {
864 if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
865 (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
866 ADDRS * addr = (ADDRS *)(src_img.base);
espenfjo34f9d5d2012-12-01 18:52:36 +0100867 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200868 src_img.format,
869 (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr,
870 0, 0,
871 android::SecHdmiClient::HDMI_MODE_VIDEO,
872 ctx->num_of_hwc_layer);
873 } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
874 (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
875 (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
876 (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100877 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200878 src_img.format,
879 (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
880 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
881 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
882 0, 0,
883 android::SecHdmiClient::HDMI_MODE_VIDEO,
884 ctx->num_of_hwc_layer);
885 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100886 SEC_HWC_Log(HWC_LOG_ERROR, "%s: Unsupported format = %d", __func__, src_img.format);
codeworkx62f02ba2012-05-20 12:00:36 +0200887 }
888 }
889#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100890 }
codeworkx62f02ba2012-05-20 12:00:36 +0200891 return 0;
892}
893
espenfjo34f9d5d2012-12-01 18:52:36 +0100894static void hwc_registerProcs(struct hwc_composer_device_1* dev,
895 hwc_procs_t const* procs)
896{
897 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
898 ctx->procs = const_cast<hwc_procs_t *>(procs);
899}
900
901static int hwc_query(struct hwc_composer_device_1* dev,
902 int what, int* value)
903{
904 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
905
906 switch (what) {
907 case HWC_BACKGROUND_LAYER_SUPPORTED:
908 // we don't support the background layer yet
909 value[0] = 0;
910 break;
911 case HWC_VSYNC_PERIOD:
912 // vsync period in nanosecond
913 value[0] = 1000000000.0 / 57;
914 break;
915 default:
916 // unsupported query
917 return -EINVAL;
918 }
919 return 0;
920}
921
922static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
923 int event, int enabled)
924{
925 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
926
927 switch (event) {
928 case HWC_EVENT_VSYNC:
929 int val = !!enabled;
930 int err = ioctl(ctx->win[0].fd, S3CFB_SET_VSYNC_INT, &val);
931 if (err < 0)
932 return -errno;
933
934 return 0;
935 }
936 return -EINVAL;
937}
938
codeworkxabfed772012-12-01 19:37:39 +0100939#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +0100940static void *hwc_vsync_sysfs_loop(void *data)
941{
942 static char buf[4096];
943 int vsync_timestamp_fd;
944 fd_set exceptfds;
945 int res;
946 int64_t timestamp = 0;
947 hwc_context_t * ctx = (hwc_context_t *)(data);
948
949 vsync_timestamp_fd = open("/sys/devices/platform/samsung-pd.2/s3cfb.0/vsync_time", O_RDONLY);
950 char thread_name[64] = "hwcVsyncThread";
951 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
952 setpriority(PRIO_PROCESS, 0, -20);
953 memset(buf, 0, sizeof(buf));
954
955 SEC_HWC_Log(HWC_LOG_DEBUG,"Using sysfs mechanism for VSYNC notification");
956
957 FD_ZERO(&exceptfds);
958 FD_SET(vsync_timestamp_fd, &exceptfds);
959 do {
960 ssize_t len = read(vsync_timestamp_fd, buf, sizeof(buf));
961 timestamp = strtoull(buf, NULL, 0);
962 ctx->procs->vsync(ctx->procs, 0, timestamp);
963 select(vsync_timestamp_fd + 1, NULL, NULL, &exceptfds, NULL);
964 lseek(vsync_timestamp_fd, 0, SEEK_SET);
965 } while (1);
966
967 return NULL;
968}
codeworkxabfed772012-12-01 19:37:39 +0100969#endif
970
971void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
972{
973 uint64_t timestamp = 0;
974 const char *s = buff;
975
976 if(!ctx->procs || !ctx->procs->vsync)
977 return;
978
979 s += strlen(s) + 1;
980
981 while(*s) {
982 if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
983 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
984
985 s += strlen(s) + 1;
986 if (s - buff >= len)
987 break;
988 }
989
990 ctx->procs->vsync(ctx->procs, 0, timestamp);
991}
992
993static void *hwc_vsync_thread(void *data)
994{
995 hwc_context_t *ctx = (hwc_context_t *)(data);
996 char uevent_desc[4096];
997
998 memset(uevent_desc, 0, sizeof(uevent_desc));
999 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1000 uevent_init();
1001
1002 while(true) {
1003
1004 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
1005
1006 bool vsync = !strcmp(uevent_desc, "change@/devices/platform/samsung-pd.2/s3cfb.0");
1007 if(vsync)
1008 handle_vsync_uevent(ctx, uevent_desc, len);
1009 }
1010
1011 return NULL;
1012}
espenfjo34f9d5d2012-12-01 18:52:36 +01001013
codeworkx62f02ba2012-05-20 12:00:36 +02001014static int hwc_device_close(struct hw_device_t *dev)
1015{
1016 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
1017 int ret = 0;
1018 int i;
1019 if (ctx) {
1020 if (destroyFimc(&ctx->fimc) < 0) {
1021 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__);
1022 ret = -1;
1023 }
codeworkx62f02ba2012-05-20 12:00:36 +02001024
codeworkx62f02ba2012-05-20 12:00:36 +02001025 for (i = 0; i < NUM_OF_WIN; i++) {
1026 if (window_close(&ctx->win[i]) < 0)
1027 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1028 }
1029
1030 free(ctx);
1031 }
1032 return ret;
1033}
espenfjo34f9d5d2012-12-01 18:52:36 +01001034static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank)
1035{
1036 // We're using an older method of screen blanking based on
1037 // early_suspend in the kernel. No need to do anything here.
1038 return 0;
1039}
codeworkx62f02ba2012-05-20 12:00:36 +02001040static int hwc_device_open(const struct hw_module_t* module, const char* name,
1041 struct hw_device_t** device)
1042{
1043 int status = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +01001044 int err = 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001045 struct hwc_win_info_t *win;
1046
1047 if (strcmp(name, HWC_HARDWARE_COMPOSER))
1048 return -EINVAL;
1049
1050 struct hwc_context_t *dev;
1051 dev = (hwc_context_t*)malloc(sizeof(*dev));
1052
1053 /* initialize our state here */
1054 memset(dev, 0, sizeof(*dev));
1055
1056 /* initialize the procs */
espenfjo34f9d5d2012-12-01 18:52:36 +01001057 dev->device.common.tag = HARDWARE_DEVICE_TAG;
1058 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
1059 dev->device.common.module = const_cast<hw_module_t*>(module);
1060 dev->device.common.close = hwc_device_close;
1061 dev->device.prepare = hwc_prepare;
1062 dev->device.set = hwc_set;
1063 dev->device.eventControl = hwc_eventControl;
1064 dev->device.blank = hwc_blank;
1065 dev->device.query = hwc_query;
1066 dev->device.registerProcs = hwc_registerProcs;
codeworkx62f02ba2012-05-20 12:00:36 +02001067 *device = &dev->device.common;
1068
1069 //initializing
1070 memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
espenfjo34f9d5d2012-12-01 18:52:36 +01001071
codeworkx62f02ba2012-05-20 12:00:36 +02001072 /* open WIN0 & WIN1 here */
1073 for (int i = 0; i < NUM_OF_WIN; i++) {
1074 if (window_open(&(dev->win[i]), i) < 0) {
1075 SEC_HWC_Log(HWC_LOG_ERROR,
1076 "%s:: Failed to open window %d device ", __func__, i);
1077 status = -EINVAL;
1078 goto err;
1079 }
1080 }
1081
1082 if (window_get_global_lcd_info(dev->win[0].fd, &dev->lcd_info) < 0) {
1083 SEC_HWC_Log(HWC_LOG_ERROR,
1084 "%s::window_get_global_lcd_info is failed : %s",
1085 __func__, strerror(errno));
1086 status = -EINVAL;
1087 goto err;
1088 }
1089
1090#if defined(BOARD_USES_HDMI)
1091 lcd_width = dev->lcd_info.xres;
1092 lcd_height = dev->lcd_info.yres;
1093#endif
1094
1095 /* initialize the window context */
1096 for (int i = 0; i < NUM_OF_WIN; i++) {
1097 win = &dev->win[i];
1098 memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1099 memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1100
1101 win->rect_info.x = 0;
1102 win->rect_info.y = 0;
1103 win->rect_info.w = win->var_info.xres;
1104 win->rect_info.h = win->var_info.yres;
1105
1106 if (window_set_pos(win) < 0) {
1107 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
1108 __func__, strerror(errno));
1109 status = -EINVAL;
1110 goto err;
1111 }
1112
1113 if (window_get_info(win, i) < 0) {
1114 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s",
1115 __func__, strerror(errno));
1116 status = -EINVAL;
1117 goto err;
1118 }
1119
1120 }
1121
codeworkx62f02ba2012-05-20 12:00:36 +02001122 //create PP
1123 if (createFimc(&dev->fimc) < 0) {
1124 SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__);
1125 status = -EINVAL;
1126 goto err;
1127 }
1128
codeworkxabfed772012-12-01 19:37:39 +01001129#ifndef SYSFS_VSYNC_NOTIFICATION
1130 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
1131 if (err) {
1132 ALOGE("%s::pthread_create() failed : %s", __func__, strerror(err));
1133 status = -err;
1134 goto err;
1135 }
1136#endif
1137
1138#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +01001139 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_sysfs_loop, dev);
1140 if (err) {
1141 SEC_HWC_Log(HWC_LOG_ERROR, "%s::pthread_create() failed : %s", __func__, strerror(err));
1142 status = -err;
codeworkx62f02ba2012-05-20 12:00:36 +02001143 goto err;
1144 }
codeworkxabfed772012-12-01 19:37:39 +01001145#endif
codeworkx62f02ba2012-05-20 12:00:36 +02001146
1147 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__);
1148
1149 return 0;
1150
1151err:
1152 if (destroyFimc(&dev->fimc) < 0)
1153 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001154
1155 for (int i = 0; i < NUM_OF_WIN; i++) {
1156 if (window_close(&dev->win[i]) < 0)
1157 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1158 }
1159
1160 return status;
1161}