diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 1d7cf7b..ff4d5a0 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -77,6 +77,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) hwc_context_t* ctx = (hwc_context_t*)(dev); ctx->overlayInUse = false; + if(ctx->mExtDisplay->getExternalDisplay()) + ovutils::setExtType(ctx->mExtDisplay->getExternalDisplay()); + //Prepare is called after a vsync, so unlock previous buffers here. ctx->qbuf->unlockAllPrevious(); @@ -110,7 +113,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) } static int hwc_eventControl(struct hwc_composer_device* dev, - int event, int enabled) + int event, int value) { int ret = 0; hwc_context_t* ctx = (hwc_context_t*)(dev); @@ -118,13 +121,16 @@ static int hwc_eventControl(struct hwc_composer_device* dev, ctx->mFbDev->common.module); switch(event) { case HWC_EVENT_VSYNC: - if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) + if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &value) < 0) ret = -errno; if(ctx->mExtDisplay->getExternalDisplay()) { - ret = ctx->mExtDisplay->enableHDMIVsync(enabled); + ret = ctx->mExtDisplay->enableHDMIVsync(value); } break; + case HWC_EVENT_ORIENTATION: + ctx->deviceOrientation = value; + break; default: ret = -EINVAL; } @@ -213,9 +219,9 @@ 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; - //XXX: This disables hardware vsync on 7x27A, 8x25 and 8x55 - // Fix when HW vsync is available on those targets - if(dev->mMDP.version < 410) + //XXX: This disables hardware vsync on 8x55 + // Fix when HW vsync is available on 8x55 + if(dev->mMDP.version == 400) dev->device.common.version = 0; else dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; diff --git a/libhwcomposer/hwc_external.cpp b/libhwcomposer/hwc_external.cpp index b5e1e89..e624b20 100644 --- a/libhwcomposer/hwc_external.cpp +++ b/libhwcomposer/hwc_external.cpp @@ -38,20 +38,20 @@ namespace qhwc { - -#define DEVICE_ROOT "/sys/devices/virtual/graphics" -#define DEVICE_NODE "fb1" - -#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE "/edid_modes" -#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd" - +static const char *extPanelName[MAX_DISPLAY_EXTERNAL_DEVICES] = { + HDMI_PANEL, + WFD_PANEL +}; ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1), mCurrentMode(-1), mHwcContext(ctx) { memset(&mVInfo, 0, sizeof(mVInfo)); + //Enable HPD for HDMI - writeHPDOption(1); + if(isHDMIConfigured()) { + writeHPDOption(1); + } } ExternalDisplay::~ExternalDisplay() @@ -197,12 +197,16 @@ bool ExternalDisplay::readResolution() return (strlen(mEDIDs) > 0); } -bool ExternalDisplay::openFramebuffer() +const char* msmFbDevicePath[2] = { "/dev/graphics/fb1", + "/dev/graphics/fb2"}; + + +bool ExternalDisplay::openFrameBuffer(int fbNum) { if (mFd == -1) { - mFd = open("/dev/graphics/fb1", O_RDWR); + mFd = open(msmFbDevicePath[fbNum-1], O_RDWR); if (mFd < 0) - ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__); + ALOGE("%s: %s not available", __FUNCTION__, msmFbDevicePath[fbNum-1]); } return (mFd > 0); } @@ -294,7 +298,7 @@ void ExternalDisplay::setResolution(int ID) { struct fb_var_screeninfo info; int ret = 0; - if (!openFramebuffer()) + if (!openFrameBuffer(EXTERN_DISPLAY_FB1)) return; ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo); if(ret < 0) { @@ -354,32 +358,85 @@ void ExternalDisplay::setResolution(int ID) } } +/* + * This function queries the msm_fb_type for fb1 and checks whether it is + * HDMI or not + * + * Returns: + * 0 -> WFD device + * 1 -> HDMI device + */ +bool ExternalDisplay::isHDMIConfigured() { + bool configured = false; + FILE *displayDeviceFP = NULL; + char fbType[MAX_FRAME_BUFFER_NAME_SIZE]; -int ExternalDisplay::getExternalDisplay() const -{ - return mExternalDisplay; + displayDeviceFP = fopen("/sys/class/graphics/fb1/msm_fb_type", "r"); + + if(displayDeviceFP) { + fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE, displayDeviceFP); + + if(!strncmp(fbType, extPanelName[0], sizeof(extPanelName[0]))) { + configured = true; + } + fclose(displayDeviceFP); + } + return configured; +} + +void ExternalDisplay::processUEventOffline(const char *str) { + const char *s1 = str + (strlen(str)-strlen(DEVICE_NODE_FB1)); + // check if it is for FB1 + if(strncmp(s1,DEVICE_NODE_FB1, strlen(DEVICE_NODE_FB1))== 0) { + enableHDMIVsync(EXTERN_DISPLAY_NONE); + closeFrameBuffer(); + resetInfo(); + setExternalDisplay(EXTERN_DISPLAY_NONE); + } + else if(strncmp(s1, DEVICE_NODE_FB2, strlen(DEVICE_NODE_FB2)) == 0) { + closeFrameBuffer(); + setExternalDisplay(EXTERN_DISPLAY_NONE); + } +} + + +void ExternalDisplay::processUEventOnline(const char *str) { + const char *s1 = str + (strlen(str)-strlen(DEVICE_NODE_FB1)); + // check if it is for FB1 + if(strncmp(s1,DEVICE_NODE_FB1, strlen(DEVICE_NODE_FB1))== 0) { + if(isHDMIConfigured()) { + // HDMI connect event. + // Tear-down WFD if it is active. + if(mExternalDisplay == EXTERN_DISPLAY_FB2) { + closeFrameBuffer(); + setExternalDisplay(EXTERN_DISPLAY_NONE); + } + } + readResolution(); + //Get the best mode and set + setResolution(getBestMode()); + enableHDMIVsync(EXTERN_DISPLAY_FB1); + setExternalDisplay(EXTERN_DISPLAY_FB1); + } + else if(strncmp(s1, DEVICE_NODE_FB2, strlen(DEVICE_NODE_FB2)) == 0) { + // WFD connect event + if(mExternalDisplay == EXTERN_DISPLAY_FB1) { + // HDMI has higher priority. + // Do Not Override. + }else { + // WFD is connected + openFrameBuffer(EXTERN_DISPLAY_FB2); + setExternalDisplay(EXTERN_DISPLAY_FB2); + } + } } void ExternalDisplay::setExternalDisplay(int connected) { - hwc_context_t* ctx = mHwcContext; if(ctx) { 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()); - //enable hdmi vsync - enableHDMIVsync(connected); - } else { - // Disable the hdmi vsync - enableHDMIVsync(connected); - closeFrameBuffer(); - resetInfo(); - } // Store the external display mExternalDisplay = connected; const char* prop = (connected) ? "1" : "0"; @@ -388,8 +445,7 @@ void ExternalDisplay::setExternalDisplay(int connected) //Invalidate hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; if(!proc) { - ALOGE("%s: HWC proc not registered", - __FUNCTION__); + ALOGE("%s: HWC proc not registered", __FUNCTION__); } else { /* Trigger redraw */ ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__); diff --git a/libhwcomposer/hwc_external.h b/libhwcomposer/hwc_external.h index 55773c0..dfe93c5 100644 --- a/libhwcomposer/hwc_external.h +++ b/libhwcomposer/hwc_external.h @@ -27,6 +27,25 @@ struct hwc_context_t; namespace qhwc { +#define DEVICE_ROOT "/sys/devices/virtual/graphics" +#define DEVICE_NODE_FB1 "fb1" +#define DEVICE_NODE_FB2 "fb2" +#define HDMI_PANEL "dtv panel" +#define WFD_PANEL "writeback panel" +#define EXTERN_DISPLAY_NONE 0 +#define EXTERN_DISPLAY_FB1 1 +#define EXTERN_DISPLAY_FB2 2 +#define MAX_FRAME_BUFFER_NAME_SIZE 80 +#define MAX_DISPLAY_EXTERNAL_DEVICES 2 +#define HPD_ENABLE 1 +#define HPD_DISABLE 0 +#define DEVICE_ONLINE true +#define DEVICE_OFFLINE false + + +#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE_FB1 "/edid_modes" +#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE_FB1 "/hpd" + class ExternalDisplay { //Type of external display - OFF, HDMI, WFD @@ -44,16 +63,19 @@ class ExternalDisplay public: ExternalDisplay(hwc_context_t* ctx); ~ExternalDisplay(); - int getExternalDisplay() const; + inline int getExternalDisplay() { return mExternalDisplay; } void setExternalDisplay(int connected); bool commit(); int enableHDMIVsync(int enable); + void processUEventOnline(const char *str); + void processUEventOffline(const char *str); + bool isHDMIConfigured(); private: bool readResolution(); int parseResolution(char* edidStr, int* edidModes); void setResolution(int ID); - bool openFramebuffer(); + bool openFrameBuffer(int fbNum); bool closeFrameBuffer(); bool writeHPDOption(int userOption) const; bool isValidMode(int ID); diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index 1953c8a..68d01ae 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -18,8 +18,8 @@ * limitations under the License. */ #define DEBUG 0 -#ifndef HWC_OBSERVER_H -#define HWC_OBSERVER_H +#ifndef HWC_UEVENTS_H +#define HWC_UEVENTS_H #include #include #include @@ -32,12 +32,11 @@ namespace qhwc { const char* MSMFB_DEVICE_FB0 = "change@/devices/virtual/graphics/fb0"; const char* MSMFB_DEVICE_FB1 = "change@/devices/virtual/graphics/fb1"; -const char* MSMFB_HDMI_NODE = "fb1"; +const char* MSMFB_FB_NODE = "fb"; static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) { int vsync = 0; - char* hdmi; int64_t timestamp = 0; const char *str = udata; hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; @@ -48,12 +47,12 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) return; } - if(hdmiconnected) + 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)); - hdmi = strcasestr(str, MSMFB_HDMI_NODE); if(vsync) { str += strlen(str) + 1; while(*str) { @@ -68,24 +67,18 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) return; } - 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; - ctx->mExtDisplay->setExternalDisplay(connected); - } else if(!(strncmp(str,"offline@",strlen("offline@")))) { - connected = 0; - ctx->mExtDisplay->setExternalDisplay(connected); - } + // 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; + if(!(strncmp(str,"online@",strlen("online@")))) { + ctx->mExtDisplay->processUEventOnline(str); + } else if(!(strncmp(str,"offline@",strlen("offline@")))) { + ctx->mExtDisplay->processUEventOffline(str); } - } static void *uevent_loop(void *param) @@ -113,4 +106,4 @@ void init_uevent_thread(hwc_context_t* ctx) } }; //namespace -#endif //HWC_OBSERVER_H +#endif //HWC_UEVENTS_H diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp index fde69d0..1508fd5 100644 --- a/libhwcomposer/hwc_uimirror.cpp +++ b/libhwcomposer/hwc_uimirror.cpp @@ -27,30 +27,6 @@ namespace qhwc { -// Function to get the primary device orientation -// Loops thru the hardware layers and returns the orientation of the max. -// number of layers -int getDeviceOrientation(hwc_context_t* ctx, hwc_layer_list_t *list) { - int orientation = list->hwLayers[0].transform; - if(!ctx) { - ALOGE("In %s: ctx is NULL!!", __FUNCTION__); - return -1; - } - for(size_t i=0; i <= list->numHwLayers;i++ ) - { - for(size_t j=i+1; j <= list->numHwLayers; j++) - { - // Should we not check for the video layer orientation as it might - // source orientation(?) - if(list->hwLayers[i].transform == list->hwLayers[j].transform) - { - orientation = list->hwLayers[i].transform; - } - } - } - return orientation; -} - //Static Members ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED; bool UIMirrorOverlay::sIsUiMirroringOn = false; @@ -120,10 +96,8 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_list_t *list) // x,y,w,h ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres); ov.setCrop(dcrop, dest); - //Get the current orientation on primary panel - int transform = getDeviceOrientation(ctx, list); ovutils::eTransform orient = - static_cast(transform); + static_cast(ctx->deviceOrientation); ov.setTransform(orient, dest); ovutils::Dim dim; diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 71c1f73..71592c4 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -124,6 +124,7 @@ struct hwc_context_t { hwc_composer_device_t device; int numHwLayers; int overlayInUse; + int deviceOrientation; //Framebuffer device framebuffer_device_t *mFbDev; diff --git a/libqdutils/gpuformats.h b/libqdutils/gpuformats.h new file mode 100644 index 0000000..cf88d35 --- /dev/null +++ b/libqdutils/gpuformats.h @@ -0,0 +1,52 @@ +/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Code Aurora Forum, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef QCOM_GPUFORMATS_H +#define QCOM_GPUFORMATS_H +#include + +namespace qdutils { +/* + * Checks if the format is supported by the GPU. + * + * @param: format to check + * + * @return true if the format is supported by the GPU. + */ +static inline bool isGPUSupportedFormat(int format) +{ + if ((format == HAL_PIXEL_FORMAT_RGB_888) || + (format == HAL_PIXEL_FORMAT_YCrCb_422_SP) || + (format == HAL_PIXEL_FORMAT_YCbCr_422_SP)) { + return false; + } + return true; +} +}; //namespace qdutils + + + +#endif /* end of include guard: QCOM_GPUFORMATS_H */