blob: 9aac891a2a11e3ba01624f5772a30c950f95f310 [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"
Simon Shieldsfe32c932016-11-20 21:25:30 +110039
codeworkx62f02ba2012-05-20 12:00:36 +020040#include <GLES/gl.h>
Simon Shieldsfe32c932016-11-20 21:25:30 +110041
codeworkx62f02ba2012-05-20 12:00:36 +020042#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
Andrew Dodde6a23d72012-12-02 21:50:58 -0500530 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
531 int overlay_win_cnt = 0;
532 int compositionType = 0;
533 int ret;
534
535 // Compat
536 hwc_display_contents_1_t* list = NULL;
537 if (numDisplays > 0) {
538 list = displays[0];
539 }
540
espenfjo34f9d5d2012-12-01 18:52:36 +0100541#if defined(BOARD_USES_HDMI)
Andrew Dodde6a23d72012-12-02 21:50:58 -0500542 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
543 int hdmi_cable_status = (int)mHdmiClient->getHdmiCableStatus();
544
545 ctx->hdmi_cable_status = hdmi_cable_status;
espenfjo34f9d5d2012-12-01 18:52:36 +0100546#endif
547
548#ifdef SKIP_DUMMY_UI_LAY_DRAWING
Andrew Dodde6a23d72012-12-02 21:50:58 -0500549 if ((list && (!(list->flags & HWC_GEOMETRY_CHANGED))) &&
550 (ctx->num_of_hwc_layer > 0)) {
551 get_hwc_ui_lay_skipdraw_decision(ctx, list);
552 return 0;
553 }
554 ctx->fb_lay_skip_initialized = 0;
555 ctx->num_of_fb_lay_skip = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100556#ifdef GL_WA_OVLY_ALL
Andrew Dodde6a23d72012-12-02 21:50:58 -0500557 ctx->ui_skip_frame_cnt = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100558#endif
559
Andrew Dodde6a23d72012-12-02 21:50:58 -0500560 for (int i = 0; i < NUM_OF_DUMMY_WIN; i++) {
561 ctx->win_virt[i].layer_prev_buf = 0;
562 ctx->win_virt[i].layer_index = -1;
563 ctx->win_virt[i].status = HWC_WIN_FREE;
564 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100565#endif
566
Andrew Dodde6a23d72012-12-02 21:50:58 -0500567 //if geometry is not changed, there is no need to do any work here
568 if (!list || (!(list->flags & HWC_GEOMETRY_CHANGED)))
codeworkx62f02ba2012-05-20 12:00:36 +0200569 return 0;
570
571 //all the windows are free here....
572 for (int i = 0 ; i < NUM_OF_WIN; i++) {
573 ctx->win[i].status = HWC_WIN_FREE;
574 ctx->win[i].buf_index = 0;
575 }
576
577 ctx->num_of_hwc_layer = 0;
578 ctx->num_of_fb_layer = 0;
579 ctx->num_2d_blit_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100580 ctx->num_of_ext_disp_video_layer = 0;
581
582 for (int i = 0; i < list->numHwLayers; i++) {
583 hwc_layer_1_t *cur = &list->hwLayers[i];
584 private_handle_t *prev_handle = NULL;
585 if (cur->handle) {
586 prev_handle = (private_handle_t *)(cur->handle);
587 SEC_HWC_Log(HWC_LOG_DEBUG, "prev_handle->usage = %d", prev_handle->usage);
588 if (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) {
589 ctx->num_of_ext_disp_layer++;
590 if ((prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP) ||
591 check_yuv_format((unsigned int)prev_handle->format) == 1) {
592 ctx->num_of_ext_disp_video_layer++;
593 }
594 }
595 }
596 }
codeworkx62f02ba2012-05-20 12:00:36 +0200597
598 for (int i = 0; i < list->numHwLayers ; i++) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100599 hwc_layer_1_t* cur = &list->hwLayers[i];
600 private_handle_t *prev_handle = (private_handle_t *)(cur->handle);
codeworkx62f02ba2012-05-20 12:00:36 +0200601
602 if (overlay_win_cnt < NUM_OF_WIN) {
603 compositionType = get_hwc_compos_decision(cur, 0, overlay_win_cnt);
604
605 if (compositionType == HWC_FRAMEBUFFER) {
606 cur->compositionType = HWC_FRAMEBUFFER;
607 ctx->num_of_fb_layer++;
608 } else {
609 ret = assign_overlay_window(ctx, cur, overlay_win_cnt, i);
610 if (ret != 0) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100611 SEC_HWC_Log(HWC_LOG_ERROR, "assign_overlay_window fail, change to frambuffer");
codeworkx62f02ba2012-05-20 12:00:36 +0200612 cur->compositionType = HWC_FRAMEBUFFER;
613 ctx->num_of_fb_layer++;
614 continue;
615 }
616
617 cur->compositionType = HWC_OVERLAY;
618 cur->hints = HWC_HINT_CLEAR_FB;
619 overlay_win_cnt++;
620 ctx->num_of_hwc_layer++;
621 }
622 } else {
623 cur->compositionType = HWC_FRAMEBUFFER;
624 ctx->num_of_fb_layer++;
625 }
espenfjo34f9d5d2012-12-01 18:52:36 +0100626#if defined(BOARD_USES_HDMI)
627 SEC_HWC_Log(HWC_LOG_DEBUG, "ext disp vid = %d, cable status = %d, composition type = %d",
628 ctx->num_of_ext_disp_video_layer, ctx->hdmi_cable_status, compositionType);
629 if (ctx->num_of_ext_disp_video_layer >= 2) {
630 if ((ctx->hdmi_cable_status) &&
631 (compositionType == HWC_OVERLAY) &&
632 (prev_handle->usage & GRALLOC_USAGE_EXTERNAL_DISP)) {
633 cur->compositionType = HWC_FRAMEBUFFER;
634 ctx->num_of_hwc_layer--;
635 overlay_win_cnt--;
636 ctx->num_of_fb_layer++;
637 cur->hints = 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200638 }
639 }
codeworkx62f02ba2012-05-20 12:00:36 +0200640#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100641 }
codeworkx62f02ba2012-05-20 12:00:36 +0200642
643#if defined(BOARD_USES_HDMI)
espenfjo34f9d5d2012-12-01 18:52:36 +0100644 mHdmiClient = android::SecHdmiClient::getInstance();
codeworkx62f02ba2012-05-20 12:00:36 +0200645 mHdmiClient->setHdmiHwcLayer(ctx->num_of_hwc_layer);
espenfjo34f9d5d2012-12-01 18:52:36 +0100646 if (ctx->num_of_ext_disp_video_layer > 1) {
647 mHdmiClient->setExtDispLayerNum(0);
648 }
codeworkx62f02ba2012-05-20 12:00:36 +0200649#endif
650
651 if (list->numHwLayers != (ctx->num_of_fb_layer + ctx->num_of_hwc_layer))
652 SEC_HWC_Log(HWC_LOG_DEBUG,
653 "%s:: numHwLayers %d num_of_fb_layer %d num_of_hwc_layer %d ",
654 __func__, list->numHwLayers, ctx->num_of_fb_layer,
655 ctx->num_of_hwc_layer);
656
657 if (overlay_win_cnt < NUM_OF_WIN) {
658 //turn off the free windows
659 for (int i = overlay_win_cnt; i < NUM_OF_WIN; i++) {
660 window_hide(&ctx->win[i]);
661 reset_win_rect_info(&ctx->win[i]);
662 }
663 }
Andrew Dodde6a23d72012-12-02 21:50:58 -0500664
codeworkx62f02ba2012-05-20 12:00:36 +0200665 return 0;
666}
667
espenfjo34f9d5d2012-12-01 18:52:36 +0100668static int hwc_set(hwc_composer_device_1_t *dev,
669 size_t numDisplays,
670 hwc_display_contents_1_t** displays)
codeworkx62f02ba2012-05-20 12:00:36 +0200671{
672 struct hwc_context_t *ctx = (struct hwc_context_t *)dev;
673 int skipped_window_mask = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100674 hwc_layer_1_t* cur;
codeworkx62f02ba2012-05-20 12:00:36 +0200675 struct hwc_win_info_t *win;
676 int ret;
677 int pmem_phyaddr;
codeworkx62f02ba2012-05-20 12:00:36 +0200678 struct sec_img src_img;
679 struct sec_img dst_img;
680 struct sec_rect src_work_rect;
681 struct sec_rect dst_work_rect;
espenfjo34f9d5d2012-12-01 18:52:36 +0100682 bool need_swap_buffers = ctx->num_of_fb_layer > 0;
codeworkx62f02ba2012-05-20 12:00:36 +0200683
684 memset(&src_img, 0, sizeof(src_img));
685 memset(&dst_img, 0, sizeof(dst_img));
686 memset(&src_work_rect, 0, sizeof(src_work_rect));
687 memset(&dst_work_rect, 0, sizeof(dst_work_rect));
688
689#if defined(BOARD_USES_HDMI)
690 int skip_hdmi_rendering = 0;
691 int rotVal = 0;
692#endif
693
Andrew Dodde6a23d72012-12-02 21:50:58 -0500694 // Only support one display
695 hwc_display_contents_1_t* list = displays[0];
696
codeworkx62f02ba2012-05-20 12:00:36 +0200697 if (!list) {
698 //turn off the all windows
699 for (int i = 0; i < NUM_OF_WIN; i++) {
700 window_hide(&ctx->win[i]);
701 reset_win_rect_info(&ctx->win[i]);
702 ctx->win[i].status = HWC_WIN_FREE;
703 }
704 ctx->num_of_hwc_layer = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +0100705 need_swap_buffers = true;
codeworkx62f02ba2012-05-20 12:00:36 +0200706
espenfjo34f9d5d2012-12-01 18:52:36 +0100707 if (list->sur == NULL && list->dpy == NULL) {
708#ifdef SKIP_DUMMY_UI_LAY_DRAWING
709 ctx->fb_lay_skip_initialized = 0;
710#endif
codeworkx62f02ba2012-05-20 12:00:36 +0200711 return HWC_EGL_ERROR;
espenfjo34f9d5d2012-12-01 18:52:36 +0100712 }
codeworkx62f02ba2012-05-20 12:00:36 +0200713 }
714
715 if(ctx->num_of_hwc_layer > NUM_OF_WIN)
716 ctx->num_of_hwc_layer = NUM_OF_WIN;
717
espenfjo34f9d5d2012-12-01 18:52:36 +0100718 /*
719 * H/W composer documentation states:
720 * There is an implicit layer containing opaque black
721 * pixels behind all the layers in the list.
722 * It is the responsibility of the hwcomposer module to make
723 * sure black pixels are output (or blended from).
724 *
725 * Since we're using a blitter, we need to erase the frame-buffer when
726 * switching to all-overlay mode.
727 *
728 */
729 if (ctx->num_of_hwc_layer &&
730 ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
731#ifdef SKIP_DUMMY_UI_LAY_DRAWING
732 if (ctx->num_of_fb_lay_skip == 0)
733#endif
734 {
735 glDisable(GL_SCISSOR_TEST);
736 glClearColor(0, 0, 0, 0);
737 glClear(GL_COLOR_BUFFER_BIT);
738 glEnable(GL_SCISSOR_TEST);
739 need_swap_buffers = true;
740 }
741 }
742 ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
743
codeworkx62f02ba2012-05-20 12:00:36 +0200744 //compose hardware layers here
745 for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) {
746 win = &ctx->win[i];
747 if (win->status == HWC_WIN_RESERVED) {
748 cur = &list->hwLayers[win->layer_index];
749
750 if (cur->compositionType == HWC_OVERLAY) {
751 if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) {
752 /*
753 * In android platform, all the graphic buffer are at least
754 * double buffered (2 or more) this buffer is already rendered.
755 * It is the redundant src buffer for FIMC rendering.
756 */
espenfjo34f9d5d2012-12-01 18:52:36 +0100757
codeworkx62f02ba2012-05-20 12:00:36 +0200758#if defined(BOARD_USES_HDMI)
759 skip_hdmi_rendering = 1;
760#endif
761 continue;
762 }
763 ctx->layer_prev_buf[i] = (uint32_t)cur->handle;
764 // initialize the src & dist context for fimc
765 set_src_dst_img_rect(cur, win, &src_img, &dst_img,
766 &src_work_rect, &dst_work_rect, i);
767
768 ret = runFimc(ctx,
769 &src_img, &src_work_rect,
770 &dst_img, &dst_work_rect,
771 cur->transform);
772
773 if (ret < 0) {
774 SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n",
775 __func__, ret);
776 skipped_window_mask |= (1 << i);
777 continue;
778 }
779
780 window_pan_display(win);
781
782 win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
783 if (win->power_state == 0)
784 window_show(win);
785 } else {
786 SEC_HWC_Log(HWC_LOG_ERROR,
787 "%s:: error : layer %d compositionType should have been"
788 " HWC_OVERLAY ", __func__, win->layer_index);
789 skipped_window_mask |= (1 << i);
790 continue;
791 }
792 } else {
793 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have "
794 "been HWC_WIN_RESERVED by now... ", __func__);
795 skipped_window_mask |= (1 << i);
796 continue;
797 }
798 }
799
codeworkx62f02ba2012-05-20 12:00:36 +0200800 if (skipped_window_mask) {
801 //turn off the free windows
802 for (int i = 0; i < NUM_OF_WIN; i++) {
803 if (skipped_window_mask & (1 << i)) {
804 window_hide(&ctx->win[i]);
805 reset_win_rect_info(&ctx->win[i]);
806 }
807 }
808 }
809
espenfjo34f9d5d2012-12-01 18:52:36 +0100810 if (need_swap_buffers) {
codeworkx62f02ba2012-05-20 12:00:36 +0200811#ifdef CHECK_EGL_FPS
812 check_fps();
813#endif
814#ifdef HWC_HWOVERLAY
815 unsigned char pixels[4];
816 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
817#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100818 EGLBoolean sucess = eglSwapBuffers((EGLDisplay)list->dpy, (EGLSurface)list->sur);
codeworkx62f02ba2012-05-20 12:00:36 +0200819 if (!sucess)
820 return HWC_EGL_ERROR;
821 }
822
823#if defined(BOARD_USES_HDMI)
824 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
825
826 if (skip_hdmi_rendering == 1)
827 return 0;
828
829 if (list == NULL) {
830 // Don't display unnecessary image
831 mHdmiClient->setHdmiEnable(0);
832 return 0;
833 } else {
834 mHdmiClient->setHdmiEnable(1);
835 }
836
837#ifdef SUPPORT_AUTO_UI_ROTATE
838 cur = &list->hwLayers[0];
839
840 if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270)
841 mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
842 else
843 mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
844#endif
845
846 // To support S3D video playback (automatic TV mode change to 3D mode)
847 if (ctx->num_of_hwc_layer == 1) {
848 if (src_img.usage != prev_usage)
espenfjo34f9d5d2012-12-01 18:52:36 +0100849 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200850
851 if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
852 (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100853 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 +0200854 else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
855 (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100856 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 +0200857
858 prev_usage = src_img.usage;
859 } else {
860 if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
861 (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) ||
862 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
863 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100864 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200865
866 prev_usage = 0;
867 }
868
869 if (ctx->num_of_hwc_layer == 1) {
870 if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
871 (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
872 ADDRS * addr = (ADDRS *)(src_img.base);
espenfjo34f9d5d2012-12-01 18:52:36 +0100873 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200874 src_img.format,
875 (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr,
876 0, 0,
877 android::SecHdmiClient::HDMI_MODE_VIDEO,
878 ctx->num_of_hwc_layer);
879 } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
880 (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
881 (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
882 (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100883 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200884 src_img.format,
885 (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
886 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
887 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
888 0, 0,
889 android::SecHdmiClient::HDMI_MODE_VIDEO,
890 ctx->num_of_hwc_layer);
891 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100892 SEC_HWC_Log(HWC_LOG_ERROR, "%s: Unsupported format = %d", __func__, src_img.format);
codeworkx62f02ba2012-05-20 12:00:36 +0200893 }
894 }
895#endif
Andrew Dodde6a23d72012-12-02 21:50:58 -0500896
codeworkx62f02ba2012-05-20 12:00:36 +0200897 return 0;
898}
899
espenfjo34f9d5d2012-12-01 18:52:36 +0100900static void hwc_registerProcs(struct hwc_composer_device_1* dev,
901 hwc_procs_t const* procs)
902{
903 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
904 ctx->procs = const_cast<hwc_procs_t *>(procs);
905}
906
907static int hwc_query(struct hwc_composer_device_1* dev,
908 int what, int* value)
909{
910 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
911
912 switch (what) {
913 case HWC_BACKGROUND_LAYER_SUPPORTED:
914 // we don't support the background layer yet
915 value[0] = 0;
916 break;
917 case HWC_VSYNC_PERIOD:
918 // vsync period in nanosecond
919 value[0] = 1000000000.0 / 57;
920 break;
921 default:
922 // unsupported query
923 return -EINVAL;
924 }
925 return 0;
926}
927
928static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
929 int event, int enabled)
930{
931 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
932
933 switch (event) {
934 case HWC_EVENT_VSYNC:
935 int val = !!enabled;
codeworkx39aefd02012-12-02 19:39:25 +0100936 int err = ioctl(ctx->global_lcd_win.fd, S3CFB_SET_VSYNC_INT, &val);
espenfjo34f9d5d2012-12-01 18:52:36 +0100937 if (err < 0)
938 return -errno;
939
940 return 0;
941 }
942 return -EINVAL;
943}
944
codeworkxabfed772012-12-01 19:37:39 +0100945#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +0100946static void *hwc_vsync_sysfs_loop(void *data)
947{
948 static char buf[4096];
949 int vsync_timestamp_fd;
950 fd_set exceptfds;
951 int res;
952 int64_t timestamp = 0;
953 hwc_context_t * ctx = (hwc_context_t *)(data);
954
955 vsync_timestamp_fd = open("/sys/devices/platform/samsung-pd.2/s3cfb.0/vsync_time", O_RDONLY);
956 char thread_name[64] = "hwcVsyncThread";
957 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
958 setpriority(PRIO_PROCESS, 0, -20);
959 memset(buf, 0, sizeof(buf));
960
961 SEC_HWC_Log(HWC_LOG_DEBUG,"Using sysfs mechanism for VSYNC notification");
962
963 FD_ZERO(&exceptfds);
964 FD_SET(vsync_timestamp_fd, &exceptfds);
965 do {
966 ssize_t len = read(vsync_timestamp_fd, buf, sizeof(buf));
967 timestamp = strtoull(buf, NULL, 0);
Flamefire5d0cdb72014-01-20 22:18:05 +0100968 if(ctx->procs)
969 ctx->procs->vsync(ctx->procs, 0, timestamp);
espenfjo34f9d5d2012-12-01 18:52:36 +0100970 select(vsync_timestamp_fd + 1, NULL, NULL, &exceptfds, NULL);
971 lseek(vsync_timestamp_fd, 0, SEEK_SET);
972 } while (1);
973
974 return NULL;
975}
codeworkxabfed772012-12-01 19:37:39 +0100976#endif
977
978void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
979{
980 uint64_t timestamp = 0;
981 const char *s = buff;
982
983 if(!ctx->procs || !ctx->procs->vsync)
984 return;
985
986 s += strlen(s) + 1;
987
988 while(*s) {
989 if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
990 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
991
992 s += strlen(s) + 1;
993 if (s - buff >= len)
994 break;
995 }
996
997 ctx->procs->vsync(ctx->procs, 0, timestamp);
998}
999
1000static void *hwc_vsync_thread(void *data)
1001{
1002 hwc_context_t *ctx = (hwc_context_t *)(data);
1003 char uevent_desc[4096];
1004
1005 memset(uevent_desc, 0, sizeof(uevent_desc));
1006 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1007 uevent_init();
1008
1009 while(true) {
1010
1011 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
1012
1013 bool vsync = !strcmp(uevent_desc, "change@/devices/platform/samsung-pd.2/s3cfb.0");
1014 if(vsync)
1015 handle_vsync_uevent(ctx, uevent_desc, len);
1016 }
1017
1018 return NULL;
1019}
espenfjo34f9d5d2012-12-01 18:52:36 +01001020
codeworkx62f02ba2012-05-20 12:00:36 +02001021static int hwc_device_close(struct hw_device_t *dev)
1022{
1023 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
1024 int ret = 0;
1025 int i;
1026 if (ctx) {
1027 if (destroyFimc(&ctx->fimc) < 0) {
1028 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__);
1029 ret = -1;
1030 }
codeworkx62f02ba2012-05-20 12:00:36 +02001031
codeworkx39aefd02012-12-02 19:39:25 +01001032 if (window_close(&ctx->global_lcd_win) < 0) {
1033 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_close() fail", __func__);
1034 ret = -1;
1035 }
1036
codeworkx62f02ba2012-05-20 12:00:36 +02001037 for (i = 0; i < NUM_OF_WIN; i++) {
1038 if (window_close(&ctx->win[i]) < 0)
1039 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1040 }
1041
1042 free(ctx);
1043 }
1044 return ret;
1045}
Andrew Dodde6a23d72012-12-02 21:50:58 -05001046
espenfjo34f9d5d2012-12-01 18:52:36 +01001047static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank)
1048{
Andrew Dodde6a23d72012-12-02 21:50:58 -05001049 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
1050 if (blank) {
1051 // release our resources, the screen is turning off
1052 // in our case, there is nothing to do.
1053 ctx->num_of_fb_layer_prev = 0;
1054 return 0;
1055 }
1056 else {
1057 // No need to unblank, will unblank on set()
1058 return 0;
1059 }
1060}
1061
codeworkx62f02ba2012-05-20 12:00:36 +02001062static int hwc_device_open(const struct hw_module_t* module, const char* name,
1063 struct hw_device_t** device)
1064{
1065 int status = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +01001066 int err = 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001067 struct hwc_win_info_t *win;
1068
1069 if (strcmp(name, HWC_HARDWARE_COMPOSER))
1070 return -EINVAL;
1071
1072 struct hwc_context_t *dev;
1073 dev = (hwc_context_t*)malloc(sizeof(*dev));
1074
1075 /* initialize our state here */
1076 memset(dev, 0, sizeof(*dev));
1077
1078 /* initialize the procs */
espenfjo34f9d5d2012-12-01 18:52:36 +01001079 dev->device.common.tag = HARDWARE_DEVICE_TAG;
1080 dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
1081 dev->device.common.module = const_cast<hw_module_t*>(module);
1082 dev->device.common.close = hwc_device_close;
1083 dev->device.prepare = hwc_prepare;
1084 dev->device.set = hwc_set;
1085 dev->device.eventControl = hwc_eventControl;
codeworkx39aefd02012-12-02 19:39:25 +01001086 dev->device.blank = hwc_blank;
espenfjo34f9d5d2012-12-01 18:52:36 +01001087 dev->device.query = hwc_query;
1088 dev->device.registerProcs = hwc_registerProcs;
codeworkx62f02ba2012-05-20 12:00:36 +02001089 *device = &dev->device.common;
1090
1091 //initializing
1092 memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
espenfjo34f9d5d2012-12-01 18:52:36 +01001093
codeworkx39aefd02012-12-02 19:39:25 +01001094 /* open WIN0 & WIN1 here */
1095 for (int i = 0; i < NUM_OF_WIN; i++) {
codeworkx62f02ba2012-05-20 12:00:36 +02001096 if (window_open(&(dev->win[i]), i) < 0) {
1097 SEC_HWC_Log(HWC_LOG_ERROR,
1098 "%s:: Failed to open window %d device ", __func__, i);
codeworkx39aefd02012-12-02 19:39:25 +01001099 status = -EINVAL;
1100 goto err;
codeworkx62f02ba2012-05-20 12:00:36 +02001101 }
codeworkx39aefd02012-12-02 19:39:25 +01001102 }
codeworkx62f02ba2012-05-20 12:00:36 +02001103
codeworkx39aefd02012-12-02 19:39:25 +01001104 /* open window 2, used to query global LCD info */
1105 if (window_open(&dev->global_lcd_win, 2) < 0) {
1106 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: Failed to open window 2 device ", __func__);
1107 status = -EINVAL;
1108 goto err;
1109 }
1110
1111 if (window_get_global_lcd_info(dev) < 0) {
codeworkx62f02ba2012-05-20 12:00:36 +02001112 SEC_HWC_Log(HWC_LOG_ERROR,
1113 "%s::window_get_global_lcd_info is failed : %s",
1114 __func__, strerror(errno));
1115 status = -EINVAL;
1116 goto err;
1117 }
1118
1119#if defined(BOARD_USES_HDMI)
1120 lcd_width = dev->lcd_info.xres;
1121 lcd_height = dev->lcd_info.yres;
1122#endif
1123
1124 /* initialize the window context */
1125 for (int i = 0; i < NUM_OF_WIN; i++) {
1126 win = &dev->win[i];
1127 memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1128 memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1129
1130 win->rect_info.x = 0;
1131 win->rect_info.y = 0;
1132 win->rect_info.w = win->var_info.xres;
1133 win->rect_info.h = win->var_info.yres;
1134
1135 if (window_set_pos(win) < 0) {
1136 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
1137 __func__, strerror(errno));
1138 status = -EINVAL;
1139 goto err;
1140 }
1141
1142 if (window_get_info(win, i) < 0) {
1143 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s",
1144 __func__, strerror(errno));
1145 status = -EINVAL;
1146 goto err;
1147 }
1148
1149 }
1150
codeworkx62f02ba2012-05-20 12:00:36 +02001151 //create PP
1152 if (createFimc(&dev->fimc) < 0) {
1153 SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__);
1154 status = -EINVAL;
1155 goto err;
1156 }
1157
codeworkxabfed772012-12-01 19:37:39 +01001158#ifndef SYSFS_VSYNC_NOTIFICATION
1159 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
1160 if (err) {
1161 ALOGE("%s::pthread_create() failed : %s", __func__, strerror(err));
1162 status = -err;
1163 goto err;
1164 }
1165#endif
1166
1167#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +01001168 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_sysfs_loop, dev);
1169 if (err) {
1170 SEC_HWC_Log(HWC_LOG_ERROR, "%s::pthread_create() failed : %s", __func__, strerror(err));
1171 status = -err;
codeworkx62f02ba2012-05-20 12:00:36 +02001172 goto err;
1173 }
codeworkxabfed772012-12-01 19:37:39 +01001174#endif
codeworkx62f02ba2012-05-20 12:00:36 +02001175
1176 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__);
1177
1178 return 0;
1179
1180err:
1181 if (destroyFimc(&dev->fimc) < 0)
1182 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001183
codeworkx39aefd02012-12-02 19:39:25 +01001184 if (window_close(&dev->global_lcd_win) < 0)
1185 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_close() fail", __func__);
1186
codeworkx62f02ba2012-05-20 12:00:36 +02001187 for (int i = 0; i < NUM_OF_WIN; i++) {
1188 if (window_close(&dev->win[i]) < 0)
1189 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1190 }
1191
1192 return status;
1193}