diff options
Diffstat (limited to 'msm8909/libhwcomposer/hwc.cpp')
-rw-r--r-- | msm8909/libhwcomposer/hwc.cpp | 977 |
1 files changed, 0 insertions, 977 deletions
diff --git a/msm8909/libhwcomposer/hwc.cpp b/msm8909/libhwcomposer/hwc.cpp deleted file mode 100644 index c6a7e0a6..00000000 --- a/msm8909/libhwcomposer/hwc.cpp +++ /dev/null @@ -1,977 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * Copyright (C) 2012-2016, The Linux Foundation. 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 ATRACE_TAG (ATRACE_TAG_GRAPHICS | ATRACE_TAG_HAL) -#include <fcntl.h> -#include <errno.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> -#include <EGL/egl.h> -#include <utils/Trace.h> -#include <sys/ioctl.h> -#include <overlay.h> -#include <overlayRotator.h> -#include <overlayWriteback.h> -#include <mdp_version.h> -#include "hwc_utils.h" -#include "hwc_fbupdate.h" -#include "hwc_mdpcomp.h" -#include "hwc_dump_layers.h" -#include "hdmi.h" -#include "hwc_copybit.h" -#include "hwc_ad.h" -#include "profiler.h" -#include "hwc_virtual.h" -#include "hwc_qdcm.h" - -using namespace qhwc; -using namespace overlay; -using namespace qQdcm; - -#define VSYNC_DEBUG 0 -#define POWER_MODE_DEBUG 1 - -static int hwc_device_open(const struct hw_module_t* module, - const char* name, - struct hw_device_t** device); - -static struct hw_module_methods_t hwc_module_methods = { - .open = hwc_device_open -}; - -static void reset_panel(struct hwc_composer_device_1* dev); - -hwc_module_t HAL_MODULE_INFO_SYM = { - .common = { - .tag = HARDWARE_MODULE_TAG, - .version_major = 2, - .version_minor = 0, - .id = HWC_HARDWARE_MODULE_ID, - .name = "Qualcomm Hardware Composer Module", - .author = "CodeAurora Forum", - .methods = &hwc_module_methods, - .dso = 0, - .reserved = {0}, - } -}; - -/* - * Save callback functions registered to HWC - */ -static void hwc_registerProcs(struct hwc_composer_device_1* dev, - hwc_procs_t const* procs) -{ - ALOGI("%s", __FUNCTION__); - hwc_context_t* ctx = (hwc_context_t*)(dev); - if(!ctx) { - ALOGE("%s: Invalid context", __FUNCTION__); - return; - } - ctx->proc = procs; - - // Now that we have the functions needed, kick off - // the uevent & vsync threads - init_uevent_thread(ctx); - init_vsync_thread(ctx); -} - -static void setPaddingRound(hwc_context_t *ctx, int numDisplays, - hwc_display_contents_1_t** displays) { - ctx->isPaddingRound = false; - for(int i = 0; i < numDisplays; i++) { - hwc_display_contents_1_t *list = displays[i]; - if (LIKELY(list && list->numHwLayers > 0)) { - if((ctx->mPrevHwLayerCount[i] == 1 or - ctx->mPrevHwLayerCount[i] == 0) and - (list->numHwLayers > 1)) { - /* If the previous cycle for dpy 'i' has 0 AppLayers and the - * current cycle has atleast 1 AppLayer, padding round needs - * to be invoked in current cycle on all the active displays - * to free up the resources. - */ - ctx->isPaddingRound = true; - } - ctx->mPrevHwLayerCount[i] = (int)list->numHwLayers; - } else { - ctx->mPrevHwLayerCount[i] = 0; - } - } -} - -/* Based on certain conditions, isPaddingRound will be set - * to make this function self-contained */ -static void setDMAState(hwc_context_t *ctx, int numDisplays, - hwc_display_contents_1_t** displays) { - - if(ctx->mRotMgr->getNumActiveSessions() == 0) - Overlay::setDMAMode(Overlay::DMA_LINE_MODE); - - for(int dpy = 0; dpy < numDisplays; dpy++) { - hwc_display_contents_1_t *list = displays[dpy]; - if (LIKELY(list && list->numHwLayers > 0)) { - for(size_t layerIndex = 0; layerIndex < list->numHwLayers; - layerIndex++) { - if(list->hwLayers[layerIndex].compositionType != - HWC_FRAMEBUFFER_TARGET) - { - hwc_layer_1_t const* layer = &list->hwLayers[layerIndex]; - private_handle_t *hnd = (private_handle_t *)layer->handle; - - /* If a layer requires rotation, set the DMA state - * to BLOCK_MODE */ - - if (canUseRotator(ctx, dpy) && - (has90Transform(layer) || getRotDownscale(ctx, layer)) - && isRotationDoable(ctx, hnd)) { - if(not (ctx->mOverlay->isDMAMultiplexingSupported() && - dpy)) { - if(ctx->mOverlay->isPipeTypeAttached( - overlay::utils::OV_MDP_PIPE_DMA)) - ctx->isPaddingRound = true; - } - Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); - } - } - } - if(dpy) { - /* Uncomment the below code for testing purpose. - Assuming the orientation value is in terms of HAL_TRANSFORM, - this needs mapping to HAL, if its in different convention */ - - /* char value[PROPERTY_VALUE_MAX]; - property_get("sys.ext_orientation", value, "0"); - ctx->mExtOrientation = atoi(value);*/ - - if(ctx->mExtOrientation || ctx->mBufferMirrorMode) { - if(ctx->mOverlay->isPipeTypeAttached( - overlay::utils::OV_MDP_PIPE_DMA)) { - ctx->isPaddingRound = true; - } - Overlay::setDMAMode(Overlay::DMA_BLOCK_MODE); - } - } - } - } -} - -static void setNumActiveDisplays(hwc_context_t *ctx, int numDisplays, - hwc_display_contents_1_t** displays) { - - ctx->numActiveDisplays = 0; - for(int i = 0; i < numDisplays; i++) { - hwc_display_contents_1_t *list = displays[i]; - if (LIKELY(list && list->numHwLayers > 0)) { - /* For display devices like SSD and screenrecord, we cannot - * rely on isActive and connected attributes of dpyAttr to - * determine if the displaydevice is active. Hence in case if - * the layer-list is non-null and numHwLayers > 0, we assume - * the display device to be active. - */ - ctx->numActiveDisplays += 1; - } - } -} - -static bool validDisplay(int disp) { - switch(disp) { - case HWC_DISPLAY_PRIMARY: - case HWC_DISPLAY_EXTERNAL: - case HWC_DISPLAY_VIRTUAL: - return true; - break; - default: - return false; - } -} - -static void reset(hwc_context_t *ctx, int numDisplays, - hwc_display_contents_1_t** displays) { - - - for(int i = 0; i < numDisplays; i++) { - hwc_display_contents_1_t *list = displays[i]; - // XXX:SurfaceFlinger no longer guarantees that this - // value is reset on every prepare. However, for the layer - // cache we need to reset it. - // We can probably rethink that later on - if (LIKELY(list && list->numHwLayers > 0)) { - for(size_t j = 0; j < list->numHwLayers; j++) { - if(list->hwLayers[j].compositionType != HWC_FRAMEBUFFER_TARGET) - list->hwLayers[j].compositionType = HWC_FRAMEBUFFER; - } - - } - - if(ctx->mMDPComp[i]) - ctx->mMDPComp[i]->reset(); - if(ctx->mFBUpdate[i]) - ctx->mFBUpdate[i]->reset(); - if(ctx->mCopyBit[i]) - ctx->mCopyBit[i]->reset(); - if(ctx->mLayerRotMap[i]) - ctx->mLayerRotMap[i]->reset(); - } - - ctx->mAD->reset(); - -} - -static void scaleDisplayFrame(hwc_context_t *ctx, int dpy, - hwc_display_contents_1_t *list) { - uint32_t origXres = ctx->dpyAttr[dpy].xres; - uint32_t origYres = ctx->dpyAttr[dpy].yres; - uint32_t newXres = ctx->dpyAttr[dpy].xres_new; - uint32_t newYres = ctx->dpyAttr[dpy].yres_new; - float xresRatio = (float)origXres / (float)newXres; - float yresRatio = (float)origYres / (float)newYres; - for (size_t i = 0; i < list->numHwLayers; i++) { - hwc_layer_1_t *layer = &list->hwLayers[i]; - hwc_rect_t& displayFrame = layer->displayFrame; - uint32_t layerWidth = displayFrame.right - displayFrame.left; - uint32_t layerHeight = displayFrame.bottom - displayFrame.top; - displayFrame.left = (int)(xresRatio * (float)displayFrame.left); - displayFrame.top = (int)(yresRatio * (float)displayFrame.top); - displayFrame.right = (int)((float)displayFrame.left + - (float)layerWidth * xresRatio); - displayFrame.bottom = (int)((float)displayFrame.top + - (float)layerHeight * yresRatio); - } -} - -static int hwc_prepare_primary(hwc_composer_device_1 *dev, - hwc_display_contents_1_t *list) { - ATRACE_CALL(); - hwc_context_t* ctx = (hwc_context_t*)(dev); - const int dpy = HWC_DISPLAY_PRIMARY; - bool fbComp = false; - static int compStart = false; - if (!ctx->mBootAnimCompleted) - processBootAnimCompleted(ctx); - - if (LIKELY(list && (list->numHwLayers > 1 || - (ctx->mMDP.version < qdutils::MDP_V4_0 && compStart))) && - (ctx->dpyAttr[dpy].isActive || - ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) - && !ctx->dpyAttr[dpy].isPause) { - compStart = true; - - // When HDMI is primary we should rely on the first valid - // draw call in order to activate the display - if (!ctx->dpyAttr[dpy].isActive) { - // If the cable is connected after HWC initialization and before - // the UEvent thread is initialized then we will miss the ONLINE - // event. We need to update the display appropriately when we get - // the first valid frame. - int cableConnected = ctx->mHDMIDisplay->getConnectedState(); - if ((cableConnected == 1) && !ctx->dpyAttr[dpy].connected) { - qhwc::handle_online(ctx, dpy); - } - ctx->mHDMIDisplay->activateDisplay(); - ctx->dpyAttr[dpy].isActive = true; - } - - if (ctx->dpyAttr[dpy].customFBSize && - list->flags & HWC_GEOMETRY_CHANGED) - scaleDisplayFrame(ctx, dpy, list); - - reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); - setListStats(ctx, list, dpy); - - fbComp = (ctx->mMDPComp[dpy]->prepare(ctx, list) < 0); - - if (fbComp) { - const int fbZ = 0; - if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) { - ctx->mOverlay->clear(dpy); - ctx->mLayerRotMap[dpy]->clear(); - } - } - - if (ctx->mMDP.version < qdutils::MDP_V4_0) { - if(ctx->mCopyBit[dpy]) - ctx->mCopyBit[dpy]->prepare(ctx, list, dpy); - } - setGPUHint(ctx, list); - } - return 0; -} - -static int hwc_prepare_external(hwc_composer_device_1 *dev, - hwc_display_contents_1_t *list) { - ATRACE_CALL(); - hwc_context_t* ctx = (hwc_context_t*)(dev); - const int dpy = HWC_DISPLAY_EXTERNAL; - - if (LIKELY(list && list->numHwLayers > 1) && - ctx->dpyAttr[dpy].isActive && - ctx->dpyAttr[dpy].connected) { - reset_layer_prop(ctx, dpy, (int)list->numHwLayers - 1); - if(!ctx->dpyAttr[dpy].isPause) { - ctx->dpyAttr[dpy].isConfiguring = false; - setListStats(ctx, list, dpy); - if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) { - const int fbZ = 0; - if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) - { - ctx->mOverlay->clear(dpy); - ctx->mLayerRotMap[dpy]->clear(); - } - } - } else { - /* External Display is in Pause state. - * Mark all application layers as OVERLAY so that - * GPU will not compose. - */ - for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) { - hwc_layer_1_t *layer = &list->hwLayers[i]; - layer->compositionType = HWC_OVERLAY; - } - } - } - return 0; -} - -static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays, - hwc_display_contents_1_t** displays) -{ - int ret = 0; - hwc_context_t* ctx = (hwc_context_t*)(dev); - - if (ctx->mPanelResetStatus) { - ALOGW("%s: panel is in bad state. reset the panel", __FUNCTION__); - reset_panel(dev); - } - - //Will be unlocked at the end of set - ctx->mDrawLock.lock(); - setPaddingRound(ctx, (int)numDisplays, displays); - setDMAState(ctx, (int)numDisplays, displays); - setNumActiveDisplays(ctx, (int)numDisplays, displays); - reset(ctx, (int)numDisplays, displays); - - ctx->mOverlay->configBegin(); - ctx->mRotMgr->configBegin(); - overlay::Writeback::configBegin(); - - for (int32_t dpy = ((int32_t)numDisplays-1); dpy >=0 ; dpy--) { - hwc_display_contents_1_t *list = displays[dpy]; - resetROI(ctx, dpy); - switch(dpy) { - case HWC_DISPLAY_PRIMARY: - ret = hwc_prepare_primary(dev, list); - break; - case HWC_DISPLAY_EXTERNAL: - ret = hwc_prepare_external(dev, list); - break; - case HWC_DISPLAY_VIRTUAL: - if(ctx->mHWCVirtual) - ret = ctx->mHWCVirtual->prepare(dev, list); - break; - default: - ret = -EINVAL; - } - } - - ctx->mOverlay->configDone(); - ctx->mRotMgr->configDone(); - overlay::Writeback::configDone(); - // If VD list is deleted, mdp overlay pipe objects and writeback object - // are deleted as part of configDone functions. - // Proceed with HWCVirtualVDS object deletion. - if(ctx->mHWCVirtual) - ctx->mHWCVirtual->destroy(ctx, numDisplays, displays); - - return ret; -} - -static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy, - int event, int enable) -{ - ATRACE_CALL(); - int ret = 0; - hwc_context_t* ctx = (hwc_context_t*)(dev); - if(!validDisplay(dpy)) { - return -EINVAL; - } - - switch(event) { - case HWC_EVENT_VSYNC: - if (ctx->vstate.enable == enable) - break; - ret = hwc_vsync_control(ctx, dpy, enable); - if(ret == 0) - ctx->vstate.enable = !!enable; - ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed to %s", - (enable)?"ENABLED":"DISABLED"); - break; -#ifdef QTI_BSP - case HWC_EVENT_ORIENTATION: - if(dpy == HWC_DISPLAY_PRIMARY) { - Locker::Autolock _l(ctx->mDrawLock); - // store the primary display orientation - ctx->deviceOrientation = enable; - } - break; -#endif - default: - ret = -EINVAL; - } - return ret; -} - -static int hwc_setPowerMode(struct hwc_composer_device_1* dev, int dpy, - int mode) -{ - ATRACE_CALL(); - hwc_context_t* ctx = (hwc_context_t*)(dev); - int ret = 0, value = 0; - - Locker::Autolock _l(ctx->mDrawLock); - - if(!validDisplay(dpy)) { - return -EINVAL; - } - - ALOGD_IF(POWER_MODE_DEBUG, "%s: Setting mode %d on display: %d", - __FUNCTION__, mode, dpy); - - switch(mode) { - case HWC_POWER_MODE_OFF: - // free up all the overlay pipes in use - // when we get a blank for either display - // makes sure that all pipes are freed - ctx->mOverlay->configBegin(); - ctx->mOverlay->configDone(); - ctx->mRotMgr->clear(); - // If VDS is connected, do not clear WB object as it - // will end up detaching IOMMU. This is required - // to send black frame to WFD sink on power suspend. - // Note: With this change, we keep the WriteBack object - // alive on power suspend for AD use case. - value = FB_BLANK_POWERDOWN; - break; - case HWC_POWER_MODE_DOZE: - case HWC_POWER_MODE_DOZE_SUSPEND: - value = FB_BLANK_VSYNC_SUSPEND; - break; - case HWC_POWER_MODE_NORMAL: - value = FB_BLANK_UNBLANK; - break; - } - - switch(dpy) { - case HWC_DISPLAY_PRIMARY: - if(ctx->mHDMIDisplay->isHDMIPrimaryDisplay()) { - if(ctx->dpyAttr[dpy].connected) { - // When HDMI is connected as primary we clean up resources - // and call commit to generate a black frame on the interface. - // However, we do not call blank since we need the timing - // generator and HDMI core to remain turned on. - if((mode == HWC_POWER_MODE_OFF) && - (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd))) { - ALOGE("%s: display commit fail for %d", __FUNCTION__, dpy); - ret = -1; - } - } - } else { - if(ioctl(ctx->dpyAttr[dpy].fd, FBIOBLANK, value) < 0 ) { - ALOGE("%s: ioctl FBIOBLANK failed for Primary with error %s" - " value %d", __FUNCTION__, strerror(errno), value); - return -errno; - } - - if(mode == HWC_POWER_MODE_NORMAL) { - // Enable HPD here, as during bootup POWER_MODE_NORMAL is set - // when SF is completely initialized - ctx->mHDMIDisplay->setHPD(1); - } - - ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF); - } - //Deliberate fall through since there is no explicit power mode for - //virtual displays. - case HWC_DISPLAY_VIRTUAL: - if(ctx->dpyAttr[HWC_DISPLAY_VIRTUAL].connected) { - const int dpy = HWC_DISPLAY_VIRTUAL; - if(mode == HWC_POWER_MODE_OFF and - (not ctx->dpyAttr[dpy].isPause)) { - if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { - ALOGE("%s: displayCommit failed for virtual", __FUNCTION__); - ret = -1; - } - } - ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF); - } - break; - case HWC_DISPLAY_EXTERNAL: - if(mode == HWC_POWER_MODE_OFF) { - if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { - ALOGE("%s: displayCommit failed for external", __FUNCTION__); - ret = -1; - } - } - ctx->dpyAttr[dpy].isActive = not(mode == HWC_POWER_MODE_OFF); - break; - default: - return -EINVAL; - } - - ALOGD_IF(POWER_MODE_DEBUG, "%s: Done setting mode %d on display %d", - __FUNCTION__, mode, dpy); - return ret; -} - -static void reset_panel(struct hwc_composer_device_1* dev) -{ - int ret = 0; - hwc_context_t* ctx = (hwc_context_t*)(dev); - - if (!ctx->dpyAttr[HWC_DISPLAY_PRIMARY].isActive) { - ALOGD ("%s : Display OFF - Skip BLANK & UNBLANK", __FUNCTION__); - ctx->mPanelResetStatus = false; - return; - } - - ALOGD("%s: setting power mode off", __FUNCTION__); - ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_OFF); - if (ret < 0) { - ALOGE("%s: FBIOBLANK failed to BLANK: %s", __FUNCTION__, - strerror(errno)); - } - - ALOGD("%s: setting power mode normal and enabling vsync", __FUNCTION__); - ret = hwc_setPowerMode(dev, HWC_DISPLAY_PRIMARY, HWC_POWER_MODE_NORMAL); - if (ret < 0) { - ALOGE("%s: FBIOBLANK failed to UNBLANK : %s", __FUNCTION__, - strerror(errno)); - } - hwc_vsync_control(ctx, HWC_DISPLAY_PRIMARY, 1); - - ctx->mPanelResetStatus = false; -} - - -static int hwc_query(struct hwc_composer_device_1* dev, - int param, int* value) -{ - hwc_context_t* ctx = (hwc_context_t*)(dev); - int supported = HWC_DISPLAY_PRIMARY_BIT; - - switch (param) { - case HWC_BACKGROUND_LAYER_SUPPORTED: - // Not supported for now - value[0] = 0; - break; - case HWC_DISPLAY_TYPES_SUPPORTED: - if(ctx->mMDP.hasOverlay) { - supported |= HWC_DISPLAY_VIRTUAL_BIT; - if(!(qdutils::MDPVersion::getInstance().is8x26() || - qdutils::MDPVersion::getInstance().is8x16() || - qdutils::MDPVersion::getInstance().is8x39())) - supported |= HWC_DISPLAY_EXTERNAL_BIT; - } - value[0] = supported; - break; - case HWC_FORMAT_RB_SWAP: - value[0] = 1; - break; - case HWC_COLOR_FILL: - value[0] = 1; - break; - default: - return -EINVAL; - } - return 0; - -} - - -static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) { - ATRACE_CALL(); - int ret = 0; - const int dpy = HWC_DISPLAY_PRIMARY; - if (LIKELY(list) && ctx->dpyAttr[dpy].isActive - && !ctx->dpyAttr[dpy].isPause) { - size_t last = list->numHwLayers - 1; - hwc_layer_1_t *fbLayer = &list->hwLayers[last]; - int fd = -1; //FenceFD from the Copybit(valid in async mode) - bool copybitDone = false; - - if (ctx->mCopyBit[dpy]) { - if (ctx->mMDP.version < qdutils::MDP_V4_0) - copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); - else - fd = ctx->mMDPComp[dpy]->drawOverlap(ctx, list); - } - - if(list->numHwLayers > 1) - hwc_sync(ctx, list, dpy, fd); - - // Dump the layers for primary - if(ctx->mHwcDebug[dpy]) - ctx->mHwcDebug[dpy]->dumpLayers(list); - - if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { - ALOGE("%s: MDPComp draw failed", __FUNCTION__); - ret = -1; - } - - //TODO We dont check for SKIP flag on this layer because we need PAN - //always. Last layer is always FB - private_handle_t *hnd = (private_handle_t *)fbLayer->handle; - if(copybitDone && ((ctx->mMDP.version >= qdutils::MDP_V4_0) -#ifdef SUPPORT_BLIT_TO_FB - || (ctx->mMDP.version == qdutils::MDP_V3_0_5) -#endif - )) { - hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); - } - - if(isAbcInUse(ctx) == true) { - int index = ctx->listStats[dpy].renderBufIndexforABC; - hwc_layer_1_t *tempLayer = &list->hwLayers[index]; - hnd = (private_handle_t *)tempLayer->handle; - } - - if(hnd) { - if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { - ALOGE("%s: FBUpdate draw failed", __FUNCTION__); - ret = -1; - } - } - - int lSplit = getLeftSplit(ctx, dpy); - qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim( - ctx->listStats[dpy].lRoi.left, - ctx->listStats[dpy].lRoi.top, - ctx->listStats[dpy].lRoi.right - ctx->listStats[dpy].lRoi.left, - ctx->listStats[dpy].lRoi.bottom - ctx->listStats[dpy].lRoi.top); - - qhwc::ovutils::Dim rRoi = qhwc::ovutils::Dim( - ctx->listStats[dpy].rRoi.left - lSplit, - ctx->listStats[dpy].rRoi.top, - ctx->listStats[dpy].rRoi.right - ctx->listStats[dpy].rRoi.left, - ctx->listStats[dpy].rRoi.bottom - ctx->listStats[dpy].rRoi.top); - - if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd, lRoi, rRoi)) { - ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); - ret = -1; - } - - } - - closeAcquireFds(list); - return ret; -} - -static int hwc_set_external(hwc_context_t *ctx, - hwc_display_contents_1_t* list) -{ - ATRACE_CALL(); - int ret = 0; - - const int dpy = HWC_DISPLAY_EXTERNAL; - - if (LIKELY(list) && ctx->dpyAttr[dpy].isActive && - ctx->dpyAttr[dpy].connected && - !ctx->dpyAttr[dpy].isPause) { - size_t last = list->numHwLayers - 1; - hwc_layer_1_t *fbLayer = &list->hwLayers[last]; - int fd = -1; //FenceFD from the Copybit(valid in async mode) - bool copybitDone = false; - if(ctx->mCopyBit[dpy]) - copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd); - - if(list->numHwLayers > 1) - hwc_sync(ctx, list, dpy, fd); - - // Dump the layers for external - if(ctx->mHwcDebug[dpy]) - ctx->mHwcDebug[dpy]->dumpLayers(list); - - if (!ctx->mMDPComp[dpy]->draw(ctx, list)) { - ALOGE("%s: MDPComp draw failed", __FUNCTION__); - ret = -1; - } - - private_handle_t *hnd = (private_handle_t *)fbLayer->handle; - if(copybitDone) { - hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer(); - } - - if(hnd) { - if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) { - ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__); - ret = -1; - } - } - - if(!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) { - ALOGE("%s: display commit fail for %d dpy!", __FUNCTION__, dpy); - ret = -1; - } - } - - closeAcquireFds(list); - return ret; -} - -static int hwc_set(hwc_composer_device_1 *dev, - size_t numDisplays, - hwc_display_contents_1_t** displays) -{ - int ret = 0; - hwc_context_t* ctx = (hwc_context_t*)(dev); - for (int dpy = 0; dpy < (int)numDisplays; dpy++) { - hwc_display_contents_1_t* list = displays[dpy]; - switch(dpy) { - case HWC_DISPLAY_PRIMARY: - ret = hwc_set_primary(ctx, list); - break; - case HWC_DISPLAY_EXTERNAL: - ret = hwc_set_external(ctx, list); - break; - case HWC_DISPLAY_VIRTUAL: - if(ctx->mHWCVirtual) - ret = ctx->mHWCVirtual->set(ctx, list); - break; - default: - ret = -EINVAL; - } - } - // This is only indicative of how many times SurfaceFlinger posts - // frames to the display. - CALC_FPS(); - MDPComp::resetIdleFallBack(); - ctx->mVideoTransFlag = false; - //Was locked at the beginning of prepare - ctx->mDrawLock.unlock(); - return ret; -} - -int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp, - uint32_t* configs, size_t* numConfigs) { - int ret = 0; - hwc_context_t* ctx = (hwc_context_t*)(dev); - - Locker::Autolock _l(ctx->mDrawLock); - - if(!validDisplay(disp)) { - return -EINVAL; - } - //Currently we allow only 1 config, reported as config id # 0 - //This config is passed in to getDisplayAttributes. Ignored for now. - - switch(disp) { - case HWC_DISPLAY_PRIMARY: - if(*numConfigs > 0) { - configs[0] = 0; - *numConfigs = 1; - } - ret = 0; //NO_ERROR - break; - case HWC_DISPLAY_EXTERNAL: - case HWC_DISPLAY_VIRTUAL: - ret = -1; //Not connected - if(ctx->dpyAttr[disp].connected) { - ret = 0; //NO_ERROR - if(*numConfigs > 0) { - configs[0] = 0; - *numConfigs = 1; - } - } - break; - } - return ret; -} - -int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp, - uint32_t /*config*/, const uint32_t* attributes, int32_t* values) { - - hwc_context_t* ctx = (hwc_context_t*)(dev); - - Locker::Autolock _l(ctx->mDrawLock); - - if(!validDisplay(disp)) { - return -EINVAL; - } - //If hotpluggable displays(i.e, HDMI, WFD) are inactive return error - if( (disp != HWC_DISPLAY_PRIMARY) && !ctx->dpyAttr[disp].connected) { - return -1; - } - - //From HWComposer - static const uint32_t DISPLAY_ATTRIBUTES[] = { - HWC_DISPLAY_VSYNC_PERIOD, - HWC_DISPLAY_WIDTH, - HWC_DISPLAY_HEIGHT, - HWC_DISPLAY_DPI_X, - HWC_DISPLAY_DPI_Y, -#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC - HWC_DISPLAY_FBFORMAT, -#endif - HWC_DISPLAY_NO_ATTRIBUTE, - }; - - const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) / - sizeof(DISPLAY_ATTRIBUTES)[0]); - - for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) { - switch (attributes[i]) { - case HWC_DISPLAY_VSYNC_PERIOD: - values[i] = ctx->dpyAttr[disp].vsync_period; - break; - case HWC_DISPLAY_WIDTH: - if (ctx->dpyAttr[disp].customFBSize) - values[i] = ctx->dpyAttr[disp].xres_new; - else - values[i] = ctx->dpyAttr[disp].xres; - - ALOGD("%s disp = %d, width = %d",__FUNCTION__, disp, - values[i]); - break; - case HWC_DISPLAY_HEIGHT: - if (ctx->dpyAttr[disp].customFBSize) - values[i] = ctx->dpyAttr[disp].yres_new; - else - values[i] = ctx->dpyAttr[disp].yres; - ALOGD("%s disp = %d, height = %d",__FUNCTION__, disp, - values[i]); - break; - case HWC_DISPLAY_DPI_X: - values[i] = (int32_t) (ctx->dpyAttr[disp].xdpi*1000.0); - break; - case HWC_DISPLAY_DPI_Y: - values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0); - break; -#ifdef GET_FRAMEBUFFER_FORMAT_FROM_HWC - case HWC_DISPLAY_FBFORMAT: - values[i] = ctx->dpyAttr[disp].fbformat; - break; -#endif - default: - ALOGE("Unknown display attribute %d", - attributes[i]); - return -EINVAL; - } - } - return 0; -} - -void hwc_dump(struct hwc_composer_device_1* dev, char *buff, int buff_len) -{ - hwc_context_t* ctx = (hwc_context_t*)(dev); - Locker::Autolock _l(ctx->mDrawLock); - android::String8 aBuf(""); - dumpsys_log(aBuf, "Qualcomm HWC state:\n"); - dumpsys_log(aBuf, " MDPVersion=%d\n", ctx->mMDP.version); - dumpsys_log(aBuf, " DisplayPanel=%c\n", ctx->mMDP.panel); - dumpsys_log(aBuf, " DynRefreshRate=%d\n", - ctx->dpyAttr[HWC_DISPLAY_PRIMARY].dynRefreshRate); - for(int dpy = 0; dpy < HWC_NUM_DISPLAY_TYPES; dpy++) { - if(ctx->mMDPComp[dpy]) - ctx->mMDPComp[dpy]->dump(aBuf, ctx); - } - char ovDump[2048] = {'\0'}; - ctx->mOverlay->getDump(ovDump, 2048); - dumpsys_log(aBuf, ovDump); - ovDump[0] = '\0'; - ctx->mRotMgr->getDump(ovDump, 1024); - dumpsys_log(aBuf, ovDump); - ovDump[0] = '\0'; - if(Writeback::getDump(ovDump, 1024)) { - dumpsys_log(aBuf, ovDump); - ovDump[0] = '\0'; - } - dumpsys_log(aBuf, "Copybit::isAbcInUse=%d\n\n",isAbcInUse(ctx) ? 1 : 0); - strlcpy(buff, aBuf.string(), buff_len); -} - -int hwc_getActiveConfig(struct hwc_composer_device_1* dev, int disp) { - hwc_context_t* ctx = (hwc_context_t*)(dev); - Locker::Autolock _l(ctx->mDrawLock); - if(!validDisplay(disp)) { - return -EINVAL; - } - - //Supports only the default config (0th index) for now - return 0; -} - -int hwc_setActiveConfig(struct hwc_composer_device_1* dev, int disp, - int index) { - hwc_context_t* ctx = (hwc_context_t*)(dev); - Locker::Autolock _l(ctx->mDrawLock); - if(!validDisplay(disp)) { - return -EINVAL; - } - - //Supports only the default config (0th index) for now - return (index == 0) ? index : -EINVAL; -} - -static int hwc_device_close(struct hw_device_t *dev) -{ - if(!dev) { - ALOGE("%s: NULL device pointer", __FUNCTION__); - return -1; - } - closeContext((hwc_context_t*)dev); - free(dev); - - return 0; -} - -static int hwc_device_open(const struct hw_module_t* module, const char* name, - struct hw_device_t** device) -{ - int status = -EINVAL; - - if (!strcmp(name, HWC_HARDWARE_COMPOSER)) { - struct hwc_context_t *dev; - dev = (hwc_context_t*)malloc(sizeof(*dev)); - if(dev == NULL) - return status; - memset(dev, 0, sizeof(*dev)); - - //Initialize hwc context - initContext(dev); - - //Setup HWC methods - dev->device.common.tag = HARDWARE_DEVICE_TAG; - dev->device.common.version = HWC_DEVICE_API_VERSION_1_5; - dev->device.common.module = const_cast<hw_module_t*>(module); - dev->device.common.close = hwc_device_close; - dev->device.prepare = hwc_prepare; - dev->device.set = hwc_set; - dev->device.eventControl = hwc_eventControl; - dev->device.setPowerMode = hwc_setPowerMode; - dev->device.query = hwc_query; - dev->device.registerProcs = hwc_registerProcs; - dev->device.dump = hwc_dump; - dev->device.getDisplayConfigs = hwc_getDisplayConfigs; - dev->device.getDisplayAttributes = hwc_getDisplayAttributes; - dev->device.getActiveConfig = hwc_getActiveConfig; - dev->device.setActiveConfig = hwc_setActiveConfig; - *device = &dev->device.common; - status = 0; - } - return status; -} |