From 9ccb3975c70708809950dcf0d34484516711c77d Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Sat, 21 Jul 2012 12:17:13 -0700 Subject: [PATCH] display: Enable vsync * Use the vsync uevents from the kernel to start surfaceflinger composition. * This patch also does some code cleanup - Move copybit specific functions to copybit files. - Cleanup verbose logging. Change-Id: I8ca3cd7a7ceb53655ed0fcf39ac2cb35e6cbe890 --- libhwcomposer/Android.mk | 4 +- libhwcomposer/hwc.cpp | 60 +++++- libhwcomposer/hwc_copybit.cpp | 42 ++-- libhwcomposer/hwc_copybit.h | 19 ++ libhwcomposer/hwc_copybitEngine.h | 40 ---- ...{hwc_ext_observer.cpp => hwc_external.cpp} | 196 ++++++------------ .../{hwc_ext_observer.h => hwc_external.h} | 58 +++--- libhwcomposer/hwc_qbuf.h | 3 + libhwcomposer/hwc_uevents.cpp | 105 ++++++++++ libhwcomposer/hwc_uimirror.cpp | 12 +- libhwcomposer/hwc_uimirror.h | 1 + libhwcomposer/hwc_utils.cpp | 76 ++++--- libhwcomposer/hwc_utils.h | 56 ++--- libhwcomposer/hwc_video.cpp | 10 +- 14 files changed, 368 insertions(+), 314 deletions(-) delete mode 100644 libhwcomposer/hwc_copybitEngine.h rename libhwcomposer/{hwc_ext_observer.cpp => hwc_external.cpp} (61%) rename libhwcomposer/{hwc_ext_observer.h => hwc_external.h} (51%) create mode 100644 libhwcomposer/hwc_uevents.cpp diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 5067a2a..9808aa5 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -10,6 +10,6 @@ LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \ LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\" LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \ - hwc_uimirror.cpp hwc_ext_observer.cpp \ - hwc_copybit.cpp + hwc_uimirror.cpp hwc_external.cpp \ + hwc_uevents.cpp hwc_copybit.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 34972b7..1029ac4 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -20,8 +20,12 @@ #include #include +#include +#include +#include #include "hwc_utils.h" +#include "hwc_qbuf.h" #include "hwc_video.h" #include "hwc_uimirror.h" #include "hwc_copybit.h" @@ -92,6 +96,47 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) return 0; } +static int hwc_eventControl(struct hwc_composer_device* dev, + int event, int enabled) +{ + int ret = 0; + hwc_context_t* ctx = (hwc_context_t*)(dev); + private_module_t* m = reinterpret_cast( + ctx->mFbDev->common.module); + switch(event) { + case HWC_EVENT_VSYNC: + if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) + ret = -errno; + break; + default: + ret = -EINVAL; + } + return ret; +} + +static int hwc_query(struct hwc_composer_device* dev, + int param, int* value) +{ + hwc_context_t* ctx = (hwc_context_t*)(dev); + private_module_t* m = reinterpret_cast( + ctx->mFbDev->common.module); + + switch (param) { + case HWC_BACKGROUND_LAYER_SUPPORTED: + // Not supported for now + value[0] = 0; + break; + case HWC_VSYNC_PERIOD: + value[0] = 1000000000.0 / m->fps; + ALOGI("fps: %d", value[0]); + break; + default: + return -EINVAL; + } + return 0; + +} + static int hwc_set(hwc_composer_device_t *dev, hwc_display_t dpy, hwc_surface_t sur, @@ -118,7 +163,7 @@ static int hwc_set(hwc_composer_device_t *dev, static int hwc_device_close(struct hw_device_t *dev) { if(!dev) { - ALOGE("hwc_device_close null device pointer"); + ALOGE("%s: NULL device pointer", __FUNCTION__); return -1; } closeContext((hwc_context_t*)dev); @@ -136,14 +181,25 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name, struct hwc_context_t *dev; dev = (hwc_context_t*)malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); + + //Initialize hwc context initContext(dev); + + //Setup HWC methods + hwc_methods_t *methods; + methods = (hwc_methods_t *)malloc(sizeof(*methods)); + memset(methods, 0, sizeof(*methods)); + methods->eventControl = hwc_eventControl; + dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = 0; + dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; dev->device.common.module = const_cast(module); dev->device.common.close = hwc_device_close; dev->device.prepare = hwc_prepare; dev->device.set = hwc_set; dev->device.registerProcs = hwc_registerProcs; + dev->device.query = hwc_query; + dev->device.methods = methods; *device = &dev->device.common; status = 0; } diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp index adcd4dc..7892632 100644 --- a/libhwcomposer/hwc_copybit.cpp +++ b/libhwcomposer/hwc_copybit.cpp @@ -18,8 +18,9 @@ * limitations under the License. */ +#include +#include #include "hwc_copybit.h" -#include "hwc_copybitEngine.h" namespace qhwc { @@ -71,6 +72,23 @@ bool CopyBit::sIsModeOn = false; bool CopyBit::sIsLayerSkip = false; void* CopyBit::egl_lib = NULL; +void CopyBit::openEglLibAndGethandle() +{ + egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY); + if (!egl_lib) { + return; + } + updateEglHandles(egl_lib); +} +void CopyBit::closeEglLib() +{ + if(egl_lib) + ::dlclose(egl_lib); + + egl_lib = NULL; + updateEglHandles(NULL); +} + void CopyBit::updateEglHandles(void* egl_lib) { if(egl_lib != NULL) { @@ -365,7 +383,7 @@ bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, if(ctx->hasOverlay) return false; - framebuffer_device_t* fbDev = ctx->mFbDevice->getFb(); + framebuffer_device_t* fbDev = ctx->mFbDev; if(!fbDev) { ALOGE("ERROR: canUseCopybit : fb device is invalid"); return false; @@ -402,27 +420,11 @@ bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, return (renderArea <= (2 * fb_w * fb_h)); } -void CopyBit::openEglLibAndGethandle() -{ - egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY); - if (!egl_lib) { - return; - } - updateEglHandles(egl_lib); -} -void CopyBit::closeEglLib() -{ - if(egl_lib) - ::dlclose(egl_lib); - - egl_lib = NULL; - updateEglHandles(NULL); -} //CopybitEngine Class functions -CopybitEngine* CopybitEngine::sInstance = 0;; +CopybitEngine* CopybitEngine::sInstance = 0; struct copybit_device_t* CopybitEngine::getEngine() { return sEngine; @@ -440,9 +442,11 @@ CopybitEngine::CopybitEngine(){ } else { ALOGE("FATAL ERROR: copybit open failed."); } + CopyBit::openEglLibAndGethandle(); } CopybitEngine::~CopybitEngine() { + CopyBit::closeEglLib(); if(sEngine) { copybit_close(sEngine); diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h index adf088b..602898e 100644 --- a/libhwcomposer/hwc_copybit.h +++ b/libhwcomposer/hwc_copybit.h @@ -31,6 +31,11 @@ namespace qhwc { //Feature for using Copybit to display RGB layers. +typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) ( + EGLDisplay dpy, + EGLSurface draw); +typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw); + class CopyBit { public: //Sets up members and prepares copybit if conditions are met @@ -75,6 +80,20 @@ private: }; +class CopybitEngine { +public: + ~CopybitEngine(); + // API to get copybit engine(non static) + struct copybit_device_t *getEngine(); + // API to get singleton + static CopybitEngine* getInstance(); +private: + CopybitEngine(); + struct copybit_device_t *sEngine; + static CopybitEngine* sInstance; // singleton +}; + + inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip) { sYuvCount = yuvCount; diff --git a/libhwcomposer/hwc_copybitEngine.h b/libhwcomposer/hwc_copybitEngine.h deleted file mode 100644 index d627e44..0000000 --- a/libhwcomposer/hwc_copybitEngine.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ -#ifndef HWC_COPYBIT_ENGINE_H -#define HWC_COPYBIT_ENGINE_H - -namespace qhwc { -class CopybitEngine { -public: - ~CopybitEngine(); - // API to get copybit engine(non static) - struct copybit_device_t *getEngine(); - // API to get singleton - static CopybitEngine* getInstance(); - -private: - CopybitEngine(); - struct copybit_device_t *sEngine; - static CopybitEngine* sInstance; // singleton -}; - -}; //namespace qhwc - -#endif //HWC_COPYBIT_ENGINE_H diff --git a/libhwcomposer/hwc_ext_observer.cpp b/libhwcomposer/hwc_external.cpp similarity index 61% rename from libhwcomposer/hwc_ext_observer.cpp rename to libhwcomposer/hwc_external.cpp index d79e2f3..3507134 100644 --- a/libhwcomposer/hwc_ext_observer.cpp +++ b/libhwcomposer/hwc_external.cpp @@ -18,9 +18,9 @@ * limitations under the License. */ +#define DEBUG 0 #include -#include -#include +#include #include #include #include @@ -31,15 +31,13 @@ #include #include #include - -#include +#include #include #include "hwc_utils.h" -#include "hwc_ext_observer.h" +#include "hwc_external.h" namespace qhwc { -#define EXT_OBSERVER_DEBUG 1 #define DEVICE_ROOT "/sys/devices/virtual/graphics" #define DEVICE_NODE "fb1" @@ -49,88 +47,19 @@ namespace qhwc { #define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd" -android::sp ExtDisplayObserver:: - sExtDisplayObserverInstance(0); - -ExtDisplayObserver::ExtDisplayObserver() : Thread(false), - fd(-1), mCurrentID(-1), mHwcContext(NULL) +ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):fd(-1), + mCurrentID(-1), mHwcContext(ctx) { //Enable HPD for HDMI writeHPDOption(1); } -ExtDisplayObserver::~ExtDisplayObserver() { +ExternalDisplay::~ExternalDisplay() +{ if (fd > 0) close(fd); } -ExtDisplayObserver *ExtDisplayObserver::getInstance() { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__); - if(sExtDisplayObserverInstance.get() == NULL) - sExtDisplayObserverInstance = new ExtDisplayObserver(); - return sExtDisplayObserverInstance.get(); -} - -void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__); - if(hwcCtx) { - mHwcContext = hwcCtx; - } - return; -} -void ExtDisplayObserver::onFirstRef() { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__); - run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY); -} - -int ExtDisplayObserver::readyToRun() { - //Initialize the uevent - uevent_init(); - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__); - return android::NO_ERROR; -} - -void ExtDisplayObserver::handleUEvent(char* str){ - int connected = 0; - // TODO: check for fb2(WFD) driver also - if(!strcasestr(str, DEVICE_NODE)) - { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); - return; - } - // Event will be of the form: - // change@/devices/virtual/graphics/fb1 ACTION=change - // DEVPATH=/devices/virtual/graphics/fb1 - // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29 - // for now just parse the online or offline are important for us. - if(!(strncmp(str,"online@",strlen("online@")))) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__); - connected = 1; - readResolution(); - //Get the best mode and set - // TODO: DO NOT call this for WFD - setResolution(getBestMode()); - } else if(!(strncmp(str,"offline@",strlen("offline@")))) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__); - connected = 0; - close(fd); - } - setExternalDisplayStatus(connected); -} - -bool ExtDisplayObserver::threadLoop() -{ - static char uEventString[1024]; - memset(uEventString, 0, sizeof(uEventString)); - int count = uevent_next_event(uEventString, sizeof(uEventString)); - if(count) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d", - __FUNCTION__, uEventString, count); - handleUEvent(uEventString); - } - return true; -} - struct disp_mode_timing_type { int video_format; @@ -213,7 +142,8 @@ static struct disp_mode_timing_type supported_video_mode_lut[] = { {m1920x1080p25_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 74250, false}, {m1920x1080p30_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 74250, false}, }; -int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len) + +int ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len) { char delim = ','; int count = 0; @@ -233,7 +163,7 @@ int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len) } return count; } -bool ExtDisplayObserver::readResolution() +bool ExternalDisplay::readResolution() { int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0); int len = -1; @@ -242,16 +172,16 @@ bool ExtDisplayObserver::readResolution() memset(mEDIDModes, 0, sizeof(mEDIDModes)); mModeCount = 0; if (hdmiEDIDFile < 0) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file '%s' not found", - __FUNCTION__, SYSFS_EDID_MODES); + ALOGD_IF(DEBUG, "%s: edid_modes file '%s' not found", + __FUNCTION__, SYSFS_EDID_MODES); return false; } else { len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1); - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: EDID string: %s length = %d", - __FUNCTION__, mEDIDs, len); + ALOGD_IF(DEBUG, "%s: EDID string: %s length = %d", + __FUNCTION__, mEDIDs, len); if ( len <= 0) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file empty '%s'", - __FUNCTION__, SYSFS_EDID_MODES); + ALOGD_IF(DEBUG, "%s: edid_modes file empty '%s'", + __FUNCTION__, SYSFS_EDID_MODES); } else { while (len > 1 && isspace(mEDIDs[len-1])) @@ -263,26 +193,26 @@ bool ExtDisplayObserver::readResolution() if(len > 0) { // GEt EDID modes from the EDID strings mModeCount = parseResolution(mEDIDs, mEDIDModes, len); - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__, - mModeCount); + ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__, + mModeCount); } return (strlen(mEDIDs) > 0); } -bool ExtDisplayObserver::openFramebuffer() +bool ExternalDisplay::openFramebuffer() { if (fd == -1) { fd = open("/dev/graphics/fb1", O_RDWR); if (fd < 0) - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available" - "\n", __FUNCTION__); + ALOGD_IF(DEBUG, "%s: /dev/graphics/fb1 not available" + "\n", __FUNCTION__); } return (fd > 0); } -int ExtDisplayObserver::getModeOrder(int mode) +int ExternalDisplay::getModeOrder(int mode) { switch (mode) { default: @@ -320,11 +250,11 @@ int ExtDisplayObserver::getModeOrder(int mode) return 16; //1080p@50Hz case m1920x1080p60_16_9: return 17; //1080p@60Hz - } + } } // Get the best mode for the current HD TV -int ExtDisplayObserver::getBestMode() { +int ExternalDisplay::getBestMode() { int bestOrder = 0; int bestMode = m640x480p60_4_3; @@ -338,14 +268,14 @@ int ExtDisplayObserver::getBestMode() { } } return bestMode; - } +} -inline bool ExtDisplayObserver::isValidMode(int ID) +inline bool ExternalDisplay::isValidMode(int ID) { return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9)); } -void ExtDisplayObserver::setResolution(int ID) +void ExternalDisplay::setResolution(int ID) { struct fb_var_screeninfo info; if (!openFramebuffer()) @@ -353,29 +283,29 @@ void ExtDisplayObserver::setResolution(int ID) //If its a valid mode and its a new ID - update var_screeninfo if ((isValidMode(ID)) && mCurrentID != ID) { const struct disp_mode_timing_type *mode = - &supported_video_mode_lut[0]; + &supported_video_mode_lut[0]; unsigned count = sizeof(supported_video_mode_lut)/sizeof - (*supported_video_mode_lut); + (*supported_video_mode_lut); for (unsigned int i = 0; i < count; ++i) { const struct disp_mode_timing_type *cur = - &supported_video_mode_lut[i]; + &supported_video_mode_lut[i]; if (cur->video_format == ID) mode = cur; } ioctl(fd, FBIOGET_VSCREENINFO, &info); - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info", __FUNCTION__, - info.reserved[3], info.xres, info.yres, - info.right_margin, info.hsync_len, info.left_margin, - info.lower_margin, info.vsync_len, info.upper_margin, - info.pixclock/1000/1000); + ALOGD_IF(DEBUG, "%s: GET Info", __FUNCTION__, + info.reserved[3], info.xres, info.yres, + info.right_margin, info.hsync_len, info.left_margin, + info.lower_margin, info.vsync_len, info.upper_margin, + info.pixclock/1000/1000); mode->set_info(info); - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info Info", __FUNCTION__, ID, - info.reserved[3], info.xres, info.yres, - info.right_margin, info.hsync_len, info.left_margin, - info.lower_margin, info.vsync_len, info.upper_margin, - info.pixclock/1000/1000); + ALOGD_IF(DEBUG, "%s: SET Info Info", __FUNCTION__, ID, + info.reserved[3], info.xres, info.yres, + info.right_margin, info.hsync_len, info.left_margin, + info.lower_margin, info.vsync_len, info.upper_margin, + info.pixclock/1000/1000); info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE; ioctl(fd, FBIOPUT_VSCREENINFO, &info); mCurrentID = ID; @@ -389,53 +319,61 @@ void ExtDisplayObserver::setResolution(int ID) } -int ExtDisplayObserver::getExternalDisplay() const +int ExternalDisplay::getExternalDisplay() const { - return mExternalDisplay; + return mExternalDisplay; } -void ExtDisplayObserver::setExternalDisplayStatus(int connected) +void ExternalDisplay::setExternalDisplayStatus(int connected) { hwc_context_t* ctx = mHwcContext; if(ctx) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__, - connected); + ALOGD_IF(DEBUG, "%s: status = %d", __FUNCTION__, + connected); + if(connected) { + readResolution(); + //Get the best mode and set + // TODO: DO NOT call this for WFD + setResolution(getBestMode()); + } else { + close(fd); + } // Store the external display - mExternalDisplay = connected;//(external_display_type)value; + mExternalDisplay = connected; //Invalidate hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; if(!proc) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered", - __FUNCTION__); + ALOGD_IF(DEBUG, "%s: HWC proc not registered", + __FUNCTION__); } else { /* Trigger redraw */ - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__); + ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__); proc->invalidate(proc); } } return; } -bool ExtDisplayObserver::writeHPDOption(int userOption) const +bool ExternalDisplay::writeHPDOption(int userOption) const { bool ret = true; int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0); if (hdmiHPDFile < 0) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d" - "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno)); + ALOGD_IF(DEBUG, "%s: state file '%s' not found : ret%d" + "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno)); ret = false; } else { int err = -1; - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__, - userOption); + ALOGD_IF(DEBUG, "%s: option = %d", __FUNCTION__, + userOption); if(userOption) err = write(hdmiHPDFile, "1", 2); else err = write(hdmiHPDFile, "0" , 2); if (err <= 0) { - ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'", - __FUNCTION__, SYSFS_HPD); + ALOGD_IF(DEBUG, "%s: file write failed '%s'", + __FUNCTION__, SYSFS_HPD); ret = false; } close(hdmiHPDFile); diff --git a/libhwcomposer/hwc_ext_observer.h b/libhwcomposer/hwc_external.h similarity index 51% rename from libhwcomposer/hwc_ext_observer.h rename to libhwcomposer/hwc_external.h index e7cb890..9e5f455 100644 --- a/libhwcomposer/hwc_ext_observer.h +++ b/libhwcomposer/hwc_external.h @@ -18,16 +18,14 @@ * limitations under the License. */ -#ifndef HWC_EXT_OBSERVER_H -#define HWC_EXT_OBSERVER_H - -#include +#ifndef HWC_EXTERNAL_DISPLAY_H +#define HWC_EXTERNAL_DISPLAY_H struct hwc_context_t; namespace qhwc { -class ExtDisplayObserver : public android::Thread +class ExternalDisplay { //Type of external display - OFF, HDMI, WFD enum external_display_type { @@ -42,39 +40,31 @@ class ExtDisplayObserver : public android::Thread EXT_MIRRORING_ON, }; public: - /*Overrides*/ - virtual bool threadLoop(); - virtual int readyToRun(); - virtual void onFirstRef(); - - virtual ~ExtDisplayObserver(); - static ExtDisplayObserver *getInstance(); - int getExternalDisplay() const; - void setHwcContext(hwc_context_t* hwcCtx); + ExternalDisplay(hwc_context_t* ctx); + ~ExternalDisplay(); + int getExternalDisplay() const; + void setExternalDisplayStatus(int connected); private: - ExtDisplayObserver(); - void setExternalDisplayStatus(int connected); - bool readResolution(); - int parseResolution(char* edidStr, int* edidModes, int len); - void setResolution(int ID); - bool openFramebuffer(); - bool writeHPDOption(int userOption) const; - bool isValidMode(int ID); - void handleUEvent(char* str); - int getModeOrder(int mode); - int getBestMode(); + bool readResolution(); + int parseResolution(char* edidStr, int* edidModes, int len); + void setResolution(int ID); + bool openFramebuffer(); + bool writeHPDOption(int userOption) const; + bool isValidMode(int ID); + void handleUEvent(char* str, int len); + int getModeOrder(int mode); + int getBestMode(); - int fd; - int mExternalDisplay; - int mCurrentID; - char mEDIDs[128]; - int mEDIDModes[64]; - int mModeCount; - hwc_context_t *mHwcContext; - static android::sp sExtDisplayObserverInstance; + int fd; + int mExternalDisplay; + int mCurrentID; + char mEDIDs[128]; + int mEDIDModes[64]; + int mModeCount; + hwc_context_t *mHwcContext; }; }; //qhwc // --------------------------------------------------------------------------- -#endif //HWC_EXT_OBSERVER_H +#endif //HWC_EXTERNAL_DISPLAY_H diff --git a/libhwcomposer/hwc_qbuf.h b/libhwcomposer/hwc_qbuf.h index a0ade8c..6d75964 100644 --- a/libhwcomposer/hwc_qbuf.h +++ b/libhwcomposer/hwc_qbuf.h @@ -15,6 +15,9 @@ * limitations under the License. */ +#include +#include + // ----------------------------------------------------------------------------- // QueuedBufferStore //This class holds currently and previously queued buffers. diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp new file mode 100644 index 0000000..a1df74b --- /dev/null +++ b/libhwcomposer/hwc_uevents.cpp @@ -0,0 +1,105 @@ +/* + * 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. + */ +#define DEBUG 0 +#ifndef HWC_OBSERVER_H +#define HWC_OBSERVER_H +#include +#include +#include +#include +#include +#include "hwc_utils.h" +#include "hwc_external.h" + +namespace qhwc { + +const char* MSMFB_DEVICE_CHANGE = "change@/devices/virtual/graphics/fb0"; +const char* MSMFB_HDMI_NODE = "fb1"; + +static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) +{ + int vsync; + char* hdmi; + int64_t timestamp = 0; + const char *str = udata; + hwc_procs* proc = reinterpret_cast(ctx->device.reserved_proc[0]); + + vsync = !strncmp(str, MSMFB_DEVICE_CHANGE, strlen(MSMFB_DEVICE_CHANGE)); + hdmi = strcasestr(str, MSMFB_HDMI_NODE); + if(!vsync && !hdmi) + return; + 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; + } + } + + if(hdmi) { + // parse HDMI events + // The event will be of the form: + // change@/devices/virtual/graphics/fb1 ACTION=change + // DEVPATH=/devices/virtual/graphics/fb1 + // SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29 + // for now just parsing onlin/offline info is enough + str = udata; + int connected = 0; + if(!(strncmp(str,"online@",strlen("online@")))) { + connected = 1; + } else if(!(strncmp(str,"offline@",strlen("offline@")))) { + connected = 0; + } + ctx->mExtDisplay->setExternalDisplayStatus(connected); + } + +} + +static void *uevent_loop(void *param) +{ + int len = 0; + static char udata[4096]; + memset(udata, 0, sizeof(udata)); + hwc_context_t * ctx = reinterpret_cast(param); + + setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); + uevent_init(); + + while(1) { + len = uevent_next_event(udata, sizeof(udata) - 2); + handle_uevent(ctx, udata, len); + } + + return NULL; +} + +void init_uevent_thread(hwc_context_t* ctx) +{ + pthread_t uevent_thread; + pthread_create(&uevent_thread, NULL, uevent_loop, (void*) ctx); +} + +}; //namespace +#endif //HWC_OBSERVER_H diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp index 4540be8..9cf91af 100644 --- a/libhwcomposer/hwc_uimirror.cpp +++ b/libhwcomposer/hwc_uimirror.cpp @@ -18,12 +18,14 @@ * limitations under the License. */ +#define HWC_UI_MIRROR 0 +#include +#include #include "hwc_uimirror.h" -#include "hwc_ext_observer.h" +#include "hwc_external.h" namespace qhwc { -#define HWC_UI_MIRROR 0 // Function to get the primary device orientation // Loops thru the hardware layers and returns the orientation of the max. @@ -59,7 +61,7 @@ bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { sState = ovutils::OV_CLOSED; sIsUiMirroringOn = false; // If external display is connected - if(ctx->mExtDisplayObserver->getExternalDisplay()) { + if(ctx->mExtDisplay->getExternalDisplay()) { sState = ovutils::OV_UI_MIRROR; configure(ctx, list); } @@ -73,7 +75,7 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_list_t *list) overlay::Overlay& ov = *(ctx->mOverlay); // Set overlay state ov.setState(sState); - framebuffer_device_t *fbDev = ctx->mFbDevice->getFb(); + framebuffer_device_t *fbDev = ctx->mFbDev; if(fbDev) { private_module_t* m = reinterpret_cast( fbDev->common.module); @@ -143,7 +145,7 @@ bool UIMirrorOverlay::draw(hwc_context_t *ctx) overlay::Overlay& ov = *(ctx->mOverlay); ovutils::eOverlayState state = ov.getState(); ovutils::eDest dest = ovutils::OV_PIPE_ALL; - framebuffer_device_t *fbDev = ctx->mFbDevice->getFb(); + framebuffer_device_t *fbDev = ctx->mFbDev; if(fbDev) { private_module_t* m = reinterpret_cast( fbDev->common.module); diff --git a/libhwcomposer/hwc_uimirror.h b/libhwcomposer/hwc_uimirror.h index af43848..98f7896 100644 --- a/libhwcomposer/hwc_uimirror.h +++ b/libhwcomposer/hwc_uimirror.h @@ -20,6 +20,7 @@ #ifndef HWC_UIMIRROR_H #define HWC_UIMIRROR_H #include "hwc_utils.h" +#include "overlay.h" #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index ae5c526..870a758 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -15,26 +15,39 @@ * limitations under the License. */ +#include #include "hwc_utils.h" #include "mdp_version.h" #include "hwc_video.h" -#include "hwc_ext_observer.h" +#include "hwc_qbuf.h" #include "hwc_copybit.h" +#include "hwc_external.h" + namespace qhwc { + +// Opens Framebuffer device +static void openFramebufferDevice(hwc_context_t *ctx) +{ + hw_module_t const *module; + if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { + framebuffer_open(module, &(ctx->mFbDev)); + } +} + void initContext(hwc_context_t *ctx) { - //XXX: target specific initializations here + openFramebufferDevice(ctx); ctx->mOverlay = overlay::Overlay::getInstance(); ctx->qbuf = new QueuedBufferStore(); ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); - ALOGI("MDP version: %d",ctx->mdpVersion); - - ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance(); - ctx->mExtDisplayObserver->setHwcContext(ctx); - ctx->mFbDevice = FbDevice::getInstance(); ctx->mCopybitEngine = CopybitEngine::getInstance(); - CopyBit::openEglLibAndGethandle(); + ctx->mExtDisplay = new ExternalDisplay(ctx); + + init_uevent_thread(ctx); + + ALOGI("Initializing Qualcomm Hardware Composer"); + ALOGI("MDP version: %d", ctx->mdpVersion); } void closeContext(hwc_context_t *ctx) @@ -48,15 +61,25 @@ void closeContext(hwc_context_t *ctx) delete ctx->mCopybitEngine; ctx->mCopybitEngine = NULL; } - if(ctx->mFbDevice) { - delete ctx->mFbDevice; - ctx->mFbDevice = NULL; + + if(ctx->mFbDev) { + framebuffer_close(ctx->mFbDev); + ctx->mFbDev = NULL; } + if(ctx->qbuf) { delete ctx->qbuf; ctx->qbuf = NULL; } - CopyBit::closeEglLib(); + + if(ctx->mExtDisplay) { + delete ctx->mExtDisplay; + ctx->mExtDisplay = NULL; + } + + + free(const_cast(ctx->device.methods)); + } void dumpLayer(hwc_layer_t const* l) @@ -163,33 +186,4 @@ void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst, } } -//FbDevice class functions -FbDevice* FbDevice::sInstance = 0;; -struct framebuffer_device_t* FbDevice::getFb() { - return sFb; -} - -FbDevice* FbDevice::getInstance() { - if(sInstance == NULL) - sInstance = new FbDevice(); - return sInstance; -} - -FbDevice::FbDevice(){ - hw_module_t const *module; - if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) { - framebuffer_open(module, &sFb); - } else { - ALOGE("FATAL ERROR: framebuffer open failed."); - } -} -FbDevice::~FbDevice() -{ - if(sFb) - { - framebuffer_close(sFb); - sFb = NULL; - } -} - };//namespace diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 0bf30c9..1e405f7 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -17,28 +17,26 @@ #ifndef HWC_UTILS_H #define HWC_UTILS_H -#include -#include + #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hwc_qbuf.h" -#include +#include #define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1)) #define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) #define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) #define FINAL_TRANSFORM_MASK 0x000F +//Fwrd decls struct hwc_context_t; +struct framebuffer_device_t; + +namespace overlay { +class Overlay; +} + namespace qhwc { +//fwrd decl +class QueuedBufferStore; enum external_display_type { EXT_TYPE_NONE, @@ -53,7 +51,8 @@ enum HWCCompositionType { }; -class ExtDisplayObserver; +class ExternalDisplay; +class CopybitEngine; // ----------------------------------------------------------------------------- // Utility functions - implemented in hwc_utils.cpp void dumpLayer(hwc_layer_t const* l); @@ -78,32 +77,12 @@ static inline bool isYuvBuffer(const private_handle_t* hnd) { static inline bool isBufferLocked(const private_handle_t* hnd) { return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags)); } -// ----------------------------------------------------------------------------- -// Copybit specific - inline or implemented in hwc_copybit.cpp -typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) ( - EGLDisplay dpy, - EGLSurface draw); -typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw); -// ----------------------------------------------------------------------------- -// Singleton for Framebuffer device -class FbDevice{ -public: - ~FbDevice(); - // API to get Fb device(non static) - struct framebuffer_device_t *getFb(); - // API to get singleton - static FbDevice* getInstance(); - -private: - FbDevice(); - struct framebuffer_device_t *sFb; - static FbDevice* sInstance; // singleton -}; +// Initialize uevent thread +void init_uevent_thread(hwc_context_t* ctx); }; //qhwc namespace - // ----------------------------------------------------------------------------- // HWC context // This structure contains overall state @@ -115,7 +94,7 @@ struct hwc_context_t { int overlayInUse; //Framebuffer device - qhwc::FbDevice* mFbDevice; + framebuffer_device_t *mFbDev; //Copybit Engine qhwc::CopybitEngine* mCopybitEngine; @@ -127,7 +106,8 @@ struct hwc_context_t { qhwc::QueuedBufferStore *qbuf; // External display related information - qhwc::ExtDisplayObserver*mExtDisplayObserver; + qhwc::ExternalDisplay *mExtDisplay; + }; #endif //HWC_UTILS_H diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index 180ab86..190e31b 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -15,13 +15,15 @@ * limitations under the License. */ +#define VIDEO_DEBUG 0 +#include +#include "hwc_qbuf.h" #include "hwc_video.h" -#include "hwc_ext_observer.h" +#include "hwc_external.h" namespace qhwc { #define FINAL_TRANSFORM_MASK 0x000F -#define VIDEO_DEBUG 0 //Static Members ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED; @@ -62,12 +64,12 @@ void VideoOverlay::chooseState(hwc_context_t *ctx) { //Support 1 video layer if(sYuvCount == 1) { //Skip on primary, display on ext. - if(sIsLayerSkip && ctx->mExtDisplayObserver->getExternalDisplay()) { + if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) { //TODO //VIDEO_ON_TV_ONLY } else if(sIsLayerSkip) { //skip on primary, no ext newState = ovutils::OV_CLOSED; - } else if(ctx->mExtDisplayObserver->getExternalDisplay()) { + } else if(ctx->mExtDisplay->getExternalDisplay()) { //display on both newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV; } else { //display on primary only