blob: bb1ae8ce2622256b4948bab380078e61309b2d8c [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
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 }
Ricardo Cerqueira99f63f22014-01-15 16:50:35 +0000713 } else {
714 list->dpy = eglGetCurrentDisplay();
715 list->sur = eglGetCurrentSurface(EGL_DRAW);
716
717 // We still don't support fences, close them all
718 for(uint32_t i = 0; i < list->numHwLayers; i++) {
719 if(list->hwLayers[i].acquireFenceFd >= 0) {
720 close(list->hwLayers[i].acquireFenceFd);
721 list->hwLayers[i].acquireFenceFd = -1;
722 }
723 }
724 list->retireFenceFd = -1;
codeworkx62f02ba2012-05-20 12:00:36 +0200725 }
726
727 if(ctx->num_of_hwc_layer > NUM_OF_WIN)
728 ctx->num_of_hwc_layer = NUM_OF_WIN;
729
espenfjo34f9d5d2012-12-01 18:52:36 +0100730 /*
731 * H/W composer documentation states:
732 * There is an implicit layer containing opaque black
733 * pixels behind all the layers in the list.
734 * It is the responsibility of the hwcomposer module to make
735 * sure black pixels are output (or blended from).
736 *
737 * Since we're using a blitter, we need to erase the frame-buffer when
738 * switching to all-overlay mode.
739 *
740 */
741 if (ctx->num_of_hwc_layer &&
742 ctx->num_of_fb_layer==0 && ctx->num_of_fb_layer_prev) {
743#ifdef SKIP_DUMMY_UI_LAY_DRAWING
744 if (ctx->num_of_fb_lay_skip == 0)
745#endif
746 {
747 glDisable(GL_SCISSOR_TEST);
748 glClearColor(0, 0, 0, 0);
749 glClear(GL_COLOR_BUFFER_BIT);
750 glEnable(GL_SCISSOR_TEST);
751 need_swap_buffers = true;
752 }
753 }
754 ctx->num_of_fb_layer_prev = ctx->num_of_fb_layer;
755
codeworkx62f02ba2012-05-20 12:00:36 +0200756 //compose hardware layers here
757 for (int i = 0; i < ctx->num_of_hwc_layer - ctx->num_2d_blit_layer; i++) {
758 win = &ctx->win[i];
759 if (win->status == HWC_WIN_RESERVED) {
760 cur = &list->hwLayers[win->layer_index];
761
762 if (cur->compositionType == HWC_OVERLAY) {
763 if (ctx->layer_prev_buf[i] == (uint32_t)cur->handle) {
764 /*
765 * In android platform, all the graphic buffer are at least
766 * double buffered (2 or more) this buffer is already rendered.
767 * It is the redundant src buffer for FIMC rendering.
768 */
espenfjo34f9d5d2012-12-01 18:52:36 +0100769
codeworkx62f02ba2012-05-20 12:00:36 +0200770#if defined(BOARD_USES_HDMI)
771 skip_hdmi_rendering = 1;
772#endif
773 continue;
774 }
775 ctx->layer_prev_buf[i] = (uint32_t)cur->handle;
776 // initialize the src & dist context for fimc
777 set_src_dst_img_rect(cur, win, &src_img, &dst_img,
778 &src_work_rect, &dst_work_rect, i);
779
780 ret = runFimc(ctx,
781 &src_img, &src_work_rect,
782 &dst_img, &dst_work_rect,
783 cur->transform);
784
785 if (ret < 0) {
786 SEC_HWC_Log(HWC_LOG_ERROR, "%s::runFimc fail : ret=%d\n",
787 __func__, ret);
788 skipped_window_mask |= (1 << i);
789 continue;
790 }
791
792 window_pan_display(win);
793
794 win->buf_index = (win->buf_index + 1) % NUM_OF_WIN_BUF;
795 if (win->power_state == 0)
796 window_show(win);
797 } else {
798 SEC_HWC_Log(HWC_LOG_ERROR,
799 "%s:: error : layer %d compositionType should have been"
800 " HWC_OVERLAY ", __func__, win->layer_index);
801 skipped_window_mask |= (1 << i);
802 continue;
803 }
804 } else {
805 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: error : window status should have "
806 "been HWC_WIN_RESERVED by now... ", __func__);
807 skipped_window_mask |= (1 << i);
808 continue;
809 }
810 }
811
codeworkx62f02ba2012-05-20 12:00:36 +0200812 if (skipped_window_mask) {
813 //turn off the free windows
814 for (int i = 0; i < NUM_OF_WIN; i++) {
815 if (skipped_window_mask & (1 << i)) {
816 window_hide(&ctx->win[i]);
817 reset_win_rect_info(&ctx->win[i]);
818 }
819 }
820 }
821
espenfjo34f9d5d2012-12-01 18:52:36 +0100822 if (need_swap_buffers) {
codeworkx62f02ba2012-05-20 12:00:36 +0200823#ifdef CHECK_EGL_FPS
824 check_fps();
825#endif
826#ifdef HWC_HWOVERLAY
827 unsigned char pixels[4];
828 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
829#endif
espenfjo34f9d5d2012-12-01 18:52:36 +0100830 EGLBoolean sucess = eglSwapBuffers((EGLDisplay)list->dpy, (EGLSurface)list->sur);
codeworkx62f02ba2012-05-20 12:00:36 +0200831 if (!sucess)
832 return HWC_EGL_ERROR;
833 }
834
835#if defined(BOARD_USES_HDMI)
836 android::SecHdmiClient *mHdmiClient = android::SecHdmiClient::getInstance();
837
838 if (skip_hdmi_rendering == 1)
839 return 0;
840
841 if (list == NULL) {
842 // Don't display unnecessary image
843 mHdmiClient->setHdmiEnable(0);
844 return 0;
845 } else {
846 mHdmiClient->setHdmiEnable(1);
847 }
848
849#ifdef SUPPORT_AUTO_UI_ROTATE
850 cur = &list->hwLayers[0];
851
852 if (cur->transform == HAL_TRANSFORM_ROT_90 || cur->transform == HAL_TRANSFORM_ROT_270)
853 mHdmiClient->setHdmiRotate(270, ctx->num_of_hwc_layer);
854 else
855 mHdmiClient->setHdmiRotate(0, ctx->num_of_hwc_layer);
856#endif
857
858 // To support S3D video playback (automatic TV mode change to 3D mode)
859 if (ctx->num_of_hwc_layer == 1) {
860 if (src_img.usage != prev_usage)
espenfjo34f9d5d2012-12-01 18:52:36 +0100861 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200862
863 if ((src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
864 (src_img.usage & GRALLOC_USAGE_PRIVATE_SBS_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100865 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 +0200866 else if ((src_img.usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
867 (src_img.usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100868 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 +0200869
870 prev_usage = src_img.usage;
871 } else {
872 if ((prev_usage & GRALLOC_USAGE_PRIVATE_SBS_LR) ||
873 (prev_usage & GRALLOC_USAGE_PRIVATE_SBS_RL) ||
874 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_LR) ||
875 (prev_usage & GRALLOC_USAGE_PRIVATE_TB_RL))
espenfjo34f9d5d2012-12-01 18:52:36 +0100876 mHdmiClient->setHdmiResolution(DEFAULT_HDMI_RESOLUTION_VALUE, android::SecHdmiClient::HDMI_2D); // V4L2_STD_1080P_60
codeworkx62f02ba2012-05-20 12:00:36 +0200877
878 prev_usage = 0;
879 }
880
881 if (ctx->num_of_hwc_layer == 1) {
882 if ((src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCbCr_420_SP_TILED)||
883 (src_img.format == HAL_PIXEL_FORMAT_CUSTOM_YCrCb_420_SP)) {
884 ADDRS * addr = (ADDRS *)(src_img.base);
espenfjo34f9d5d2012-12-01 18:52:36 +0100885 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200886 src_img.format,
887 (unsigned int)addr->addr_y, (unsigned int)addr->addr_cbcr, (unsigned int)addr->addr_cbcr,
888 0, 0,
889 android::SecHdmiClient::HDMI_MODE_VIDEO,
890 ctx->num_of_hwc_layer);
891 } else if ((src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_SP) ||
892 (src_img.format == HAL_PIXEL_FORMAT_YCrCb_420_SP) ||
893 (src_img.format == HAL_PIXEL_FORMAT_YCbCr_420_P) ||
894 (src_img.format == HAL_PIXEL_FORMAT_YV12)) {
espenfjo34f9d5d2012-12-01 18:52:36 +0100895 mHdmiClient->blit2Hdmi(src_work_rect.w, src_work_rect.h,
codeworkx62f02ba2012-05-20 12:00:36 +0200896 src_img.format,
897 (unsigned int)ctx->fimc.params.src.buf_addr_phy_rgb_y,
898 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cb,
899 (unsigned int)ctx->fimc.params.src.buf_addr_phy_cr,
900 0, 0,
901 android::SecHdmiClient::HDMI_MODE_VIDEO,
902 ctx->num_of_hwc_layer);
903 } else {
espenfjo34f9d5d2012-12-01 18:52:36 +0100904 SEC_HWC_Log(HWC_LOG_ERROR, "%s: Unsupported format = %d", __func__, src_img.format);
codeworkx62f02ba2012-05-20 12:00:36 +0200905 }
906 }
907#endif
Andrew Dodde6a23d72012-12-02 21:50:58 -0500908
codeworkx62f02ba2012-05-20 12:00:36 +0200909 return 0;
910}
911
espenfjo34f9d5d2012-12-01 18:52:36 +0100912static void hwc_registerProcs(struct hwc_composer_device_1* dev,
913 hwc_procs_t const* procs)
914{
915 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
916 ctx->procs = const_cast<hwc_procs_t *>(procs);
917}
918
919static int hwc_query(struct hwc_composer_device_1* dev,
920 int what, int* value)
921{
922 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
923
924 switch (what) {
925 case HWC_BACKGROUND_LAYER_SUPPORTED:
926 // we don't support the background layer yet
927 value[0] = 0;
928 break;
929 case HWC_VSYNC_PERIOD:
930 // vsync period in nanosecond
931 value[0] = 1000000000.0 / 57;
932 break;
933 default:
934 // unsupported query
935 return -EINVAL;
936 }
937 return 0;
938}
939
940static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
941 int event, int enabled)
942{
943 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
944
945 switch (event) {
946 case HWC_EVENT_VSYNC:
947 int val = !!enabled;
codeworkx39aefd02012-12-02 19:39:25 +0100948 int err = ioctl(ctx->global_lcd_win.fd, S3CFB_SET_VSYNC_INT, &val);
espenfjo34f9d5d2012-12-01 18:52:36 +0100949 if (err < 0)
950 return -errno;
951
952 return 0;
953 }
954 return -EINVAL;
955}
956
codeworkxabfed772012-12-01 19:37:39 +0100957#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +0100958static void *hwc_vsync_sysfs_loop(void *data)
959{
960 static char buf[4096];
961 int vsync_timestamp_fd;
962 fd_set exceptfds;
963 int res;
964 int64_t timestamp = 0;
965 hwc_context_t * ctx = (hwc_context_t *)(data);
966
967 vsync_timestamp_fd = open("/sys/devices/platform/samsung-pd.2/s3cfb.0/vsync_time", O_RDONLY);
968 char thread_name[64] = "hwcVsyncThread";
969 prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
970 setpriority(PRIO_PROCESS, 0, -20);
971 memset(buf, 0, sizeof(buf));
972
973 SEC_HWC_Log(HWC_LOG_DEBUG,"Using sysfs mechanism for VSYNC notification");
974
975 FD_ZERO(&exceptfds);
976 FD_SET(vsync_timestamp_fd, &exceptfds);
977 do {
978 ssize_t len = read(vsync_timestamp_fd, buf, sizeof(buf));
979 timestamp = strtoull(buf, NULL, 0);
980 ctx->procs->vsync(ctx->procs, 0, timestamp);
981 select(vsync_timestamp_fd + 1, NULL, NULL, &exceptfds, NULL);
982 lseek(vsync_timestamp_fd, 0, SEEK_SET);
983 } while (1);
984
985 return NULL;
986}
codeworkxabfed772012-12-01 19:37:39 +0100987#endif
988
989void handle_vsync_uevent(hwc_context_t *ctx, const char *buff, int len)
990{
991 uint64_t timestamp = 0;
992 const char *s = buff;
993
994 if(!ctx->procs || !ctx->procs->vsync)
995 return;
996
997 s += strlen(s) + 1;
998
999 while(*s) {
1000 if (!strncmp(s, "VSYNC=", strlen("VSYNC=")))
1001 timestamp = strtoull(s + strlen("VSYNC="), NULL, 0);
1002
1003 s += strlen(s) + 1;
1004 if (s - buff >= len)
1005 break;
1006 }
1007
1008 ctx->procs->vsync(ctx->procs, 0, timestamp);
1009}
1010
1011static void *hwc_vsync_thread(void *data)
1012{
1013 hwc_context_t *ctx = (hwc_context_t *)(data);
1014 char uevent_desc[4096];
1015
1016 memset(uevent_desc, 0, sizeof(uevent_desc));
1017 setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
1018 uevent_init();
1019
1020 while(true) {
1021
1022 int len = uevent_next_event(uevent_desc, sizeof(uevent_desc) - 2);
1023
1024 bool vsync = !strcmp(uevent_desc, "change@/devices/platform/samsung-pd.2/s3cfb.0");
1025 if(vsync)
1026 handle_vsync_uevent(ctx, uevent_desc, len);
1027 }
1028
1029 return NULL;
1030}
espenfjo34f9d5d2012-12-01 18:52:36 +01001031
codeworkx62f02ba2012-05-20 12:00:36 +02001032static int hwc_device_close(struct hw_device_t *dev)
1033{
1034 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
1035 int ret = 0;
1036 int i;
1037 if (ctx) {
1038 if (destroyFimc(&ctx->fimc) < 0) {
1039 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc fail", __func__);
1040 ret = -1;
1041 }
codeworkx62f02ba2012-05-20 12:00:36 +02001042
codeworkx39aefd02012-12-02 19:39:25 +01001043 if (window_close(&ctx->global_lcd_win) < 0) {
1044 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_close() fail", __func__);
1045 ret = -1;
1046 }
1047
codeworkx62f02ba2012-05-20 12:00:36 +02001048 for (i = 0; i < NUM_OF_WIN; i++) {
1049 if (window_close(&ctx->win[i]) < 0)
1050 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1051 }
1052
1053 free(ctx);
1054 }
1055 return ret;
1056}
Andrew Dodde6a23d72012-12-02 21:50:58 -05001057
espenfjo34f9d5d2012-12-01 18:52:36 +01001058static int hwc_blank(struct hwc_composer_device_1 *dev, int dpy, int blank)
1059{
Andrew Dodde6a23d72012-12-02 21:50:58 -05001060 struct hwc_context_t* ctx = (struct hwc_context_t*)dev;
1061 if (blank) {
1062 // release our resources, the screen is turning off
1063 // in our case, there is nothing to do.
1064 ctx->num_of_fb_layer_prev = 0;
1065 return 0;
1066 }
1067 else {
1068 // No need to unblank, will unblank on set()
1069 return 0;
1070 }
1071}
1072
Ricardo Cerqueira99f63f22014-01-15 16:50:35 +00001073int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
1074 uint32_t* configs, size_t* numConfigs) {
1075 int status = 0;
1076 switch(disp) {
1077 case HWC_DISPLAY_PRIMARY:
1078 if(*numConfigs > 0) {
1079 configs[0] = 0;
1080 *numConfigs = 1;
1081 }
1082 status = 0;
1083 break;
1084 case HWC_DISPLAY_EXTERNAL:
1085 status = -1; //Not connected, this is broken atm
1086 break;
1087 }
1088 return status;
1089}
1090
1091int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
1092 uint32_t config, const uint32_t* attributes, int32_t* values) {
1093
1094 hwc_context_t* ctx = (hwc_context_t*)(dev);
1095 if(disp == HWC_DISPLAY_EXTERNAL) {
1096 return -1;
1097 }
1098
1099 static const uint32_t DISPLAY_ATTRIBUTES[] = {
1100 HWC_DISPLAY_VSYNC_PERIOD,
1101 HWC_DISPLAY_WIDTH,
1102 HWC_DISPLAY_HEIGHT,
1103 HWC_DISPLAY_DPI_X,
1104 HWC_DISPLAY_DPI_Y,
1105 HWC_DISPLAY_NO_ATTRIBUTE,
1106 };
1107
1108 const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
1109 sizeof(DISPLAY_ATTRIBUTES)[0]);
1110
1111 struct fb_var_screeninfo info = ctx->lcd_info;
1112
1113 for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
1114 switch (attributes[i]) {
1115 case HWC_DISPLAY_VSYNC_PERIOD:
1116 values[i] = (int32_t) (1000000000.0 / 57);
1117 ALOGD("My vsync period is %d for %d",values[i],disp);
1118 break;
1119 case HWC_DISPLAY_WIDTH:
1120 values[i] = info.xres;
1121 ALOGD("My width is %d for %d",values[i],disp);
1122 break;
1123 case HWC_DISPLAY_HEIGHT:
1124 values[i] = info.yres;
1125 ALOGD("My height is %d for %d",values[i],disp);
1126 break;
1127 case HWC_DISPLAY_DPI_X:
1128 values[i] = (int32_t) ((info.xres * 25.4f) / info.width);
1129 values[i]*=1000;
1130 ALOGD("My hdpi is %d for %d",values[i],disp);
1131 break;
1132 case HWC_DISPLAY_DPI_Y:
1133 values[i] = (int32_t) ((info.yres * 25.4f) / info.height);
1134 values[i]*=1000;
1135 ALOGD("My vdpi is %d for %d",values[i],disp);
1136 break;
1137 default:
1138 ALOGE("Unknown display attribute %d",
1139 attributes[i]);
1140 return -EINVAL;
1141 }
1142 }
1143 return 0;
1144}
1145
codeworkx62f02ba2012-05-20 12:00:36 +02001146static int hwc_device_open(const struct hw_module_t* module, const char* name,
1147 struct hw_device_t** device)
1148{
1149 int status = 0;
espenfjo34f9d5d2012-12-01 18:52:36 +01001150 int err = 0;
codeworkx62f02ba2012-05-20 12:00:36 +02001151 struct hwc_win_info_t *win;
1152
1153 if (strcmp(name, HWC_HARDWARE_COMPOSER))
1154 return -EINVAL;
1155
1156 struct hwc_context_t *dev;
1157 dev = (hwc_context_t*)malloc(sizeof(*dev));
1158
1159 /* initialize our state here */
1160 memset(dev, 0, sizeof(*dev));
1161
1162 /* initialize the procs */
espenfjo34f9d5d2012-12-01 18:52:36 +01001163 dev->device.common.tag = HARDWARE_DEVICE_TAG;
Ricardo Cerqueira99f63f22014-01-15 16:50:35 +00001164 dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
espenfjo34f9d5d2012-12-01 18:52:36 +01001165 dev->device.common.module = const_cast<hw_module_t*>(module);
1166 dev->device.common.close = hwc_device_close;
1167 dev->device.prepare = hwc_prepare;
1168 dev->device.set = hwc_set;
1169 dev->device.eventControl = hwc_eventControl;
codeworkx39aefd02012-12-02 19:39:25 +01001170 dev->device.blank = hwc_blank;
espenfjo34f9d5d2012-12-01 18:52:36 +01001171 dev->device.query = hwc_query;
1172 dev->device.registerProcs = hwc_registerProcs;
Ricardo Cerqueira99f63f22014-01-15 16:50:35 +00001173 dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
1174 dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
codeworkx62f02ba2012-05-20 12:00:36 +02001175 *device = &dev->device.common;
1176
1177 //initializing
1178 memset(&(dev->fimc), 0, sizeof(s5p_fimc_t));
espenfjo34f9d5d2012-12-01 18:52:36 +01001179
codeworkx39aefd02012-12-02 19:39:25 +01001180 /* open WIN0 & WIN1 here */
1181 for (int i = 0; i < NUM_OF_WIN; i++) {
codeworkx62f02ba2012-05-20 12:00:36 +02001182 if (window_open(&(dev->win[i]), i) < 0) {
1183 SEC_HWC_Log(HWC_LOG_ERROR,
1184 "%s:: Failed to open window %d device ", __func__, i);
codeworkx39aefd02012-12-02 19:39:25 +01001185 status = -EINVAL;
1186 goto err;
codeworkx62f02ba2012-05-20 12:00:36 +02001187 }
codeworkx39aefd02012-12-02 19:39:25 +01001188 }
codeworkx62f02ba2012-05-20 12:00:36 +02001189
codeworkx39aefd02012-12-02 19:39:25 +01001190 /* open window 2, used to query global LCD info */
1191 if (window_open(&dev->global_lcd_win, 2) < 0) {
1192 SEC_HWC_Log(HWC_LOG_ERROR, "%s:: Failed to open window 2 device ", __func__);
1193 status = -EINVAL;
1194 goto err;
1195 }
1196
1197 if (window_get_global_lcd_info(dev) < 0) {
codeworkx62f02ba2012-05-20 12:00:36 +02001198 SEC_HWC_Log(HWC_LOG_ERROR,
1199 "%s::window_get_global_lcd_info is failed : %s",
1200 __func__, strerror(errno));
1201 status = -EINVAL;
1202 goto err;
1203 }
1204
1205#if defined(BOARD_USES_HDMI)
1206 lcd_width = dev->lcd_info.xres;
1207 lcd_height = dev->lcd_info.yres;
1208#endif
1209
1210 /* initialize the window context */
1211 for (int i = 0; i < NUM_OF_WIN; i++) {
1212 win = &dev->win[i];
1213 memcpy(&win->lcd_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1214 memcpy(&win->var_info, &dev->lcd_info, sizeof(struct fb_var_screeninfo));
1215
1216 win->rect_info.x = 0;
1217 win->rect_info.y = 0;
1218 win->rect_info.w = win->var_info.xres;
1219 win->rect_info.h = win->var_info.yres;
1220
1221 if (window_set_pos(win) < 0) {
1222 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_set_pos is failed : %s",
1223 __func__, strerror(errno));
1224 status = -EINVAL;
1225 goto err;
1226 }
1227
1228 if (window_get_info(win, i) < 0) {
1229 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_get_info is failed : %s",
1230 __func__, strerror(errno));
1231 status = -EINVAL;
1232 goto err;
1233 }
1234
1235 }
1236
codeworkx62f02ba2012-05-20 12:00:36 +02001237 //create PP
1238 if (createFimc(&dev->fimc) < 0) {
1239 SEC_HWC_Log(HWC_LOG_ERROR, "%s::creatFimc() fail", __func__);
1240 status = -EINVAL;
1241 goto err;
1242 }
1243
codeworkxabfed772012-12-01 19:37:39 +01001244#ifndef SYSFS_VSYNC_NOTIFICATION
1245 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev);
1246 if (err) {
1247 ALOGE("%s::pthread_create() failed : %s", __func__, strerror(err));
1248 status = -err;
1249 goto err;
1250 }
1251#endif
1252
1253#ifdef SYSFS_VSYNC_NOTIFICATION
espenfjo34f9d5d2012-12-01 18:52:36 +01001254 err = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_sysfs_loop, dev);
1255 if (err) {
1256 SEC_HWC_Log(HWC_LOG_ERROR, "%s::pthread_create() failed : %s", __func__, strerror(err));
1257 status = -err;
codeworkx62f02ba2012-05-20 12:00:36 +02001258 goto err;
1259 }
codeworkxabfed772012-12-01 19:37:39 +01001260#endif
codeworkx62f02ba2012-05-20 12:00:36 +02001261
1262 SEC_HWC_Log(HWC_LOG_DEBUG, "%s:: hwc_device_open: SUCCESS", __func__);
1263
1264 return 0;
1265
1266err:
1267 if (destroyFimc(&dev->fimc) < 0)
1268 SEC_HWC_Log(HWC_LOG_ERROR, "%s::destroyFimc() fail", __func__);
codeworkx62f02ba2012-05-20 12:00:36 +02001269
codeworkx39aefd02012-12-02 19:39:25 +01001270 if (window_close(&dev->global_lcd_win) < 0)
1271 SEC_HWC_Log(HWC_LOG_ERROR, "%s::window_close() fail", __func__);
1272
codeworkx62f02ba2012-05-20 12:00:36 +02001273 for (int i = 0; i < NUM_OF_WIN; i++) {
1274 if (window_close(&dev->win[i]) < 0)
1275 SEC_HWC_Log(HWC_LOG_DEBUG, "%s::window_close() fail", __func__);
1276 }
1277
1278 return status;
1279}