diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 8ad7e17..2ef979a 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -17,6 +17,7 @@ LOCAL_SRC_FILES := hwc.cpp \ hwc_utils.cpp \ hwc_uimirror.cpp \ hwc_uevents.cpp \ + hwc_vsync.cpp \ hwc_copybit.cpp \ hwc_mdpcomp.cpp \ hwc_extonly.cpp diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 1df07a3..2b34be7 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -73,8 +73,10 @@ static void hwc_registerProcs(struct hwc_composer_device* dev, } ctx->device.reserved_proc[0] = (void*)procs; - // Now that we have the functions needed, kick off the uevent thread + // Now that we have the functions needed, kick off + // the uevent & vsync threads init_uevent_thread(ctx); + init_vsync_thread(ctx); } static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) @@ -243,12 +245,18 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, methods->eventControl = hwc_eventControl; dev->device.common.tag = HARDWARE_DEVICE_TAG; -#ifdef NO_HW_VSYNC - dev->device.common.version = 0; - ALOGI("%s: Hardware VSYNC not supported", __FUNCTION__); -#else - dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; - ALOGI("%s: Hardware VSYNC supported", __FUNCTION__); +#ifndef NO_HW_VSYNC + //XXX: This disables hardware vsync on 8x55 + // Fix when HW vsync is available on 8x55 + if(dev->mMDP.version == 400 || (dev->mMDP.version >= 500)) { +#endif + dev->device.common.version = 0; + ALOGI("%s: Hardware VSYNC not supported", __FUNCTION__); +#ifndef NO_HW_VSYNC + } else { + dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; + ALOGI("%s: Hardware VSYNC supported", __FUNCTION__); + } #endif dev->device.common.module = const_cast(module); dev->device.common.close = hwc_device_close; diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index dc94eac..2ebc8f2 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -18,8 +18,6 @@ * limitations under the License. */ #define DEBUG 0 -#ifndef HWC_UEVENTS_H -#define HWC_UEVENTS_H #include #include #include @@ -29,45 +27,21 @@ #include "hwc_utils.h" #include "hwc_external.h" -namespace qhwc { +#define PAGE_SIZE 4096 -const char* MSMFB_DEVICE_FB0 = "change@/devices/virtual/graphics/fb0"; -const char* MSMFB_DEVICE_FB1 = "change@/devices/virtual/graphics/fb1"; -const char* MSMFB_FB_NODE = "fb"; +namespace qhwc { static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) { int vsync = 0; int64_t timestamp = 0; const char *str = udata; - hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; - int hdmiconnected = ctx->mExtDisplay->getExternalDisplay(); if(!strcasestr(str, "@/devices/virtual/graphics/fb")) { ALOGD_IF(DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); return; } - if(ctx->mExtDisplay->isHDMIConfigured() && - (hdmiconnected == EXTERN_DISPLAY_FB1)) - vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1)); - else - vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0)); - - if(vsync) { - str += strlen(str) + 1; - while(*str) { - if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) { - timestamp = strtoull(str + strlen("VSYNC="), NULL, 0); - proc->vsync(proc, 0, timestamp); - } - str += strlen(str) + 1; - if(str - udata >= len) - break; - } - return; - } - // parse HDMI events // The event will be of the form: // change@/devices/virtual/graphics/fb1 ACTION=change @@ -85,8 +59,7 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) static void *uevent_loop(void *param) { int len = 0; - static char udata[4096]; - memset(udata, 0, sizeof(udata)); + static char udata[PAGE_SIZE]; hwc_context_t * ctx = reinterpret_cast(param); char thread_name[64] = "hwcUeventThread"; @@ -110,4 +83,3 @@ void init_uevent_thread(hwc_context_t* ctx) } }; //namespace -#endif //HWC_UEVENTS_H diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index dfac883..774810f 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -121,6 +121,9 @@ static inline bool isExtCC(const private_handle_t* hnd) { // Initialize uevent thread void init_uevent_thread(hwc_context_t* ctx); +// Initialize vsync thread +void init_vsync_thread(hwc_context_t* ctx); + inline void getLayerResolution(const hwc_layer_t* layer, int& width, int& height) { diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp new file mode 100644 index 0000000..4e4eb44 --- /dev/null +++ b/libhwcomposer/hwc_vsync.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * Not a Contribution, Apache license notifications and license are + * retained for attribution purposes only. + + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// WARNING : Excessive logging, if VSYNC_DEBUG enabled +#define VSYNC_DEBUG 0 + +#include +#include +#include +#include +#include "hwc_utils.h" +#include "hwc_external.h" +#include "string.h" + +#define PAGE_SIZE 4096 + +namespace qhwc { + +static void *vsync_loop(void *param) +{ + const char* vsync_timestamp_fb0 = "/sys/class/graphics/fb0/vsync_event"; + const char* vsync_timestamp_fb1 = "/sys/class/graphics/fb1/vsync_event"; + + hwc_context_t * ctx = reinterpret_cast(param); + + char thread_name[64] = "hwcVsyncThread"; + prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0); + setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); + + static char vdata[PAGE_SIZE]; + + uint64_t cur_timestamp=0; + int32_t len = -1, fd_timestamp = -1; + bool fb1_vsync = false; + + /* Currently read vsync timestamp from drivers + VSYNC=41800875994 + */ + + hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; + + do { + + int hdmiconnected = ctx->mExtDisplay->getExternalDisplay(); + + // vsync for primary OR HDMI ? + if(ctx->mExtDisplay->isHDMIConfigured() && + (hdmiconnected == EXTERN_DISPLAY_FB1)){ + fb1_vsync = true; + } else { + fb1_vsync = false; + } + + // try to open timestamp sysfs + if (fb1_vsync){ + fd_timestamp = open(vsync_timestamp_fb1, O_RDONLY); + } else { + fd_timestamp = open(vsync_timestamp_fb0, O_RDONLY); + } + if (fd_timestamp < 0) { + ALOGE ("FATAL:%s:not able to open file:%s, %s", __FUNCTION__, + (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, + strerror(errno)); + return NULL; + } + + // Open success - read now + len = read(fd_timestamp, vdata, PAGE_SIZE); + if (len < 0){ + ALOGE ("FATAL:%s:not able to read file:%s, %s", __FUNCTION__, + (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, + strerror(errno)); + return NULL; + } + + // extract timestamp + const char *str = vdata; + if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) { + cur_timestamp = strtoull(str + strlen("VSYNC="), NULL, 0); + } else { + ALOGE ("FATAL:%s:timestamp data not in correct format", + __FUNCTION__); + } + // send timestamp to HAL + ALOGD_IF (VSYNC_DEBUG, "%s: timestamp %llu sent to HWC for %s", + __FUNCTION__, cur_timestamp, (fb1_vsync) ? "fb1" : "fb0"); + proc->vsync(proc, 0, cur_timestamp); + + // close open fds + close (fd_timestamp); + + // reset fd + fd_timestamp = -1; + + // repeat, whatever, you just did + } while (true); +} + +void init_vsync_thread(hwc_context_t* ctx) +{ + pthread_t vsync_thread; + ALOGI("Initializing VSYNC Thread"); + pthread_create(&vsync_thread, NULL, vsync_loop, (void*) ctx); +} + +}; //namespace