author | stark.li <stark.li@amlogic.com> | 2014-09-16 06:37:57 (GMT) |
---|---|---|
committer | Sandy lUo <sandy.luo@amlogic.com> | 2014-09-16 06:37:57 (GMT) |
commit | 0652b0620300af9ee0abf9e5c76c6903f95ebf1d (patch) | |
tree | a3e3fc9822c972509607d77edcf578123e235b77 | |
parent | 6200aa7dfa5b8b91c6eb6d8fc4ad4f5063d19bc1 (diff) | |
download | hwcomposer-0652b0620300af9ee0abf9e5c76c6903f95ebf1d.zip hwcomposer-0652b0620300af9ee0abf9e5c76c6903f95ebf1d.tar.gz hwcomposer-0652b0620300af9ee0abf9e5c76c6903f95ebf1d.tar.bz2 |
PD#89016:add hw fence
Squashed commit of the following:
commit cff48a0bfd2493ab544c196ffc7cddff6b054bb3
Author: stark.li <stark.li@amlogic.com>
Date: Mon Sep 15 16:35:38 2014 +0800
fixed compile issue
Change-Id: I2f9ea4f316aa07a24085daf02dd98e2c35c5f272
commit bdcdfd1198e8b36ee25d0b7246fd66833d54be5a
Author: stark.li <stark.li@amlogic.com>
Date: Mon Sep 15 14:27:07 2014 +0800
Conflicts:
Android.mk
hwcomposer.cpp
Change-Id: I2203d10be96cf7bca08f895f176a63a1a6dc45e3
commit fdc34de7315f87c5dc7551bc4625239b6aa6b30b
Author: stark.li <stark.li@amlogic.com>
Date: Fri Sep 12 13:45:54 2014 +0800
add some dump info and loglevel
Change-Id: I73009b9e3d145712f65c7245597afc0799c0ab4f
commit 615a250eab4623c06c58e98668119e461782efa6
Author: stark.li <stark.li@amlogic.com>
Date: Thu Sep 11 14:13:24 2014 +0800
fixed mali r4p1 can not resume issue
Change-Id: Ice664914d30ee5187dc7a9b8e4a465f28f2eb04f
commit 8d35d4a138a6a7a17b3da1607d702d4b16ff6d05
Author: stark.li <stark.li@amlogic.com>
Date: Tue Sep 9 09:49:07 2014 +0800
fix some benchmark can not display all results
Change-Id: If533a17fd9d08ffbf0ab598ec8d78b928f1a58c5
commit 4ec6531bfb03e02d925af96a6085d2204ea0196e
Author: stark.li <stark.li@amlogic.com>
Date: Mon Sep 1 14:27:54 2014 +0800
rename external display define
Change-Id: I164f25679dfb9ebe517ff3fbdac35fd5136f4cf6
commit 2072d56ba010cce022b5c0b2290161cd22618fc1
Author: stark.li <stark.li@amlogic.com>
Date: Thu Aug 28 15:46:11 2014 +0800
PD#91153 add overlay to instead videohole to play video
Change-Id: I26190cc5afaf3cf777d65ce7bbe2b832178b1d7b
commit 7aa92330d7aef2e4520855cec8342fd744672a14
Author: stark.li <stark.li@amlogic.com>
Date: Thu Aug 28 15:18:25 2014 +0800
fix fbpost same framebuffer when blank(suspend)
Change-Id: I43438894dfedd4c8eb9378f703461ebd3c91d1fd
commit a9c32109060f36e0827b13876b464fa6fe7dfc0c
Author: jintao.xu <jintao.xu@amlogic.com>
Date: Tue Jul 8 14:45:20 2014 +0800
PD #92195 omx decoder 4k2k video display
commit 7b8c9c26774f945ded9a815a2abacaf84fbf9dcb
Author: jianfeng.wang <jianfeng.wang@amlogic.com>
Date: Fri Apr 11 14:07:13 2014 +0800
PD#86062 hwc no need closing acquire fence fd
commit 9e8efbb052fd50a8c7e53f03ae2d0a393c0ab090
Author: jianfeng.wang <jianfeng.wang@amlogic.com>
Date: Mon Mar 31 18:39:52 2014 +0800
sync acquire fence ,work with kernel work queue version
commit 26472cc18a86ef7decd3698a5a5cebafb7e63a38
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Fri Mar 21 10:05:47 2014 +0800
don't close acquire fence,it may be in use
commit e06d73350e982083a68e7b23c25365d4862dd775
Author: stark.li <stark.li@amlogic.com>
Date: Thu Mar 20 11:15:23 2014 +0800
fix compile error
commit e79abc6400185bc2625cd6bcc3d77c52c7fba70f
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Fri Mar 14 14:22:09 2014 +0800
add code for suppot fence
commit 9c494b37927572f7d71d6abfec18a1bd7dfe21b2
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Fri Mar 14 10:17:23 2014 +0800
refactor for use hw vysnc
commit 7a4374dc4c88c649ef5a299a78d6ccf564d532a5
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Thu Mar 13 16:44:56 2014 +0800
don't unregister fraembuffer when device unpluged,for sf may be using frame buffers
commit 9337e212d1ac0238999d8dc4e2430ed63ddce8f9
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Thu Mar 13 15:56:38 2014 +0800
fix external fb register bug
commit 320b27dab89e0f04dbc3c406f9023da4507c21f2
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Thu Mar 13 13:48:27 2014 +0800
fix fence wait bug and
commit 32f28b6ac86972e0b07eb743eb8ade625e1187eb
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Wed Mar 12 20:12:29 2014 +0800
update for useing framebuffer api and struct
commit cd081d6249991c1c1378f13a76ea11d8761267fb
Author: stark.li <stark.li@amlogic.com>
Date: Thu Mar 6 18:54:23 2014 +0800
settle and cleanup some functions
commit 806e03d1bec232984ba96cb7129f854a671269cd
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Wed Feb 12 15:48:19 2014 +0800
PD #86062: add debug mode, and add simulate hot plug
commit 0aefdde6c1bb61ff4474afaf6fa27c420e09417f
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Tue Jan 28 14:51:10 2014 +0800
pd#86062: update for framebuffer
commit 49bb70e68bef1883e6bf813e9fe38ff087c69944
Author: sky.zhou <sky.zhou@amlogic.com>
Date: Tue Jan 28 13:13:31 2014 +0800
pd#86062: update with framebuffer struct
commit 2e5351b65c091e5effca7b88a423afc48672d5af
Author: wei.wang <wei.wang@amlogic.com>
Date: Sun Jan 26 17:58:15 2014 +0800
pd#86062:add fb_post_hdmi() etc. to support hdmi display
commit 40cd34acced1d7d2960f75dbe9677345bb7609de
Author: wei.wang <wei.wang@amlogic.com>
Date: Thu Jan 16 16:14:37 2014 +0800
pd#86062:check if hdmi is plug in by hdmi-check-point
commit 536f79c5165f9d245eafd8b3d073d8ddcba80154
Author: stark.li <stark.li@amlogic.com>
Date: Wed Jan 15 17:17:11 2014 +0800
merge ww's changes
commit f23898bafb5243a7619999f5c22721834dde0e1c
Author: stark.li <stark.li@amlogic.com>
Date: Wed Jan 15 16:55:37 2014 +0800
add post func in hwc
commit a2c93975e30038a160b6f30339be1354597d0427
Author: stark.li <stark.li@amlogic.com>
Date: Wed Jan 15 09:52:32 2014 +0800
fix fenceid is not closed leads to reboot surfaceflinger
commit ea48801a100efcfd22a219a2bfc1906b94b5811c
Author: wei.wang <wei.wang@amlogic.com>
Date: Mon Jan 13 17:02:15 2014 +0800
pd#86062: add api to support HWC 1.1
commit 41e76d0164ecd6b916700735ec1ba7b90649c9b9
Author: stark.li <stark.li@amlogic.com>
Date: Mon Jan 13 13:35:35 2014 +0800
new hwcomposer 1.1 minmum2
commit 92454f287c08619eb59c678c4fb07a6db7d7a149
Author: stark.li <stark.li@amlogic.com>
Date: Mon Jan 13 13:19:24 2014 +0800
new hwcomposer 1.1 minmum
Change-Id: Ia24fdf027a0e66ec18433045974bbd0c0e8e3804
-rwxr-xr-x | Android.mk | 7 | ||||
-rwxr-xr-x | hwcomposer.cpp | 821 |
2 files changed, 708 insertions, 120 deletions
@@ -9,7 +9,7 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw -LOCAL_SHARED_LIBRARIES := liblog libEGL libutils libcutils +LOCAL_SHARED_LIBRARIES := liblog libEGL libutils libcutils libhardware libsync libfbcnf LOCAL_STATIC_LIBRARIES := libomxutil LOCAL_SRC_FILES := hwcomposer.cpp @@ -30,6 +30,11 @@ LOCAL_C_INCLUDES += \ LOCAL_CFLAGS += -DWITH_LIBPLAYER_MODULE=1 endif +ifeq ($(TARGET_EXTERNAL_DISPLAY),true) +#LOCAL_CFLAGS += -DDEBUG_EXTERNAL_DISPLAY_ON_PANEL +LOCAL_CFLAGS += -DWITH_EXTERNAL_DISPLAY +endif + LOCAL_MODULE := hwcomposer.amlogic LOCAL_CFLAGS += -DLOG_TAG=\"hwcomposer\" LOCAL_MODULE_TAGS := optional diff --git a/hwcomposer.cpp b/hwcomposer.cpp index 2701bab..f456562 100755 --- a/hwcomposer.cpp +++ b/hwcomposer.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -//#define LOG_NDEBUG 0 -#define LOG_TAG "hwcomposer" +#define LOG_NDEBUG 0 +#define LOG_TAG "HWComposer" #include <hardware/hardware.h> #include <fcntl.h> @@ -42,44 +42,143 @@ #include <cutils/properties.h> #include <utils/String8.h> +#include <hardware/gralloc.h> #include <hardware/hwcomposer.h> +#include <hardware_legacy/uevent.h> +#include <utils/String8.h> #include <EGL/egl.h> #include <utils/Vector.h> #include <utils/Timers.h> // for private_handle_t #include <gralloc_priv.h> +#include <gralloc_helper.h> #if WITH_LIBPLAYER_MODULE #include <Amavutils.h> #endif #include <system/graphics.h> + +#include <sync/sync.h> + #ifndef LOGD #define LOGD ALOGD #endif + +#define LogLevel 3 +///Defines for debug statements - Macro LOG_TAG needs to be defined in the respective files +#define HWC_LOGVA(str) ALOGV_IF(LogLevel >=6,"%5d %s - " str, __LINE__,__FUNCTION__); +#define HWC_LOGVB(str,...) ALOGV_IF(LogLevel >=6,"%5d %s - " str, __LINE__, __FUNCTION__, __VA_ARGS__); +#define HWC_LOGDA(str) ALOGD_IF(LogLevel >=5,"%5d %s - " str, __LINE__,__FUNCTION__); +#define HWC_LOGDB(str, ...) ALOGD_IF(LogLevel >=5,"%5d %s - " str, __LINE__, __FUNCTION__, __VA_ARGS__); +#define HWC_LOGIA(str) ALOGI_IF(LogLevel >=4,"%5d %s - " str, __LINE__, __FUNCTION__); +#define HWC_LOGIB(str, ...) ALOGI_IF(LogLevel >=4,"%5d %s - " str, __LINE__,__FUNCTION__, __VA_ARGS__); +#define HWC_LOGWA(str) ALOGW_IF(LogLevel >=3,"%5d %s - " str, __LINE__, __FUNCTION__); +#define HWC_LOGWB(str, ...) ALOGW_IF(LogLevel >=3,"%5d %s - " str, __LINE__,__FUNCTION__, __VA_ARGS__); +#define HWC_LOGEA(str) ALOGE_IF(LogLevel >=2,"%5d %s - " str, __LINE__, __FUNCTION__); +#define HWC_LOGEB(str, ...) ALOGE_IF(LogLevel >=2,"%5d %s - " str, __LINE__,__FUNCTION__, __VA_ARGS__); + +#define LOG_FUNCTION_NAME HWC_LOGVA("ENTER"); +#define LOG_FUNCTION_NAME_EXIT HWC_LOGVA("EXIT"); +#define DBG_LOGA(str) ALOGI_IF(LogLevel >=4,"%10s-%5d %s - " str, HWC_BUILD_NAME, __LINE__,__FUNCTION__) +#define DBG_LOGB(str, ...) ALOGI_IF(LogLevel >=4,"%10s-%5d %s - " str, HWC_BUILD_NAME, __LINE__,__FUNCTION__, __VA_ARGS__); + #include "tvp/OmxUtil.h" static int Amvideo_Handle = 0; + extern "C" int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *request, struct timespec *remain); /*****************************************************************************/ +static int chk_and_dup(int fence) +{ + if (fence < 0){ + HWC_LOGWB("not a vliad fence %d",fence); + return -1; + } + + int dup_fence = dup(fence); + if(dup_fence < 0){ + HWC_LOGWB("fence dup failed: %s", strerror(errno)); + } + + return dup_fence; +} + + +#define MAX_SUPPORT_DISPLAYS HWC_NUM_PHYSICAL_DISPLAY_TYPES + +typedef struct display_context_t{ + bool connected; + struct framebuffer_info_t fb_info; + struct private_handle_t* fb_hnd; +}display_context_t; +struct hwc_context_1_t; + +int init_display(hwc_context_1_t* context,int displayType); +int uninit_display(hwc_context_1_t* context,int displayType); + +#define getDisplayInfo(ctx,disp) \ + display_context_t * display_ctx = &(ctx->display_ctxs[disp]);\ + framebuffer_info_t* fbinfo = &(display_ctx->fb_info); struct hwc_context_1_t { - hwc_composer_device_1_t device; + hwc_composer_device_1_t base; + /* our private state goes below here */ - hwc_layer_1_t const* saved_layer; + hwc_layer_1_t const* saved_layer; unsigned saved_transform; int saved_left; int saved_top; int saved_right; int saved_bottom; - int vsync_enable; + + //int vsync_fd; + //hwc_post_data_t bufs; + + +#if 0 + //alloc_device_t *alloc_device; + int force_gpu; + int fd; + int32_t xres; + int32_t yres; + int32_t xdpi; + int32_t ydpi; + + bool external_hpd; + bool external_fb_needed; + int external_w; + int external_h; + int external_mixer0; + bool external_enabled; + bool external_blanked; + //external_layer_t external_layers[2]; + //hwc_gsc_data_t gsc[NUM_GSC_UNITS]; + //struct s3c_fb_win_config last_config[NUM_HW_WINDOWS]; + //size_t last_fb_window; + //const void *last_handles[NUM_HW_WINDOWS]; + +#endif + + + //vsync. + int32_t vsync_period; + int vsync_enable; + bool blank_status; + + const hwc_procs_t *procs; pthread_t vsync_thread; + pthread_t hotplug_thread; + + + private_module_t *gralloc_module; + display_context_t display_ctxs[MAX_SUPPORT_DISPLAYS]; }; static int hwc_device_open(const struct hw_module_t* module, const char* name, @@ -90,18 +189,19 @@ static struct hw_module_methods_t hwc_module_methods = { }; hwc_module_t HAL_MODULE_INFO_SYM = { - common: { - tag: HARDWARE_MODULE_TAG, - version_major: 1, - version_minor: 0, - id: HWC_HARDWARE_MODULE_ID, - name: "hwcomposer module", - author: "Amlogic", - methods: &hwc_module_methods, - dso : NULL, - reserved : {0}, - } -}; + common: { + tag: HARDWARE_MODULE_TAG, + version_major: 1, + version_minor: 0, + id: HWC_HARDWARE_MODULE_ID, + name: "hwcomposer module", + author: "Amlogic", + methods: &hwc_module_methods, + dso : NULL, + reserved : {0}, + } + }; + static pthread_cond_t hwc_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t hwc_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -109,6 +209,38 @@ static pthread_mutex_t hwc_mutex = PTHREAD_MUTEX_INITIALIZER; /*****************************************************************************/ +static void dump_handle(private_handle_t *h) +{ + //ALOGV("\t\tformat = %d, width = %u, height = %u, stride = %u, vstride = %u", + // h->format, h->width, h->height, h->stride, h->vstride); +} + +static void dump_layer(hwc_layer_1_t const *l) +{ + HWC_LOGVB("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, " + "{%d,%d,%d,%d}, {%d,%d,%d,%d}", + l->compositionType, l->flags, l->handle, l->transform, + l->blending, + l->sourceCrop.left, + l->sourceCrop.top, + l->sourceCrop.right, + l->sourceCrop.bottom, + l->displayFrame.left, + l->displayFrame.top, + l->displayFrame.right, + l->displayFrame.bottom); + + if(l->handle && !(l->flags & HWC_SKIP_LAYER)) + dump_handle(private_handle_t::dynamicCast(l->handle)); +} +#if 0 +inline int WIDTH(const hwc_rect &rect) { return rect.right - rect.left; } +inline int HEIGHT(const hwc_rect &rect) { return rect.bottom - rect.top; } +template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; } +template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; } +#endif +/*****************************************************************************/ + int video_on_vpp2_enabled(void) { int ret = 0; @@ -124,7 +256,7 @@ int video_on_vpp2_enabled(void) return ret; } -static void hwc_overlay_compose(hwc_composer_device_1_t *dev, hwc_layer_1_t const* l) { +static void hwc_overlay_compose(hwc_context_1_t *dev, hwc_layer_1_t const* l) { int angle; struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)dev; @@ -155,7 +287,7 @@ static void hwc_overlay_compose(hwc_composer_device_1_t *dev, hwc_layer_1_t cons } } - static char last_free_scale[32] = {0}; + static char last_free_scale[32] = {0}; int free_scale_changed = 0; char free_scale[32]; memset(free_scale, 0, sizeof(free_scale)); @@ -229,23 +361,95 @@ static void hwc_overlay_compose(hwc_composer_device_1_t *dev, hwc_layer_1_t cons } } -/*static void dump_layer(hwc_layer_t const* l) { - LOGD("\ttype=%d, flags=%08x, handle=%p, tr=%02x, blend=%04x, {%d,%d,%d,%d}, {%d,%d,%d,%d}", - l->compositionType, l->flags, l->handle, l->transform, l->blending, - l->sourceCrop.left, - l->sourceCrop.top, - l->sourceCrop.right, - l->sourceCrop.bottom, - l->displayFrame.left, - l->displayFrame.top, - l->displayFrame.right, - l->displayFrame.bottom); -}*/ +static void hwc_dump(hwc_composer_device_1* dev, char *buff, int buff_len) +{ + if (buff_len <= 0) + return; -static int hwc_blank(struct hwc_composer_device_1* dev, - int disp, - int blank) + struct hwc_context_1_t *pdev = (struct hwc_context_1_t *)dev; + +#if 0 +#ifdef HWC_BASIC_INFO + HWC_LOGDB("\n--------------------------------\n" + "branch name: %s\n" + "git version: %s \n" + "last changed: %s\n" + "build-time: %s\n" + "build-name: %s\n" + "uncommitted-file-num:%d\n" + "ssh user@%s, cd %s\n" + "hostname %s\n" + "--------------------------------\n", + HWC_BRANCH_NAME, + HWC_GIT_VERSION, + HWC_LAST_CHANGED, + HWC_BUILD_TIME, + HWC_BUILD_NAME, + HWC_GIT_UNCOMMIT_FILE_NUM, + HWC_IP, HWC_PATH, HWC_HOSTNAME + ); +#endif +#endif + + android::String8 result; + + for (int i = 0; i < MAX_SUPPORT_DISPLAYS; i++) + { + getDisplayInfo(pdev,i); + + if (display_ctx->connected){ + result.appendFormat(" %8s Display connected: %3s\n", + HWC_DISPLAY_EXTERNAL == i ? "External":"Primiary", display_ctx->connected ? "Yes" : "No"); + result.appendFormat(" w=%u, h=%u, xdpi=%f, ydpi=%f, osdIdx=%d\n", + fbinfo->info.xres, + fbinfo->info.yres, + fbinfo->xdpi, + fbinfo->ydpi, + fbinfo->fbIdx); + } + } + + //result.append( + // " type | handle | color | blend | format | position | size | gsc \n" + // "----------+----------|----------+-------+--------+---------------+---------------------\n"); + // 8_______ | 8_______ | 8_______ | 5____ | 6_____ | [5____,5____] | [5____,5____] | 3__ \n" + + result.append("\n"); + + strlcpy(buff, result.string(), buff_len); +} + +static int hwc_blank(struct hwc_composer_device_1 *dev, int disp, int blank) +{ + struct hwc_context_1_t *pdev = + (struct hwc_context_1_t *)dev; + + //TODO: need impl + if (disp == HWC_DISPLAY_PRIMARY){ + pdev->blank_status = ( blank ? true : false); + } + + return 0; +} + +static int hwc_query(struct hwc_composer_device_1* dev, int what, int *value) { + struct hwc_context_1_t *pdev = + (struct hwc_context_1_t *)dev; + + switch (what) { + case HWC_BACKGROUND_LAYER_SUPPORTED: + // we support the background layer + value[0] = 1; + break; + case HWC_VSYNC_PERIOD: + // vsync period in nanosecond + value[0] = pdev->vsync_period; + break; + default: + // unsupported query + return -EINVAL; + } return 0; } @@ -258,7 +462,7 @@ static int hwc_eventControl(struct hwc_composer_device_1* dev, switch (event) { case HWC_EVENT_VSYNC: - ctx->vsync_enable =enabled; + ctx->vsync_enable = enabled; pthread_mutex_lock(&hwc_mutex); pthread_cond_signal(&hwc_cond); pthread_mutex_unlock(&hwc_mutex); @@ -267,40 +471,131 @@ static int hwc_eventControl(struct hwc_composer_device_1* dev, return -EINVAL; } +#if 0 +inline bool intersect(const hwc_rect &r1, const hwc_rect &r2) +{ + return !(r1.left > r2.right || + r1.right < r2.left || + r1.top > r2.bottom || + r1.bottom < r2.top); +} + +inline hwc_rect intersection(const hwc_rect &r1, const hwc_rect &r2) +{ + hwc_rect i; + i.top = max(r1.top, r2.top); + i.bottom = min(r1.bottom, r2.bottom); + i.left = max(r1.left, r2.left); + i.right = min(r1.right, r2.right); + return i; +} + +#endif + + static int hwc_prepare(struct hwc_composer_device_1 *dev, size_t numDisplays, hwc_display_contents_1_t** displays) { - hwc_display_contents_1_t *list = displays[0]; - for (size_t i=0 ; i<list->numHwLayers ; i++) { - hwc_layer_1_t* l = &list->hwLayers[i]; - if (l->handle) { - private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(l->handle); - if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OVERLAY) { - l->hints = HWC_HINT_CLEAR_FB; - l->compositionType = HWC_OVERLAY; + int err = 0, i = 0; + hwc_context_1_t *pdev = (hwc_context_1_t *)dev; + hwc_display_contents_1_t *display_content = NULL; + + if (!numDisplays || !displays) + return 0; + + LOG_FUNCTION_NAME + //retireFenceFd will close in surfaceflinger, just reset it. + for(i=0;i<numDisplays;i++){ + display_content = displays[i]; + if( display_content ){ + display_content->retireFenceFd = -1; + for (size_t i=0 ; i< display_content->numHwLayers ; i++) { + hwc_layer_1_t* l = &display_content->hwLayers[i]; + if (l->handle) { + private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(l->handle); + if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OVERLAY) { + l->hints = HWC_HINT_CLEAR_FB; + l->compositionType = HWC_OVERLAY; + continue; + } + } + } + } + } + LOG_FUNCTION_NAME_EXIT + return 0; +} +static int fb_post(hwc_context_1_t *pdev, + hwc_display_contents_1_t* contents, int display_type){ + int err = 0; + size_t i = 0; + for (i = 0; i < contents->numHwLayers; i++) { + if (contents->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET){ + hwc_layer_1_t *layer = &(contents->hwLayers[i]); + if (private_handle_t::validate(layer->handle) < 0) { + break; + } + getDisplayInfo(pdev, display_type); + + #ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL + int acquireFence = layer->acquireFenceFd; + if(display_type != displayWho()){ + close(acquireFence); + acquireFence = -1; continue; } + #endif + + layer->releaseFenceFd = fb_post_with_fence_locked(fbinfo,layer->handle,layer->acquireFenceFd); + + if(layer->releaseFenceFd >= 0){ + //layer->releaseFenceFd = releaseFence; + contents->retireFenceFd = chk_and_dup(layer->releaseFenceFd); + HWC_LOGDB("Get release fence %d, retire fence %d",layer->releaseFenceFd,contents->retireFenceFd); + }else{ + HWC_LOGEB("No valid release_fence returned. %d ",layer->releaseFenceFd); + if(layer->releaseFenceFd < -1)//-1 means no fence, less than -1 is some error + err = layer->releaseFenceFd; + + contents->retireFenceFd = layer->releaseFenceFd = -1; + } } } - return 0; + return err; +} + + +#ifdef DEBUG_EXTERNAL_DISPLAY_ON_PANEL +int displayWho(){ + int ret = 0; + char val[PROPERTY_VALUE_MAX]; + memset(val, 0, sizeof(val)); + if (property_get("debug.display_external", val, "0") + && strcmp(val, "1") == 0) { + ret = 1; + } + + return ret; } +#endif static int hwc_set(struct hwc_composer_device_1 *dev, - size_t numDisplays, - hwc_display_contents_1_t** displays) + size_t numDisplays, hwc_display_contents_1_t** displays) { - // On version 1.0(HWC_DEVICE_API_VERSION_1_0), the OpenGL ES target surface is communicated - // by the (dpy, sur) fields and we are guaranteed to have only - // a single display. - if (numDisplays != 1) { - return 0; - } - bool istvp = false; + int err = 0, i = 0;; + hwc_context_1_t *pdev = (hwc_context_1_t *)dev; + hwc_display_contents_1_t *display_content = NULL; + if (!numDisplays || !displays) + return 0; + + LOG_FUNCTION_NAME + //TODO: need improve the way to set video axis. #if WITH_LIBPLAYER_MODULE + bool istvp = false; hwc_display_contents_1_t *list = displays[0]; - for (size_t i=0 ; i<list->numHwLayers ; i++) { + for (i=0 ; i<list->numHwLayers ; i++) { hwc_layer_1_t* l = &list->hwLayers[i]; if (l->handle) { private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(l->handle); @@ -309,7 +604,7 @@ static int hwc_set(struct hwc_composer_device_1 *dev, istvp = true; } if (hnd->flags & private_handle_t::PRIV_FLAGS_VIDEO_OVERLAY) { - hwc_overlay_compose(dev, l); + hwc_overlay_compose(pdev, l); } } } @@ -319,65 +614,135 @@ static int hwc_set(struct hwc_composer_device_1 *dev, } #endif - - EGLBoolean success = eglSwapBuffers(displays[0]->dpy, displays[0]->sur); - if (!success) { - return HWC_EGL_ERROR; + for(i=0;i<numDisplays;i++){ + display_content = displays[i]; + if(display_content){ + if(i <= HWC_DISPLAY_EXTERNAL){ + //physic display + err = fb_post(pdev,display_content,i); + } else { + HWC_LOGEB("display %d is not supported",i); + } + } } - return 0; + + LOG_FUNCTION_NAME_EXIT + return err; } -static int hwc_device_close(struct hw_device_t *dev) +static int hwc_close(hw_device_t *device) { - struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)dev; - if (ctx) { - free(ctx); + struct hwc_context_1_t *dev = (struct hwc_context_1_t *)device; + + LOG_FUNCTION_NAME + + pthread_kill(dev->vsync_thread, SIGTERM); + pthread_join(dev->vsync_thread, NULL); + + uninit_display(dev,HWC_DISPLAY_PRIMARY); + uninit_display(dev,HWC_DISPLAY_EXTERNAL); + + if (dev) { + free(dev); } + + LOG_FUNCTION_NAME_EXIT return 0; } +//#define USE_HW_VSYNC +#ifdef USE_HW_VSYNC +/* +Still have bugs, don't use it. +*/ +int wait_next_vsync(struct hwc_context_1_t* ctx, nsecs_t* vsync_timestamp){ + static nsecs_t previewTime = 0; + nsecs_t vsyncDiff=0; + const nsecs_t period = ctx->vsync_period; + //we will delay hw vsync if missing one vsync interrupt isr. + int ret = 0; + + if (ioctl(ctx->display_ctxs[0].fb_info.fd, FBIO_WAITFORVSYNC, &ret) == -1){ + HWC_LOGEB("ioctrl error %d",ctx->display_ctxs[0].fb_info.fd); + ret=-1; + }else { + if(ret == 1){ + *vsync_timestamp = systemTime(CLOCK_MONOTONIC); + vsyncDiff=*vsync_timestamp - previewTime; + if(previewTime != 0) + HWC_LOGEB("wait for vsync success %lld",vsyncDiff); + vsyncDiff%=period; + if(vsyncDiff > 500000) + { + nsecs_t sleep ; + sleep = (period - vsyncDiff); + *vsync_timestamp+=sleep; + struct timespec spec; + spec.tv_sec = *vsync_timestamp / 1000000000; + spec.tv_nsec = *vsync_timestamp % 1000000000; + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); + } + previewTime = *vsync_timestamp; + ret=0; + }else{ + HWC_LOGEA("wait for vsync fail"); + ret=-1; + } + } + return ret; +} + +#else +//software +int wait_next_vsync(struct hwc_context_1_t* ctx , nsecs_t* vsync_timestamp){ + static nsecs_t nextFakeVSync = 0; + + const nsecs_t period = ctx->vsync_period; + const nsecs_t now = systemTime(CLOCK_MONOTONIC); + nsecs_t next_vsync = nextFakeVSync; + nsecs_t sleep = next_vsync - now; + if (sleep < 0) { + // we missed, find where the next vsync should be + sleep = (period - ((now - next_vsync) % period)); + next_vsync = now + sleep; + } + nextFakeVSync = next_vsync + period; + + struct timespec spec; + spec.tv_sec = next_vsync / 1000000000; + spec.tv_nsec = next_vsync % 1000000000; + + int err; + do { + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); + } while (err<0 && errno == EINTR); + *vsync_timestamp = next_vsync; + + return err; +} + +#endif static void *hwc_vsync_thread(void *data) { struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)data; nsecs_t nextFakeVSync = 0; + nsecs_t timestamp; setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY-1); sleep(2); while (true) { pthread_mutex_lock(&hwc_mutex); - while(ctx->vsync_enable==false) - { + while(ctx->vsync_enable==false) { pthread_cond_wait(&hwc_cond, &hwc_mutex); } pthread_mutex_unlock(&hwc_mutex); - //const nsecs_t period = 20000000; //50Hz - const nsecs_t period = 16666666; //60Hz - const nsecs_t now = systemTime(CLOCK_MONOTONIC); - nsecs_t next_vsync = nextFakeVSync; - nsecs_t sleep = next_vsync - now; - if (sleep < 0) { - // we missed, find where the next vsync should be - sleep = (period - ((now - next_vsync) % period)); - next_vsync = now + sleep; - } - nextFakeVSync = next_vsync + period; - - struct timespec spec; - spec.tv_sec = next_vsync / 1000000000; - spec.tv_nsec = next_vsync % 1000000000; - - int err; - do { - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); - } while (err<0 && errno == EINTR); - - if (err == 0) { + if (wait_next_vsync(ctx,×tamp) == 0) { if (ctx->procs) { - ctx->procs->vsync(ctx->procs, 0, next_vsync); + ctx->procs->vsync(ctx->procs, 0, timestamp); } } } @@ -385,49 +750,267 @@ static void *hwc_vsync_thread(void *data) return NULL; } +#ifdef WITH_EXTERNAL_DISPLAY + +#define SIMULATE_HOT_PLUG 1 +static bool chkExternalConnected(){ + LOG_FUNCTION_NAME + +#ifdef SIMULATE_HOT_PLUG + HWC_LOGDA("Simulate hot plug"); + char val[PROPERTY_VALUE_MAX]; + memset(val, 0, sizeof(val)); + property_get("debug.connect_external", val, "0"); + return (atoi(val)>0) ? true : false; +#else + //TODO:need to check hotplug callback for different device. + //Should consider different device. + + //use uevent. + HWC_LOGDA("hot plug is not implemented!!alwasy return true now."); + return true; +#endif + + LOG_FUNCTION_NAME_EXIT +} + +static void *hwc_hotplug_thread(void *data) +{ + struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)data; + + while (true) { + sleep(2);//sleep 1 s. + + if (ctx->procs) { + bool connect = chkExternalConnected(); + getDisplayInfo(ctx,HWC_DISPLAY_EXTERNAL); + if(display_ctx->connected != connect ){ + HWC_LOGDB("external new state : %d",connect); + if(display_ctx->connected == false ){ + init_display(ctx,HWC_DISPLAY_EXTERNAL); + } else { + uninit_display(ctx,HWC_DISPLAY_EXTERNAL); + } + ctx->procs->hotplug(ctx->procs, HWC_DISPLAY_EXTERNAL, connect); + } + } + } + return NULL; +} +#endif -static void hwc_registerProcs(hwc_composer_device_1_t *dev, +static void hwc_registerProcs(hwc_composer_device_1 *dev, hwc_procs_t const* procs) { struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)dev; - if (ctx) { + if (ctx) ctx->procs = procs; +} + +static int hwc_getDisplayConfigs(hwc_composer_device_1_t *dev, + int disp ,uint32_t *config ,size_t *numConfigs) +{ + struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)dev; + + if(*numConfigs == 0) + return 0; + + LOG_FUNCTION_NAME + + getDisplayInfo(ctx,disp); + + if(disp == HWC_DISPLAY_PRIMARY){ + config[0] = 0; + *numConfigs = 1; + return 0; + } else if(disp == HWC_DISPLAY_EXTERNAL) { + HWC_LOGEB("hwc_getDisplayConfigs:connect = %d",display_ctx->connected); + if(!display_ctx->connected){ + return -EINVAL; + } + + config[0] = 0; + *numConfigs = 1; + return 0; } + + LOG_FUNCTION_NAME_EXIT + return -EINVAL; } -/*****************************************************************************/ +static int hwc_getDisplayAttributes(hwc_composer_device_1_t *dev, + int disp, uint32_t config, const uint32_t *attributes, int32_t *values) +{ + struct hwc_context_1_t* ctx = (struct hwc_context_1_t*)dev; + + LOG_FUNCTION_NAME + + getDisplayInfo(ctx,disp); + + for (int i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) { + switch(attributes[i]) { + case HWC_DISPLAY_VSYNC_PERIOD: + values[i] = ctx->vsync_period; + break; + case HWC_DISPLAY_WIDTH: + values[i] = fbinfo->info.xres; + break; + case HWC_DISPLAY_HEIGHT: + values[i] = fbinfo->info.yres; + break; + case HWC_DISPLAY_DPI_X: + values[i] = fbinfo->xdpi*1000; + break; + case HWC_DISPLAY_DPI_Y: + values[i] = fbinfo->ydpi*1000; + break; + default: + HWC_LOGEB("unknown display attribute %u", attributes[i]); + values[i] = -EINVAL; + break; + } + } + + LOG_FUNCTION_NAME_EXIT + + return 0; +} static int hwc_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device) { - int status = -EINVAL; - if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { - struct hwc_context_1_t *dev; - dev = (hwc_context_1_t*)malloc(sizeof(*dev)); - - /* initialize our state here */ - memset(dev, 0, sizeof(*dev)); - - /* initialize the procs */ - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = HWC_DEVICE_API_VERSION_1_0; - dev->device.common.module = const_cast<hw_module_t*>(module); - dev->device.common.close = hwc_device_close; - - dev->device.blank = hwc_blank; - dev->device.eventControl = hwc_eventControl; - dev->device.registerProcs = hwc_registerProcs; - dev->device.prepare = hwc_prepare; - dev->device.set = hwc_set; - dev->vsync_enable = false; - *device = &dev->device.common; - status = 0; + int ret; + + if (strcmp(name, HWC_HARDWARE_COMPOSER)) { + return -EINVAL; + } + + struct hwc_context_1_t *dev; + dev = (struct hwc_context_1_t *)malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, + (const struct hw_module_t **)&dev->gralloc_module)) { + HWC_LOGEA("failed to get gralloc hw module"); + ret = -EINVAL; + goto err_get_module; + } + + //init primiary display + //default is alwasy false,will check it in hot plug. + init_display(dev,HWC_DISPLAY_PRIMARY); + + //60HZ, willchanged to use hw vsync. + dev->vsync_period = 16666666; + + dev->base.common.tag = HARDWARE_DEVICE_TAG; + dev->base.common.version = HWC_DEVICE_API_VERSION_1_1; + dev->base.common.module = const_cast<hw_module_t *>(module); + dev->base.common.close = hwc_close; + + dev->base.prepare = hwc_prepare; + dev->base.set = hwc_set; + dev->base.eventControl = hwc_eventControl; + dev->base.blank = hwc_blank; + dev->base.query = hwc_query; + dev->base.registerProcs = hwc_registerProcs; + + dev->base.dump = hwc_dump; + dev->base.getDisplayConfigs = hwc_getDisplayConfigs; + dev->base.getDisplayAttributes = hwc_getDisplayAttributes; + dev->vsync_enable = false; + dev->blank_status = false; + *device = &dev->base.common; + + ret = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev); + if (ret) { + HWC_LOGEB("failed to start vsync thread: %s", strerror(ret)); + ret = -ret; + goto err_vsync; + } + +#ifdef WITH_EXTERNAL_DISPLAY + //temp solution, will change to use uevnet from kernel + ret = pthread_create(&dev->hotplug_thread, NULL, hwc_hotplug_thread, dev); + if (ret) { + HWC_LOGEB("failed to start hotplug thread: %s", strerror(ret)); + ret = -ret; + goto err_vsync; + } +#endif + + return 0; + +err_vsync: + uninit_display(dev,HWC_DISPLAY_PRIMARY); +err_get_module: + if (dev) + free(dev); + return ret; +} + + + +/* +Operater of framebuffer +*/ +int init_display(hwc_context_1_t* context,int displayType){ + getDisplayInfo(context, displayType); + + if(display_ctx->connected){ + return 0; + } + + pthread_mutex_lock(&hwc_mutex); + + if( !display_ctx->fb_hnd ){ + //init information from osd. + fbinfo->displayType = displayType; + fbinfo->fbIdx = getOsdIdx(fbinfo->displayType); + int err = init_frame_buffer_locked(fbinfo); + int bufferSize = fbinfo->finfo.line_length * fbinfo->info.yres; + int usage = 0; + if(displayType > 0) + usage |= GRALLOC_USAGE_EXTERNAL_DISP ; + + //Register the framebuffer to gralloc module + display_ctx->fb_hnd = new private_handle_t(private_handle_t::PRIV_FLAGS_FRAMEBUFFER, usage, fbinfo->fbSize, 0, + 0, fbinfo->fd, bufferSize); + context->gralloc_module->base.registerBuffer(&(context->gralloc_module->base),display_ctx->fb_hnd); + HWC_LOGDB("init_frame_buffer get frame size %d usage %d",bufferSize,usage); + } + + display_ctx->connected = true; + pthread_mutex_unlock(&hwc_mutex); + return 0; +} + +int uninit_display(hwc_context_1_t* context,int displayType){ + getDisplayInfo(context, displayType); + + if(display_ctx->connected == false){ + return 0; + } + + pthread_mutex_lock(&hwc_mutex); + #if 0 + //un-register the framebuffer in gralloc module + if(display->fb_hnd){ + context->gralloc_module->base.unregisterBuffer(&(context->gralloc_module->base),display->fb_hnd); + delete display->fb_hnd; + display->fb_hnd = NULL; - status = pthread_create(&dev->vsync_thread, NULL, hwc_vsync_thread, dev); - if (status) { - ALOGE("failed to start vsync thread: %s", strerror(status)); + if(fbinfo->fd >= 0){ + close(fbinfo->fd); + fbinfo->fd= -1; } - } - return status; + } + #endif + + display_ctx->connected = false; + pthread_mutex_unlock(&hwc_mutex); + + return 0; } + |