From 9ccb3975c70708809950dcf0d34484516711c77d Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Sat, 21 Jul 2012 12:17:13 -0700 Subject: [PATCH 01/12] 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 From a72904b1dc8e933bacba83fd2aa6137ce66bdda0 Mon Sep 17 00:00:00 2001 From: "Arun Kumar K.R" Date: Mon, 23 Jul 2012 13:44:38 -0700 Subject: [PATCH 02/12] hwc: enable vsync for external display - wait for hdmi vsync when connected to hdmi - add commit to call PANDISPLAY for updating ext display - add functions to close fb and reset info Change-Id: Icdd3620bd9d15240a88a26a3f1bf9c07d58d011b --- libhwcomposer/hwc.cpp | 7 ++ libhwcomposer/hwc_external.cpp | 172 +++++++++++++++++++++++---------- libhwcomposer/hwc_external.h | 15 ++- libhwcomposer/hwc_uevents.cpp | 24 +++-- libhwcomposer/hwc_uimirror.cpp | 14 ++- 5 files changed, 166 insertions(+), 66 deletions(-) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 1029ac4..81ccad2 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -29,6 +29,7 @@ #include "hwc_video.h" #include "hwc_uimirror.h" #include "hwc_copybit.h" +#include "hwc_external.h" using namespace qhwc; @@ -107,6 +108,10 @@ static int hwc_eventControl(struct hwc_composer_device* dev, case HWC_EVENT_VSYNC: if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0) ret = -errno; + + if(ctx->mExtDisplay->getExternalDisplay()) { + ret = ctx->mExtDisplay->enableHDMIVsync(enabled); + } break; default: ret = -EINVAL; @@ -149,6 +154,8 @@ static int hwc_set(hwc_composer_device_t *dev, CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); UIMirrorOverlay::draw(ctx); + if(ctx->mExtDisplay->getExternalDisplay()) + ctx->mExtDisplay->commit(); } else { ctx->mOverlay->setState(ovutils::OV_CLOSED); ctx->qbuf->unlockAllPrevious(); diff --git a/libhwcomposer/hwc_external.cpp b/libhwcomposer/hwc_external.cpp index 3507134..b5e1e89 100644 --- a/libhwcomposer/hwc_external.cpp +++ b/libhwcomposer/hwc_external.cpp @@ -42,22 +42,21 @@ namespace qhwc { #define DEVICE_ROOT "/sys/devices/virtual/graphics" #define DEVICE_NODE "fb1" -#define SYSFS_CONNECTED DEVICE_ROOT "/" DEVICE_NODE "/connected" #define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE "/edid_modes" #define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd" -ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):fd(-1), - mCurrentID(-1), mHwcContext(ctx) +ExternalDisplay::ExternalDisplay(hwc_context_t* ctx):mFd(-1), + mCurrentMode(-1), mHwcContext(ctx) { + memset(&mVInfo, 0, sizeof(mVInfo)); //Enable HPD for HDMI writeHPDOption(1); } ExternalDisplay::~ExternalDisplay() { - if (fd > 0) - close(fd); + closeFrameBuffer(); } struct disp_mode_timing_type { @@ -143,7 +142,7 @@ static struct disp_mode_timing_type supported_video_mode_lut[] = { {m1920x1080p30_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 74250, false}, }; -int ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len) +int ExternalDisplay::parseResolution(char* edidStr, int* edidModes) { char delim = ','; int count = 0; @@ -152,27 +151,25 @@ int ExternalDisplay::parseResolution(char* edidStr, int* edidModes, int len) // Ex: 16,4,5,3,32,34,1 // Parse this string to get mode(int) start = (char*) edidStr; - for(int i=0; i 0) { // GEt EDID modes from the EDID strings - mModeCount = parseResolution(mEDIDs, mEDIDModes, len); + mModeCount = parseResolution(mEDIDs, mEDIDModes); ALOGD_IF(DEBUG, "%s: mModeCount = %d", __FUNCTION__, mModeCount); } @@ -202,15 +199,33 @@ bool ExternalDisplay::readResolution() bool ExternalDisplay::openFramebuffer() { - if (fd == -1) { - fd = open("/dev/graphics/fb1", O_RDWR); - if (fd < 0) - ALOGD_IF(DEBUG, "%s: /dev/graphics/fb1 not available" - "\n", __FUNCTION__); + if (mFd == -1) { + mFd = open("/dev/graphics/fb1", O_RDWR); + if (mFd < 0) + ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__); } - return (fd > 0); + return (mFd > 0); } +bool ExternalDisplay::closeFrameBuffer() +{ + int ret = 0; + if(mFd > 0) { + ret = close(mFd); + mFd = -1; + } + return (ret == 0); +} + +// clears the vinfo, edid, best modes +void ExternalDisplay::resetInfo() +{ + memset(&mVInfo, 0, sizeof(mVInfo)); + memset(mEDIDs, 0, sizeof(mEDIDs)); + memset(mEDIDModes, 0, sizeof(mEDIDModes)); + mModeCount = 0; + mCurrentMode = -1; +} int ExternalDisplay::getModeOrder(int mode) { @@ -278,10 +293,23 @@ inline bool ExternalDisplay::isValidMode(int ID) void ExternalDisplay::setResolution(int ID) { struct fb_var_screeninfo info; + int ret = 0; if (!openFramebuffer()) return; + ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo); + if(ret < 0) { + ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__, + strerror(errno)); + } + + ALOGD_IF(DEBUG, "%s: GET Info", __FUNCTION__, + mVInfo.reserved[3], mVInfo.xres, mVInfo.yres, + mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin, + mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin, + mVInfo.pixclock/1000/1000); //If its a valid mode and its a new ID - update var_screeninfo - if ((isValidMode(ID)) && mCurrentID != ID) { + if ((isValidMode(ID)) && mCurrentMode != ID) { const struct disp_mode_timing_type *mode = &supported_video_mode_lut[0]; unsigned count = sizeof(supported_video_mode_lut)/sizeof @@ -292,30 +320,38 @@ void ExternalDisplay::setResolution(int ID) if (cur->video_format == ID) mode = cur; } - ioctl(fd, FBIOGET_VSCREENINFO, &info); - 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(DEBUG, "%s: SET Info Infoset_info(mVInfo); + 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; + mVInfo.reserved[3], mVInfo.xres, mVInfo.yres, + mVInfo.right_margin, mVInfo.hsync_len, mVInfo.left_margin, + mVInfo.lower_margin, mVInfo.vsync_len, mVInfo.upper_margin, + mVInfo.pixclock/1000/1000); + mVInfo.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE; + ret = ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo); + if(ret < 0) { + ALOGD("In %s: FBIOPUT_VSCREENINFO failed Err Str = %s", + __FUNCTION__, strerror(errno)); + } + mCurrentMode = ID; } //Powerup - ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK); - ioctl(fd, FBIOGET_VSCREENINFO, &info); + ret = ioctl(mFd, FBIOBLANK, FB_BLANK_UNBLANK); + if(ret < 0) { + ALOGD("In %s: FBIOBLANK failed Err Str = %s", __FUNCTION__, + strerror(errno)); + } + ret = ioctl(mFd, FBIOGET_VSCREENINFO, &mVInfo); + if(ret < 0) { + ALOGD("In %s: FBIOGET_VSCREENINFO failed Err Str = %s", __FUNCTION__, + strerror(errno)); + } //Pan_Display - ioctl(fd, FBIOPAN_DISPLAY, &info); - property_set("hw.hdmiON", "1"); + ret = ioctl(mFd, FBIOPAN_DISPLAY, &mVInfo); + if(ret < 0) { + ALOGD("In %s: FBIOPAN_DISPLAY failed Err Str = %s", __FUNCTION__, + strerror(errno)); + } } @@ -324,7 +360,7 @@ int ExternalDisplay::getExternalDisplay() const return mExternalDisplay; } -void ExternalDisplay::setExternalDisplayStatus(int connected) +void ExternalDisplay::setExternalDisplay(int connected) { hwc_context_t* ctx = mHwcContext; @@ -336,15 +372,23 @@ void ExternalDisplay::setExternalDisplayStatus(int connected) //Get the best mode and set // TODO: DO NOT call this for WFD setResolution(getBestMode()); + //enable hdmi vsync + enableHDMIVsync(connected); } else { - close(fd); + // Disable the hdmi vsync + enableHDMIVsync(connected); + closeFrameBuffer(); + resetInfo(); } // Store the external display mExternalDisplay = connected; + const char* prop = (connected) ? "1" : "0"; + // set system property + property_set("hw.hdmiON", prop); //Invalidate hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; if(!proc) { - ALOGD_IF(DEBUG, "%s: HWC proc not registered", + ALOGE("%s: HWC proc not registered", __FUNCTION__); } else { /* Trigger redraw */ @@ -360,8 +404,9 @@ bool ExternalDisplay::writeHPDOption(int userOption) const bool ret = true; int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0); if (hdmiHPDFile < 0) { - ALOGD_IF(DEBUG, "%s: state file '%s' not found : ret%d" - "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno)); + ALOGE("%s: state file '%s' not found : ret%d" + "err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, + strerror(errno)); ret = false; } else { int err = -1; @@ -372,7 +417,7 @@ bool ExternalDisplay::writeHPDOption(int userOption) const else err = write(hdmiHPDFile, "0" , 2); if (err <= 0) { - ALOGD_IF(DEBUG, "%s: file write failed '%s'", + ALOGE("%s: file write failed '%s'", __FUNCTION__, SYSFS_HPD); ret = false; } @@ -380,5 +425,30 @@ bool ExternalDisplay::writeHPDOption(int userOption) const } return ret; } + +bool ExternalDisplay::commit() +{ + if(mFd == -1) { + return false; + } else if(ioctl(mFd, FBIOPUT_VSCREENINFO, &mVInfo) == -1) { + ALOGE("%s: FBIOPUT_VSCREENINFO failed, str: %s", __FUNCTION__, + strerror(errno)); + return false; + } + return true; +} + +int ExternalDisplay::enableHDMIVsync(int enable) +{ + if(mFd > 0) { + int ret = ioctl(mFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable); + if (ret<0) { + ALOGE("%s: enabling HDMI vsync failed, str: %s", __FUNCTION__, + strerror(errno)); + } + } + return -errno; +} + }; diff --git a/libhwcomposer/hwc_external.h b/libhwcomposer/hwc_external.h index 9e5f455..55773c0 100644 --- a/libhwcomposer/hwc_external.h +++ b/libhwcomposer/hwc_external.h @@ -21,6 +21,8 @@ #ifndef HWC_EXTERNAL_DISPLAY_H #define HWC_EXTERNAL_DISPLAY_H +#include + struct hwc_context_t; namespace qhwc { @@ -43,26 +45,31 @@ class ExternalDisplay ExternalDisplay(hwc_context_t* ctx); ~ExternalDisplay(); int getExternalDisplay() const; - void setExternalDisplayStatus(int connected); + void setExternalDisplay(int connected); + bool commit(); + int enableHDMIVsync(int enable); private: bool readResolution(); - int parseResolution(char* edidStr, int* edidModes, int len); + int parseResolution(char* edidStr, int* edidModes); void setResolution(int ID); bool openFramebuffer(); + bool closeFrameBuffer(); bool writeHPDOption(int userOption) const; bool isValidMode(int ID); void handleUEvent(char* str, int len); int getModeOrder(int mode); int getBestMode(); + void resetInfo(); - int fd; + int mFd; int mExternalDisplay; - int mCurrentID; + int mCurrentMode; char mEDIDs[128]; int mEDIDModes[64]; int mModeCount; hwc_context_t *mHwcContext; + fb_var_screeninfo mVInfo; }; }; //qhwc diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp index a1df74b..f58fbd3 100644 --- a/libhwcomposer/hwc_uevents.cpp +++ b/libhwcomposer/hwc_uevents.cpp @@ -30,21 +30,30 @@ namespace qhwc { -const char* MSMFB_DEVICE_CHANGE = "change@/devices/virtual/graphics/fb0"; +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"; static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) { - int vsync; + int vsync = 0; char* hdmi; int64_t timestamp = 0; const char *str = udata; - hwc_procs* proc = reinterpret_cast(ctx->device.reserved_proc[0]); + hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; + int hdmiconnected = ctx->mExtDisplay->getExternalDisplay(); - vsync = !strncmp(str, MSMFB_DEVICE_CHANGE, strlen(MSMFB_DEVICE_CHANGE)); - hdmi = strcasestr(str, MSMFB_HDMI_NODE); - if(!vsync && !hdmi) + if(!strcasestr(str, "@/devices/virtual/graphics/fb")) { + ALOGD_IF(DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__); return; + } + + if(hdmiconnected) + 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) { @@ -56,6 +65,7 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) if(str - udata >= len) break; } + return; } if(hdmi) { @@ -72,7 +82,7 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len) } else if(!(strncmp(str,"offline@",strlen("offline@")))) { connected = 0; } - ctx->mExtDisplay->setExternalDisplayStatus(connected); + ctx->mExtDisplay->setExternalDisplay(connected); } } diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp index 9cf91af..3bbe30e 100644 --- a/libhwcomposer/hwc_uimirror.cpp +++ b/libhwcomposer/hwc_uimirror.cpp @@ -33,7 +33,7 @@ namespace qhwc { int getDeviceOrientation(hwc_context_t* ctx, hwc_layer_list_t *list) { int orientation = list->hwLayers[0].transform; if(!ctx) { - ALOGD_IF(HWC_UI_MIRROR, "In %s: ctx is NULL!!", __FUNCTION__); + ALOGE("In %s: ctx is NULL!!", __FUNCTION__); return -1; } for(size_t i=0; i <= list->numHwLayers;i++ ) @@ -60,6 +60,12 @@ bool UIMirrorOverlay::sIsUiMirroringOn = false; bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { sState = ovutils::OV_CLOSED; sIsUiMirroringOn = false; + + if(!ctx->hasOverlay) { + ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring", + __FUNCTION__); + return false; + } // If external display is connected if(ctx->mExtDisplay->getExternalDisplay()) { sState = ovutils::OV_UI_MIRROR; @@ -95,7 +101,7 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_list_t *list) dest = ovutils::OV_PIPE0; } - ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_MEMORY_ID_TYPE_FB; + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; /* - TODO: Secure content if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { ovutils::setMdpFlags(mdpFlags, @@ -160,20 +166,20 @@ bool UIMirrorOverlay::draw(hwc_context_t *ctx) if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset, ovutils::OV_PIPE0)) { ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + ret = false; } break; case ovutils::OV_2D_TRUE_UI_MIRROR: if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset, ovutils::OV_PIPE2)) { ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + ret = false; } break; default: break; } - // TODO: - // Call PANDISPLAY ioctl here to kickoff } return ret; } From bd86fcfff6a3b958c65506b57537cc4a1027f544 Mon Sep 17 00:00:00 2001 From: Jeykumar Sankaran Date: Mon, 23 Jul 2012 12:22:21 -0700 Subject: [PATCH 03/12] display: Add support for MDP Composition This change 1) implements MDP Composition upto 3 layers 2) adds invalidator support to fall back to FB composition during idle screen condition. Change-Id: I8d724f905c943f986b68596e2548a7f5a8ce6588 --- libhwcomposer/Android.mk | 3 +- libhwcomposer/hwc.cpp | 4 + libhwcomposer/hwc_mdpcomp.cpp | 829 ++++++++++++++++++++++++++++++++ libhwcomposer/hwc_mdpcomp.h | 220 +++++++++ libhwcomposer/hwc_utils.cpp | 5 + libhwcomposer/hwc_utils.h | 13 + libqdutils/Android.mk | 3 +- libqdutils/idle_invalidator.cpp | 18 +- 8 files changed, 1084 insertions(+), 11 deletions(-) create mode 100755 libhwcomposer/hwc_mdpcomp.cpp create mode 100755 libhwcomposer/hwc_mdpcomp.h mode change 100644 => 100755 libqdutils/idle_invalidator.cpp diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 9808aa5..05d033e 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -11,5 +11,6 @@ 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_external.cpp \ - hwc_uevents.cpp hwc_copybit.cpp + hwc_uevents.cpp hwc_copybit.cpp \ + hwc_mdpcomp.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 81ccad2..10c2948 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -30,6 +30,7 @@ #include "hwc_uimirror.h" #include "hwc_copybit.h" #include "hwc_external.h" +#include "hwc_mdpcomp.h" using namespace qhwc; @@ -84,6 +85,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) //Nothing here } else if(UIMirrorOverlay::prepare(ctx, list)) { ctx->overlayInUse = true; + } else if(MDPComp::configure(dev, list)) { + ctx->overlayInUse = true; } else if (0) { //Other features ctx->overlayInUse = true; @@ -152,6 +155,7 @@ static int hwc_set(hwc_composer_device_t *dev, if (LIKELY(list)) { VideoOverlay::draw(ctx, list); CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); + MDPComp::draw(ctx, list); EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); UIMirrorOverlay::draw(ctx); if(ctx->mExtDisplay->getExternalDisplay()) diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp new file mode 100755 index 0000000..8107400 --- /dev/null +++ b/libhwcomposer/hwc_mdpcomp.cpp @@ -0,0 +1,829 @@ +/* + * 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. + */ + +#include "hwc_mdpcomp.h" +#include "hwc_qbuf.h" +#include "hwc_external.h" + +#define SUPPORT_4LAYER 0 + +namespace qhwc { + +/****** Class PipeMgr ***********/ + +void inline PipeMgr::reset() { + mVGPipes = MAX_VG; + mVGUsed = 0; + mVGIndex = 0; + mRGBPipes = MAX_RGB; + mRGBUsed = 0; + mRGBIndex = MAX_VG; + mTotalAvail = mVGPipes + mRGBPipes; + memset(&mStatus, 0x0 , sizeof(int)*mTotalAvail); +} + +int PipeMgr::req_for_pipe(int pipe_req) { + + switch(pipe_req) { + case PIPE_REQ_VG: //VG + if(mVGPipes){ + mVGPipes--; + mVGUsed++; + mTotalAvail--; + return PIPE_REQ_VG; + } + case PIPE_REQ_RGB: // RGB + if(mRGBPipes) { + mRGBPipes--; + mRGBUsed++; + mTotalAvail--; + return PIPE_REQ_RGB; + } + return PIPE_NONE; + case PIPE_REQ_FB: //FB + if(mRGBPipes) { + mRGBPipes--; + mRGBUsed++; + mTotalAvail--; + mStatus[VAR_INDEX] = PIPE_IN_FB_MODE; + return PIPE_REQ_FB; + } + default: + break; + }; + return PIPE_NONE; +} + +int PipeMgr::assign_pipe(int pipe_pref) { + switch(pipe_pref) { + case PIPE_REQ_VG: //VG + if(mVGUsed) { + mVGUsed--; + mStatus[mVGIndex] = PIPE_IN_COMP_MODE; + return mVGIndex++; + } + case PIPE_REQ_RGB: //RGB + if(mRGBUsed) { + mRGBUsed--; + mStatus[mRGBIndex] = PIPE_IN_COMP_MODE; + return mRGBIndex++; + } + default: + ALOGE("%s: PipeMgr:invalid case in pipe_mgr_assign", + __FUNCTION__); + return -1; + }; +} + +/****** Class MDPComp ***********/ + +MDPComp::State MDPComp::sMDPCompState = MDPCOMP_OFF; +struct MDPComp::frame_info MDPComp::sCurrentFrame; +PipeMgr MDPComp::sPipeMgr; +IdleInvalidator *MDPComp::idleInvalidator = NULL; +bool MDPComp::sIdleFallBack = false; +bool MDPComp::sDebugLogs = false; +int MDPComp::sSkipCount = 0; +int MDPComp::sMaxLayers = 0; + +bool MDPComp::deinit() { + //XXX: Tear down MDP comp state + return true; +} + +void MDPComp::timeout_handler(void *udata) { + struct hwc_context_t* ctx = (struct hwc_context_t*)(udata); + + if(!ctx) { + ALOGE("%s: received empty data in timer callback", __FUNCTION__); + return; + } + + hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; + + if(!proc) { + ALOGE("%s: HWC proc not registered", __FUNCTION__); + return; + } + sIdleFallBack = true; + /* Trigger SF to redraw the current frame */ + proc->invalidate(proc); +} + +void MDPComp::reset( hwc_context_t *ctx, hwc_layer_list_t* list ) { + sCurrentFrame.count = 0; + free(sCurrentFrame.pipe_layer); + sCurrentFrame.pipe_layer = NULL; + + //Reset MDP pipes + sPipeMgr.reset(); + sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE); + +#if SUPPORT_4LAYER + configure_var_pipe(ctx); +#endif + + //Reset flags and states + unsetMDPCompLayerFlags(ctx, list); + if(sMDPCompState == MDPCOMP_ON) { + sMDPCompState = MDPCOMP_OFF_PENDING; + } +} + +void MDPComp::setLayerIndex(hwc_layer_t* layer, const int pipe_index) +{ + layer->flags &= ~HWC_MDPCOMP_INDEX_MASK; + layer->flags |= pipe_index << MDPCOMP_INDEX_OFFSET; +} + +int MDPComp::getLayerIndex(hwc_layer_t* layer) +{ + int byp_index = -1; + + if(layer->flags & HWC_MDPCOMP) { + byp_index = ((layer->flags & HWC_MDPCOMP_INDEX_MASK) >> + MDPCOMP_INDEX_OFFSET); + byp_index = (byp_index < sMaxLayers ? byp_index : -1 ); + } + return byp_index; +} +void MDPComp::print_info(hwc_layer_t* layer) +{ + hwc_rect_t sourceCrop = layer->sourceCrop; + hwc_rect_t displayFrame = layer->displayFrame; + + int s_l = sourceCrop.left; + int s_t = sourceCrop.top; + int s_r = sourceCrop.right; + int s_b = sourceCrop.bottom; + + int d_l = displayFrame.left; + int d_t = displayFrame.top; + int d_r = displayFrame.right; + int d_b = displayFrame.bottom; + + ALOGD_IF(isDebug(), "src:[%d,%d,%d,%d] (%d x %d) \ + dst:[%d,%d,%d,%d] (%d x %d)", + s_l, s_t, s_r, s_b, (s_r - s_l), (s_b - s_t), + d_l, d_t, d_r, d_b, (d_r - d_l), (d_b - d_t)); +} +/* + * Configures pipe(s) for MDP composition + */ +int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_t *layer, + mdp_pipe_info& mdp_info) { + + int nPipeIndex = mdp_info.index; + + if (ctx) { + + private_handle_t *hnd = (private_handle_t *)layer->handle; + + overlay::Overlay& ov = *(ctx->mOverlay); + + if(!hnd) { + ALOGE("%s: layer handle is NULL", __FUNCTION__); + return -1; + } + + + int hw_w = ctx->mFbDev->width; + int hw_h = ctx->mFbDev->height; + + + hwc_rect_t sourceCrop = layer->sourceCrop; + hwc_rect_t displayFrame = layer->displayFrame; + + const int src_w = sourceCrop.right - sourceCrop.left; + const int src_h = sourceCrop.bottom - sourceCrop.top; + + hwc_rect_t crop = sourceCrop; + int crop_w = crop.right - crop.left; + int crop_h = crop.bottom - crop.top; + + hwc_rect_t dst = displayFrame; + int dst_w = dst.right - dst.left; + int dst_h = dst.bottom - dst.top; + + //REDUNDANT ?? + if(hnd != NULL && + (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) { + ALOGE("%s: failed due to non-pmem memory",__FUNCTION__); + return -1; + } + + if(dst.left < 0 || dst.top < 0 || + dst.right > hw_w || dst.bottom > hw_h) { + ALOGD_IF(isDebug(),"%s: Destination has negative coordinates", + __FUNCTION__); + + qhwc::calculate_crop_rects(crop, dst, hw_w, hw_h); + + //Update calulated width and height + crop_w = crop.right - crop.left; + crop_h = crop.bottom - crop.top; + + dst_w = dst.right - dst.left; + dst_h = dst.bottom - dst.top; + } + + if( (dst_w > hw_w)|| (dst_h > hw_h)) { + ALOGD_IF(isDebug(),"%s: Dest rect exceeds FB", __FUNCTION__); + print_info(layer); + dst_w = hw_w; + dst_h = hw_h; + } + + // Determine pipe to set based on pipe index + ovutils::eDest dest = ovutils::OV_PIPE_ALL; + if (nPipeIndex == 0) { + dest = ovutils::OV_PIPE0; + } else if (nPipeIndex == 1) { + dest = ovutils::OV_PIPE1; + } else if (nPipeIndex == 2) { + dest = ovutils::OV_PIPE2; + } + + ovutils::eZorder zOrder = ovutils::ZORDER_0; + + if(mdp_info.z_order == 0 ) { + zOrder = ovutils::ZORDER_0; + } else if(mdp_info.z_order == 1 ) { + zOrder = ovutils::ZORDER_1; + } else if(mdp_info.z_order == 2 ) { + zOrder = ovutils::ZORDER_2; + } + + // Order order order + // setSource - just setting source + // setParameter - changes src w/h/f accordingly + // setCrop - ROI - src_rect + // setPosition - dst_rect + // commit - commit changes to mdp driver + // queueBuffer - not here, happens when draw is called + + ovutils::eTransform orient = + static_cast(layer->transform); + + ov.setTransform(orient, dest); + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::eMdpFlags mdpFlags = mdp_info.isVG ? ovutils::OV_MDP_PIPE_SHARE + : ovutils::OV_MDP_FLAGS_NONE; + ovutils::eIsFg isFG = mdp_info.isFG ? ovutils::IS_FG_SET + : ovutils::IS_FG_OFF; + ovutils::PipeArgs parg(mdpFlags, + info, + zOrder, + isFG, + ovutils::ROT_FLAG_DISABLED); + + ovutils::PipeArgs pargs[MAX_PIPES] = { parg, parg, parg }; + if (!ov.setSource(pargs, dest)) { + ALOGE("%s: setSource failed", __FUNCTION__); + return -1; + } + + ovutils::Dim dcrop(crop.left, crop.top, crop_w, crop_h); + if (!ov.setCrop(dcrop, dest)) { + ALOGE("%s: setCrop failed", __FUNCTION__); + return -1; + } + + ovutils::Dim dim(dst.left, dst.top, dst_w, dst_h); + if (!ov.setPosition(dim, dest)) { + ALOGE("%s: setPosition failed", __FUNCTION__); + return -1; + } + + ALOGD_IF(isDebug(),"%s: MDP set: crop[%d,%d,%d,%d] dst[%d,%d,%d,%d] \ + nPipe: %d isFG: %d zorder: %d",__FUNCTION__, dcrop.x, + dcrop.y,dcrop.w, dcrop.h, dim.x, dim.y, dim.w, dim.h, + nPipeIndex,mdp_info.isFG, mdp_info.z_order); + + if (!ov.commit(dest)) { + ALOGE("%s: commit failed", __FUNCTION__); + return -1; + } + } + return 0; +} + +/* + * MDPComp not possible when + * 1. We have more than sMaxLayers + * 2. External display connected + * 3. Composition is triggered by + * Idle timer expiry + * 4. Rotation is needed + * 5. Overlay in use + */ + +bool MDPComp::is_doable(hwc_composer_device_t *dev, + const hwc_layer_list_t* list) { + hwc_context_t* ctx = (hwc_context_t*)(dev); + + if(!ctx) { + ALOGE("%s: hwc context is NULL", __FUNCTION__); + return false; + } + + //Number of layers + if(list->numHwLayers < 1 || list->numHwLayers > sMaxLayers) { + ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__); + return false; + } + + //Disable MDPComp when ext display connected + if(ctx->mExtDisplay->getExternalDisplay()) { + ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__); + } + + //FB composition on idle timeout + if(sIdleFallBack) { + ALOGD_IF(isDebug(), "%s: idle fallback",__FUNCTION__); + return false; + } + + //MDP composition is not efficient if rotation is needed. + for(unsigned int i = 0; i < list->numHwLayers; ++i) { + if(list->hwLayers[i].transform) { + ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__); + return false; + } + } + + return true; +} + +void MDPComp::setMDPCompLayerFlags(hwc_layer_list_t* list) { + + for(int index = 0 ; index < sCurrentFrame.count; index++ ) + { + int layer_index = sCurrentFrame.pipe_layer[index].layer_index; + if(layer_index >= 0) { + hwc_layer_t* layer = &(list->hwLayers[layer_index]); + + layer->flags |= HWC_MDPCOMP; + layer->compositionType = HWC_OVERLAY; + layer->hints |= HWC_HINT_CLEAR_FB; + } + } +} + +void MDPComp::get_layer_info(hwc_layer_t* layer, int& flags) { + + private_handle_t* hnd = (private_handle_t*)layer->handle; + + if(layer->flags & HWC_SKIP_LAYER) { + flags |= MDPCOMP_LAYER_SKIP; + } else if(hnd != NULL && + (hnd->flags & private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM )) { + flags |= MDPCOMP_LAYER_UNSUPPORTED_MEM; + } + + if(layer->blending != HWC_BLENDING_NONE) + flags |= MDPCOMP_LAYER_BLEND; + + int dst_w, dst_h; + getLayerResolution(layer, dst_w, dst_h); + + hwc_rect_t sourceCrop = layer->sourceCrop; + const int src_w = sourceCrop.right - sourceCrop.left; + const int src_h = sourceCrop.bottom - sourceCrop.top; + if(((src_w > dst_w) || (src_h > dst_h))) { + flags |= MDPCOMP_LAYER_DOWNSCALE; + } +} + +int MDPComp::mark_layers(hwc_layer_list_t* list, layer_mdp_info* layer_info, + frame_info& current_frame) { + + int layer_count = list->numHwLayers; + + if(layer_count > sMaxLayers) { + if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) { + ALOGE("%s: binding var pipe to FB failed!!", __FUNCTION__); + return 0; + } + } + + //Parse layers from higher z-order + for(int index = layer_count - 1 ; index >= 0; index-- ) { + hwc_layer_t* layer = &list->hwLayers[index]; + + int layer_prop = 0; + get_layer_info(layer, layer_prop); + + ALOGD_IF(isDebug(),"%s: prop for layer [%d]: %x", __FUNCTION__, + index, layer_prop); + + //Both in cases of NON-CONTIGUOUS memory or SKIP layer, + //current version of mdp composition falls back completely to FB + //composition. + //TO DO: Support dual mode composition + + if(layer_prop & MDPCOMP_LAYER_UNSUPPORTED_MEM) { + ALOGD_IF(isDebug(), "%s: Non contigous memory",__FUNCTION__); + return MDPCOMP_ABORT; + } + + if(layer_prop & MDPCOMP_LAYER_SKIP) { + ALOGD_IF(isDebug(), "%s:skip layer",__FUNCTION__); + return MDPCOMP_ABORT; + } + + //Request for MDP pipes + int pipe_pref = PIPE_REQ_VG; + + if((layer_prop & MDPCOMP_LAYER_DOWNSCALE) && + (layer_prop & MDPCOMP_LAYER_BLEND)) { + pipe_pref = PIPE_REQ_RGB; + } + + int allocated_pipe = sPipeMgr.req_for_pipe( pipe_pref); + if(allocated_pipe) { + layer_info[index].can_use_mdp = true; + layer_info[index].pipe_pref = allocated_pipe; + current_frame.count++; + }else { + ALOGE("%s: pipe marking in mark layer fails for : %d", + __FUNCTION__, allocated_pipe); + return MDPCOMP_FAILURE; + } + } + return MDPCOMP_SUCCESS; +} + +void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) { + for(int i = 0 ; i < count; i++ ) { + layer_info[i].can_use_mdp = false; + layer_info[i].pipe_pref = PIPE_NONE; + } +} + +bool MDPComp::alloc_layer_pipes(hwc_layer_list_t* list, + layer_mdp_info* layer_info, frame_info& current_frame) { + + int layer_count = list->numHwLayers; + int mdp_count = current_frame.count; + int fallback_count = layer_count - mdp_count; + int frame_pipe_count = 0; + + ALOGD_IF(isDebug(), "%s: dual mode: %d total count: %d \ + mdp count: %d fallback count: %d", + __FUNCTION__, (layer_count != mdp_count), + layer_count, mdp_count, fallback_count); + + for(int index = 0 ; index < layer_count ; index++ ) { + hwc_layer_t* layer = &list->hwLayers[index]; + + if(layer_info[index].can_use_mdp) { + pipe_layer_pair& info = current_frame.pipe_layer[frame_pipe_count]; + mdp_pipe_info& pipe_info = info.pipe_index; + + pipe_info.index = sPipeMgr.assign_pipe(layer_info[index].pipe_pref); + pipe_info.isVG = (layer_info[index].pipe_pref == PIPE_REQ_VG); + pipe_info.isFG = (frame_pipe_count == 0); + /* if VAR pipe is attached to FB, FB will be updated with + VSYNC WAIT flag, so no need to set VSYNC WAIT for any + bypass pipes. if not, set VSYNC WAIT to the last updating pipe*/ + pipe_info.vsync_wait = + (sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) ? false: + (frame_pipe_count == (mdp_count - 1)); + /* All the layers composed on FB will have MDP zorder 0, so start + assigning from 1*/ + pipe_info.z_order = index - + (fallback_count ? fallback_count - 1 : fallback_count); + + info.layer_index = index; + frame_pipe_count++; + } + } + return 1; +} + +//returns array of layers and their allocated pipes +bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_layer_list_t* list, + frame_info& current_frame ) { + + int layer_count = list->numHwLayers; + + /* clear pipe status */ + sPipeMgr.reset(); + + layer_mdp_info* bp_layer_info = (layer_mdp_info*) + malloc(sizeof(layer_mdp_info)* layer_count); + + reset_layer_mdp_info(bp_layer_info, layer_count); + + /* iterate through layer list to mark candidate */ + if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) { + free(bp_layer_info); + current_frame.count = 0; + ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__); + return false; + } + current_frame.pipe_layer = (pipe_layer_pair*) + malloc(sizeof(pipe_layer_pair) * current_frame.count); + + /* allocate MDP pipes for marked layers */ + alloc_layer_pipes( list, bp_layer_info, current_frame); + + free(bp_layer_info); + return true; +} +#if SUPPORT_4LAYER +int MDPComp::configure_var_pipe(hwc_context_t* ctx) { + + if(!ctx) { + ALOGE("%s: invalid context", __FUNCTION__); + return -1; + } + + framebuffer_device_t *fbDev = ctx->fbDev; + if (!fbDev) { + ALOGE("%s: fbDev is NULL", __FUNCTION__); + return -1; + } + + int new_mode = -1, cur_mode; + fbDev->perform(fbDev,EVENT_GET_VAR_PIPE_MODE, (void*)&cur_mode); + + if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_FB_MODE) { + new_mode = VAR_PIPE_FB_ATTACH; + } else if(sPipeMgr.getStatus(VAR_INDEX) == PIPE_IN_BYP_MODE) { + new_mode = VAR_PIPE_FB_DETACH; + fbDev->perform(fbDev,EVENT_WAIT_POSTBUFFER,NULL); + } + + ALOGD_IF(isDebug(),"%s: old_mode: %d new_mode: %d", __FUNCTION__, + cur_mode, new_mode); + + if((new_mode != cur_mode) && (new_mode >= 0)) { + if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&new_mode) < 0) { + ALOGE("%s: Setting var pipe mode failed", __FUNCTION__); + } + } + + return 0; +} +#endif + +bool MDPComp::setup(hwc_context_t* ctx, hwc_layer_list_t* list) { + int nPipeIndex, vsync_wait, isFG; + int numHwLayers = list->numHwLayers; + + frame_info ¤t_frame = sCurrentFrame; + current_frame.count = 0; + + if(!ctx) { + ALOGE("%s: invalid context", __FUNCTION__); + return -1; + } + + framebuffer_device_t *fbDev = ctx->mFbDev; + if (!fbDev) { + ALOGE("%s: fbDev is NULL", __FUNCTION__); + return -1; + } + + if(!parse_and_allocate(ctx, list, current_frame)) { +#if SUPPORT_4LAYER + int mode = VAR_PIPE_FB_ATTACH; + if(fbDev->perform(fbDev,EVENT_SET_VAR_PIPE_MODE,(void*)&mode) < 0 ) { + ALOGE("%s: setting var pipe mode failed", __FUNCTION__); + } +#endif + ALOGD_IF(isDebug(), "%s: Falling back to FB", __FUNCTION__); + return false; + } +#if SUPPORT_4LAYER + configure_var_pipe(ctx); +#endif + + overlay::Overlay& ov = *(ctx->mOverlay); + ovutils::eOverlayState state = ov.getState(); + + if (current_frame.count == 1) { + state = ovutils::OV_BYPASS_1_LAYER; + } else if (current_frame.count == 2) { + state = ovutils::OV_BYPASS_2_LAYER; + } else if (current_frame.count == 3) { + state = ovutils::OV_BYPASS_3_LAYER; + } + + ov.setState(state); + + + for (int index = 0 ; index < current_frame.count; index++) { + int layer_index = current_frame.pipe_layer[index].layer_index; + hwc_layer_t* layer = &list->hwLayers[layer_index]; + mdp_pipe_info& cur_pipe = current_frame.pipe_layer[index].pipe_index; + + if( prepare(ctx, layer, cur_pipe) != 0 ) { + ALOGD_IF(isDebug(), "%s: MDPComp failed to configure overlay for \ + layer %d with pipe index:%d",__FUNCTION__, + index, cur_pipe.index); + return false; + } else { + setLayerIndex(layer, index); + } + } + return true; +} + +void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_layer_list_t* list) +{ + if (!list) + return; + + for (int index = 0 ; index < sCurrentFrame.count; index++) { + int l_index = sCurrentFrame.pipe_layer[index].layer_index; + if(list->hwLayers[l_index].flags & HWC_MDPCOMP) { + list->hwLayers[l_index].flags &= ~HWC_MDPCOMP; + } + } +} + +int MDPComp::draw(hwc_context_t *ctx, hwc_layer_list_t* list) { + + if(!isEnabled()) { + ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled",__FUNCTION__); + return 0; + } + + if(!ctx || !list) { + ALOGE("%s: invalid contxt or list",__FUNCTION__); + return -1; + } + + overlay::Overlay& ov = *(ctx->mOverlay); + + for(unsigned int i = 0; i < list->numHwLayers; i++ ) + { + hwc_layer_t *layer = &list->hwLayers[i]; + + if(!(layer->flags & HWC_MDPCOMP)) { + ALOGD_IF(isDebug(), "%s: Layer Not flagged for MDP comp", + __FUNCTION__); + continue; + } + + int data_index = getLayerIndex(layer); + mdp_pipe_info& pipe_info = + sCurrentFrame.pipe_layer[data_index].pipe_index; + int index = pipe_info.index; + + if(index < 0) { + ALOGE("%s: Invalid pipe index (%d)", __FUNCTION__, index); + return -1; + } + + /* reset Invalidator */ + if(idleInvalidator) + idleInvalidator->markForSleep(); + + ovutils::eDest dest; + + if (index == 0) { + dest = ovutils::OV_PIPE0; + } else if (index == 1) { + dest = ovutils::OV_PIPE1; + } else if (index == 2) { + dest = ovutils::OV_PIPE2; + } + + if (ctx ) { + private_handle_t *hnd = (private_handle_t *)layer->handle; + if(!hnd) { + ALOGE("%s handle null", __FUNCTION__); + return -1; + } + + //lock buffer before queue + //XXX: Handle lock failure + ctx->qbuf->lockAndAdd(hnd); + + ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \ + using pipe: %d", __FUNCTION__, layer, + hnd, index ); + + if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + return -1; + } + } + layer->flags &= ~HWC_MDPCOMP; + layer->flags |= HWC_MDPCOMP_INDEX_MASK; + } + return 0; +} + +bool MDPComp::init(hwc_context_t *dev) { + + if(!dev) { + ALOGE("%s: Invalid hwc context!!",__FUNCTION__); + return false; + } + +#if SUPPORT_4LAYER + if(MAX_MDPCOMP_LAYERS > MAX_STATIC_PIPES) { + framebuffer_device_t *fbDev = dev->fbDevice; + if(fbDev == NULL) { + ALOGE("%s: FATAL: framebuffer device is NULL", __FUNCTION__); + return false; + } + + //Receive VAR pipe object from framebuffer + if(fbDev->perform(fbDev,EVENT_GET_VAR_PIPE,(void*)&ov) < 0) { + ALOGE("%s: FATAL: getVariablePipe failed!!", __FUNCTION__); + return false; + } + + sPipeMgr.setStatus(VAR_INDEX, PIPE_IN_FB_MODE); + } +#endif + char property[PROPERTY_VALUE_MAX]; + + sMaxLayers = 0; + if(property_get("debug.mdpcomp.maxlayer", property, NULL) > 0) { + if(atoi(property) != 0) + sMaxLayers = atoi(property); + } + + sDebugLogs = false; + if(property_get("debug.mdpcomp.logs", property, NULL) > 0) { + if(atoi(property) != 0) + sDebugLogs = true; + } + + unsigned long idle_timeout = DEFAULT_IDLE_TIME; + if(property_get("debug.mdpcomp.idletime", property, NULL) > 0) { + if(atoi(property) != 0) + idle_timeout = atoi(property); + } + + //create Idle Invalidator + idleInvalidator = IdleInvalidator::getInstance(); + + if(idleInvalidator == NULL) { + ALOGE("%s: failed to instantiate idleInvalidator object", __FUNCTION__); + } else { + idleInvalidator->init(timeout_handler, dev, idle_timeout); + } + return true; +} + +bool MDPComp::configure(hwc_composer_device_t *dev, hwc_layer_list_t* list) { + + if(!isEnabled()) { + ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__); + return false; + } + + hwc_context_t* ctx = (hwc_context_t*)(dev); + + bool isMDPCompUsed = true; + bool doable = is_doable(dev, list); + + if(doable) { + if(setup(ctx, list)) { + setMDPCompLayerFlags(list); + sMDPCompState = MDPCOMP_ON; + } else { + ALOGD_IF(isDebug(),"%s: MDP Comp Failed",__FUNCTION__); + isMDPCompUsed = false; + } + } else { + ALOGD_IF( isDebug(),"%s: MDP Comp not possible[%d]",__FUNCTION__, + doable); + isMDPCompUsed = false; + } + + //Reset states + if(!isMDPCompUsed) { + //Reset current frame + reset(ctx, list); + } + + sIdleFallBack = false; + + return isMDPCompUsed; +} +}; //namespace + diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h new file mode 100755 index 0000000..199204c --- /dev/null +++ b/libhwcomposer/hwc_mdpcomp.h @@ -0,0 +1,220 @@ +/* + * 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_MDP_COMP +#define HWC_MDP_COMP + +#include +#include +#include +#include + +#define MAX_STATIC_PIPES 3 +#define MDPCOMP_INDEX_OFFSET 4 +#define DEFAULT_IDLE_TIME 2000 + +#define MAX_VG 2 +#define MAX_RGB 2 +#define VAR_INDEX 3 +#define MAX_PIPES (MAX_VG + MAX_RGB) +#define HWC_MDPCOMP_INDEX_MASK 0x00000030 + + +//struct hwc_context_t; + +namespace qhwc { + +// pipe status +enum { + PIPE_UNASSIGNED = 0, + PIPE_IN_FB_MODE, + PIPE_IN_COMP_MODE, +}; + +// pipe request +enum { + PIPE_NONE = 0, + PIPE_REQ_VG, + PIPE_REQ_RGB, + PIPE_REQ_FB, +}; + +// MDP Comp Status +enum { + MDPCOMP_SUCCESS = 0, + MDPCOMP_FAILURE, + MDPCOMP_ABORT, +}; + +//This class manages the status of 4 MDP pipes and keeps +//track of Variable pipe mode. +class PipeMgr { + +public: + PipeMgr() { reset();} + //reset pipemgr params + void reset(); + + //Based on the preference received, pipe mgr + //allocates the best available pipe to handle + //the case + int req_for_pipe(int pipe_req); + + //Allocate requested pipe and update availablity + int assign_pipe(int pipe_pref); + + // Get/Set pipe status + void setStatus(int pipe_index, int pipe_status) { + mStatus[pipe_index] = pipe_status; + } + int getStatus(int pipe_index) { + return mStatus[pipe_index]; + } +private: + int mVGPipes; + int mVGUsed; + int mVGIndex; + int mRGBPipes; + int mRGBUsed; + int mRGBIndex; + int mTotalAvail; + int mStatus[MAX_PIPES]; +}; + + +class MDPComp { + enum State { + MDPCOMP_ON = 0, + MDPCOMP_OFF, + MDPCOMP_OFF_PENDING, + }; + + enum { + MDPCOMP_LAYER_BLEND = 1, + MDPCOMP_LAYER_DOWNSCALE = 2, + MDPCOMP_LAYER_SKIP = 4, + MDPCOMP_LAYER_UNSUPPORTED_MEM = 8, + }; + + struct mdp_pipe_info { + int index; + int z_order; + bool isVG; + bool isFG; + bool vsync_wait; + }; + + struct pipe_layer_pair { + int layer_index; + mdp_pipe_info pipe_index; + native_handle_t* handle; + }; + + struct frame_info { + int count; + struct pipe_layer_pair* pipe_layer; + + }; + + struct layer_mdp_info { + bool can_use_mdp; + int pipe_pref; + }; + + static State sMDPCompState; + static IdleInvalidator *idleInvalidator; + static struct frame_info sCurrentFrame; + static PipeMgr sPipeMgr; + static int sSkipCount; + static int sMaxLayers; + static bool sDebugLogs; + static bool sIdleFallBack; + +public: + /* Handler to invoke frame redraw on Idle Timer expiry */ + static void timeout_handler(void *udata); + + /* configure/tear-down MDPComp params*/ + static bool init(hwc_context_t *ctx); + static bool deinit(); + + /*sets up mdp comp for the current frame */ + static bool configure(hwc_composer_device_t *ctx, hwc_layer_list_t* list); + + /* draw */ + static int draw(hwc_context_t *ctx, hwc_layer_list_t *list); + + /* store frame stats */ + static void setStats(int skipCt) { sSkipCount = skipCt;}; + +private: + + /* get/set pipe index associated with overlay layers */ + static void setLayerIndex(hwc_layer_t* layer, const int pipe_index); + static int getLayerIndex(hwc_layer_t* layer); + + /* set/reset flags for MDPComp */ + static void setMDPCompLayerFlags(hwc_layer_list_t* list); + static void unsetMDPCompLayerFlags(hwc_context_t* ctx, + hwc_layer_list_t* list); + + static void print_info(hwc_layer_t* layer); + + /* configure's overlay pipes for the frame */ + static int prepare(hwc_context_t *ctx, hwc_layer_t *layer, + mdp_pipe_info& mdp_info); + + /* checks for conditions where mdpcomp is not possible */ + static bool is_doable(hwc_composer_device_t *dev, + const hwc_layer_list_t* list); + + static bool setup(hwc_context_t* ctx, hwc_layer_list_t* list); + + /* parses layer for properties affecting mdp comp */ + static void get_layer_info(hwc_layer_t* layer, int& flags); + + /* iterates through layer list to choose candidate to use overlay */ + static int mark_layers(hwc_layer_list_t* list, layer_mdp_info* layer_info, + frame_info& current_frame); + static bool parse_and_allocate(hwc_context_t* ctx, hwc_layer_list_t* list, + frame_info& current_frame ); + + /* clears layer info struct */ + static void reset_layer_mdp_info(layer_mdp_info* layer_mdp_info,int count); + + /* allocates pipes to selected candidates */ + static bool alloc_layer_pipes(hwc_layer_list_t* list, + layer_mdp_info* layer_info, + frame_info& current_frame); + /* updates variable pipe mode for the current frame */ + static int configure_var_pipe(hwc_context_t* ctx); + + /* get/set states */ + static State get_state() { return sMDPCompState; }; + static void set_state(State state) { sMDPCompState = state; }; + + /* reset state */ + static void reset( hwc_context_t *ctx, hwc_layer_list_t* list ); + + /* Is feature enabled */ + static bool isEnabled() { return sMaxLayers ? true : false; }; + /* Is debug enabled */ + static bool isDebug() { return sDebugLogs ? true : false; }; +}; +}; //namespace +#endif diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index 870a758..0b62a98 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -22,6 +22,7 @@ #include "hwc_qbuf.h" #include "hwc_copybit.h" #include "hwc_external.h" +#include "hwc_mdpcomp.h" namespace qhwc { @@ -43,6 +44,7 @@ void initContext(hwc_context_t *ctx) ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); ctx->mCopybitEngine = CopybitEngine::getInstance(); ctx->mExtDisplay = new ExternalDisplay(ctx); + MDPComp::init(ctx); init_uevent_thread(ctx); @@ -103,6 +105,7 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list) int yuvCount = 0; int yuvLayerIndex = -1; bool isYuvLayerSkip = false; + int skipCount = 0; for (size_t i = 0; i < list->numHwLayers; i++) { private_handle_t *hnd = @@ -120,11 +123,13 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list) if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) { isYuvLayerSkip = true; } + skipCount++; } } VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); + MDPComp::setStats(skipCount); ctx->numHwLayers = list->numHwLayers; return; diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 1e405f7..a6c1446 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -50,6 +50,12 @@ enum HWCCompositionType { HWC_USE_COPYBIT // This layer is to be handled by copybit }; +enum { + HWC_MDPCOMP = 0x00000002, + HWC_LAYER_RESERVED_0 = 0x00000004, + HWC_LAYER_RESERVED_1 = 0x00000008 +}; + class ExternalDisplay; class CopybitEngine; @@ -81,6 +87,13 @@ static inline bool isBufferLocked(const private_handle_t* hnd) { // Initialize uevent thread void init_uevent_thread(hwc_context_t* ctx); +inline void getLayerResolution(const hwc_layer_t* layer, + int& width, int& height) +{ + hwc_rect_t displayFrame = layer->displayFrame; + width = displayFrame.right - displayFrame.left; + height = displayFrame.bottom - displayFrame.top; +} }; //qhwc namespace // ----------------------------------------------------------------------------- diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk index dfeae09..61daeac 100644 --- a/libqdutils/Android.mk +++ b/libqdutils/Android.mk @@ -8,5 +8,6 @@ LOCAL_SHARED_LIBRARIES := $(common_libs) LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes) LOCAL_CFLAGS := $(common_flags) LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) -LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp +LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp \ + idle_invalidator.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp old mode 100644 new mode 100755 index 0b98e11..d0c0f73 --- a/libqdutils/idle_invalidator.cpp +++ b/libqdutils/idle_invalidator.cpp @@ -27,10 +27,10 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "IdleInvalidator.h" +#include "idle_invalidator.h" #include -#define II_DEBUG 1 +#define II_DEBUG 0 static const char *threadName = "Invalidator"; InvalidatorHandler IdleInvalidator::mHandler = NULL; @@ -38,12 +38,12 @@ android::sp IdleInvalidator::sInstance(0); IdleInvalidator::IdleInvalidator(): Thread(false), mHwcContext(0), mSleepAgain(false), mSleepTime(0) { - ALOGE_IF(II_DEBUG, "shs %s", __func__); + ALOGD_IF(II_DEBUG, "%s", __func__); } int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data, unsigned int idleSleepTime) { - ALOGE_IF(II_DEBUG, "shs %s", __func__); + ALOGD_IF(II_DEBUG, "%s", __func__); /* store registered handler */ mHandler = reg_handler; @@ -53,8 +53,8 @@ int IdleInvalidator::init(InvalidatorHandler reg_handler, void* user_data, } bool IdleInvalidator::threadLoop() { - ALOGE_IF(II_DEBUG, "shs %s", __func__); - usleep(mSleepTime * 1000); + ALOGD_IF(II_DEBUG, "%s", __func__); + usleep(mSleepTime * 500); if(mSleepAgain) { //We need to sleep again! mSleepAgain = false; @@ -66,12 +66,12 @@ bool IdleInvalidator::threadLoop() { } int IdleInvalidator::readyToRun() { - ALOGE_IF(II_DEBUG, "shs %s", __func__); + ALOGD_IF(II_DEBUG, "%s", __func__); return 0; /*NO_ERROR*/ } void IdleInvalidator::onFirstRef() { - ALOGE_IF(II_DEBUG, "shs %s", __func__); + ALOGD_IF(II_DEBUG, "%s", __func__); } void IdleInvalidator::markForSleep() { @@ -81,7 +81,7 @@ void IdleInvalidator::markForSleep() { } IdleInvalidator *IdleInvalidator::getInstance() { - ALOGE_IF(II_DEBUG, "shs %s", __func__); + ALOGD_IF(II_DEBUG, "%s", __func__); if(sInstance.get() == NULL) sInstance = new IdleInvalidator(); return sInstance.get(); From 912842f62dff8ed80d52869e09c6598fc8d01b83 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Wed, 25 Jul 2012 18:27:14 -0700 Subject: [PATCH 04/12] display: Get panel type from framebuffer Change-Id: I5dc16125bbb7d864dcb7106166e91b950a44d686 --- libhwcomposer/hwc.cpp | 1 + libhwcomposer/hwc_copybit.cpp | 4 ++-- libhwcomposer/hwc_uimirror.cpp | 2 +- libhwcomposer/hwc_utils.cpp | 7 ++++--- libhwcomposer/hwc_utils.h | 14 ++++++++++---- libhwcomposer/hwc_video.cpp | 2 +- libqdutils/mdp_version.cpp | 19 ++++++++++--------- libqdutils/mdp_version.h | 14 ++++++++++++++ 8 files changed, 43 insertions(+), 20 deletions(-) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 10c2948..ad0000c 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -24,6 +24,7 @@ #include #include +#include #include "hwc_utils.h" #include "hwc_qbuf.h" #include "hwc_video.h" diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp index 7892632..99aecca 100644 --- a/libhwcomposer/hwc_copybit.cpp +++ b/libhwcomposer/hwc_copybit.cpp @@ -380,7 +380,7 @@ bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, { // XXX : TODO , currently returning false for MDP4 targets, // This has to be modified after adding C2D support. - if(ctx->hasOverlay) + if(ctx->mMDP.hasOverlay) return false; framebuffer_device_t* fbDev = ctx->mFbDev; @@ -397,7 +397,7 @@ bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, LINK_eglGetCurrentSurface == NULL ) return false; - if(!ctx->hasOverlay) { + if(!ctx->mMDP.hasOverlay) { if (numYUVBuffers) return true; } diff --git a/libhwcomposer/hwc_uimirror.cpp b/libhwcomposer/hwc_uimirror.cpp index 3bbe30e..d2b766d 100644 --- a/libhwcomposer/hwc_uimirror.cpp +++ b/libhwcomposer/hwc_uimirror.cpp @@ -61,7 +61,7 @@ bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { sState = ovutils::OV_CLOSED; sIsUiMirroringOn = false; - if(!ctx->hasOverlay) { + if(!ctx->mMDP.hasOverlay) { ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring", __FUNCTION__); return false; diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index 0b62a98..dd890a9 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -40,8 +40,9 @@ void initContext(hwc_context_t *ctx) openFramebufferDevice(ctx); ctx->mOverlay = overlay::Overlay::getInstance(); ctx->qbuf = new QueuedBufferStore(); - ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion(); - ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); + ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion(); + ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay(); + ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType(); ctx->mCopybitEngine = CopybitEngine::getInstance(); ctx->mExtDisplay = new ExternalDisplay(ctx); MDPComp::init(ctx); @@ -49,7 +50,7 @@ void initContext(hwc_context_t *ctx) init_uevent_thread(ctx); ALOGI("Initializing Qualcomm Hardware Composer"); - ALOGI("MDP version: %d", ctx->mdpVersion); + ALOGI("MDP version: %d", ctx->mMDP.version); } void closeContext(hwc_context_t *ctx) diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index a6c1446..9ce0815 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -37,6 +37,14 @@ class Overlay; namespace qhwc { //fwrd decl class QueuedBufferStore; +class ExternalDisplay; +class CopybitEngine; + +struct MDPInfo { + int version; + char panel; + bool hasOverlay; +}; enum external_display_type { EXT_TYPE_NONE, @@ -57,8 +65,6 @@ enum { }; -class ExternalDisplay; -class CopybitEngine; // ----------------------------------------------------------------------------- // Utility functions - implemented in hwc_utils.cpp void dumpLayer(hwc_layer_t const* l); @@ -102,8 +108,6 @@ inline void getLayerResolution(const hwc_layer_t* layer, struct hwc_context_t { hwc_composer_device_t device; int numHwLayers; - int mdpVersion; - bool hasOverlay; int overlayInUse; //Framebuffer device @@ -121,6 +125,8 @@ struct hwc_context_t { // External display related information qhwc::ExternalDisplay *mExtDisplay; + qhwc::MDPInfo mMDP; + }; #endif //HWC_UTILS_H diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index 190e31b..5b20ba4 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -35,7 +35,7 @@ bool VideoOverlay::sIsLayerSkip = false; //Cache stats, figure out the state, config overlay bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { sIsModeOn = false; - if(!ctx->hasOverlay) { + if(!ctx->mMDP.hasOverlay) { ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__); return false; } diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp index 25f1142..78ca52f 100644 --- a/libqdutils/mdp_version.cpp +++ b/libqdutils/mdp_version.cpp @@ -34,10 +34,11 @@ ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::MDPVersion); namespace qdutils { -static int getMDPVersionFromFB() +MDPVersion::MDPVersion() { int fb_fd = open("/dev/graphics/fb0", O_RDWR); int mdp_version = MDP_V_UNKNOWN; + char panel_type = 0; struct fb_fix_screeninfo fb_finfo; if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) { ALOGE("FBIOGET_FSCREENINFO failed"); @@ -61,18 +62,18 @@ static int getMDPVersionFromFB() } else { mdp_version = MDP_V_UNKNOWN; } + int len = strlen("msmfbXX_"); + if (mdp_version == MDP_V3_0_3) + len++; + panel_type = fb_finfo.id[len]; + } close(fb_fd); - return mdp_version; -} - -MDPVersion::MDPVersion() -{ - mMDPVersion = getMDPVersionFromFB(); + mMDPVersion = mdp_version; + mHasOverlay = false; if((mMDPVersion >= MDP_V4_0) || (mMDPVersion == MDP_V_UNKNOWN)) mHasOverlay = true; - else - mHasOverlay = false; + mPanelType = panel_type; } }; //namespace qdutils diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h index 5ec0c67..9137cd4 100644 --- a/libqdutils/mdp_version.h +++ b/libqdutils/mdp_version.h @@ -52,15 +52,29 @@ enum mdp_version { MDSS_V5 = 500, }; +#define MDDI_PANEL '1' +#define EBI2_PANEL '2' +#define LCDC_PANEL '3' +#define EXT_MDDI_PANEL '4' +#define TV_PANEL '5' +#define DTV_PANEL '7' +#define MIPI_VIDEO_PANEL '8' +#define MIPI_CMD_PANEL '9' +#define WRITEBACK_PANEL 'a' +#define LVDS_PANEL 'b' + + class MDPVersion : public Singleton { public: MDPVersion(); ~MDPVersion() { } int getMDPVersion() {return mMDPVersion;} + char getPanelType() {return mPanelType;} bool hasOverlay() {return mHasOverlay;} private: int mMDPVersion; + char mPanelType; bool mHasOverlay; }; }; //namespace qdutils From 32dd0125d9ce93afce76510e9a5c979651324ccc Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Thu, 26 Jul 2012 13:10:55 -0700 Subject: [PATCH 05/12] hwc: Disable HW vsync for some targets 7x27A, 8x25 and 8x55 do not support HW vsync yet. This change checks for their MDP version and disables HW vsync on them. This change should be reverted once hardware vsync is available on these targets. Change-Id: I0cb884f571346b3595169cb4b3c01bbdb7ecaaee --- libhwcomposer/hwc.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index ad0000c..442f8f6 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -204,7 +204,12 @@ 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; - dev->device.common.version = HWC_DEVICE_API_VERSION_0_3; + //XXX: This disables hardware vsync on 7x27A, 8x25 and 8x55 + // Fix when HW vsync is available on those targets + if(dev->mMDP.version < 410) + dev->device.common.version = 0; + else + 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; From 446b9369479ce5f42d41cda3eb225bcc037c4bd2 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Thu, 19 Jul 2012 18:14:30 -0700 Subject: [PATCH 06/12] overlay: Refactor State Transitions. Refactor transitions by templatizing to have default behavior for most cases and full specializations for specific cases. Partial specialization of functions is not allowed, so create templatized intermediate functions for those use cases. For ex: if we have 8 states, we don't need 8x8 transition handlers. Add and define OV_DUAL_DISPLAY state. Add a GenericPipe for subtitles to OV_2D_VIDEO_ON_PANEL_TV state. Add a 2D_VIDEO_ON_TV state and its transitions. Change-Id: I53b017b9a41db5894c263ccb446b7ec8875ef3aa --- libhwcomposer/hwc_video.cpp | 260 +++++--- liboverlay/Android.mk | 3 +- liboverlay/overlay.cpp | 14 + liboverlay/overlayState.h | 961 ++++++++++-------------------- liboverlay/overlayTransitions.cpp | 504 ---------------- liboverlay/overlayUtils.h | 9 +- 6 files changed, 511 insertions(+), 1240 deletions(-) delete mode 100644 liboverlay/overlayTransitions.cpp diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index 5b20ba4..a0ae331 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -39,11 +39,15 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__); return false; } + if(sYuvLayerIndex == -1) { + return false; + } chooseState(ctx); //if the state chosen above is CLOSED, skip this block. if(sState != ovutils::OV_CLOSED) { if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) { markFlags(&list->hwLayers[sYuvLayerIndex]); + sIsModeOn = true; } } @@ -65,8 +69,7 @@ void VideoOverlay::chooseState(hwc_context_t *ctx) { if(sYuvCount == 1) { //Skip on primary, display on ext. if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) { - //TODO - //VIDEO_ON_TV_ONLY + newState = ovutils::OV_2D_VIDEO_ON_TV; } else if(sIsLayerSkip) { //skip on primary, no ext newState = ovutils::OV_CLOSED; } else if(ctx->mExtDisplay->getExternalDisplay()) { @@ -88,110 +91,169 @@ void VideoOverlay::markFlags(hwc_layer_t *layer) { layer->compositionType = HWC_OVERLAY; layer->hints |= HWC_HINT_CLEAR_FB; break; - //TODO - //case ovutils::OV_2D_VIDEO_ON_TV: - //just break, dont update flags. + case ovutils::OV_2D_VIDEO_ON_TV: + break; //dont update flags. default: break; } } -bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *layer) -{ - if (LIKELY(ctx->mOverlay)) { +/* Helpers */ +bool configPrimVid(hwc_context_t *ctx, hwc_layer_t *layer) { + overlay::Overlay& ov = *(ctx->mOverlay); + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); - overlay::Overlay& ov = *(ctx->mOverlay); - // Set overlay state - ov.setState(sState); + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { + ovutils::setMdpFlags(mdpFlags, + ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + } - private_handle_t *hnd = (private_handle_t *)layer->handle; - ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; + if (ctx->numHwLayers == 1) { + isFgFlag = ovutils::IS_FG_SET; + } - //TODO change this based on state. - ovutils::eDest dest = ovutils::OV_PIPE_ALL; + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_0, + isFgFlag, + ovutils::ROT_FLAG_DISABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, ovutils::OV_PIPE0); - ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; - if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { - ovutils::setMdpFlags(mdpFlags, - ovutils::OV_MDP_SECURE_OVERLAY_SESSION); - } + hwc_rect_t sourceCrop = layer->sourceCrop; + // x,y,w,h + ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, + sourceCrop.right - sourceCrop.left, + sourceCrop.bottom - sourceCrop.top); - ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; - if (ctx->numHwLayers == 1) { - isFgFlag = ovutils::IS_FG_SET; - } + ovutils::Dim dpos; + hwc_rect_t displayFrame = layer->displayFrame; + dpos.x = displayFrame.left; + dpos.y = displayFrame.top; + dpos.w = (displayFrame.right - displayFrame.left); + dpos.h = (displayFrame.bottom - displayFrame.top); - ovutils::PipeArgs parg(mdpFlags, - info, - ovutils::ZORDER_0, - isFgFlag, - ovutils::ROT_FLAG_DISABLED); - ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; - ov.setSource(pargs, dest); - - hwc_rect_t sourceCrop = layer->sourceCrop; - // x,y,w,h - ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, - sourceCrop.right - sourceCrop.left, - sourceCrop.bottom - sourceCrop.top); - //Only for External - ov.setCrop(dcrop, ovutils::OV_PIPE1); - - // FIXME: Use source orientation for TV when source is portrait - //Only for External - ov.setTransform(0, dest); - - ovutils::Dim dpos; - hwc_rect_t displayFrame = layer->displayFrame; - dpos.x = displayFrame.left; - dpos.y = displayFrame.top; - dpos.w = (displayFrame.right - displayFrame.left); - dpos.h = (displayFrame.bottom - displayFrame.top); - - //Only for External - ov.setPosition(dpos, ovutils::OV_PIPE1); - - //Calculate the rect for primary based on whether the supplied position - //is within or outside bounds. - const int fbWidth = + //Calculate the rect for primary based on whether the supplied position + //is within or outside bounds. + const int fbWidth = ovutils::FrameBufferInfo::getInstance()->getWidth(); - const int fbHeight = + const int fbHeight = ovutils::FrameBufferInfo::getInstance()->getHeight(); - if( displayFrame.left < 0 || + if( displayFrame.left < 0 || displayFrame.top < 0 || displayFrame.right > fbWidth || displayFrame.bottom > fbHeight) { - calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight); + calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight); - //Update calculated width and height - dcrop.w = sourceCrop.right - sourceCrop.left; - dcrop.h = sourceCrop.bottom - sourceCrop.top; + //Update calculated width and height + dcrop.w = sourceCrop.right - sourceCrop.left; + dcrop.h = sourceCrop.bottom - sourceCrop.top; - dpos.w = displayFrame.right - displayFrame.left; - dpos.h = displayFrame.bottom - displayFrame.top; - } - - //Only for Primary - ov.setCrop(dcrop, ovutils::OV_PIPE0); - - int transform = layer->transform & FINAL_TRANSFORM_MASK; - ovutils::eTransform orient = - static_cast(transform); - ov.setTransform(orient, ovutils::OV_PIPE0); - - ov.setPosition(dpos, ovutils::OV_PIPE0); - - //Both prim and external - if (!ov.commit(dest)) { - ALOGE("%s: commit fails", __FUNCTION__); - return false; - } - - sIsModeOn = true; + dpos.w = displayFrame.right - displayFrame.left; + dpos.h = displayFrame.bottom - displayFrame.top; } - return sIsModeOn; + + //Only for Primary + ov.setCrop(dcrop, ovutils::OV_PIPE0); + + int transform = layer->transform & FINAL_TRANSFORM_MASK; + ovutils::eTransform orient = + static_cast(transform); + ov.setTransform(orient, ovutils::OV_PIPE0); + + ov.setPosition(dpos, ovutils::OV_PIPE0); + + if (!ov.commit(ovutils::OV_PIPE0)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + return true; +} + +bool configExtVid(hwc_context_t *ctx, hwc_layer_t *layer) { + overlay::Overlay& ov = *(ctx->mOverlay); + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) { + ovutils::setMdpFlags(mdpFlags, + ovutils::OV_MDP_SECURE_OVERLAY_SESSION); + } + + ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; + if (ctx->numHwLayers == 1) { + isFgFlag = ovutils::IS_FG_SET; + } + + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_0, + isFgFlag, + ovutils::ROT_FLAG_DISABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, ovutils::OV_PIPE1); + + hwc_rect_t sourceCrop = layer->sourceCrop; + // x,y,w,h + ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, + sourceCrop.right - sourceCrop.left, + sourceCrop.bottom - sourceCrop.top); + //Only for External + ov.setCrop(dcrop, ovutils::OV_PIPE1); + + // FIXME: Use source orientation for TV when source is portrait + //Only for External + ov.setTransform(0, ovutils::OV_PIPE1); + + ovutils::Dim dpos; + hwc_rect_t displayFrame = layer->displayFrame; + dpos.x = displayFrame.left; + dpos.y = displayFrame.top; + dpos.w = (displayFrame.right - displayFrame.left); + dpos.h = (displayFrame.bottom - displayFrame.top); + + //Only for External + ov.setPosition(dpos, ovutils::OV_PIPE1); + + if (!ov.commit(ovutils::OV_PIPE1)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + return true; +} + +bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer) +{ + bool ret = true; + if (LIKELY(ctx->mOverlay)) { + overlay::Overlay& ov = *(ctx->mOverlay); + // Set overlay state + ov.setState(sState); + switch(sState) { + case ovutils::OV_2D_VIDEO_ON_PANEL: + ret &= configPrimVid(ctx, yuvLayer); + break; + case ovutils::OV_2D_VIDEO_ON_PANEL_TV: + ret &= configExtVid(ctx, yuvLayer); + ret &= configPrimVid(ctx, yuvLayer); + break; + case ovutils::OV_2D_VIDEO_ON_TV: + ret &= configExtVid(ctx, yuvLayer); + break; + default: + return false; + } + } else { + //Ov null + return false; + } + return ret; } bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) @@ -211,37 +273,47 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) switch (state) { case ovutils::OV_2D_VIDEO_ON_PANEL_TV: - case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: // Play external if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) { ALOGE("%s: queueBuffer failed for external", __FUNCTION__); ret = false; } - // Play primary if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) { ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); ret = false; } - // Wait for external vsync to be done if (!ov.waitForVsync(ovutils::OV_PIPE1)) { ALOGE("%s: waitForVsync failed for external", __FUNCTION__); ret = false; } break; - default: - // In most cases, displaying only to one (primary or external) - // so use OV_PIPE_ALL since overlay will ignore NullPipes - if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE_ALL)) { - ALOGE("%s: queueBuffer failed", __FUNCTION__); + case ovutils::OV_2D_VIDEO_ON_PANEL: + // Play primary + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) { + ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); ret = false; } break; + case ovutils::OV_2D_VIDEO_ON_TV: + // Play external + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + ret = false; + } + // Wait for external vsync to be done + if (!ov.waitForVsync(ovutils::OV_PIPE1)) { + ALOGE("%s: waitForVsync failed for external", __FUNCTION__); + ret = false; + } + default: + ALOGE("%s Unused state %s", __FUNCTION__, + ovutils::getStateString(state)); + break; } return ret; } - }; //namespace qhwc diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk index 67bb85f..bb83111 100644 --- a/liboverlay/Android.mk +++ b/liboverlay/Android.mk @@ -13,7 +13,6 @@ LOCAL_SRC_FILES := \ overlayCtrl.cpp \ overlayUtils.cpp \ overlayMdp.cpp \ - overlayRotator.cpp \ - overlayTransitions.cpp + overlayRotator.cpp include $(BUILD_SHARED_LIBRARY) diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index a05a307..4dea6ef 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -54,6 +54,7 @@ bool Overlay::commit(utils::eDest dest) switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -63,6 +64,7 @@ bool Overlay::commit(utils::eDest dest) case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->commit(dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -85,6 +87,7 @@ bool Overlay::queueBuffer(int fd, uint32_t offset, switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -94,6 +97,7 @@ bool Overlay::queueBuffer(int fd, uint32_t offset, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->queueBuffer(fd, offset, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -115,6 +119,7 @@ bool Overlay::waitForVsync(utils::eDest dest) switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -124,6 +129,7 @@ bool Overlay::waitForVsync(utils::eDest dest) case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->waitForVsync(dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -146,6 +152,7 @@ bool Overlay::setCrop(const utils::Dim& d, switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -155,6 +162,7 @@ bool Overlay::setCrop(const utils::Dim& d, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->setCrop(d, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -176,6 +184,7 @@ bool Overlay::setPosition(const utils::Dim& d, switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -185,6 +194,7 @@ bool Overlay::setPosition(const utils::Dim& d, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->setPosition(d, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -207,6 +217,7 @@ bool Overlay::setTransform(const int orient, switch (st) { case utils::OV_2D_VIDEO_ON_PANEL: case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL: case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: @@ -216,6 +227,7 @@ bool Overlay::setTransform(const int orient, case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: if(!mOv->setTransform(transform, dest)) { ALOGE("Overlay %s failed", __FUNCTION__); return false; @@ -247,11 +259,13 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES], case utils::OV_BYPASS_1_LAYER: case utils::OV_BYPASS_2_LAYER: case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: break; case utils::OV_3D_VIDEO_ON_3D_PANEL: case utils::OV_3D_VIDEO_ON_3D_TV: //TODO set zorder for channel 1 as 1 in 3D pipe case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: break; case utils::OV_2D_TRUE_UI_MIRROR: diff --git a/liboverlay/overlayState.h b/liboverlay/overlayState.h index ea6860f..518eafa 100644 --- a/liboverlay/overlayState.h +++ b/liboverlay/overlayState.h @@ -46,17 +46,15 @@ namespace overlay { class OverlayState : utils::NoCopy { public: - /**/ + /*ctor*/ explicit OverlayState(); - /**/ + /*dtor*/ ~OverlayState(); /* return current state */ utils::eOverlayState state() const; - /* Overlay Event */ - /* Hard reset to a new state. If the state is the same * as the current one, it would be a no-op */ OverlayImplBase* reset(utils::eOverlayState s); @@ -68,54 +66,31 @@ public: OverlayImplBase* handleEvent(utils::eOverlayState s, OverlayImplBase* ov); - /* Transitions from XXX to XXX */ - OverlayImplBase* handle_closed(utils::eOverlayState s); - OverlayImplBase* handle_2D_2DPanel(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_2D_2DTV(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_3D_2DPanel(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_3D_3DPanel(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_3D_3DTV(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_3D_2DTV(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_UI_Mirror(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_2D_trueUI_Mirror(utils::eOverlayState s, - OverlayImplBase* ov); - OverlayImplBase* handle_bypass(utils::eOverlayState s, - OverlayImplBase* ov); - - /* Transition from any state to 2D video on 2D panel */ - OverlayImplBase* handle_xxx_to_2D_2DPanel(OverlayImplBase* ov); - - /* Transition from any state to 2D video on 2D panel and 2D TV */ - OverlayImplBase* handle_xxx_to_2D_2DTV(OverlayImplBase* ov); - - /* Transition from any state to 3D video on 2D panel */ - OverlayImplBase* handle_xxx_to_3D_2DPanel(OverlayImplBase* ov); - - /* Transition from any state to 3D video on 2D panel and 2D TV */ - OverlayImplBase* handle_xxx_to_3D_2DTV(OverlayImplBase* ov); - - /* Transition from any state to 2D video true UI mirroring (2D video + UI) */ - OverlayImplBase* handle_xxx_to_2D_trueUI_Mirror(OverlayImplBase* ov); - - /* Transitions from any state to 1 layer composition bypass */ - OverlayImplBase* handle_xxx_to_bypass1(OverlayImplBase* ov); - - /* Transitions from any state to 2 layers composition bypass */ - OverlayImplBase* handle_xxx_to_bypass2(OverlayImplBase* ov); - - /* Transitions from any state to 3 layers composition bypass */ - OverlayImplBase* handle_xxx_to_bypass3(OverlayImplBase* ov); - /* Dump */ void dump() const; + private: + + /* Transitions from a state to a state. Default behavior is to move from an + * old state to CLOSED and from CLOSED to a new state. Any impl wishing to + * copy pipes should specialize this call */ + template + OverlayImplBase* handle_from_to(OverlayImplBase* ov); + + /* Just a convenient intermediate function to bring down the number of + * combinations arising from multiple states */ + template + OverlayImplBase* handle_from(utils::eOverlayState toState, + OverlayImplBase* ov); + + /* Substitues for partially specialized templated handle functions since the + * standard doesn't allow partial specialization of functions */ + template + OverlayImplBase* handle_xxx_to_CLOSED(OverlayImplBase* ov); + + template + OverlayImplBase* handle_CLOSED_to_xxx(OverlayImplBase* ov); + /* States here */ utils::eOverlayState mState; }; @@ -133,7 +108,7 @@ template struct StateTraits {}; template <> struct StateTraits { - typedef overlay::GenericPipe pipe0; + typedef overlay::GenericPipe pipe0; //prim video typedef overlay::NullPipe pipe1; // place holder typedef overlay::NullPipe pipe2; // place holder @@ -141,20 +116,33 @@ template <> struct StateTraits typedef NullRotator rot1; typedef NullRotator rot2; - typedef overlay::OverlayImpl ovimpl; + typedef overlay::OverlayImpl ovimpl; }; template <> struct StateTraits { - typedef overlay::GenericPipe pipe0; - typedef overlay::VideoExtPipe pipe1; - typedef overlay::NullPipe pipe2; // place holder + typedef overlay::GenericPipe pipe0; //prim video + typedef overlay::VideoExtPipe pipe1; //ext video + typedef overlay::GenericPipe pipe2; //ext subtitle typedef Rotator rot0; typedef Rotator rot1; typedef NullRotator rot2; - typedef overlay::OverlayImpl ovimpl; + typedef overlay::OverlayImpl ovimpl; +}; + +template <> struct StateTraits +{ + typedef overlay::NullPipe pipe0; //nothing on primary with mdp + typedef overlay::VideoExtPipe pipe1; //ext video + typedef overlay::GenericPipe pipe2; //ext subtitle + + typedef NullRotator rot0; + typedef Rotator rot1; + typedef NullRotator rot2; + + typedef overlay::OverlayImpl ovimpl; }; template <> struct StateTraits @@ -219,7 +207,7 @@ template <> struct StateTraits typedef NullRotator rot1; typedef NullRotator rot2; - typedef overlay::OverlayImpl ovimpl; + typedef overlay::OverlayImpl ovimpl; }; template <> struct StateTraits @@ -245,7 +233,7 @@ template <> struct StateTraits typedef NullRotator rot1; typedef NullRotator rot2; - typedef overlay::OverlayImpl ovimpl; + typedef overlay::OverlayImpl ovimpl; }; template <> struct StateTraits @@ -258,7 +246,7 @@ template <> struct StateTraits typedef NullRotator rot1; typedef NullRotator rot2; - typedef overlay::OverlayImpl ovimpl; + typedef overlay::OverlayImpl ovimpl; }; template <> struct StateTraits @@ -274,47 +262,197 @@ template <> struct StateTraits typedef overlay::OverlayImpl ovimpl; }; +template <> struct StateTraits +{ + typedef overlay::GenericPipe pipe0; + typedef overlay::GenericPipe pipe1; + typedef overlay::NullPipe pipe2; + + typedef NullRotator rot0; + typedef NullRotator rot1; + typedef NullRotator rot2; + + typedef overlay::OverlayImpl ovimpl; +}; + //------------------------Inlines -------------------------------- -inline OverlayState::OverlayState() : mState(utils::OV_CLOSED) -{} +inline OverlayState::OverlayState() : mState(utils::OV_CLOSED){} inline OverlayState::~OverlayState() {} - -inline utils::eOverlayState OverlayState::state() const -{ - return mState; -} - -inline OverlayImplBase* OverlayState::reset(utils::eOverlayState s) -{ +inline utils::eOverlayState OverlayState::state() const { return mState; } +inline OverlayImplBase* OverlayState::reset(utils::eOverlayState s) { return handleEvent(s, 0); } - -inline void OverlayState::dump() const -{ +inline void OverlayState::dump() const { ALOGE("== Dump state %d start/end ==", mState); } -template -inline OverlayImplBase* handle_closed_to_xxx() +inline OverlayImplBase* OverlayState::handleEvent(utils::eOverlayState toState, + OverlayImplBase* ov) { - OverlayImplBase* ov = new typename StateTraits::ovimpl; - RotatorBase* rot0 = new typename StateTraits::rot0; - RotatorBase* rot1 = new typename StateTraits::rot1; - RotatorBase* rot2 = new typename StateTraits::rot2; + OverlayImplBase* newov = ov; // at least, we return the same + if (mState != toState) { + ALOGD_IF(DEBUG_OVERLAY, "%s: state changed %s-->%s", + __FUNCTION__, getStateString(mState), getStateString(toState)); + } else { + ALOGD_IF(DEBUG_OVERLAY, "%s: no state change, state=%s", + __FUNCTION__, getStateString(toState)); + return newov; + } + + switch(mState) + { + case utils::OV_CLOSED: + newov = handle_from(toState, ov); + break; + case utils::OV_2D_VIDEO_ON_PANEL: + newov = handle_from(toState, ov); + break; + case utils::OV_2D_VIDEO_ON_PANEL_TV: + newov = handle_from(toState, ov); + break; + case utils::OV_2D_VIDEO_ON_TV: + newov = handle_from(toState, ov); + break; + case utils::OV_3D_VIDEO_ON_2D_PANEL: + newov = handle_from(toState, ov); + break; + case utils::OV_3D_VIDEO_ON_3D_PANEL: + newov = handle_from(toState, ov); + break; + case utils::OV_3D_VIDEO_ON_3D_TV: + newov = handle_from(toState, ov); + break; + case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: + newov = handle_from(toState, + ov); + break; + case utils::OV_UI_MIRROR: + newov = handle_from(toState, ov); + break; + case utils::OV_2D_TRUE_UI_MIRROR: + newov = handle_from(toState, ov); + break; + case utils::OV_BYPASS_1_LAYER: + newov = handle_from(toState, ov); + break; + case utils::OV_BYPASS_2_LAYER: + newov = handle_from(toState, ov); + break; + case utils::OV_BYPASS_3_LAYER: + newov = handle_from(toState, ov); + break; + case utils::OV_DUAL_DISP: + newov = handle_from(toState, ov); + break; + default: + OVASSERT(1 == 0, "%s: unknown state = %d", __FUNCTION__, mState); + + } + return newov; +} + +template +inline OverlayImplBase* OverlayState::handle_from(utils::eOverlayState toState, + OverlayImplBase* ov) { + + switch(toState) + { + case utils::OV_CLOSED: + ov = handle_xxx_to_CLOSED(ov); + break; + case utils::OV_2D_VIDEO_ON_PANEL: + ov = handle_from_to(ov); + break; + case utils::OV_2D_VIDEO_ON_PANEL_TV: + ov = handle_from_to(ov); + break; + case utils::OV_2D_VIDEO_ON_TV: + ov = handle_from_to(ov); + break; + case utils::OV_3D_VIDEO_ON_2D_PANEL: + ov = handle_from_to(ov); + break; + case utils::OV_3D_VIDEO_ON_3D_PANEL: + ov = handle_from_to(ov); + break; + case utils::OV_3D_VIDEO_ON_3D_TV: + ov = handle_from_to(ov); + break; + case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: + ov = handle_from_to(ov); + break; + case utils::OV_UI_MIRROR: + ov = handle_from_to(ov); + break; + case utils::OV_2D_TRUE_UI_MIRROR: + ov = handle_from_to(ov); + break; + case utils::OV_BYPASS_1_LAYER: + ov = handle_from_to(ov); + break; + case utils::OV_BYPASS_2_LAYER: + ov = handle_from_to(ov); + break; + case utils::OV_BYPASS_3_LAYER: + ov = handle_from_to(ov); + break; + case utils::OV_DUAL_DISP: + ov = handle_from_to(ov); + break; + default: + OVASSERT(1 == 0, "%s: unknown state = %d", __FUNCTION__, toState); + } + mState = toState; + return ov; +} + + +/* Transition default from any to any. Does in two steps. + * Moves from OLD to CLOSED and then from CLOSED to NEW + */ +template +inline OverlayImplBase* OverlayState::handle_from_to(OverlayImplBase* ov) { + handle_xxx_to_CLOSED(ov); + return handle_CLOSED_to_xxx(ov); +} + +//---------------Specializations------------- + + +/* Transition from CLOSED to ANY */ +template +inline OverlayImplBase* OverlayState::handle_CLOSED_to_xxx( + OverlayImplBase* /*ignored*/) { + //If going from CLOSED to CLOSED, nothing to do. + if(TO_STATE == utils::OV_CLOSED) return NULL; + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(utils::OV_CLOSED), + utils::getStateString(TO_STATE)); + OverlayImplBase* ov = new typename StateTraits::ovimpl; + RotatorBase* rot0 = new typename StateTraits::rot0; + RotatorBase* rot1 = new typename StateTraits::rot1; + RotatorBase* rot2 = new typename StateTraits::rot2; if(!ov->init(rot0, rot1, rot2)) { - ALOGE("Overlay failed to init in state %d", STATE); + ALOGE("Overlay failed to init in state %d", TO_STATE); return 0; } return ov; } -inline OverlayImplBase* handle_xxx_to_closed(OverlayImplBase* ov) +/* Transition from ANY to CLOSED */ +template +inline OverlayImplBase* OverlayState::handle_xxx_to_CLOSED(OverlayImplBase* ov) { + //If going from CLOSED to CLOSED, nothing to do. + if(FROM_STATE == utils::OV_CLOSED) return NULL; + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(FROM_STATE), + utils::getStateString(utils::OV_CLOSED)); OVASSERT(ov, "%s: ov is null", __FUNCTION__); - if(!ov->close()) { ALOGE("%s: Failed to ov close", __FUNCTION__); } @@ -323,580 +461,125 @@ inline OverlayImplBase* handle_xxx_to_closed(OverlayImplBase* ov) return 0; } -/* Hard transitions from any state to any state will close and then init */ -template -inline OverlayImplBase* handle_xxx_to_xxx(OverlayImplBase* ov) -{ +/* Transition from 2D_VIDEO_ON_PANEL to 2D_VIDEO_ON_PANEL_TV */ +template<> +inline OverlayImplBase* OverlayState::handle_from_to< + utils::OV_2D_VIDEO_ON_PANEL, + utils::OV_2D_VIDEO_ON_PANEL_TV>( + OverlayImplBase* ov) { OVASSERT(ov, "%s: ov is null", __FUNCTION__); + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL), + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL_TV)); + // Create new ovimpl based on new state + typedef StateTraits NewState; + OverlayImplBase* newov = new NewState::ovimpl; - handle_xxx_to_closed(ov); - return handle_closed_to_xxx(); -} - -inline OverlayImplBase* OverlayState::handleEvent(utils::eOverlayState newState, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; // at least, we return the same - if (mState != newState) { - ALOGE_IF(DEBUG_OVERLAY, "%s: state changed %s-->%s", - __FUNCTION__, getStateString(mState), getStateString(newState)); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: no state change, state=%s", - __FUNCTION__, getStateString(newState)); - return newov; - } - - switch(mState) - { - case utils::OV_CLOSED: - newov = handle_closed(newState); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_2D_2DPanel(newState, ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_2D_2DTV(newState, ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_3D_2DPanel(newState, ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_3D_3DPanel(newState, ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_3D_3DTV(newState, ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_3D_2DTV(newState, ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_UI_Mirror(newState, ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_2D_trueUI_Mirror(newState, ov); - break; - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - newov = handle_bypass(newState, ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, mState); - } - - // FIXME, how to communicate bad transition? - // Should we have bool returned from transition func? - // This is also a very good interview question. - + //copy pipe0/rot0 (primary video) + newov->copyOvPipe(ov, utils::OV_PIPE0); + //close old pipe1, create new pipe1 + ov->closePipe(utils::OV_PIPE1); + RotatorBase* rot1 = new NewState::rot1; + newov->initPipe(rot1, utils::OV_PIPE1); + //close old pipe2, create new pipe2 + ov->closePipe(utils::OV_PIPE2); + RotatorBase* rot2 = new NewState::rot2; + newov->initPipe(rot2, utils::OV_PIPE2); + // All pipes are copied or deleted so no more need for previous ovimpl + delete ov; + ov = 0; return newov; } -// Transitions from closed to XXX -inline OverlayImplBase* OverlayState::handle_closed(utils::eOverlayState s) -{ - OverlayImplBase* ov = 0; - switch(s) - { - case utils::OV_CLOSED: - // no state change - break; - case utils::OV_2D_VIDEO_ON_PANEL: - ov = handle_closed_to_xxx(); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - ov = handle_closed_to_xxx(); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - ov = handle_closed_to_xxx(); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - ov = handle_closed_to_xxx(); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - ov = handle_closed_to_xxx(); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - ov = handle_closed_to_xxx(); - break; - case utils::OV_UI_MIRROR: - ov = handle_closed_to_xxx(); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - ov = handle_closed_to_xxx(); - break; - case utils::OV_BYPASS_1_LAYER: - ov = handle_closed_to_xxx(); - break; - case utils::OV_BYPASS_2_LAYER: - ov = handle_closed_to_xxx(); - break; - case utils::OV_BYPASS_3_LAYER: - ov = handle_closed_to_xxx(); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return ov; -} +/* Transition from 2D_VIDEO_ON_PANEL_TV to 2D_VIDEO_ON_PANEL */ +template<> +inline OverlayImplBase* OverlayState::handle_from_to< + utils::OV_2D_VIDEO_ON_PANEL_TV, + utils::OV_2D_VIDEO_ON_PANEL>( + OverlayImplBase* ov) { + OVASSERT(ov, "%s: ov is null", __FUNCTION__); + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL_TV), + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL)); -// Transitions from 2D video on 2D panel to XXX -inline OverlayImplBase* OverlayState::handle_2D_2DPanel( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - // no state change - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_2D_2DTV(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_2D_trueUI_Mirror(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; + // Create new ovimpl based on new state + typedef StateTraits NewState; + OverlayImplBase* newov = new NewState::ovimpl; + + //copy pipe0/rot0 (primary video) + newov->copyOvPipe(ov, utils::OV_PIPE0); + //close old pipe1, create new pipe1 + ov->closePipe(utils::OV_PIPE1); + RotatorBase* rot1 = new NewState::rot1; + newov->initPipe(rot1, utils::OV_PIPE1); + //close old pipe2, create new pipe2 + ov->closePipe(utils::OV_PIPE2); + RotatorBase* rot2 = new NewState::rot2; + newov->initPipe(rot2, utils::OV_PIPE2); + // All pipes are copied or deleted so no more need for previous ovimpl + delete ov; + ov = 0; return newov; } -// Transitions from 2D video on 2D panel and 2D TV to XXX -inline OverlayImplBase* OverlayState::handle_2D_2DTV( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_2D_2DPanel(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - // no state change - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_2D_trueUI_Mirror(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; +/* Transition from 2D_VIDEO_ON_PANEL_TV to 2D_VIDEO_ON_TV */ +template<> +inline OverlayImplBase* OverlayState::handle_from_to< + utils::OV_2D_VIDEO_ON_PANEL_TV, + utils::OV_2D_VIDEO_ON_TV>( + OverlayImplBase* ov) { + OVASSERT(ov, "%s: ov is null", __FUNCTION__); + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL_TV), + utils::getStateString(utils::OV_2D_VIDEO_ON_TV)); + + // Create new ovimpl based on new state + typedef StateTraits NewState; + OverlayImplBase* newov = new NewState::ovimpl; + + //close old pipe0, create new pipe0 + ov->closePipe(utils::OV_PIPE0); + RotatorBase* rot0 = new NewState::rot0; + newov->initPipe(rot0, utils::OV_PIPE0); + //copy pipe1/rot1 (ext video) + newov->copyOvPipe(ov, utils::OV_PIPE1); + //copy pipe2/rot2 (ext cc) + newov->copyOvPipe(ov, utils::OV_PIPE2); + // All pipes are copied or deleted so no more need for previous ovimpl + delete ov; + ov = 0; return newov; } -// Transitions from 3D video on 2D panel to XXX -inline OverlayImplBase* OverlayState::handle_3D_2DPanel( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - // no state change - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_3D_2DTV(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; +/* Transition from 2D_VIDEO_ON_TV to 2D_VIDEO_ON_PANEL_TV */ +template<> +inline OverlayImplBase* OverlayState::handle_from_to< + utils::OV_2D_VIDEO_ON_TV, + utils::OV_2D_VIDEO_ON_PANEL_TV>( + OverlayImplBase* ov) { + OVASSERT(ov, "%s: ov is null", __FUNCTION__); + ALOGD("FROM_STATE = %s TO_STATE = %s", + utils::getStateString(utils::OV_2D_VIDEO_ON_TV), + utils::getStateString(utils::OV_2D_VIDEO_ON_PANEL_TV)); + + // Create new ovimpl based on new state + typedef StateTraits NewState; + OverlayImplBase* newov = new NewState::ovimpl; + + //close old pipe0, create new pipe0 + ov->closePipe(utils::OV_PIPE0); + RotatorBase* rot0 = new NewState::rot0; + newov->initPipe(rot0, utils::OV_PIPE0); + //copy pipe1/rot1 (ext video) + newov->copyOvPipe(ov, utils::OV_PIPE1); + //copy pipe2/rot2 (ext cc) + newov->copyOvPipe(ov, utils::OV_PIPE2); + // All pipes are copied or deleted so no more need for previous ovimpl + delete ov; + ov = 0; return newov; } -// Transitions from 3D video on 3D panel to XXX -inline OverlayImplBase* OverlayState::handle_3D_3DPanel( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - // no state change - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - -// Transitions from 3D video on 3D TV to XXX -inline OverlayImplBase* OverlayState::handle_3D_3DTV( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - // no state change - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - -// Transitions from 3D video on 2D panel and 2D TV to XXX -inline OverlayImplBase* OverlayState::handle_3D_2DTV( - utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_3D_2DPanel(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - // no state change - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - -// Transitions from UI mirroring to XXX -inline OverlayImplBase* OverlayState::handle_UI_Mirror(utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - // no state change - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - -// Transitions from 2D video true UI mirroring (2D video + UI) to XXX -inline OverlayImplBase* OverlayState::handle_2D_trueUI_Mirror(utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_2D_2DPanel(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_2D_2DTV(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - // no state change - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_xxx(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - -// Transitions from composition bypass to XXX -inline OverlayImplBase* OverlayState::handle_bypass(utils::eOverlayState s, - OverlayImplBase* ov) -{ - OverlayImplBase* newov = ov; - switch(s) - { - case utils::OV_CLOSED: - newov = handle_xxx_to_closed(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_VIDEO_ON_PANEL_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_3D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_2D_TRUE_UI_MIRROR: - newov = handle_xxx_to_xxx(ov); - break; - case utils::OV_BYPASS_1_LAYER: - newov = handle_xxx_to_bypass1(ov); - break; - case utils::OV_BYPASS_2_LAYER: - newov = handle_xxx_to_bypass2(ov); - break; - case utils::OV_BYPASS_3_LAYER: - newov = handle_xxx_to_bypass3(ov); - break; - default: - ALOGE("%s: unknown state=%d", __FUNCTION__, s); - } - mState = s; - return newov; -} - - } // overlay #endif // OVERLAY_STATE_H diff --git a/liboverlay/overlayTransitions.cpp b/liboverlay/overlayTransitions.cpp deleted file mode 100644 index 8096ad5..0000000 --- a/liboverlay/overlayTransitions.cpp +++ /dev/null @@ -1,504 +0,0 @@ -/* -* Copyright (c) 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. -*/ - -#include "overlayState.h" - -namespace overlay { - -/* - * Transition from any state to 2D video on 2D panel - */ -OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel( - OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl(); - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (GenericPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); - ov->closePipe(utils::OV_PIPE0); - RotatorBase* rot0 = new NewState::rot0; - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); - ov->closePipe(utils::OV_PIPE1); - RotatorBase* rot1 = new NewState::rot1; - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - ov->closePipe(utils::OV_PIPE2); - RotatorBase* rot2 = new NewState::rot2; - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transition from any state to 2D video on 2D panel and 2D TV - */ -OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV( - OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (GenericPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (VideoExtPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transition from any state to 3D video on 2D panel - */ -OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel( - OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //================================================================= - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl. - // (which also makes previous pipe ref 0, so nobody can use) - // - Otherwise init pipe for new ovimpl and delete from previous - //================================================================= - - // pipe0/rot0 (M3DPrimaryPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transition from any state to 3D video on 2D panel and 2D TV - */ -OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV( - OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (M3DPrimaryPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (M3DExtPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_M3D_EXTERNAL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (M3DExtPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (M3DExtPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transition from any state to 2D true UI mirroring (2D video + UI) - */ -OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror( - OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (GenericPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_GENERIC) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (VideoExtPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (UIMirrorPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_UI_MIRROR) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (UIMirrorPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (UIMirrorPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transitions from any state to 1 layer composition bypass - */ -OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transitions from any state to 2 layers composition bypass - */ -OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (NullPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_NULL) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -/* - * Transitions from any state to 3 layers composition bypass - */ -OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov) -{ - OVASSERT(ov, "%s: ov is null", __FUNCTION__); - ALOGE("%s", __FUNCTION__); - - // Create new ovimpl based on new state - typedef StateTraits NewState; - OverlayImplBase* newov = new NewState::ovimpl; - - //=========================================================== - // For each pipe: - // - If pipe matches, copy from previous into new ovimpl - // - Otherwise init for new and delete from previous ovimpl - //=========================================================== - - // pipe0/rot0 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE0); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__); - RotatorBase* rot0 = new NewState::rot0; - ov->closePipe(utils::OV_PIPE0); - newov->initPipe(rot0, utils::OV_PIPE0); - } - - // pipe1/rot1 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE1); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__); - RotatorBase* rot1 = new NewState::rot1; - ov->closePipe(utils::OV_PIPE1); - newov->initPipe(rot1, utils::OV_PIPE1); - } - - // pipe2/rot2 (BypassPipe) - if (ov->getOvPipeType(utils::OV_PIPE2) == utils::OV_PIPE_TYPE_BYPASS) { - ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (BypassPipe)", __FUNCTION__); - newov->copyOvPipe(ov, utils::OV_PIPE2); - } else { - ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (BypassPipe)", __FUNCTION__); - RotatorBase* rot2 = new NewState::rot2; - ov->closePipe(utils::OV_PIPE2); - newov->initPipe(rot2, utils::OV_PIPE2); - } - - // All pipes are copied or deleted so no more need for previous ovimpl - delete ov; - ov = 0; - - return newov; -} - -} // overlay diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h index f82fb88..f070bd1 100644 --- a/liboverlay/overlayUtils.h +++ b/liboverlay/overlayUtils.h @@ -370,6 +370,7 @@ enum eOverlayState{ /* 2D Video */ OV_2D_VIDEO_ON_PANEL, OV_2D_VIDEO_ON_PANEL_TV, + OV_2D_VIDEO_ON_TV, /* 3D Video on one display (panel or TV) */ OV_3D_VIDEO_ON_2D_PANEL, @@ -382,12 +383,14 @@ enum eOverlayState{ /* UI Mirroring */ OV_UI_MIRROR, OV_2D_TRUE_UI_MIRROR, - OV_M3D_TRUE_UI_MIRROR, // Not yet supported /* Composition Bypass */ OV_BYPASS_1_LAYER, OV_BYPASS_2_LAYER, OV_BYPASS_3_LAYER, + + /* External only for dual-disp */ + OV_DUAL_DISP, }; inline void setMdpFlags(eMdpFlags& f, eMdpFlags v) { @@ -606,6 +609,8 @@ inline const char* getStateString(eOverlayState state){ return "OV_2D_VIDEO_ON_PANEL"; case OV_2D_VIDEO_ON_PANEL_TV: return "OV_2D_VIDEO_ON_PANEL_TV"; + case OV_2D_VIDEO_ON_TV: + return "OV_2D_VIDEO_ON_TV"; case OV_3D_VIDEO_ON_2D_PANEL: return "OV_3D_VIDEO_ON_2D_PANEL"; case OV_3D_VIDEO_ON_3D_PANEL: @@ -624,6 +629,8 @@ inline const char* getStateString(eOverlayState state){ return "OV_BYPASS_2_LAYER"; case OV_BYPASS_3_LAYER: return "OV_BYPASS_3_LAYER"; + case OV_DUAL_DISP: + return "OV_DUAL_DISP"; default: return "UNKNOWN_STATE"; } From bf3c454efea3b3c6ad6a1aabbaab339b2adf66fa Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Sat, 21 Jul 2012 19:06:55 -0700 Subject: [PATCH 07/12] hwc: Add support for external-only layers Add support for different types of external-only layers EXTERNAL_ONLY: General purpose EXTERNAL_BLOCK: Blocks the display of other ext-only layers EXTERNAL_CC: Used for closed captions with videos. Change-Id: I7cb531a55a2f0015e3a51673faf08941bcea1923 --- libgralloc/alloc_controller.cpp | 2 +- libgralloc/gpu.cpp | 6 +- libgralloc/gralloc_priv.h | 10 +- libhwcomposer/Android.mk | 14 ++- libhwcomposer/hwc.cpp | 8 ++ libhwcomposer/hwc_extonly.cpp | 161 ++++++++++++++++++++++++++++++++ libhwcomposer/hwc_extonly.h | 82 ++++++++++++++++ libhwcomposer/hwc_utils.cpp | 21 ++++- libhwcomposer/hwc_utils.h | 15 +++ libhwcomposer/hwc_video.cpp | 91 +++++++++++++++--- libhwcomposer/hwc_video.h | 28 ++++-- liboverlay/overlayState.h | 2 +- 12 files changed, 409 insertions(+), 31 deletions(-) create mode 100644 libhwcomposer/hwc_extonly.cpp create mode 100644 libhwcomposer/hwc_extonly.h diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp index 5d0cf2b..d21c3c3 100644 --- a/libgralloc/alloc_controller.cpp +++ b/libgralloc/alloc_controller.cpp @@ -71,7 +71,7 @@ static bool canFallback(int usage, bool triedSystem) if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED | GRALLOC_USAGE_PRIVATE_CP_BUFFER)) return false; - if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_EXTERNAL_ONLY)) + if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY)) return false; //Return true by default return true; diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp index 4f00e4a..1ffcdfb 100644 --- a/libgralloc/gpu.cpp +++ b/libgralloc/gpu.cpp @@ -146,11 +146,13 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED; } - if (usage & GRALLOC_USAGE_EXTERNAL_ONLY) { + if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) { flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY; //The EXTERNAL_BLOCK flag is always an add-on - if (usage & GRALLOC_USAGE_EXTERNAL_BLOCK) { + if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) { flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK; + }if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) { + flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC; } } diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index 1333edb..ae28a57 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -74,18 +74,20 @@ enum { GRALLOC_USAGE_PRIVATE_DO_NOT_MAP = 0X00800000, /* Buffer content should be displayed on an external display only */ - GRALLOC_USAGE_EXTERNAL_ONLY = 0x00010000, + GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x00010000, /* Only this buffer content should be displayed on external, even if * other EXTERNAL_ONLY buffers are available. Used during suspend. */ - GRALLOC_USAGE_EXTERNAL_BLOCK = 0x00020000, + GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00020000, + + /* Close Caption displayed on an external display only */ + GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x00040000, /* Use this flag to request content protected buffers. Please note * that this flag is different from the GRALLOC_USAGE_PROTECTED flag * which can be used for buffers that are not secured for DRM * but still need to be protected from screen captures - * 0x00040000 is reserved and these values are subject to change. */ GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00080000, }; @@ -165,6 +167,8 @@ struct private_handle_t : public native_handle { PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000, // Display only this buffer on external PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000, + // Display this buffer on external as close caption + PRIV_FLAGS_EXTERNAL_CC = 0x00008000, }; // file-descriptors diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk index 05d033e..51f1e00 100644 --- a/libhwcomposer/Android.mk +++ b/libhwcomposer/Android.mk @@ -9,8 +9,14 @@ LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \ libqdutils libhardware_legacy libdl libmemalloc 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_external.cpp \ - hwc_uevents.cpp hwc_copybit.cpp \ - hwc_mdpcomp.cpp +LOCAL_SRC_FILES := hwc.cpp \ + hwc_video.cpp \ + hwc_utils.cpp \ + hwc_uimirror.cpp \ + hwc_external.cpp \ + hwc_uevents.cpp \ + hwc_copybit.cpp \ + hwc_mdpcomp.cpp \ + hwc_extonly.cpp + include $(BUILD_SHARED_LIBRARY) diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 442f8f6..6ee461c 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -32,6 +32,7 @@ #include "hwc_copybit.h" #include "hwc_external.h" #include "hwc_mdpcomp.h" +#include "hwc_extonly.h" using namespace qhwc; @@ -80,10 +81,16 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) ctx->qbuf->unlockAllPrevious(); if (LIKELY(list)) { + //reset for this draw round + VideoOverlay::reset(); + ExtOnly::reset(); + getLayerStats(ctx, list); if(VideoOverlay::prepare(ctx, list)) { ctx->overlayInUse = true; //Nothing here + } else if(ExtOnly::prepare(ctx, list)) { + ctx->overlayInUse = true; } else if(UIMirrorOverlay::prepare(ctx, list)) { ctx->overlayInUse = true; } else if(MDPComp::configure(dev, list)) { @@ -155,6 +162,7 @@ static int hwc_set(hwc_composer_device_t *dev, hwc_context_t* ctx = (hwc_context_t*)(dev); if (LIKELY(list)) { VideoOverlay::draw(ctx, list); + ExtOnly::draw(ctx, list); CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur); MDPComp::draw(ctx, list); EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur); diff --git a/libhwcomposer/hwc_extonly.cpp b/libhwcomposer/hwc_extonly.cpp new file mode 100644 index 0000000..77a96b6 --- /dev/null +++ b/libhwcomposer/hwc_extonly.cpp @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * 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. + */ + +#include "hwc_extonly.h" +#include "hwc_external.h" +#include "hwc_qbuf.h" + +namespace qhwc { + +#define EXTONLY_DEBUG 0 + +//Static Members +ovutils::eOverlayState ExtOnly::sState = ovutils::OV_CLOSED; +int ExtOnly::sExtCount = 0; +int ExtOnly::sExtIndex = -1; +bool ExtOnly::sIsExtBlock = false; +bool ExtOnly::sIsModeOn = false; + +//Cache stats, figure out the state, config overlay +bool ExtOnly::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { + sIsModeOn = false; + if(!ctx->mMDP.hasOverlay) { + ALOGD_IF(EXTONLY_DEBUG,"%s, this hw doesnt support overlay", + __FUNCTION__); + return false; + } + if(sExtIndex == -1) { + return false; + } + chooseState(ctx); + //if the state chosen above is CLOSED, skip this block. + if(sState != ovutils::OV_CLOSED) { + hwc_layer_t *extLayer = &list->hwLayers[sExtIndex]; + if(configure(ctx, extLayer)) { + markFlags(extLayer); + sIsModeOn = true; + } + } + + ALOGD_IF(EXTONLY_DEBUG, "%s: stats: extCount = %d, extIndex = %d," + "IsExtBlock = %d, IsModeOn = %d", + __func__, sExtCount, sExtIndex, + sIsExtBlock, sIsModeOn); + + return sIsModeOn; +} + +void ExtOnly::chooseState(hwc_context_t *ctx) { + ALOGD_IF(EXTONLY_DEBUG, "%s: old state = %s", __FUNCTION__, + ovutils::getStateString(sState)); + + ovutils::eOverlayState newState = ovutils::OV_CLOSED; + + if(sExtCount > 0 && + ctx->mExtDisplay->getExternalDisplay()) { + newState = ovutils::OV_DUAL_DISP; + } + + sState = newState; + ALOGD_IF(EXTONLY_DEBUG, "%s: new chosen state = %s", __FUNCTION__, + ovutils::getStateString(sState)); +} + +void ExtOnly::markFlags(hwc_layer_t *layer) { + switch(sState) { + case ovutils::OV_DUAL_DISP: + layer->compositionType = HWC_OVERLAY; + break; + default: + break; + } +} + +bool ExtOnly::configure(hwc_context_t *ctx, hwc_layer_t *layer) { + + overlay::Overlay& ov = *(ctx->mOverlay); + ov.setState(sState); + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_0, + isFgFlag, + ovutils::ROT_FLAG_DISABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, ovutils::OV_PIPE0); + + hwc_rect_t sourceCrop = layer->sourceCrop; + // x,y,w,h + ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, + sourceCrop.right - sourceCrop.left, + sourceCrop.bottom - sourceCrop.top); + ov.setCrop(dcrop, ovutils::OV_PIPE0); + + ov.setTransform(0, ovutils::OV_PIPE0); + + //Setting position same as crop + //FIXME stretch to full screen + ov.setPosition(dcrop, ovutils::OV_PIPE0); + + if (!ov.commit(ovutils::OV_PIPE0)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + return true; +} + +bool ExtOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list) +{ + if(!sIsModeOn || sExtIndex == -1) { + return true; + } + + private_handle_t *hnd = (private_handle_t *) + list->hwLayers[sExtIndex].handle; + + // Lock this buffer for read. + ctx->qbuf->lockAndAdd(hnd); + bool ret = true; + overlay::Overlay& ov = *(ctx->mOverlay); + ovutils::eOverlayState state = ov.getState(); + + switch (state) { + case ovutils::OV_DUAL_DISP: + // Play external + if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) { + ALOGE("%s: queueBuffer failed for external", __FUNCTION__); + ret = false; + } + // Wait for external vsync to be done + if (!ov.waitForVsync(ovutils::OV_PIPE0)) { + ALOGE("%s: waitForVsync failed for external", __FUNCTION__); + ret = false; + } + break; + default: + ALOGE("%s Unused state %s", __FUNCTION__, + ovutils::getStateString(state)); + break; + } + + return ret; +} + +}; //namespace qhwc diff --git a/libhwcomposer/hwc_extonly.h b/libhwcomposer/hwc_extonly.h new file mode 100644 index 0000000..26d5fb9 --- /dev/null +++ b/libhwcomposer/hwc_extonly.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012, Code Aurora Forum. All rights reserved. + * + * 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_EXTONLY_H +#define HWC_EXTONLY_H + +#include +#include "hwc_utils.h" + +#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true )) +#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false )) + +namespace qhwc { +//Feature for using overlay to display external-only layers on HDTV +class ExtOnly { +public: + //Sets up members and prepares overlay if conditions are met + static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list); + //Draws layer if this feature is on + static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list); + //Receives data from hwc + static void setStats(int extCount, int extIndex, bool isExtBlock); + //resets values + static void reset(); +private: + //Choose an appropriate overlay state based on conditions + static void chooseState(hwc_context_t *ctx); + //Configures overlay + static bool configure(hwc_context_t *ctx, hwc_layer_t *layer); + //Marks layer flags if this feature is used + static void markFlags(hwc_layer_t *layer); + //returns ext-only count + static int getExtCount(); + + //The chosen overlay state. + static ovutils::eOverlayState sState; + //Number of ext-only layers in this drawing round. Used for stats/debugging. + //This does not reflect the closed caption layer count even though its + //ext-only. + static int sExtCount; + //Index of ext-only layer. If there are 2 such layers with 1 marked as BLOCK + //then this will hold the index of BLOCK layer. + static int sExtIndex; + //Flags if ext-only layer is BLOCK, which means only this layer (sExtIndex) + //is displayed even if other ext-only layers are present to block their + //content. This is used for stats / debugging only. + static bool sIsExtBlock; + //Flags if this feature is on. + static bool sIsModeOn; +}; + +inline void ExtOnly::setStats(int extCount, int extIndex, bool isExtBlock) { + sExtCount = extCount; + sExtIndex = extIndex; + sIsExtBlock = isExtBlock; +} + +inline int ExtOnly::getExtCount() { return sExtCount; } +inline void ExtOnly::reset() { + sExtCount = 0; + sExtIndex = -1; + sIsExtBlock = false; + sIsModeOn = false; + sState = ovutils::OV_CLOSED; +} + +}; //namespace qhwc + +#endif //HWC_EXTONLY_H diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index dd890a9..8bc8bfc 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -23,6 +23,7 @@ #include "hwc_copybit.h" #include "hwc_external.h" #include "hwc_mdpcomp.h" +#include "hwc_extonly.h" namespace qhwc { @@ -107,18 +108,32 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list) int yuvLayerIndex = -1; bool isYuvLayerSkip = false; int skipCount = 0; + int ccLayerIndex = -1; //closed caption + int extLayerIndex = -1; //ext-only or block except closed caption + int extCount = 0; //ext-only except closed caption + bool isExtBlockPresent = false; //is BLOCK layer present for (size_t i = 0; i < list->numHwLayers; i++) { private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; - if (isYuvBuffer(hnd)) { + if (UNLIKELY(isYuvBuffer(hnd))) { yuvCount++; yuvLayerIndex = i; //Animating if (isSkipLayer(&list->hwLayers[i])) { isYuvLayerSkip = true; } + } else if(UNLIKELY(isExtCC(hnd))) { + ccLayerIndex = i; + } else if(UNLIKELY(isExtBlock(hnd))) { + extCount++; + extLayerIndex = i; + isExtBlockPresent = true; + } else if(UNLIKELY(isExtOnly(hnd))) { + extCount++; + //If BLOCK layer present, dont cache index, display BLOCK only. + if(isExtBlockPresent == false) extLayerIndex = i; } else if (isSkipLayer(&list->hwLayers[i])) { //Popups //If video layer is below a skip layer if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) { @@ -128,7 +143,9 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list) } } - VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); + VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip, + ccLayerIndex); + ExtOnly::setStats(extCount, extLayerIndex, isExtBlockPresent); CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip); MDPComp::setStats(skipCount); diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 9ce0815..71c1f73 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -90,6 +90,21 @@ static inline bool isBufferLocked(const private_handle_t* hnd) { return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags)); } +//Return true if buffer is for external display only +static inline bool isExtOnly(const private_handle_t* hnd) { + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY)); +} + +//Return true if buffer is for external display only with a BLOCK flag. +static inline bool isExtBlock(const private_handle_t* hnd) { + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK)); +} + +//Return true if buffer is for external display only with a Close Caption flag. +static inline bool isExtCC(const private_handle_t* hnd) { + return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC)); +} + // Initialize uevent thread void init_uevent_thread(hwc_context_t* ctx); diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index a0ae331..4fb88d7 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -29,8 +29,9 @@ namespace qhwc { ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED; int VideoOverlay::sYuvCount = 0; int VideoOverlay::sYuvLayerIndex = -1; +bool VideoOverlay::sIsYuvLayerSkip = false; +int VideoOverlay::sCCLayerIndex = -1; bool VideoOverlay::sIsModeOn = false; -bool VideoOverlay::sIsLayerSkip = false; //Cache stats, figure out the state, config overlay bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { @@ -45,15 +46,21 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { chooseState(ctx); //if the state chosen above is CLOSED, skip this block. if(sState != ovutils::OV_CLOSED) { - if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) { + hwc_layer_t *yuvLayer = &list->hwLayers[sYuvLayerIndex]; + hwc_layer_t *ccLayer = NULL; + if(sCCLayerIndex != -1) + ccLayer = &list->hwLayers[sCCLayerIndex]; + + if(configure(ctx, yuvLayer, ccLayer)) { markFlags(&list->hwLayers[sYuvLayerIndex]); sIsModeOn = true; } } ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d," - "IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount, - sYuvLayerIndex, sIsModeOn, sIsLayerSkip); + "IsYuvLayerSkip = %d, ccLayerIndex = %d, IsModeOn = %d", + __FUNCTION__, sYuvCount, sYuvLayerIndex, + sIsYuvLayerSkip, sCCLayerIndex, sIsModeOn); return sIsModeOn; } @@ -63,14 +70,13 @@ void VideoOverlay::chooseState(hwc_context_t *ctx) { ovutils::getStateString(sState)); ovutils::eOverlayState newState = ovutils::OV_CLOSED; - //TODO check if device supports overlay and hdmi //Support 1 video layer if(sYuvCount == 1) { //Skip on primary, display on ext. - if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) { + if(sIsYuvLayerSkip && ctx->mExtDisplay->getExternalDisplay()) { newState = ovutils::OV_2D_VIDEO_ON_TV; - } else if(sIsLayerSkip) { //skip on primary, no ext + } else if(sIsYuvLayerSkip) { //skip on primary, no ext newState = ovutils::OV_CLOSED; } else if(ctx->mExtDisplay->getExternalDisplay()) { //display on both @@ -228,8 +234,49 @@ bool configExtVid(hwc_context_t *ctx, hwc_layer_t *layer) { return true; } -bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer) -{ +bool configExtCC(hwc_context_t *ctx, hwc_layer_t *layer) { + if(layer == NULL) + return true; + + overlay::Overlay& ov = *(ctx->mOverlay); + private_handle_t *hnd = (private_handle_t *)layer->handle; + ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size); + ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF; + ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE; + ovutils::PipeArgs parg(mdpFlags, + info, + ovutils::ZORDER_1, + isFgFlag, + ovutils::ROT_FLAG_DISABLED); + ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg }; + ov.setSource(pargs, ovutils::OV_PIPE2); + + hwc_rect_t sourceCrop = layer->sourceCrop; + // x,y,w,h + ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, + sourceCrop.right - sourceCrop.left, + sourceCrop.bottom - sourceCrop.top); + //Only for External + ov.setCrop(dcrop, ovutils::OV_PIPE2); + + // FIXME: Use source orientation for TV when source is portrait + //Only for External + ov.setTransform(0, ovutils::OV_PIPE2); + + //Setting position same as crop + //FIXME stretch to full screen + ov.setPosition(dcrop, ovutils::OV_PIPE2); + + if (!ov.commit(ovutils::OV_PIPE2)) { + ALOGE("%s: commit fails", __FUNCTION__); + return false; + } + return true; +} + +bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer, + hwc_layer_t *ccLayer) { + bool ret = true; if (LIKELY(ctx->mOverlay)) { overlay::Overlay& ov = *(ctx->mOverlay); @@ -241,10 +288,12 @@ bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer) break; case ovutils::OV_2D_VIDEO_ON_PANEL_TV: ret &= configExtVid(ctx, yuvLayer); + ret &= configExtCC(ctx, ccLayer); ret &= configPrimVid(ctx, yuvLayer); break; case ovutils::OV_2D_VIDEO_ON_TV: ret &= configExtVid(ctx, yuvLayer); + ret &= configExtCC(ctx, ccLayer); break; default: return false; @@ -262,11 +311,18 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) return true; } - private_handle_t *hnd = - (private_handle_t *)list->hwLayers[sYuvLayerIndex].handle; + private_handle_t *hnd = (private_handle_t *) + list->hwLayers[sYuvLayerIndex].handle; + + private_handle_t *cchnd = NULL; + if(sCCLayerIndex != -1) { + cchnd = (private_handle_t *)list->hwLayers[sCCLayerIndex].handle; + ctx->qbuf->lockAndAdd(cchnd); + } // Lock this buffer for read. ctx->qbuf->lockAndAdd(hnd); + bool ret = true; overlay::Overlay& ov = *(ctx->mOverlay); ovutils::eOverlayState state = ov.getState(); @@ -278,6 +334,12 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) ALOGE("%s: queueBuffer failed for external", __FUNCTION__); ret = false; } + //Play CC on external + if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset, + ovutils::OV_PIPE2)) { + ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__); + ret = false; + } // Play primary if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) { ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); @@ -302,11 +364,18 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) ALOGE("%s: queueBuffer failed for external", __FUNCTION__); ret = false; } + //Play CC on external + if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset, + ovutils::OV_PIPE2)) { + ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__); + ret = false; + } // Wait for external vsync to be done if (!ov.waitForVsync(ovutils::OV_PIPE1)) { ALOGE("%s: waitForVsync failed for external", __FUNCTION__); ret = false; } + break; default: ALOGE("%s Unused state %s", __FUNCTION__, ovutils::getStateString(state)); diff --git a/libhwcomposer/hwc_video.h b/libhwcomposer/hwc_video.h index c6c6c22..62a32a9 100644 --- a/libhwcomposer/hwc_video.h +++ b/libhwcomposer/hwc_video.h @@ -30,12 +30,16 @@ public: //Draws layer if this feature is on static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list); //Receives data from hwc - static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip); + static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip, + int ccLayerIndex); + //resets values + static void reset(); private: //Choose an appropriate overlay state based on conditions static void chooseState(hwc_context_t *ctx); - //Configures overlay - static bool configure(hwc_context_t *ctx, hwc_layer_t *layer); + //Configures overlay for video prim and ext + static bool configure(hwc_context_t *ctx, hwc_layer_t *yuvlayer, + hwc_layer_t *ccLayer); //Marks layer flags if this feature is used static void markFlags(hwc_layer_t *layer); //returns yuv count @@ -48,20 +52,30 @@ private: //Index of YUV layer, relevant only if count is 1 static int sYuvLayerIndex; //Flags if a yuv layer is animating or below something that is animating - static bool sIsLayerSkip; + static bool sIsYuvLayerSkip; + //Holds the closed caption layer index, -1 by default + static int sCCLayerIndex; //Flags if this feature is on. static bool sIsModeOn; }; inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex, - bool isYuvLayerSkip) { + bool isYuvLayerSkip, int ccLayerIndex) { sYuvCount = yuvCount; sYuvLayerIndex = yuvLayerIndex; - sIsLayerSkip = isYuvLayerSkip; + sIsYuvLayerSkip = isYuvLayerSkip; + sCCLayerIndex = ccLayerIndex; } inline int VideoOverlay::getYuvCount() { return sYuvCount; } - +inline void VideoOverlay::reset() { + sYuvCount = 0; + sYuvLayerIndex = -1; + sIsYuvLayerSkip = false; + sCCLayerIndex = -1; + sIsModeOn = false; + sState = ovutils::OV_CLOSED; +} }; //namespace qhwc #endif //HWC_VIDEO_H diff --git a/liboverlay/overlayState.h b/liboverlay/overlayState.h index 518eafa..e4fbece 100644 --- a/liboverlay/overlayState.h +++ b/liboverlay/overlayState.h @@ -265,7 +265,7 @@ template <> struct StateTraits template <> struct StateTraits { typedef overlay::GenericPipe pipe0; - typedef overlay::GenericPipe pipe1; + typedef overlay::NullPipe pipe1; typedef overlay::NullPipe pipe2; typedef NullRotator rot0; From 8d90904f86fb3b6403284c90079dd0c18bd08f94 Mon Sep 17 00:00:00 2001 From: Prabhanjan Kandula Date: Wed, 25 Jul 2012 11:18:15 +0530 Subject: [PATCH 08/12] HDMI: Fallback to MM heap. - IOMMU heap is not available for all targets. we should have a fallback heap always as IOMMU can be disabled. Change-Id: I7e987ac69ba5e5fdd6228b50930e064a4420a472 --- liboverlay/overlayMem.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h index f8109d1..caf0437 100644 --- a/liboverlay/overlayMem.h +++ b/liboverlay/overlayMem.h @@ -139,11 +139,21 @@ inline bool OvMem::open(uint32_t numbufs, data.uncached = true; err = mAlloc->allocate(data, allocFlags, 0); - if (err != 0) { - ALOGE("OvMem: error allocating memory"); + //see if we can fallback to other heap + //we can try MM_HEAP once if it's not secure playback + if (err != 0 && !isSecure) { + allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP; + err = mAlloc->allocate(data, allocFlags, 0); + if (err != 0) { + ALOGE(" could not allocate from fallback heap"); + return false; + } + } else if (err != 0) { + ALOGE("OvMem: error allocating memory can not fall back"); return false; } + mFd = data.fd; mBaseAddr = data.base; mAllocType = data.allocType; From f08d84f218ded2e0479e8e112dc0d26af31d7908 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Fri, 27 Jul 2012 11:35:40 -0700 Subject: [PATCH 09/12] liboverlay: Update format translation. Update format translation from HAL to MDP. Add support for RGB_888, YCbCr_444_SP, YCrCb_444_SP formats. Change-Id: I6323cd07bfe74c7cc60bf2b59dd81e2ae8a2ce27 --- liboverlay/overlayUtils.cpp | 51 +++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp index ce18174..161f05c 100644 --- a/liboverlay/overlayUtils.cpp +++ b/liboverlay/overlayUtils.cpp @@ -149,31 +149,50 @@ bool FrameBufferInfo::supportTrueMirroring() const { } //-------------------------------------------------------- - +//Refer to graphics.h, gralloc_priv.h, msm_mdp.h int getMdpFormat(int format) { switch (format) { + //From graphics.h case HAL_PIXEL_FORMAT_RGBA_8888 : return MDP_RGBA_8888; - case HAL_PIXEL_FORMAT_BGRA_8888: - return MDP_BGRA_8888; - case HAL_PIXEL_FORMAT_RGB_565: - return MDP_RGB_565; case HAL_PIXEL_FORMAT_RGBX_8888: return MDP_RGBX_8888; - case HAL_PIXEL_FORMAT_YCbCr_422_SP: - return MDP_Y_CBCR_H2V1; - case HAL_PIXEL_FORMAT_YCrCb_422_SP: - return MDP_Y_CRCB_H2V1; - case HAL_PIXEL_FORMAT_YCbCr_420_SP: - return MDP_Y_CBCR_H2V2; - case HAL_PIXEL_FORMAT_YCrCb_420_SP: - return MDP_Y_CRCB_H2V2; - case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: - return MDP_Y_CBCR_H2V2_TILE; + case HAL_PIXEL_FORMAT_RGB_888: + return MDP_RGB_888; + case HAL_PIXEL_FORMAT_RGB_565: + return MDP_RGB_565; + case HAL_PIXEL_FORMAT_BGRA_8888: + return MDP_BGRA_8888; case HAL_PIXEL_FORMAT_YV12: return MDP_Y_CR_CB_H2V2; + case HAL_PIXEL_FORMAT_YCbCr_422_SP: + return MDP_Y_CBCR_H2V1; + case HAL_PIXEL_FORMAT_YCrCb_420_SP: + return MDP_Y_CRCB_H2V2; + + //From gralloc_priv.h + case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: + return MDP_Y_CBCR_H2V2_TILE; + case HAL_PIXEL_FORMAT_YCbCr_420_SP: + return MDP_Y_CBCR_H2V2; + case HAL_PIXEL_FORMAT_YCrCb_422_SP: + return MDP_Y_CRCB_H2V1; + case HAL_PIXEL_FORMAT_YCbCr_444_SP: + return MDP_Y_CBCR_H1V1; + case HAL_PIXEL_FORMAT_YCrCb_444_SP: + return MDP_Y_CRCB_H1V1; + default: - ALOGE("Error getMdpFormat format=0x%x", format); + //Unsupported by MDP + //---graphics.h-------- + //HAL_PIXEL_FORMAT_RGBA_5551 + //HAL_PIXEL_FORMAT_RGBA_4444 + //HAL_PIXEL_FORMAT_YCbCr_422_I + //---gralloc_priv.h----- + //HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01 + //HAL_PIXEL_FORMAT_R_8 = 0x10D + //HAL_PIXEL_FORMAT_RG_88 = 0x10E + ALOGE("%s: Unsupported format = 0x%x", __func__, format); return -1; } // not reached From 97d3484b12a9d09a770bb38fc1063d7f88ec4b12 Mon Sep 17 00:00:00 2001 From: Neti Ravi Kumar Date: Sat, 21 Jul 2012 21:02:05 +0530 Subject: [PATCH 10/12] libhwcomposer: Add C2D support to copybit Change-Id: Icb1a010f8079bb3f2122d8520c87d60b757d73bd --- libcopybit/copybit_c2d.cpp | 11 ++ libhwcomposer/hwc.cpp | 3 +- libhwcomposer/hwc_copybit.cpp | 213 ++++++++++++++++++++++------------ libhwcomposer/hwc_copybit.h | 12 +- 4 files changed, 163 insertions(+), 76 deletions(-) diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index 72aa279..af03015 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -126,6 +126,7 @@ struct copybit_context_t { int fb_width; int fb_height; bool isPremultipliedAlpha; + bool mBlitToFB; }; struct blitlist{ @@ -783,6 +784,16 @@ static int set_parameter_copybit( case COPYBIT_FRAMEBUFFER_HEIGHT: ctx->fb_height = value; break; + case COPYBIT_BLIT_TO_FRAMEBUFFER: + if (COPYBIT_ENABLE == value) { + ctx->mBlitToFB = value; + } else if (COPYBIT_DISABLE == value) { + ctx->mBlitToFB = value; + } else { + ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d", + __FUNCTION__, value); + } + break; default: ALOGE("%s: default case param=0x%x", __FUNCTION__, name); return -EINVAL; diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 6ee461c..1d7cf7b 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -86,6 +86,8 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) ExtOnly::reset(); getLayerStats(ctx, list); + // Mark all layers to COPYBIT initially + CopyBit::prepare(ctx, list); if(VideoOverlay::prepare(ctx, list)) { ctx->overlayInUse = true; //Nothing here @@ -102,7 +104,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) // fail in non-overlay targets. ctx->overlayInUse = false; } - CopyBit::prepare(ctx, list); } return 0; diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp index 99aecca..f14d00f 100644 --- a/libhwcomposer/hwc_copybit.cpp +++ b/libhwcomposer/hwc_copybit.cpp @@ -18,9 +18,12 @@ * limitations under the License. */ +#define DEBUG_COPYBIT 0 #include #include #include "hwc_copybit.h" +#include "hwc_copybit.h" +#include "comptype.h" namespace qhwc { @@ -102,32 +105,124 @@ void CopyBit::updateEglHandles(void* egl_lib) } } -bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { - for (int i=list->numHwLayers-1; i >= 0 ; i--) { - private_handle_t *hnd = - (private_handle_t *)list->hwLayers[i].handle; - if (isSkipLayer(&list->hwLayers[i])) { - break; - } else if(canUseCopybit(ctx, list, getYuvCount()) - && !ctx->overlayInUse){ - list->hwLayers[i].compositionType = HWC_USE_COPYBIT; - } else { - list->hwLayers[i].compositionType = HWC_FRAMEBUFFER; - } +bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) { + // return true for non-overlay targets + if(ctx->mMDP.hasOverlay) { + return false; } return true; } + +bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx, hwc_layer_list_t *list) { + int compositionType = + qdutils::QCCompositionType::getInstance().getCompositionType(); + + if ((compositionType & qdutils::COMPOSITION_TYPE_C2D) || + (compositionType & qdutils::COMPOSITION_TYPE_DYN)) { + if (sYuvCount) { + //Overlay up & running. Dont use COPYBIT for RGB layers. + // TODO need to implement blending with C2D + return false; + } + } + + if (compositionType & qdutils::COMPOSITION_TYPE_DYN) { + // DYN Composition: + // use copybit, if (TotalRGBRenderArea < 2 * FB Area) + // this is done based on perf inputs in ICS + // TODO: Above condition needs to be re-evaluated in JB + + framebuffer_device_t *fbDev = ctx->mFbDev; + if (!fbDev) { + ALOGE("%s:Invalid FB device", __FUNCTION__); + return false; + } + unsigned int fbArea = (fbDev->width * fbDev->height); + unsigned int renderArea = getRGBRenderingArea(list); + ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u", + __FUNCTION__, renderArea, fbArea); + if (renderArea < (2 * fbArea)) { + return true; + } + } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) { + // MDP composition, use COPYBIT always + return true; + } else if ((compositionType & qdutils::COMPOSITION_TYPE_C2D)) { + // C2D composition, use COPYBIT + return true; + } + return false; +} + +unsigned int CopyBit::getRGBRenderingArea(const hwc_layer_list_t *list) { + //Calculates total rendering area for RGB layers + unsigned int renderArea = 0; + unsigned int w=0, h=0; + for (unsigned int i=0; inumHwLayers; i++) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + if (hnd) { + if (BUFFER_TYPE_UI == hnd->bufferType) { + getLayerResolution(&list->hwLayers[i], w, h); + renderArea += (w*h); + } + } + } + return renderArea; +} + +bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) { + + int compositionType = + qdutils::QCCompositionType::getInstance().getCompositionType(); + + if ((compositionType & qdutils::COMPOSITION_TYPE_GPU) || + (compositionType & qdutils::COMPOSITION_TYPE_CPU)) { + //GPU/CPU composition, don't change layer composition type + return true; + } + + bool useCopybitForYUV = canUseCopybitForYUV(ctx); + bool useCopybitForRGB = canUseCopybitForRGB(ctx, list); + + if(!(validateParams(ctx, list))) { + ALOGE("%s:Invalid Params", __FUNCTION__); + return false; + } + + for (int i=list->numHwLayers-1; i >= 0 ; i--) { + private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle; + + if (isSkipLayer(&list->hwLayers[i])) { + return true; + } else if (hnd->bufferType == BUFFER_TYPE_VIDEO) { + //YUV layer, check, if copybit can be used + if (useCopybitForYUV) { + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + } + } else if (hnd->bufferType == BUFFER_TYPE_UI) { + //RGB layer, check, if copybit can be used + if (useCopybitForRGB) { + list->hwLayers[i].compositionType = HWC_USE_COPYBIT; + } + } + } + return true; +} + bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy, - EGLSurface sur){ + EGLSurface sur){ + // draw layers marked for COPYBIT + int retVal = true; for (size_t i=0; inumHwLayers; i++) { - if (list->hwLayers[i].flags & HWC_SKIP_LAYER) { - continue; - } else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) { - drawLayerUsingCopybit(ctx, &(list->hwLayers[i]), - (EGLDisplay)dpy, - (EGLSurface)sur, - LINK_eglGetRenderBufferANDROID, - LINK_eglGetCurrentSurface); + if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) { + retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]), + (EGLDisplay)dpy, + (EGLSurface)sur, + LINK_eglGetRenderBufferANDROID, + LINK_eglGetCurrentSurface); + if(retVal<0) { + ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__); + } } } return true; @@ -307,9 +402,8 @@ int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect}; region_iterator tmp_it(tmp_hwc_reg); copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0); - // TODO : alpha not defined , fix this - // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, - // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha); + //TODO: once, we are able to read layer alpha, update this + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255); err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect, &srcRect, &tmp_it); if(err < 0){ @@ -335,9 +429,8 @@ int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, renderBuffer->height); copybit->set_parameter(copybit, COPYBIT_TRANSFORM, layer->transform); - // TODO : alpha not defined , fix this - // copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, - // (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha); + //TODO: once, we are able to read layer alpha, update this + copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255); copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA, (layer->blending == HWC_BLENDING_PREMULT)? COPYBIT_ENABLE : COPYBIT_DISABLE); @@ -366,8 +459,8 @@ int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer, return err; } -void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width, - int& height) +void CopyBit::getLayerResolution(const hwc_layer_t* layer, + unsigned int& width, unsigned int& height) { hwc_rect_t displayFrame = layer->displayFrame; @@ -375,54 +468,32 @@ void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width, height = displayFrame.bottom - displayFrame.top; } -bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list, - const int numYUVBuffers) -{ - // XXX : TODO , currently returning false for MDP4 targets, - // This has to be modified after adding C2D support. - if(ctx->mMDP.hasOverlay) - return false; +bool CopyBit::validateParams(hwc_context_t *ctx, const hwc_layer_list_t *list) { + //Validate parameters + if (!ctx) { + ALOGE("%s:Invalid HWC context", __FUNCTION__); + return false; + } else if (!list) { + ALOGE("%s:Invalid HWC layer list", __FUNCTION__); + return false; + } - framebuffer_device_t* fbDev = ctx->mFbDev; - if(!fbDev) { - ALOGE("ERROR: canUseCopybit : fb device is invalid"); - return false; - } + framebuffer_device_t *fbDev = ctx->mFbDev; - if (!list) - return false; + if (!fbDev) { + ALOGE("%s:Invalid FB device", __FUNCTION__); + return false; + } - // If , couldnt link to adreno library return false. - if(LINK_eglGetRenderBufferANDROID == NULL || - LINK_eglGetCurrentSurface == NULL ) - return false; + if (LINK_eglGetRenderBufferANDROID == NULL || + LINK_eglGetCurrentSurface == NULL) { + ALOGE("%s:Not able to link to ADRENO", __FUNCTION__); + return false; + } - if(!ctx->mMDP.hasOverlay) { - if (numYUVBuffers) - return true; - } - - int fb_w = fbDev->width; - int fb_h = fbDev->height; - - /* - * Use copybit only when we need to blit - * max 2 full screen sized regions - */ - - unsigned int renderArea = 0; - - for(unsigned int i = 0; i < list->numHwLayers; i++ ) { - int w, h; - getLayerResolution(&list->hwLayers[i], w, h); - renderArea += w*h; - } - - return (renderArea <= (2 * fb_w * fb_h)); + return true; } - - //CopybitEngine Class functions CopybitEngine* CopybitEngine::sInstance = 0; diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h index 602898e..8390968 100644 --- a/libhwcomposer/hwc_copybit.h +++ b/libhwcomposer/hwc_copybit.h @@ -51,8 +51,11 @@ public: EGLDisplay dpy, EGLSurface surface, functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID, functype_eglGetCurrentSurface LINK_eglGetCurrentSurface); - static bool canUseCopybit(hwc_context_t* ctx, const hwc_layer_list_t* list, - const int numYUVBuffers); + static bool canUseCopybitForYUV (hwc_context_t *ctx); + static bool canUseCopybitForRGB (hwc_context_t *ctx, + hwc_layer_list_t *list); + static bool validateParams (hwc_context_t *ctx, + const hwc_layer_list_t *list); static void closeEglLib(); static void openEglLibAndGethandle(); private: @@ -75,9 +78,10 @@ private: static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID; static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface; - static void getLayerResolution(const hwc_layer_t* layer, int& width, - int& height); + static unsigned int getRGBRenderingArea (const hwc_layer_list_t *list); + static void getLayerResolution(const hwc_layer_t* layer, + unsigned int &width, unsigned int& height); }; class CopybitEngine { From a710720dbd61b1436df856f1d57bea07d72e01c2 Mon Sep 17 00:00:00 2001 From: Saurabh Shah Date: Mon, 30 Jul 2012 11:17:03 -0700 Subject: [PATCH 11/12] liboverlay: Remove waitForVsync, getOvPipeType APIs Remove waitForVsync support. Vsync will be done explicitly by clients outside of overlay. Remove support for the unused getOvPipeType API. Remove redundant state checks in class Overlay Change-Id: I34f00e1334bbd9fad130bdefeaf0426ebbd638a1 --- libhwcomposer/hwc_extonly.cpp | 5 - libhwcomposer/hwc_video.cpp | 10 -- liboverlay/mdpWrapper.h | 12 -- liboverlay/overlay.cpp | 222 ++++++------------------- liboverlay/overlay.h | 1 - liboverlay/overlayCtrlData.h | 12 -- liboverlay/overlayImpl.h | 70 -------- liboverlay/overlayMdp.h | 12 -- liboverlay/overlayUtils.h | 14 -- liboverlay/pipes/overlay3DPipe.h | 36 ---- liboverlay/pipes/overlayGenPipe.h | 16 -- liboverlay/pipes/overlayUIMirrorPipe.h | 7 - liboverlay/pipes/overlayVideoExtPipe.h | 8 - 13 files changed, 53 insertions(+), 372 deletions(-) diff --git a/libhwcomposer/hwc_extonly.cpp b/libhwcomposer/hwc_extonly.cpp index 77a96b6..6793760 100644 --- a/libhwcomposer/hwc_extonly.cpp +++ b/libhwcomposer/hwc_extonly.cpp @@ -143,11 +143,6 @@ bool ExtOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list) ALOGE("%s: queueBuffer failed for external", __FUNCTION__); ret = false; } - // Wait for external vsync to be done - if (!ov.waitForVsync(ovutils::OV_PIPE0)) { - ALOGE("%s: waitForVsync failed for external", __FUNCTION__); - ret = false; - } break; default: ALOGE("%s Unused state %s", __FUNCTION__, diff --git a/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp index 4fb88d7..e2d9be2 100644 --- a/libhwcomposer/hwc_video.cpp +++ b/libhwcomposer/hwc_video.cpp @@ -345,11 +345,6 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) ALOGE("%s: queueBuffer failed for primary", __FUNCTION__); ret = false; } - // Wait for external vsync to be done - if (!ov.waitForVsync(ovutils::OV_PIPE1)) { - ALOGE("%s: waitForVsync failed for external", __FUNCTION__); - ret = false; - } break; case ovutils::OV_2D_VIDEO_ON_PANEL: // Play primary @@ -370,11 +365,6 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list) ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__); ret = false; } - // Wait for external vsync to be done - if (!ov.waitForVsync(ovutils::OV_PIPE1)) { - ALOGE("%s: waitForVsync failed for external", __FUNCTION__); - ret = false; - } break; default: ALOGE("%s Unused state %s", __FUNCTION__, diff --git a/liboverlay/mdpWrapper.h b/liboverlay/mdpWrapper.h index 8c5f624..b1eb76c 100644 --- a/liboverlay/mdpWrapper.h +++ b/liboverlay/mdpWrapper.h @@ -75,9 +75,6 @@ bool getOverlay(int fd, mdp_overlay& ov); /* MSMFB_OVERLAY_PLAY */ bool play(int fd, msmfb_overlay_data& od); -/* MSMFB_OVERLAY_PLAY_WAIT */ -bool waitForVsync(int fd, msmfb_overlay_data& od); - /* MSMFB_OVERLAY_3D */ bool set3D(int fd, msmfb_overlay_3d& ov); @@ -191,15 +188,6 @@ inline bool play(int fd, msmfb_overlay_data& od) { return true; } -inline bool waitForVsync(int fd, msmfb_overlay_data& od) { - if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) < 0) { - ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%s", - strerror(errno)); - return false; - } - return true; -} - inline bool set3D(int fd, msmfb_overlay_3d& ov) { if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) < 0) { ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%s", diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp index 4dea6ef..3fdb7c4 100644 --- a/liboverlay/overlay.cpp +++ b/liboverlay/overlay.cpp @@ -36,6 +36,35 @@ namespace overlay { +//Helper +bool isStateValid(const utils::eOverlayState& st) { + switch (st) { + case utils::OV_CLOSED: + ALOGE("Overlay %s failed, state is OV_CLOSED; set state first", + __FUNCTION__); + return false; + break; + case utils::OV_2D_VIDEO_ON_PANEL: + case utils::OV_2D_VIDEO_ON_PANEL_TV: + case utils::OV_2D_VIDEO_ON_TV: + case utils::OV_3D_VIDEO_ON_2D_PANEL: + case utils::OV_3D_VIDEO_ON_3D_PANEL: + case utils::OV_3D_VIDEO_ON_3D_TV: + case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: + case utils::OV_UI_MIRROR: + case utils::OV_2D_TRUE_UI_MIRROR: + case utils::OV_BYPASS_1_LAYER: + case utils::OV_BYPASS_2_LAYER: + case utils::OV_BYPASS_3_LAYER: + case utils::OV_DUAL_DISP: + break; + default: + OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); + return false; + } + return true; +} + Overlay::Overlay(): mOv(0) { } @@ -51,28 +80,11 @@ bool Overlay::commit(utils::eDest dest) "%s Overlay and Rotator should be init at this point", __FUNCTION__); utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->commit(dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); + if(isStateValid(st)) { + if(!mOv->commit(dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } return true; } @@ -84,60 +96,11 @@ bool Overlay::queueBuffer(int fd, uint32_t offset, "%s Overlay and Rotator should be init at this point", __FUNCTION__); utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->queueBuffer(fd, offset, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); - return false; - } - return true; -} - -bool Overlay::waitForVsync(utils::eDest dest) -{ - OVASSERT(mOv, - "%s Overlay and Rotator should be init at this point", - __FUNCTION__); - utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->waitForVsync(dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); + if(isStateValid(st)) { + if(!mOv->queueBuffer(fd, offset, dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } return true; } @@ -149,28 +112,11 @@ bool Overlay::setCrop(const utils::Dim& d, "%s Overlay and Rotator should be init at this point", __FUNCTION__); utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->setCrop(d, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); + if(isStateValid(st)) { + if(!mOv->setCrop(d, dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } return true; } @@ -181,28 +127,11 @@ bool Overlay::setPosition(const utils::Dim& d, "%s Overlay and Rotator should be init at this point", __FUNCTION__); utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->setPosition(d, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "setPos Unknown state %d", st); + if(isStateValid(st)) { + if(!mOv->setPosition(d, dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } return true; } @@ -214,28 +143,11 @@ bool Overlay::setTransform(const int orient, static_cast(orient); utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - case utils::OV_UI_MIRROR: - case utils::OV_2D_TRUE_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - if(!mOv->setTransform(transform, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__ , st); + if(isStateValid(st)) { + if(!mOv->setTransform(transform, dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } return true; } @@ -247,40 +159,12 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES], args[0], args[1], args[2] }; utils::eOverlayState st = mState.state(); - switch (st) { - case utils::OV_CLOSED: - ALOGE("Overlay %s failed, state is OV_CLOSED, set state first", - __FUNCTION__); - return false; - break; - case utils::OV_2D_VIDEO_ON_PANEL: - case utils::OV_3D_VIDEO_ON_2D_PANEL: - case utils::OV_UI_MIRROR: - case utils::OV_BYPASS_1_LAYER: - case utils::OV_BYPASS_2_LAYER: - case utils::OV_BYPASS_3_LAYER: - case utils::OV_DUAL_DISP: - break; - case utils::OV_3D_VIDEO_ON_3D_PANEL: - case utils::OV_3D_VIDEO_ON_3D_TV: - //TODO set zorder for channel 1 as 1 in 3D pipe - case utils::OV_2D_VIDEO_ON_PANEL_TV: - case utils::OV_2D_VIDEO_ON_TV: - case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV: - break; - case utils::OV_2D_TRUE_UI_MIRROR: - // TODO Set zorder, external VG pipe (video) gets 0, RGB pipe (UI) gets 1 - break; - default: - OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st); + if(isStateValid(st)) { + if (!mOv->setSource(margs, dest)) { + ALOGE("Overlay %s failed", __FUNCTION__); return false; + } } - - if (!mOv->setSource(margs, dest)) { - ALOGE("Overlay %s failed", __FUNCTION__); - return false; - } - return true; } diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h index b3324eb..12b3883 100644 --- a/liboverlay/overlay.h +++ b/liboverlay/overlay.h @@ -57,7 +57,6 @@ public: bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL); - bool waitForVsync(utils::eDest dest = utils::OV_PIPE1); void dump() const; diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h index 1398ec4..3c7eb42 100644 --- a/liboverlay/overlayCtrlData.h +++ b/liboverlay/overlayCtrlData.h @@ -119,9 +119,6 @@ public: /* queue buffer to the overlay */ bool queueBuffer(int fd, uint32_t offset); - /* wait for vsync to be done */ - bool waitForVsync(); - /* sump the state of the obj */ void dump() const; @@ -218,15 +215,6 @@ inline bool Data::queueBuffer(int fd, uint32_t offset) { return mMdp.play(fd, offset); } -inline bool Data::waitForVsync() { - // Call mdp waitForVsync - if(!mMdp.waitForVsync()){ - ALOGE("Error in MDP %s", __FUNCTION__); - return false; - } - return true; -} - inline void Data::dump() const { ALOGE("== Dump Data MDP start =="); mMdp.dump(); diff --git a/liboverlay/overlayImpl.h b/liboverlay/overlayImpl.h index 6f950c0..1d22694 100644 --- a/liboverlay/overlayImpl.h +++ b/liboverlay/overlayImpl.h @@ -72,9 +72,6 @@ public: virtual bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL) = 0; - /* Wait for vsync to be done on dest */ - virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1) = 0; - /* Crop existing destination using Dim coordinates */ virtual bool setCrop(const utils::Dim& d, utils::eDest dest = utils::OV_PIPE_ALL) = 0; @@ -92,9 +89,6 @@ public: virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES], utils::eDest dest = utils::OV_PIPE_ALL) = 0; - /* Get the overlay pipe type */ - virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const = 0; - /* Dump underlying state */ virtual void dump() const = 0; }; @@ -110,11 +104,6 @@ public: bool setTransform(const utils::eTransform& param) { return true; } bool setSource(const utils::PipeArgs& args) { return true; } bool queueBuffer(int fd, uint32_t offset) { return true; } - bool waitForVsync() { return true; } - // NullPipe will return by val here as opposed to other Pipes. - utils::eOverlayPipeType getOvPipeType() const { - return utils::OV_PIPE_TYPE_NULL; - } void dump() const {} }; @@ -157,8 +146,6 @@ public: utils::eDest dest = utils::OV_PIPE_ALL); virtual bool queueBuffer(int fd, uint32_t offset, utils::eDest dest = utils::OV_PIPE_ALL); - virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1); - virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const; virtual void dump() const; private: @@ -615,63 +602,6 @@ bool OverlayImpl::queueBuffer(int fd, uint32_t offset, return true; } -template -bool OverlayImpl::waitForVsync(utils::eDest dest) -{ - OVASSERT(mPipe0 && mPipe1 && mPipe2, - "%s: Pipes are null p0=%p p1=%p p2=%p", - __FUNCTION__, mPipe0, mPipe1, mPipe2); - - if (utils::OV_PIPE0 & dest) { - if(!mPipe0->waitForVsync()) { - ALOGE("OverlayImpl p0 failed to waitForVsync"); - return false; - } - } - - if (utils::OV_PIPE1 & dest) { - if(!mPipe1->waitForVsync()) { - ALOGE("OverlayImpl p1 failed to waitForVsync"); - return false; - } - } - - if (utils::OV_PIPE2 & dest) { - if(!mPipe2->waitForVsync()) { - ALOGE("OverlayImpl p2 failed to waitForVsync"); - return false; - } - } - - return true; -} - -template -utils::eOverlayPipeType OverlayImpl::getOvPipeType( - utils::eDest dest) const -{ - OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d", - __FUNCTION__, dest); - - if (utils::OV_PIPE0 & dest) { - OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__); - return mPipe0->getOvPipeType(); - } - - if (utils::OV_PIPE1 & dest) { - OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__); - return mPipe1->getOvPipeType(); - } - - if (utils::OV_PIPE2 & dest) { - OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__); - return mPipe2->getOvPipeType(); - } - - // Should never get here - return utils::OV_PIPE_TYPE_NULL; -} - template void OverlayImpl::dump() const { diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h index 30bda79..1ccd64b 100644 --- a/liboverlay/overlayMdp.h +++ b/liboverlay/overlayMdp.h @@ -221,9 +221,6 @@ public: /* calls wrapper play */ bool play(int fd, uint32_t offset); - /* calls wrapper waitForVsync */ - bool waitForVsync(); - /* dump state of the object */ void dump() const; private: @@ -493,15 +490,6 @@ inline bool MdpData::play(int fd, uint32_t offset) { return true; } -inline bool MdpData::waitForVsync() { - if(!mdp_wrapper::waitForVsync(mFd.getFD(), mOvData)){ - ALOGE("%s failed", __FUNCTION__); - dump(); - return false; - } - return true; -} - } // overlay #endif // OVERLAY_MDP_H diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h index f070bd1..a09010c 100644 --- a/liboverlay/overlayUtils.h +++ b/liboverlay/overlayUtils.h @@ -268,25 +268,11 @@ enum eMdpFlags { OV_MDP_FLAGS_NONE = 0, OV_MDP_PIPE_SHARE = MDP_OV_PIPE_SHARE, OV_MDP_DEINTERLACE = MDP_DEINTERLACE, - OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT, //deprecated OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION, OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90, OV_MDP_MEMORY_ID_TYPE_FB = MDP_MEMORY_ID_TYPE_FB, }; -enum eOverlayPipeType { - OV_PIPE_TYPE_NULL, - OV_PIPE_TYPE_BYPASS, - OV_PIPE_TYPE_GENERIC, - OV_PIPE_TYPE_VIDEO_EXT, - OV_PIPE_TYPE_M3D_EXTERNAL, - OV_PIPE_TYPE_M3D_PRIMARY, - OV_PIPE_TYPE_RGB, - OV_PIPE_TYPE_S3D_EXTERNAL, - OV_PIPE_TYPE_S3D_PRIMARY, - OV_PIPE_TYPE_UI_MIRROR -}; - enum eZorder { ZORDER_0, ZORDER_1, diff --git a/liboverlay/pipes/overlay3DPipe.h b/liboverlay/pipes/overlay3DPipe.h index 86ebed7..aaff336 100644 --- a/liboverlay/pipes/overlay3DPipe.h +++ b/liboverlay/pipes/overlay3DPipe.h @@ -54,12 +54,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& d); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mM3d; @@ -86,12 +84,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& d); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mM3d; @@ -118,12 +114,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& d); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mS3d; @@ -150,12 +144,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& d); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: /* needed for 3D related IOCTL */ @@ -196,9 +188,6 @@ inline bool M3DExtPipe::queueBuffer(int fd, uint32_t offset) { return mM3d.queueBuffer(fd, offset); } template -inline bool M3DExtPipe::waitForVsync() { - return mM3d.waitForVsync(); } -template inline bool M3DExtPipe::setCrop(const utils::Dim& d) { utils::Dim _dim; if(!utils::getCropS3D(d, _dim, mM3Dfmt)){ @@ -237,10 +226,6 @@ inline bool M3DExtPipe::setSource(const utils::PipeArgs& args) return mM3d.setSource(args); } template -inline utils::eOverlayPipeType M3DExtPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_M3D_EXTERNAL; -} -template inline void M3DExtPipe::dump() const { ALOGE("M3DExtPipe Pipe fmt=%d", mM3Dfmt); mM3d.dump(); @@ -272,9 +257,6 @@ inline bool M3DPrimaryPipe::queueBuffer(int fd, uint32_t offset) { return mM3d.queueBuffer(fd, offset); } template -inline bool M3DPrimaryPipe::waitForVsync() { - return mM3d.waitForVsync(); } -template inline bool M3DPrimaryPipe::setCrop(const utils::Dim& d) { utils::Dim _dim; if(!utils::getCropS3D(d, _dim, mM3Dfmt)){ @@ -300,10 +282,6 @@ inline bool M3DPrimaryPipe::setSource(const utils::PipeArgs& args) return mM3d.setSource(args); } template -inline utils::eOverlayPipeType M3DPrimaryPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_M3D_PRIMARY; -} -template inline void M3DPrimaryPipe::dump() const { ALOGE("M3DPrimaryPipe Pipe fmt=%d", mM3Dfmt); mM3d.dump(); @@ -337,9 +315,6 @@ inline bool S3DExtPipe::queueBuffer(int fd, uint32_t offset) { return mS3d.queueBuffer(fd, offset); } template -inline bool S3DExtPipe::waitForVsync() { - return mS3d.waitForVsync(); } -template inline bool S3DExtPipe::setCrop(const utils::Dim& d) { utils::Dim _dim; if(!utils::getCropS3D(d, _dim, mS3Dfmt)){ @@ -371,10 +346,6 @@ inline bool S3DExtPipe::setSource(const utils::PipeArgs& args) { return mS3d.setSource(args); } template -inline utils::eOverlayPipeType S3DExtPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_S3D_EXTERNAL; -} -template inline void S3DExtPipe::dump() const { ALOGE("S3DExtPipe Pipe fmt=%d", mS3Dfmt); mS3d.dump(); @@ -419,9 +390,6 @@ inline bool S3DPrimaryPipe::queueBuffer(int fd, uint32_t offset) { return mS3d.queueBuffer(fd, offset); } template -inline bool S3DPrimaryPipe::waitForVsync() { - return mS3d.waitForVsync(); } -template inline bool S3DPrimaryPipe::setCrop(const utils::Dim& d) { utils::Dim _dim; if(!utils::getCropS3D(d, _dim, mS3Dfmt)){ @@ -487,10 +455,6 @@ inline bool S3DPrimaryPipe::setSource(const utils::PipeArgs& args) return mS3d.setSource(args); } template -inline utils::eOverlayPipeType S3DPrimaryPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_S3D_PRIMARY; -} -template inline void S3DPrimaryPipe::dump() const { ALOGE("S3DPrimaryPipe Pipe fmt=%d", mS3Dfmt); mS3d.dump(); diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h index c2d774b..cbcb05a 100644 --- a/liboverlay/pipes/overlayGenPipe.h +++ b/liboverlay/pipes/overlayGenPipe.h @@ -63,8 +63,6 @@ public: /* Data APIs */ /* queue buffer to the overlay */ bool queueBuffer(int fd, uint32_t offset); - /* wait for vsync to be done */ - bool waitForVsync(); /* return cached startup args */ const utils::PipeArgs& getArgs() const; @@ -90,9 +88,6 @@ public: /* return Ctrl fd. Used for S3D */ int getCtrlFd() const; - /* Get the overlay pipe type */ - utils::eOverlayPipeType getOvPipeType() const; - /* dump the state of the object */ void dump() const; private: @@ -280,12 +275,6 @@ inline int GenericPipe::getCtrlFd() const { return mCtrlData.ctrl.getFd(); } -template -inline bool GenericPipe::waitForVsync() { - OVASSERT(isOpen(), "State is closed, cannot waitForVsync"); - return mCtrlData.data.waitForVsync(); -} - template inline utils::Dim GenericPipe::getAspectRatio( const utils::Whf& whf) const @@ -312,11 +301,6 @@ inline utils::Dim GenericPipe::getCrop() const return mCtrlData.ctrl.getCrop(); } -template -inline utils::eOverlayPipeType GenericPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_GENERIC; -} - template void GenericPipe::dump() const { diff --git a/liboverlay/pipes/overlayUIMirrorPipe.h b/liboverlay/pipes/overlayUIMirrorPipe.h index 1c22020..c2b73bd 100644 --- a/liboverlay/pipes/overlayUIMirrorPipe.h +++ b/liboverlay/pipes/overlayUIMirrorPipe.h @@ -50,12 +50,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& dim); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mUI; @@ -79,8 +77,6 @@ inline bool UIMirrorPipe::commit() { return mUI.commit(); } inline bool UIMirrorPipe::queueBuffer(int fd, uint32_t offset) { return mUI.queueBuffer(fd, offset); } -inline bool UIMirrorPipe::waitForVsync() { - return mUI.waitForVsync(); } inline bool UIMirrorPipe::setCrop(const utils::Dim& dim) { return mUI.setCrop(dim); } @@ -162,9 +158,6 @@ inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) { return mUI.setSource(arg); } -inline utils::eOverlayPipeType UIMirrorPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_UI_MIRROR; -} inline void UIMirrorPipe::dump() const { ALOGE("UI Mirror Pipe"); mUI.dump(); diff --git a/liboverlay/pipes/overlayVideoExtPipe.h b/liboverlay/pipes/overlayVideoExtPipe.h index 8196fe7..d4e1f3f 100644 --- a/liboverlay/pipes/overlayVideoExtPipe.h +++ b/liboverlay/pipes/overlayVideoExtPipe.h @@ -50,12 +50,10 @@ public: bool close(); bool commit(); bool queueBuffer(int fd, uint32_t offset); - bool waitForVsync(); bool setCrop(const utils::Dim& dim); bool setPosition(const utils::Dim& dim); bool setTransform(const utils::eTransform& param); bool setSource(const utils::PipeArgs& args); - utils::eOverlayPipeType getOvPipeType() const; void dump() const; private: overlay::GenericPipe mVideoExt; @@ -74,9 +72,6 @@ inline bool VideoExtPipe::commit() { return mVideoExt.commit(); } inline bool VideoExtPipe::queueBuffer(int fd, uint32_t offset) { return mVideoExt.queueBuffer(fd, offset); } -inline bool VideoExtPipe::waitForVsync() { - return mVideoExt.waitForVsync(); -} inline bool VideoExtPipe::setCrop(const utils::Dim& dim) { return mVideoExt.setCrop(dim); } @@ -105,9 +100,6 @@ inline bool VideoExtPipe::setSource(const utils::PipeArgs& args) { utils::PipeArgs arg(args); return mVideoExt.setSource(arg); } -inline utils::eOverlayPipeType VideoExtPipe::getOvPipeType() const { - return utils::OV_PIPE_TYPE_VIDEO_EXT; -} inline void VideoExtPipe::dump() const { ALOGE("Video Ext Pipe"); mVideoExt.dump(); From be02ab0d74969518af87022e4733ea62b90b0c80 Mon Sep 17 00:00:00 2001 From: Naseer Ahmed Date: Sat, 14 Jul 2012 21:08:13 -0700 Subject: [PATCH 12/12] display: Clean up gralloc * Remove pmem and ashmem implementations * Remove usage of RefBase * Reduce log verbosity Change-Id: If8ef543d236e5305bd5430f4f9c62c51b3a13787 --- common.mk | 2 +- libcopybit/copybit.cpp | 3 +- libcopybit/copybit_c2d.cpp | 13 +- libgralloc/alloc_controller.cpp | 200 +-------------- libgralloc/alloc_controller.h | 59 +---- libgralloc/ashmemalloc.cpp | 138 ----------- libgralloc/ashmemalloc.h | 56 ----- libgralloc/gpu.cpp | 14 +- libgralloc/gpu.h | 5 +- libgralloc/gralloc.cpp | 4 +- libgralloc/gralloc_priv.h | 55 ++--- libgralloc/ionalloc.cpp | 16 +- libgralloc/mapper.cpp | 33 +-- libgralloc/memalloc.h | 3 +- libgralloc/pmem_bestfit_alloc.cpp | 195 --------------- libgralloc/pmem_bestfit_alloc.h | 129 ---------- libgralloc/pmemalloc.cpp | 387 ------------------------------ libgralloc/pmemalloc.h | 106 -------- libhwcomposer/hwc_mdpcomp.cpp | 0 libhwcomposer/hwc_mdpcomp.h | 0 liboverlay/overlayMem.h | 12 +- liboverlay/pipes/overlayGenPipe.h | 4 - libqdutils/idle_invalidator.cpp | 0 23 files changed, 81 insertions(+), 1353 deletions(-) delete mode 100644 libgralloc/ashmemalloc.cpp delete mode 100644 libgralloc/ashmemalloc.h delete mode 100644 libgralloc/pmem_bestfit_alloc.cpp delete mode 100644 libgralloc/pmem_bestfit_alloc.h delete mode 100644 libgralloc/pmemalloc.cpp delete mode 100644 libgralloc/pmemalloc.h mode change 100755 => 100644 libhwcomposer/hwc_mdpcomp.cpp mode change 100755 => 100644 libhwcomposer/hwc_mdpcomp.h mode change 100755 => 100644 libqdutils/idle_invalidator.cpp diff --git a/common.mk b/common.mk index 0bc64a3..a48476e 100644 --- a/common.mk +++ b/common.mk @@ -15,7 +15,7 @@ endif common_libs := liblog libutils libcutils libhardware #Common C flags -common_flags := -DUSE_ION -DDEBUG_CALC_FPS -Wno-missing-field-initializers +common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers ifeq ($(ARCH_ARM_HAVE_NEON),true) common_flags += -D__ARM_HAVE_NEON endif diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp index ee8c12e..2e2956c 100644 --- a/libcopybit/copybit.cpp +++ b/libcopybit/copybit.cpp @@ -426,8 +426,7 @@ static int stretch_copybit( } if(src->format == HAL_PIXEL_FORMAT_YV12) { - int usage = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | - GRALLOC_USAGE_PRIVATE_MM_HEAP; + int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP; if (0 == alloc_buffer(&yv12_handle,src->w,src->h, src->format, usage)){ if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){ diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp index af03015..5eec414 100644 --- a/libcopybit/copybit_c2d.cpp +++ b/libcopybit/copybit_c2d.cpp @@ -49,7 +49,6 @@ using gralloc::IMemAlloc; using gralloc::IonController; using gralloc::alloc_data; -using android::sp; C2D_STATUS (*LINK_c2dCreateSurface)( uint32 *surface_id, uint32 surface_bits, @@ -110,7 +109,7 @@ enum eC2DFlags { FLAGS_YUV_DESTINATION = 1<<1 }; -static android::sp sAlloc = 0; +static gralloc::IAllocController* sAlloc = 0; /******************************************************************************/ /** State information for each device instance */ @@ -933,7 +932,7 @@ static int get_temp_buffer(const bufferInfo& info, alloc_data& data) int allocFlags = GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP; if (sAlloc == 0) { - sAlloc = gralloc::IAllocController::getInstance(false); + sAlloc = gralloc::IAllocController::getInstance(); } if (sAlloc == 0) { @@ -941,7 +940,7 @@ static int get_temp_buffer(const bufferInfo& info, alloc_data& data) return COPYBIT_FAILURE; } - int err = sAlloc->allocate(data, allocFlags, 0); + int err = sAlloc->allocate(data, allocFlags); if (0 != err) { ALOGE("%s: allocate failed", __FUNCTION__); return COPYBIT_FAILURE; @@ -955,7 +954,7 @@ static int get_temp_buffer(const bufferInfo& info, alloc_data& data) static void free_temp_buffer(alloc_data &data) { if (-1 != data.fd) { - sp memalloc = sAlloc->getAllocator(data.allocType); + IMemAlloc* memalloc = sAlloc->getAllocator(data.allocType); memalloc->free_buffer(data.base, data.size, 0, data.fd); } } @@ -1174,7 +1173,7 @@ static int stretch_copybit_internal( copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT); // Flush the cache - sp memalloc = sAlloc->getAllocator(src_hnd->flags); + IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags); if (memalloc->clean_buffer((void *)(src_hnd->base), src_hnd->size, src_hnd->offset, src_hnd->fd)) { ALOGE("%s: clean_buffer failed", __FUNCTION__); @@ -1245,7 +1244,7 @@ static int stretch_copybit_internal( // copy the temp. destination without the alignment to the actual destination. copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT); // Invalidate the cache. - sp memalloc = sAlloc->getAllocator(dst_hnd->flags); + IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags); memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size, dst_hnd->offset, dst_hnd->fd); } diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp index d21c3c3..1802a75 100644 --- a/libgralloc/alloc_controller.cpp +++ b/libgralloc/alloc_controller.cpp @@ -28,30 +28,16 @@ */ #include -#include #include #include "gralloc_priv.h" #include "alloc_controller.h" #include "memalloc.h" #include "ionalloc.h" -#include "pmemalloc.h" -#include "ashmemalloc.h" #include "gr.h" #include "comptype.h" using namespace gralloc; using namespace qdutils; -using android::sp; - -const int GRALLOC_HEAP_MASK = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | - GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP | - GRALLOC_USAGE_PRIVATE_SMI_HEAP | - GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP | - GRALLOC_USAGE_PRIVATE_IOMMU_HEAP | - GRALLOC_USAGE_PRIVATE_MM_HEAP | - GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP | - GRALLOC_USAGE_PRIVATE_CAMERA_HEAP; - //Common functions static bool canFallback(int usage, bool triedSystem) @@ -88,18 +74,11 @@ static bool useUncached(int usage) return false; } -sp IAllocController::sController = NULL; -sp IAllocController::getInstance(bool useMasterHeap) +IAllocController* IAllocController::sController = NULL; +IAllocController* IAllocController::getInstance(void) { if(sController == NULL) { -#ifdef USE_ION sController = new IonController(); -#else - if(useMasterHeap) - sController = new PmemAshmemController(); - else - sController = new PmemKernelController(); -#endif } return sController; } @@ -111,8 +90,7 @@ IonController::IonController() mIonAlloc = new IonAlloc(); } -int IonController::allocate(alloc_data& data, int usage, - int compositionType) +int IonController::allocate(alloc_data& data, int usage) { int ionFlags = 0; int ret; @@ -135,20 +113,12 @@ int IonController::allocate(alloc_data& data, int usage, if(usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID); - if(usage & GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP) - ionFlags |= ION_HEAP(ION_CP_WB_HEAP_ID); - if(usage & GRALLOC_USAGE_PRIVATE_CAMERA_HEAP) ionFlags |= ION_HEAP(ION_CAMERA_HEAP_ID); if(usage & GRALLOC_USAGE_PRIVATE_CP_BUFFER) ionFlags |= ION_SECURE; - if(usage & GRALLOC_USAGE_PRIVATE_DO_NOT_MAP) - data.allocType |= private_handle_t::PRIV_FLAGS_NOT_MAPPED; - else - data.allocType &= ~(private_handle_t::PRIV_FLAGS_NOT_MAPPED); - // if no flags are set, default to // SF + IOMMU heaps, so that bypass can work // we can fall back to system heap if @@ -180,9 +150,9 @@ int IonController::allocate(alloc_data& data, int usage, return ret; } -sp IonController::getAllocator(int flags) +IMemAlloc* IonController::getAllocator(int flags) { - sp memalloc; + IMemAlloc* memalloc; if (flags & private_handle_t::PRIV_FLAGS_USES_ION) { memalloc = mIonAlloc; } else { @@ -192,151 +162,6 @@ sp IonController::getAllocator(int flags) return memalloc; } -//-------------- PmemKernelController-----------------------// -//XXX: Remove - we're not using pmem anymore -#if 0 -PmemKernelController::PmemKernelController() -{ - mPmemAdspAlloc = new PmemKernelAlloc(DEVICE_PMEM_ADSP); - // XXX: Right now, there is no need to maintain an instance - // of the SMI allocator as we need it only in a few cases -} - -PmemKernelController::~PmemKernelController() -{ -} - -int PmemKernelController::allocate(alloc_data& data, int usage, - int compositionType) -{ - int ret = 0; - bool adspFallback = false; - if (!(usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP)) - adspFallback = true; - - // Try SMI first - if ((usage & GRALLOC_USAGE_PRIVATE_SMI_HEAP) || - (usage & GRALLOC_USAGE_EXTERNAL_DISP) || - (usage & GRALLOC_USAGE_PROTECTED)) - { - int tempFd = open(DEVICE_PMEM_SMIPOOL, O_RDWR, 0); - if(tempFd > 0) { - close(tempFd); - sp memalloc; - memalloc = new PmemKernelAlloc(DEVICE_PMEM_SMIPOOL); - ret = memalloc->alloc_buffer(data); - if(ret >= 0) - return ret; - else { - if(adspFallback) - ALOGW("Allocation from SMI failed, trying ADSP"); - } - } - } - - if ((usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) || adspFallback) { - ret = mPmemAdspAlloc->alloc_buffer(data); - } - return ret; -} - -sp PmemKernelController::getAllocator(int flags) -{ - sp memalloc; - if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) - memalloc = mPmemAdspAlloc; - else { - ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); - memalloc = NULL; - } - - return memalloc; -} - -//-------------- PmemAshmmemController-----------------------// - -PmemAshmemController::PmemAshmemController() -{ - mPmemUserspaceAlloc = new PmemUserspaceAlloc(); - mAshmemAlloc = new AshmemAlloc(); - mPmemKernelCtrl = new PmemKernelController(); -} - -PmemAshmemController::~PmemAshmemController() -{ -} - -int PmemAshmemController::allocate(alloc_data& data, int usage, - int compositionType) -{ - int ret = 0; - data.allocType = 0; - - // Make buffers cacheable by default - data.uncached = false; - - // Override if we explicitly need uncached buffers - if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED) - data.uncached = true; - - // If ADSP or SMI is requested use the kernel controller - if(usage & (GRALLOC_USAGE_PRIVATE_ADSP_HEAP| - GRALLOC_USAGE_PRIVATE_SMI_HEAP)) { - ret = mPmemKernelCtrl->allocate(data, usage, compositionType); - if(ret < 0) - ALOGE("%s: Failed to allocate ADSP/SMI memory", __func__); - else - data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP; - return ret; - } - - if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP) { - ret = mAshmemAlloc->alloc_buffer(data); - if(ret >= 0) { - data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; - data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; - } - return ret; - } - - // if no memory specific flags are set, - // default to EBI heap, so that bypass - // can work. We can fall back to system - // heap if we run out. - ret = mPmemUserspaceAlloc->alloc_buffer(data); - - // Fallback - if(ret >= 0 ) { - data.allocType = private_handle_t::PRIV_FLAGS_USES_PMEM; - } else if(ret < 0 && canFallback(usage, false)) { - ALOGW("Falling back to ashmem"); - ret = mAshmemAlloc->alloc_buffer(data); - if(ret >= 0) { - data.allocType = private_handle_t::PRIV_FLAGS_USES_ASHMEM; - data.allocType |= private_handle_t::PRIV_FLAGS_NONCONTIGUOUS_MEM; - } - } - - return ret; -} - -sp PmemAshmemController::getAllocator(int flags) -{ - sp memalloc; - if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) - memalloc = mPmemUserspaceAlloc; - else if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM_ADSP) - memalloc = mPmemKernelCtrl->getAllocator(flags); - else if (flags & private_handle_t::PRIV_FLAGS_USES_ASHMEM) - memalloc = mAshmemAlloc; - else { - ALOGE("%s: Invalid flags passed: 0x%x", __FUNCTION__, flags); - memalloc = NULL; - } - - return memalloc; -} -#endif size_t getBufferSizeAndDimensions(int width, int height, int format, int& alignedw, int &alignedh) { @@ -417,8 +242,8 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage) { alloc_data data; int alignedw, alignedh; - android::sp sAlloc = - gralloc::IAllocController::getInstance(false); + gralloc::IAllocController* sAlloc = + gralloc::IAllocController::getInstance(); data.base = 0; data.fd = -1; data.offset = 0; @@ -427,14 +252,15 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage) data.uncached = useUncached(usage); int allocFlags = usage; - int err = sAlloc->allocate(data, allocFlags, 0); + int err = sAlloc->allocate(data, allocFlags); if (0 != err) { ALOGE("%s: allocate failed", __FUNCTION__); return -ENOMEM; } private_handle_t* hnd = new private_handle_t(data.fd, data.size, - data.allocType, 0, format, alignedw, alignedh); + data.allocType, 0, format, + alignedw, alignedh); hnd->base = (int) data.base; hnd->offset = data.offset; hnd->gpuaddr = 0; @@ -444,10 +270,10 @@ int alloc_buffer(private_handle_t **pHnd, int w, int h, int format, int usage) void free_buffer(private_handle_t *hnd) { - android::sp sAlloc = - gralloc::IAllocController::getInstance(false); + gralloc::IAllocController* sAlloc = + gralloc::IAllocController::getInstance(); if (hnd && hnd->fd > 0) { - sp memalloc = sAlloc->getAllocator(hnd->flags); + IMemAlloc* memalloc = sAlloc->getAllocator(hnd->flags); memalloc->free_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd); } if(hnd) diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h index 134ad40..f04917a 100644 --- a/libgralloc/alloc_controller.h +++ b/libgralloc/alloc_controller.h @@ -29,86 +29,43 @@ #ifndef GRALLOC_ALLOCCONTROLLER_H #define GRALLOC_ALLOCCONTROLLER_H -#include - namespace gralloc { struct alloc_data; class IMemAlloc; class IonAlloc; -class IAllocController : public android::RefBase { +class IAllocController { public: /* Allocate using a suitable method * Returns the type of buffer allocated */ - virtual int allocate(alloc_data& data, int usage, - int compositionType) = 0; + virtual int allocate(alloc_data& data, int usage) = 0; - virtual android::sp getAllocator(int flags) = 0; + virtual IMemAlloc* getAllocator(int flags) = 0; virtual ~IAllocController() {}; - static android::sp getInstance(bool useMasterHeap); + static IAllocController* getInstance(void); private: - static android::sp sController; + static IAllocController* sController; }; class IonController : public IAllocController { public: - virtual int allocate(alloc_data& data, int usage, - int compositionType); + virtual int allocate(alloc_data& data, int usage); - virtual android::sp getAllocator(int flags); + virtual IMemAlloc* getAllocator(int flags); IonController(); private: - android::sp mIonAlloc; + IonAlloc* mIonAlloc; }; - -class PmemKernelController : public IAllocController { - - public: - virtual int allocate(alloc_data& data, int usage, - int compositionType); - - virtual android::sp getAllocator(int flags); - - PmemKernelController (); - - ~PmemKernelController (); - - private: - android::sp mPmemAdspAlloc; - -}; - -// Main pmem controller - this should only -// be used within gralloc -class PmemAshmemController : public IAllocController { - - public: - virtual int allocate(alloc_data& data, int usage, - int compositionType); - - virtual android::sp getAllocator(int flags); - - PmemAshmemController(); - - ~PmemAshmemController(); - - private: - android::sp mPmemUserspaceAlloc; - android::sp mAshmemAlloc; - android::sp mPmemKernelCtrl; - -}; - } //end namespace gralloc #endif // GRALLOC_ALLOCCONTROLLER_H diff --git a/libgralloc/ashmemalloc.cpp b/libgralloc/ashmemalloc.cpp deleted file mode 100644 index b659d90..0000000 --- a/libgralloc/ashmemalloc.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "ashmemalloc.h" - -using gralloc::AshmemAlloc; -int AshmemAlloc::alloc_buffer(alloc_data& data) -{ - int err = 0; - int fd = -1; - void* base = 0; - int offset = 0; - char name[ASHMEM_NAME_LEN]; - snprintf(name, ASHMEM_NAME_LEN, "gralloc-buffer-%x", data.pHandle); - int prot = PROT_READ | PROT_WRITE; - fd = ashmem_create_region(name, data.size); - if (fd < 0) { - ALOGE("couldn't create ashmem (%s)", strerror(errno)); - err = -errno; - } else { - if (ashmem_set_prot_region(fd, prot) < 0) { - ALOGE("ashmem_set_prot_region(fd=%d, prot=%x) failed (%s)", - fd, prot, strerror(errno)); - close(fd); - err = -errno; - } else { - base = mmap(0, data.size, prot, MAP_SHARED|MAP_POPULATE|MAP_LOCKED, fd, 0); - if (base == MAP_FAILED) { - ALOGE("alloc mmap(fd=%d, size=%d, prot=%x) failed (%s)", - fd, data.size, prot, strerror(errno)); - close(fd); - err = -errno; - } else { - memset((char*)base + offset, 0, data.size); - } - } - } - if(err == 0) { - data.fd = fd; - data.base = base; - data.offset = offset; - clean_buffer(base, data.size, offset, fd); - ALOGD("ashmem: Allocated buffer base:%p size:%d fd:%d", - base, data.size, fd); - - } - return err; - -} - -int AshmemAlloc::free_buffer(void* base, size_t size, int offset, int fd) -{ - ALOGD("ashmem: Freeing buffer base:%p size:%d fd:%d", - base, size, fd); - int err = 0; - - if(!base) { - ALOGE("Invalid free"); - return -EINVAL; - } - err = unmap_buffer(base, size, offset); - close(fd); - return err; -} - -int AshmemAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) -{ - int err = 0; - void *base = 0; - - base = mmap(0, size, PROT_READ| PROT_WRITE, - MAP_SHARED|MAP_POPULATE, fd, 0); - *pBase = base; - if(base == MAP_FAILED) { - ALOGE("ashmem: Failed to map memory in the client: %s", - strerror(errno)); - err = -errno; - } else { - ALOGD("ashmem: Mapped buffer base:%p size:%d fd:%d", - base, size, fd); - } - return err; -} - -int AshmemAlloc::unmap_buffer(void *base, size_t size, int offset) -{ - ALOGD("ashmem: Unmapping buffer base: %p size: %d", base, size); - int err = munmap(base, size); - if(err) { - ALOGE("ashmem: Failed to unmap memory at %p: %s", - base, strerror(errno)); - } - return err; - -} -int AshmemAlloc::clean_buffer(void *base, size_t size, int offset, int fd) -{ - int err = 0; - if (ioctl(fd, ASHMEM_CACHE_FLUSH_RANGE, NULL)) { - ALOGE("ashmem: ASHMEM_CACHE_FLUSH_RANGE failed fd = %d", fd); - } - - return err; -} - diff --git a/libgralloc/ashmemalloc.h b/libgralloc/ashmemalloc.h deleted file mode 100644 index 50daf04..0000000 --- a/libgralloc/ashmemalloc.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 GRALLOC_ASHMEMALLOC_H -#define GRALLOC_ASHMEMALLOC_H - -#include "memalloc.h" -#include - -namespace gralloc { -class AshmemAlloc : public IMemAlloc { - - public: - virtual int alloc_buffer(alloc_data& data); - - virtual int free_buffer(void *base, size_t size, - int offset, int fd); - - virtual int map_buffer(void **pBase, size_t size, - int offset, int fd); - - virtual int unmap_buffer(void *base, size_t size, - int offset); - - virtual int clean_buffer(void*base, size_t size, - int offset, int fd); - -}; -} -#endif /* GRALLOC_ASHMEMALLOC_H */ diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp index 1ffcdfb..2db6274 100644 --- a/libgralloc/gpu.cpp +++ b/libgralloc/gpu.cpp @@ -29,10 +29,9 @@ #include "alloc_controller.h" using namespace gralloc; -using android::sp; gpu_context_t::gpu_context_t(const private_module_t* module, - sp alloc_ctrl ) : + IAllocController* alloc_ctrl ) : mAllocCtrl(alloc_ctrl) { // Zero out the alloc_device_t @@ -44,9 +43,6 @@ gpu_context_t::gpu_context_t(const private_module_t* module, common.module = const_cast(&module->base.common); common.close = gralloc_close; alloc = gralloc_alloc; -#if 0 - allocSize = gralloc_alloc_size; -#endif free = gralloc_free; } @@ -56,8 +52,8 @@ int gpu_context_t::gralloc_alloc_framebuffer_locked(size_t size, int usage, { private_module_t* m = reinterpret_cast(common.module); - // we don't support allocations with both the FB and PMEM_ADSP flags - if (usage & GRALLOC_USAGE_PRIVATE_ADSP_HEAP) { + // we don't support framebuffer allocations with graphics heap flags + if (usage & GRALLOC_HEAP_MASK) { return -EINVAL; } @@ -140,7 +136,7 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage, else data.align = getpagesize(); data.pHandle = (unsigned int) pHandle; - err = mAllocCtrl->allocate(data, usage, 0); + err = mAllocCtrl->allocate(data, usage); if (usage & GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED) { flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED; @@ -244,7 +240,7 @@ int gpu_context_t::free_impl(private_handle_t const* hnd) { m->bufferMask &= ~(1<base, const_cast(hnd)); - sp memalloc = mAllocCtrl->getAllocator(hnd->flags); + IMemAlloc* memalloc = mAllocCtrl->getAllocator(hnd->flags); int err = memalloc->free_buffer((void*)hnd->base, (size_t) hnd->size, hnd->offset, hnd->fd); if(err) diff --git a/libgralloc/gpu.h b/libgralloc/gpu.h index 487f4d1..5a6c0ea 100644 --- a/libgralloc/gpu.h +++ b/libgralloc/gpu.h @@ -25,7 +25,6 @@ #include #include -#include #include "gralloc_priv.h" #include @@ -35,7 +34,7 @@ class IAllocController; class gpu_context_t : public alloc_device_t { public: gpu_context_t(const private_module_t* module, - android::spalloc_ctrl); + IAllocController* alloc_ctrl); int gralloc_alloc_framebuffer_locked(size_t size, int usage, buffer_handle_t* pHandle); @@ -69,7 +68,7 @@ class gpu_context_t : public alloc_device_t { static int gralloc_close(struct hw_device_t *dev); private: - android::sp mAllocCtrl; + IAllocController* mAllocCtrl; void getGrallocInformationFromFormat(int inputFormat, int *colorFormat, int *bufferType); diff --git a/libgralloc/gralloc.cpp b/libgralloc/gralloc.cpp index cf57fee..7924ae3 100644 --- a/libgralloc/gralloc.cpp +++ b/libgralloc/gralloc.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -33,7 +32,6 @@ #include "alloc_controller.h" using namespace gralloc; -using android::sp; int fb_device_open(const hw_module_t* module, const char* name, hw_device_t** device); @@ -102,7 +100,7 @@ int gralloc_device_open(const hw_module_t* module, const char* name, const private_module_t* m = reinterpret_cast( module); gpu_context_t *dev; - sp alloc_ctrl = IAllocController::getInstance(true); + IAllocController* alloc_ctrl = IAllocController::getInstance(); dev = new gpu_context_t(m, alloc_ctrl); *device = &dev->common; status = 0; diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h index ae28a57..d199f4c 100644 --- a/libgralloc/gralloc_priv.h +++ b/libgralloc/gralloc_priv.h @@ -34,33 +34,22 @@ enum { /* gralloc usage bits indicating the type * of allocation that should be used */ - /* ADSP heap is deprecated, use only if using pmem */ - GRALLOC_USAGE_PRIVATE_ADSP_HEAP = GRALLOC_USAGE_PRIVATE_0, - /* SF heap is used for application buffers, is not secured */ - GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP = GRALLOC_USAGE_PRIVATE_1, - /* SMI heap is deprecated, use only if using pmem */ - GRALLOC_USAGE_PRIVATE_SMI_HEAP = GRALLOC_USAGE_PRIVATE_2, /* SYSTEM heap comes from kernel vmalloc, * can never be uncached, is not secured*/ - GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_3, + GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP = GRALLOC_USAGE_PRIVATE_0, + /* SF heap is used for application buffers, is not secured */ + GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP = GRALLOC_USAGE_PRIVATE_1, /* IOMMU heap comes from manually allocated pages, * can be cached/uncached, is not secured */ - GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = 0x01000000, + GRALLOC_USAGE_PRIVATE_IOMMU_HEAP = GRALLOC_USAGE_PRIVATE_2, /* MM heap is a carveout heap for video, can be secured*/ - GRALLOC_USAGE_PRIVATE_MM_HEAP = 0x02000000, - /* WRITEBACK heap is a carveout heap for writeback, can be secured*/ - GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP = 0x04000000, + GRALLOC_USAGE_PRIVATE_MM_HEAP = GRALLOC_USAGE_PRIVATE_3, /* CAMERA heap is a carveout heap for camera, is not secured*/ - GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x08000000, + GRALLOC_USAGE_PRIVATE_CAMERA_HEAP = 0x01000000, /* Set this for allocating uncached memory (using O_DSYNC) * cannot be used with noncontiguous heaps */ - GRALLOC_USAGE_PRIVATE_UNCACHED = 0x00100000, - - /* This flag needs to be set when using a non-contiguous heap from ION. - * If not set, the system heap is assumed to be coming from ashmem - */ - GRALLOC_USAGE_PRIVATE_ION = 0x00200000, + GRALLOC_USAGE_PRIVATE_UNCACHED = 0x02000000, /* This flag can be set to disable genlock synchronization * for the gralloc buffer. If this flag is set the caller @@ -68,28 +57,32 @@ enum { * WARNING - flag is outside the standard PRIVATE region * and may need to be moved if the gralloc API changes */ - GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED = 0X00400000, - - /* Set this flag when you need to avoid mapping the memory in userspace */ - GRALLOC_USAGE_PRIVATE_DO_NOT_MAP = 0X00800000, + GRALLOC_USAGE_PRIVATE_UNSYNCHRONIZED = 0X04000000, /* Buffer content should be displayed on an external display only */ - GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x00010000, + GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x08000000, /* Only this buffer content should be displayed on external, even if * other EXTERNAL_ONLY buffers are available. Used during suspend. */ - GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00020000, + GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00100000, /* Close Caption displayed on an external display only */ - GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x00040000, + GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x00200000, /* Use this flag to request content protected buffers. Please note * that this flag is different from the GRALLOC_USAGE_PROTECTED flag * which can be used for buffers that are not secured for DRM * but still need to be protected from screen captures */ - GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00080000, + GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00400000, + + /* Legacy heaps - these heaps are no-ops so we are making them zero + * The flags need to be around to compile certain HALs which have + * not cleaned up the code + */ + GRALLOC_USAGE_PRIVATE_ADSP_HEAP = 0x0, + GRALLOC_USAGE_PRIVATE_SMI_HEAP = 0x0, }; enum { @@ -98,12 +91,12 @@ enum { GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 0x080000001, }; +#define GRALLOC_HEAP_MASK (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\ + GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |\ + GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |\ + GRALLOC_USAGE_PRIVATE_MM_HEAP |\ + GRALLOC_USAGE_PRIVATE_CAMERA_HEAP) -#define INTERLACE_MASK 0x80 -#define S3D_FORMAT_MASK 0xFF000 -#define DEVICE_PMEM "/dev/pmem" -#define DEVICE_PMEM_ADSP "/dev/pmem_adsp" -#define DEVICE_PMEM_SMIPOOL "/dev/pmem_smipool" /*****************************************************************************/ enum { /* OEM specific HAL formats */ diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp index 80f448f..8af5a96 100644 --- a/libgralloc/ionalloc.cpp +++ b/libgralloc/ionalloc.cpp @@ -27,7 +27,7 @@ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - +#define DEBUG 0 #include #include #include @@ -118,9 +118,7 @@ int IonAlloc::alloc_buffer(alloc_data& data) return err; } - if(!(data.flags & ION_SECURE) && - !(data.allocType & private_handle_t::PRIV_FLAGS_NOT_MAPPED)) { - + if(!(data.flags & ION_SECURE)) { base = mmap(0, ionAllocData.len, PROT_READ|PROT_WRITE, MAP_SHARED, fd_data.fd, 0); if(base == MAP_FAILED) { @@ -144,7 +142,7 @@ int IonAlloc::alloc_buffer(alloc_data& data) data.base = base; data.fd = fd_data.fd; ioctl(mIonFd, ION_IOC_FREE, &handle_data); - ALOGD("ion: Allocated buffer base:%p size:%d fd:%d", + ALOGD_IF(DEBUG, "ion: Allocated buffer base:%p size:%d fd:%d", data.base, ionAllocData.len, data.fd); return 0; } @@ -153,7 +151,7 @@ int IonAlloc::alloc_buffer(alloc_data& data) int IonAlloc::free_buffer(void* base, size_t size, int offset, int fd) { Locker::Autolock _l(mLock); - ALOGD("ion: Freeing buffer base:%p size:%d fd:%d", + ALOGD_IF(DEBUG, "ion: Freeing buffer base:%p size:%d fd:%d", base, size, fd); int err = 0; err = open_device(); @@ -181,10 +179,10 @@ int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) *pBase = base; if(base == MAP_FAILED) { err = -errno; - ALOGD("ion: Failed to map memory in the client: %s", + ALOGE("ion: Failed to map memory in the client: %s", strerror(errno)); } else { - ALOGD("ion: Mapped buffer base:%p size:%d offset:%d fd:%d", + ALOGD_IF(DEBUG, "ion: Mapped buffer base:%p size:%d offset:%d fd:%d", base, size, offset, fd); } return err; @@ -192,7 +190,7 @@ int IonAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) int IonAlloc::unmap_buffer(void *base, size_t size, int offset) { - ALOGD("ion: Unmapping buffer base:%p size:%d", base, size); + ALOGD_IF(DEBUG, "ion: Unmapping buffer base:%p size:%d", base, size); int err = 0; if(munmap(base, size)) { err = -errno; diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp index 4249f3f..99f9f08 100644 --- a/libgralloc/mapper.cpp +++ b/libgralloc/mapper.cpp @@ -44,15 +44,14 @@ #include "memalloc.h" using namespace gralloc; -using android::sp; /*****************************************************************************/ // Return the type of allocator - // these are used for mapping/unmapping -static sp getAllocator(int flags) +static IMemAlloc* getAllocator(int flags) { - sp memalloc; - sp alloc_ctrl = IAllocController::getInstance(true); + IMemAlloc* memalloc; + IAllocController* alloc_ctrl = IAllocController::getInstance(); memalloc = alloc_ctrl->getAllocator(flags); return memalloc; } @@ -66,7 +65,7 @@ static int gralloc_map(gralloc_module_t const* module, if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) && !(hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER)) { size_t size = hnd->size; - sp memalloc = getAllocator(hnd->flags) ; + IMemAlloc* memalloc = getAllocator(hnd->flags) ; int err = memalloc->map_buffer(&mappedAddress, size, hnd->offset, hnd->fd); if(err) { @@ -98,7 +97,7 @@ static int gralloc_unmap(gralloc_module_t const* module, int err = -EINVAL; void* base = (void*)hnd->base; size_t size = hnd->size; - sp memalloc = getAllocator(hnd->flags) ; + IMemAlloc* memalloc = getAllocator(hnd->flags) ; if(memalloc != NULL) err = memalloc->unmap_buffer(base, size, hnd->offset); if (err) { @@ -284,7 +283,7 @@ int gralloc_unlock(gralloc_module_t const* module, if (hnd->flags & private_handle_t::PRIV_FLAGS_NEEDS_FLUSH) { int err; - sp memalloc = getAllocator(hnd->flags) ; + IMemAlloc* memalloc = getAllocator(hnd->flags) ; err = memalloc->clean_buffer((void*)hnd->base, hnd->size, hnd->offset, hnd->fd); ALOGE_IF(err < 0, "cannot flush handle %p (offs=%x len=%x, flags = 0x%x) err=%s\n", @@ -328,25 +327,7 @@ int gralloc_perform(struct gralloc_module_t const* module, private_handle_t::sNumFds, private_handle_t::sNumInts); hnd->magic = private_handle_t::sMagic; hnd->fd = fd; - unsigned int contigFlags = GRALLOC_USAGE_PRIVATE_ADSP_HEAP | - GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP | - GRALLOC_USAGE_PRIVATE_SMI_HEAP; - - if (memoryFlags & contigFlags) { - // check if the buffer is a pmem buffer - pmem_region region; - if (ioctl(fd, PMEM_GET_SIZE, ®ion) < 0) - hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; - else - hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM | - private_handle_t::PRIV_FLAGS_DO_NOT_FLUSH; - } else { - if (memoryFlags & GRALLOC_USAGE_PRIVATE_ION) - hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; - else - hnd->flags = private_handle_t::PRIV_FLAGS_USES_ASHMEM; - } - + hnd->flags = private_handle_t::PRIV_FLAGS_USES_ION; hnd->size = size; hnd->offset = offset; hnd->base = intptr_t(base) + offset; diff --git a/libgralloc/memalloc.h b/libgralloc/memalloc.h index 349078d..af509fb 100644 --- a/libgralloc/memalloc.h +++ b/libgralloc/memalloc.h @@ -31,7 +31,6 @@ #define GRALLOC_MEMALLOC_H #include -#include namespace gralloc { @@ -47,7 +46,7 @@ struct alloc_data { int allocType; }; -class IMemAlloc : public android::RefBase { +class IMemAlloc { public: // Allocate buffer - fill in the alloc_data diff --git a/libgralloc/pmem_bestfit_alloc.cpp b/libgralloc/pmem_bestfit_alloc.cpp deleted file mode 100644 index 3b91dec..0000000 --- a/libgralloc/pmem_bestfit_alloc.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. - * - * 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. - */ - -#include - -#include "pmem_bestfit_alloc.h" - - -// align all the memory blocks on a cache-line boundary -const int SimpleBestFitAllocator::kMemoryAlign = 32; - -SimpleBestFitAllocator::SimpleBestFitAllocator() -: mHeapSize(0) -{ -} - -SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size) -: mHeapSize(0) -{ - setSize(size); -} - -SimpleBestFitAllocator::~SimpleBestFitAllocator() -{ - while(!mList.isEmpty()) { - delete mList.remove(mList.head()); - } -} - -ssize_t SimpleBestFitAllocator::setSize(size_t size) -{ - Locker::Autolock _l(mLock); - if (mHeapSize != 0) return -EINVAL; - size_t pagesize = getpagesize(); - mHeapSize = ((size + pagesize-1) & ~(pagesize-1)); - chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign); - mList.insertHead(node); - return size; -} - -size_t SimpleBestFitAllocator::size() const -{ - return mHeapSize; -} - -ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags) -{ - Locker::Autolock _l(mLock); - if (mHeapSize == 0) return -EINVAL; - ssize_t offset = alloc(size, flags); - return offset; -} - -ssize_t SimpleBestFitAllocator::deallocate(size_t offset) -{ - Locker::Autolock _l(mLock); - if (mHeapSize == 0) return -EINVAL; - chunk_t const * const freed = dealloc(offset); - if (freed) { - return 0; - } - return -ENOENT; -} - -ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags) -{ - if (size == 0) { - return 0; - } - size = (size + kMemoryAlign-1) / kMemoryAlign; - chunk_t* free_chunk = 0; - chunk_t* cur = mList.head(); - - size_t pagesize = getpagesize(); - while (cur) { - int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ; - - // best fit - if (cur->free && (cur->size >= (size+extra))) { - if ((!free_chunk) || (cur->size < free_chunk->size)) { - free_chunk = cur; - } - if (cur->size == size) { - break; - } - } - cur = cur->next; - } - - if (free_chunk) { - const size_t free_size = free_chunk->size; - free_chunk->free = 0; - free_chunk->size = size; - if (free_size > size) { - int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ; - if (extra) { - chunk_t* split = new chunk_t(free_chunk->start, extra); - free_chunk->start += extra; - mList.insertBefore(free_chunk, split); - } - - ALOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)), - "page is not aligned!!!"); - - const ssize_t tail_free = free_size - (size+extra); - if (tail_free > 0) { - chunk_t* split = new chunk_t( - free_chunk->start + free_chunk->size, tail_free); - mList.insertAfter(free_chunk, split); - } - } - return (free_chunk->start)*kMemoryAlign; - } - // we are out of PMEM. Print pmem stats - // check if there is any leak or fragmentation - - ALOGD (" Out of PMEM. Dumping PMEM stats for debugging"); - ALOGD (" ------------- PRINT PMEM STATS --------------"); - - cur = mList.head(); - static uint32_t node_count; - static uint64_t allocated, free_space; - - while (cur) { - ALOGD (" Node %d -> Start Address : %u Size %u Free info %d",\ - node_count++, cur->start, cur->size, cur->free); - - // if cur-> free is 1 , the node is free - // calculate the total allocated and total free stats also - - if (cur->free) - free_space += cur->size; - else - allocated += cur->size; - // read next node - cur = cur->next; - } - ALOGD (" Total Allocated: %l Total Free: %l", allocated, free_space ); - - node_count = 0; - allocated = 0; - free_space = 0; - ALOGD ("----------------------------------------------"); - return -ENOMEM; -} - -SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start) -{ - start = start / kMemoryAlign; - chunk_t* cur = mList.head(); - while (cur) { - if (cur->start == start) { - ALOG_FATAL_IF(cur->free, - "block at offset 0x%08lX of size 0x%08lX already freed", - cur->start*kMemoryAlign, cur->size*kMemoryAlign); - - // merge freed blocks together - chunk_t* freed = cur; - cur->free = 1; - do { - chunk_t* const p = cur->prev; - chunk_t* const n = cur->next; - if (p && (p->free || !cur->size)) { - freed = p; - p->size += cur->size; - mList.remove(cur); - delete cur; - } - cur = n; - } while (cur && cur->free); - - ALOG_FATAL_IF(!freed->free, - "freed block at offset 0x%08lX of size 0x%08lX is not free!", - freed->start * kMemoryAlign, freed->size * kMemoryAlign); - - return freed; - } - cur = cur->next; - } - return 0; -} diff --git a/libgralloc/pmem_bestfit_alloc.h b/libgralloc/pmem_bestfit_alloc.h deleted file mode 100644 index 4346ec3..0000000 --- a/libgralloc/pmem_bestfit_alloc.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved. - * - * 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 GRALLOC_ALLOCATOR_H_ -#define GRALLOC_ALLOCATOR_H_ - -#include -#include - -#include "gr.h" -#include "pmemalloc.h" - -// ---------------------------------------------------------------------------- - -/* - * A simple templatized doubly linked-list implementation - */ -template -class LinkedList -{ - NODE* mFirst; - NODE* mLast; - - public: - LinkedList() : mFirst(0), mLast(0) { } - bool isEmpty() const { return mFirst == 0; } - NODE const* head() const { return mFirst; } - NODE* head() { return mFirst; } - NODE const* tail() const { return mLast; } - NODE* tail() { return mLast; } - - void insertAfter(NODE* node, NODE* newNode) { - newNode->prev = node; - newNode->next = node->next; - if (node->next == 0) mLast = newNode; - else node->next->prev = newNode; - node->next = newNode; - } - - void insertBefore(NODE* node, NODE* newNode) { - newNode->prev = node->prev; - newNode->next = node; - if (node->prev == 0) mFirst = newNode; - else node->prev->next = newNode; - node->prev = newNode; - } - - void insertHead(NODE* newNode) { - if (mFirst == 0) { - mFirst = mLast = newNode; - newNode->prev = newNode->next = 0; - } else { - newNode->prev = 0; - newNode->next = mFirst; - mFirst->prev = newNode; - mFirst = newNode; - } - } - - void insertTail(NODE* newNode) { - if (mLast == 0) { - insertHead(newNode); - } else { - newNode->prev = mLast; - newNode->next = 0; - mLast->next = newNode; - mLast = newNode; - } - } - - NODE* remove(NODE* node) { - if (node->prev == 0) mFirst = node->next; - else node->prev->next = node->next; - if (node->next == 0) mLast = node->prev; - else node->next->prev = node->prev; - return node; - } -}; - -class SimpleBestFitAllocator : public gralloc::PmemUserspaceAlloc::Allocator -{ - public: - - SimpleBestFitAllocator(); - SimpleBestFitAllocator(size_t size); - virtual ~SimpleBestFitAllocator(); - - virtual ssize_t setSize(size_t size); - - virtual ssize_t allocate(size_t size, uint32_t flags = 0); - virtual ssize_t deallocate(size_t offset); - virtual size_t size() const; - - private: - struct chunk_t { - chunk_t(size_t start, size_t size) - : start(start), size(size), free(1), prev(0), next(0) { - } - size_t start; - size_t size : 28; - int free : 4; - mutable chunk_t* prev; - mutable chunk_t* next; - }; - - ssize_t alloc(size_t size, uint32_t flags); - chunk_t* dealloc(size_t start); - - static const int kMemoryAlign; - mutable Locker mLock; - LinkedList mList; - size_t mHeapSize; -}; -#endif /* GRALLOC_ALLOCATOR_H_ */ diff --git a/libgralloc/pmemalloc.cpp b/libgralloc/pmemalloc.cpp deleted file mode 100644 index 2286fb0..0000000 --- a/libgralloc/pmemalloc.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/* - * 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. - */ -#include -#include -#include -#include -#include -#include -#include -#include "gralloc_priv.h" -#include "pmemalloc.h" -#include "pmem_bestfit_alloc.h" - -using namespace gralloc; -using android::sp; - -// Common functions between userspace -// and kernel allocators -static int getPmemTotalSize(int fd, size_t* size) -{ - //XXX: 7x27 - int err = 0; - pmem_region region; - if (ioctl(fd, PMEM_GET_TOTAL_SIZE, ®ion)) { - err = -errno; - } else { - *size = region.len; - } - return err; -} - -static int getOpenFlags(bool uncached) -{ - if(uncached) - return O_RDWR | O_SYNC; - else - return O_RDWR; -} - -static int connectPmem(int fd, int master_fd) { - if (ioctl(fd, PMEM_CONNECT, master_fd)) - return -errno; - return 0; -} - -static int mapSubRegion(int fd, int offset, size_t size) { - struct pmem_region sub = { offset, size }; - if (ioctl(fd, PMEM_MAP, &sub)) - return -errno; - return 0; -} - -static int unmapSubRegion(int fd, int offset, size_t size) { - struct pmem_region sub = { offset, size }; - if (ioctl(fd, PMEM_UNMAP, &sub)) - return -errno; - return 0; -} - -static int alignPmem(int fd, size_t size, int align) { - struct pmem_allocation allocation; - allocation.size = size; - allocation.align = align; - if (ioctl(fd, PMEM_ALLOCATE_ALIGNED, &allocation)) - return -errno; - return 0; -} - -static int cleanPmem(void *base, size_t size, int offset, int fd) { - struct pmem_addr pmem_addr; - pmem_addr.vaddr = (unsigned long) base; - pmem_addr.offset = offset; - pmem_addr.length = size; - if (ioctl(fd, PMEM_CLEAN_INV_CACHES, &pmem_addr)) - return -errno; - return 0; -} - -//-------------- PmemUserspaceAlloc-----------------------// -PmemUserspaceAlloc::PmemUserspaceAlloc() -{ - mPmemDev = DEVICE_PMEM; - mMasterFd = FD_INIT; - mAllocator = new SimpleBestFitAllocator(); - pthread_mutex_init(&mLock, NULL); -} - -PmemUserspaceAlloc::~PmemUserspaceAlloc() -{ -} - -int PmemUserspaceAlloc::init_pmem_area_locked() -{ - ALOGD("%s: Opening master pmem FD", __FUNCTION__); - int err = 0; - int fd = open(mPmemDev, O_RDWR, 0); - if (fd >= 0) { - size_t size = 0; - err = getPmemTotalSize(fd, &size); - ALOGD("%s: Total pmem size: %d", __FUNCTION__, size); - if (err < 0) { - ALOGE("%s: PMEM_GET_TOTAL_SIZE failed (%d), limp mode", mPmemDev, - err); - size = 8<<20; // 8 MiB - } - mAllocator->setSize(size); - - void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, - 0); - if (base == MAP_FAILED) { - err = -errno; - ALOGE("%s: Failed to map pmem master fd: %s", mPmemDev, - strerror(errno)); - base = 0; - close(fd); - fd = -1; - } else { - mMasterFd = fd; - mMasterBase = base; - } - } else { - err = -errno; - ALOGE("%s: Failed to open pmem device: %s", mPmemDev, - strerror(errno)); - } - return err; -} - -int PmemUserspaceAlloc::init_pmem_area() -{ - pthread_mutex_lock(&mLock); - int err = mMasterFd; - if (err == FD_INIT) { - // first time, try to initialize pmem - ALOGD("%s: Initializing pmem area", __FUNCTION__); - err = init_pmem_area_locked(); - if (err) { - ALOGE("%s: failed to initialize pmem area", mPmemDev); - mMasterFd = err; - } - } else if (err < 0) { - // pmem couldn't be initialized, never use it - } else { - // pmem OK - err = 0; - } - pthread_mutex_unlock(&mLock); - return err; - -} - -int PmemUserspaceAlloc::alloc_buffer(alloc_data& data) -{ - int err = init_pmem_area(); - if (err == 0) { - void* base = mMasterBase; - size_t size = data.size; - int offset = mAllocator->allocate(size); - if (offset < 0) { - // no more pmem memory - ALOGE("%s: No more pmem available", mPmemDev); - err = -ENOMEM; - } else { - int openFlags = getOpenFlags(data.uncached); - - // now create the "sub-heap" - int fd = open(mPmemDev, openFlags, 0); - err = fd < 0 ? fd : 0; - - // and connect to it - if (err == 0) - err = connectPmem(fd, mMasterFd); - - // and make it available to the client process - if (err == 0) - err = mapSubRegion(fd, offset, size); - - if (err < 0) { - ALOGE("%s: Failed to initialize pmem sub-heap: %d", mPmemDev, - err); - close(fd); - mAllocator->deallocate(offset); - fd = -1; - } else { - ALOGD("%s: Allocated buffer base:%p size:%d offset:%d fd:%d", - mPmemDev, base, size, offset, fd); - memset((char*)base + offset, 0, size); - //Clean cache before flushing to ensure pmem is properly flushed - err = clean_buffer((void*)((intptr_t) base + offset), size, offset, fd); - if (err < 0) { - ALOGE("cleanPmem failed: (%s)", strerror(errno)); - } - cacheflush(intptr_t(base) + offset, intptr_t(base) + offset + size, 0); - data.base = base; - data.offset = offset; - data.fd = fd; - } - } - } - return err; - -} - -int PmemUserspaceAlloc::free_buffer(void* base, size_t size, int offset, int fd) -{ - ALOGD("%s: Freeing buffer base:%p size:%d offset:%d fd:%d", - mPmemDev, base, size, offset, fd); - int err = 0; - if (fd >= 0) { - int err = unmapSubRegion(fd, offset, size); - ALOGE_IF(err<0, "PMEM_UNMAP failed (%s), fd=%d, sub.offset=%u, " - "sub.size=%u", strerror(errno), fd, offset, size); - if (err == 0) { - // we can't deallocate the memory in case of UNMAP failure - // because it would give that process access to someone else's - // surfaces, which would be a security breach. - mAllocator->deallocate(offset); - } - close(fd); - } - return err; -} - -int PmemUserspaceAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) -{ - int err = 0; - size += offset; - void *base = mmap(0, size, PROT_READ| PROT_WRITE, - MAP_SHARED, fd, 0); - *pBase = base; - if(base == MAP_FAILED) { - err = -errno; - ALOGE("%s: Failed to map buffer size:%d offset:%d fd:%d Error: %s", - mPmemDev, size, offset, fd, strerror(errno)); - } else { - ALOGD("%s: Mapped buffer base:%p size:%d offset:%d fd:%d", - mPmemDev, base, size, offset, fd); - } - return err; - -} - -int PmemUserspaceAlloc::unmap_buffer(void *base, size_t size, int offset) -{ - int err = 0; - //pmem hack - base = (void*)(intptr_t(base) - offset); - size += offset; - ALOGD("%s: Unmapping buffer base:%p size:%d offset:%d", - mPmemDev , base, size, offset); - if (munmap(base, size) < 0) { - err = -errno; - ALOGE("%s: Failed to unmap memory at %p :%s", - mPmemDev, base, strerror(errno)); - - } - - return err; -} - -int PmemUserspaceAlloc::clean_buffer(void *base, size_t size, int offset, int fd) -{ - return cleanPmem(base, size, offset, fd); -} - - -//-------------- PmemKernelAlloc-----------------------// - -PmemKernelAlloc::PmemKernelAlloc(const char* pmemdev) : - mPmemDev(pmemdev) -{ -} - -PmemKernelAlloc::~PmemKernelAlloc() -{ -} - -int PmemKernelAlloc::alloc_buffer(alloc_data& data) -{ - int err, offset = 0; - int openFlags = getOpenFlags(data.uncached); - int size = data.size; - - int fd = open(mPmemDev, openFlags, 0); - if (fd < 0) { - err = -errno; - ALOGE("%s: Error opening %s", __FUNCTION__, mPmemDev); - return err; - } - - if (data.align == 8192) { - // Tile format buffers need physical alignment to 8K - // Default page size does not need this ioctl - err = alignPmem(fd, size, 8192); - if (err < 0) { - ALOGE("alignPmem failed"); - } - } - void* base = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - if (base == MAP_FAILED) { - err = -errno; - ALOGE("%s: failed to map pmem fd: %s", mPmemDev, - strerror(errno)); - close(fd); - return err; - } - memset(base, 0, size); - clean_buffer((void*)((intptr_t) base + offset), size, offset, fd); - data.base = base; - data.offset = 0; - data.fd = fd; - ALOGD("%s: Allocated buffer base:%p size:%d fd:%d", - mPmemDev, base, size, fd); - return 0; - -} - -int PmemKernelAlloc::free_buffer(void* base, size_t size, int offset, int fd) -{ - ALOGD("%s: Freeing buffer base:%p size:%d fd:%d", - mPmemDev, base, size, fd); - - int err = unmap_buffer(base, size, offset); - close(fd); - return err; -} - -int PmemKernelAlloc::map_buffer(void **pBase, size_t size, int offset, int fd) -{ - int err = 0; - void *base = mmap(0, size, PROT_READ| PROT_WRITE, - MAP_SHARED, fd, 0); - *pBase = base; - if(base == MAP_FAILED) { - err = -errno; - ALOGE("%s: Failed to map memory in the client: %s", - mPmemDev, strerror(errno)); - } else { - ALOGD("%s: Mapped buffer base:%p size:%d, fd:%d", - mPmemDev, base, size, fd); - } - return err; - -} - -int PmemKernelAlloc::unmap_buffer(void *base, size_t size, int offset) -{ - int err = 0; - if (munmap(base, size)) { - err = -errno; - ALOGW("%s: Error unmapping memory at %p: %s", - mPmemDev, base, strerror(err)); - } - return err; - -} -int PmemKernelAlloc::clean_buffer(void *base, size_t size, int offset, int fd) -{ - return cleanPmem(base, size, offset, fd); -} - diff --git a/libgralloc/pmemalloc.h b/libgralloc/pmemalloc.h deleted file mode 100644 index 82794ec..0000000 --- a/libgralloc/pmemalloc.h +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 GRALLOC_PMEMALLOC_H -#define GRALLOC_PMEMALLOC_H - -#include -#include -#include "memalloc.h" - -namespace gralloc { -class PmemUserspaceAlloc : public IMemAlloc { - - public: - class Allocator: public android::RefBase { - public: - virtual ~Allocator() {}; - virtual ssize_t setSize(size_t size) = 0; - virtual size_t size() const = 0; - virtual ssize_t allocate(size_t size, uint32_t flags = 0) = 0; - virtual ssize_t deallocate(size_t offset) = 0; - }; - - virtual int alloc_buffer(alloc_data& data); - - virtual int free_buffer(void *base, size_t size, - int offset, int fd); - - virtual int map_buffer(void **pBase, size_t size, - int offset, int fd); - - virtual int unmap_buffer(void *base, size_t size, - int offset); - - virtual int clean_buffer(void*base, size_t size, - int offset, int fd); - - PmemUserspaceAlloc(); - - ~PmemUserspaceAlloc(); - - private: - int mMasterFd; - void* mMasterBase; - const char* mPmemDev; - android::sp mAllocator; - pthread_mutex_t mLock; - int init_pmem_area(); - int init_pmem_area_locked(); - -}; - -class PmemKernelAlloc : public IMemAlloc { - - public: - virtual int alloc_buffer(alloc_data& data); - - virtual int free_buffer(void *base, size_t size, - int offset, int fd); - - virtual int map_buffer(void **pBase, size_t size, - int offset, int fd); - - virtual int unmap_buffer(void *base, size_t size, - int offset); - - virtual int clean_buffer(void*base, size_t size, - int offset, int fd); - - PmemKernelAlloc(const char* device); - - ~PmemKernelAlloc(); - private: - const char* mPmemDev; - - -}; - -} -#endif /* GRALLOC_PMEMALLOC_H */ diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp old mode 100755 new mode 100644 diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h old mode 100755 new mode 100644 diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h index caf0437..60ed8fe 100644 --- a/liboverlay/overlayMem.h +++ b/liboverlay/overlayMem.h @@ -94,12 +94,11 @@ private: uint32_t mNumBuffers; /* gralloc alloc controller */ - android::sp mAlloc; + gralloc::IAllocController* mAlloc; }; //-------------------Inlines----------------------------------- -using android::sp; using gralloc::IMemAlloc; using gralloc::alloc_data; @@ -109,7 +108,7 @@ inline OvMem::OvMem() { mAllocType = 0; mBufSz = 0; mNumBuffers = 0; - mAlloc = gralloc::IAllocController::getInstance(false); + mAlloc = gralloc::IAllocController::getInstance(); } inline OvMem::~OvMem() { } @@ -121,7 +120,6 @@ inline bool OvMem::open(uint32_t numbufs, int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP; if(isSecure) { allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP; - allocFlags |= GRALLOC_USAGE_PRIVATE_DO_NOT_MAP; allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER; } @@ -138,12 +136,12 @@ inline bool OvMem::open(uint32_t numbufs, data.align = getpagesize(); data.uncached = true; - err = mAlloc->allocate(data, allocFlags, 0); + err = mAlloc->allocate(data, allocFlags); //see if we can fallback to other heap //we can try MM_HEAP once if it's not secure playback if (err != 0 && !isSecure) { allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP; - err = mAlloc->allocate(data, allocFlags, 0); + err = mAlloc->allocate(data, allocFlags); if (err != 0) { ALOGE(" could not allocate from fallback heap"); return false; @@ -169,7 +167,7 @@ inline bool OvMem::close() return true; } - sp memalloc = mAlloc->getAllocator(mAllocType); + IMemAlloc* memalloc = mAlloc->getAllocator(mAllocType); ret = memalloc->free_buffer(mBaseAddr, mBufSz * mNumBuffers, 0, mFd); if (ret != 0) { ALOGE("OvMem: error freeing buffer"); diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h index cbcb05a..f3d5141 100644 --- a/liboverlay/pipes/overlayGenPipe.h +++ b/liboverlay/pipes/overlayGenPipe.h @@ -182,10 +182,6 @@ inline bool GenericPipe::setSource( const utils::PipeArgs& args) { utils::PipeArgs newargs(args); - //Interlace video handling. - if(newargs.whf.format & INTERLACE_MASK) { - setMdpFlags(newargs.mdpFlags, utils::OV_MDP_DEINTERLACE); - } utils::Whf whf(newargs.whf); //Extract HAL format from lower bytes. Deinterlace if interlaced. whf.format = utils::getColorFormat(whf.format); diff --git a/libqdutils/idle_invalidator.cpp b/libqdutils/idle_invalidator.cpp old mode 100755 new mode 100644