diff options
author | Andy Qiu <junhai.qiu@intel.com> | 2014-09-10 18:33:00 -0700 |
---|---|---|
committer | Ed Tam <etam@google.com> | 2014-09-12 17:48:55 -0700 |
commit | af3bf2227c951a59e2dcc44ab90790d247225375 (patch) | |
tree | 5d86ac2803d6552e9ce9e35010dff3237b41a9c3 | |
parent | 9f04a62c6e8c91ebeb199986ae11fc5107492df2 (diff) | |
download | hwcomposer-af3bf2227c951a59e2dcc44ab90790d247225375.tar.gz |
support 480/576 mode.
Bug: 17391301
BZ: 222162
Change-Id: I96ac2695455723978f5a7c4fb5b5f74c4719580f
Signed-off-by: Andy Qiu <junhai.qiu@intel.com>
-rwxr-xr-x[-rw-r--r--] | common/base/Drm.cpp | 25 | ||||
-rwxr-xr-x[-rw-r--r--] | common/base/Drm.h | 1 | ||||
-rwxr-xr-x | common/base/HwcLayerList.cpp | 21 | ||||
-rwxr-xr-x[-rw-r--r--] | common/planes/DisplayPlane.cpp | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | include/BufferManager.h | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | include/DisplayPlane.h | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | include/DisplayQuery.h | 1 | ||||
-rwxr-xr-x | ips/anniedale/AnnOverlayPlane.cpp | 47 | ||||
-rwxr-xr-x | ips/anniedale/AnnOverlayPlane.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | ips/anniedale/AnnRGBPlane.cpp | 54 | ||||
-rwxr-xr-x[-rw-r--r--] | ips/anniedale/AnnRGBPlane.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | ips/tangier/TngDisplayQuery.cpp | 26 | ||||
-rwxr-xr-x[-rw-r--r--] | platforms/merrifield_plus/PlatfBufferManager.cpp | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | platforms/merrifield_plus/PlatfBufferManager.h | 2 |
14 files changed, 224 insertions, 10 deletions
diff --git a/common/base/Drm.cpp b/common/base/Drm.cpp index 5239d0a..ada30cc 100644..100755 --- a/common/base/Drm.cpp +++ b/common/base/Drm.cpp @@ -467,6 +467,31 @@ bool Drm::getPhysicalSize(int device, uint32_t& width, uint32_t& height) return true; } +bool Drm::getDisplayResolution(int device, uint32_t& width, uint32_t& height) +{ + Mutex::Autolock _l(mLock); + + int outputIndex = getOutputIndex(device); + if (outputIndex < 0) { + return false; + } + + DrmOutput *output= &mOutputs[outputIndex]; + if (output->connected == false) { + ELOGTRACE("device is not connected"); + return false; + } + + width = output->mode.hdisplay; + height = output->mode.vdisplay; + + if (!width || !height) { + ELOGTRACE("invalid width or height"); + return false; + } + return true; +} + bool Drm::isConnected(int device) { Mutex::Autolock _l(mLock); diff --git a/common/base/Drm.h b/common/base/Drm.h index a50b17c..ff77ffd 100644..100755 --- a/common/base/Drm.h +++ b/common/base/Drm.h @@ -61,6 +61,7 @@ public: int getDrmFd() const; bool getModeInfo(int device, drmModeModeInfo& mode); bool getPhysicalSize(int device, uint32_t& width, uint32_t& height); + bool getDisplayResolution(int device, uint32_t& width, uint32_t& height); bool isSameDrmMode(drmModeModeInfoPtr mode, drmModeModeInfoPtr base) const; int getPanelOrientation(int device); diff --git a/common/base/HwcLayerList.cpp b/common/base/HwcLayerList.cpp index 774a9e2..a6326fc 100755 --- a/common/base/HwcLayerList.cpp +++ b/common/base/HwcLayerList.cpp @@ -337,7 +337,13 @@ bool HwcLayerList::initialize() rgbOverlayLayers.removeItemsAt(0); } - allocatePlanes(); + if (!DisplayQuery::forceFbScaling(mDisplayIndex)) { + allocatePlanes(); + } else { + // force GLES composition on all layers, then use GPU or hardware + // overlay to scale buffer to match display resolution + assignPrimaryPlane(); + } //dump(); return true; @@ -589,7 +595,18 @@ bool HwcLayerList::assignPrimaryPlane() bool HwcLayerList::assignPrimaryPlaneHelper(HwcLayer *hwcLayer, int zorder) { - ZOrderLayer *zlayer = addZOrderLayer(DisplayPlane::PLANE_PRIMARY, hwcLayer, zorder); + int type = DisplayPlane::PLANE_PRIMARY; + if (DisplayQuery::forceFbScaling(mDisplayIndex)) { + type = DisplayPlane::PLANE_OVERLAY; + // use overlay plane as primary plane. Color is converted to NV12 first then overlay + // hardware will perform scaling to display resolution. + + // can use primary plane as well, but frame buffer needs to be scaled to match display resolution, + // (primary plane does not support RGB scaling). There is issue in DDK blit function (RGB scaling + // yields corrupt output) + } + + ZOrderLayer *zlayer = addZOrderLayer(type, hwcLayer, zorder); bool ok = attachPlanes(); if (!ok) { removeZOrderLayer(zlayer); diff --git a/common/planes/DisplayPlane.cpp b/common/planes/DisplayPlane.cpp index 0056363..ce4a5f5 100644..100755 --- a/common/planes/DisplayPlane.cpp +++ b/common/planes/DisplayPlane.cpp @@ -17,6 +17,7 @@ #include <Hwcomposer.h> #include <DisplayPlane.h> #include <GraphicBuffer.h> +#include <DisplayQuery.h> namespace android { namespace intel { @@ -35,7 +36,12 @@ DisplayPlane::DisplayPlane(int index, int type, int disp) mPlaneAlpha(0), mBlending(HWC_BLENDING_NONE), mCurrentDataBuffer(0), - mUpdateMasks(0) + mUpdateMasks(0), + mForceScaling(false), + mDisplayWidth(0), + mDisplayHeight(0), + mScalingSource(0), + mScalingTarget(0) { CTRACE(); memset(&mPosition, 0, sizeof(mPosition)); @@ -105,6 +111,11 @@ void DisplayPlane::setPosition(int x, int y, int w, int h) { ALOGTRACE("Position = %d, %d - %dx%d", x, y, w, h); + if (mForceScaling) { + // set in assignToDevice + return; + } + if (mPosition.x != x || mPosition.y != y || mPosition.w != w || mPosition.h != h) { mUpdateMasks |= PLANE_POSITION_CHANGED; @@ -331,6 +342,22 @@ bool DisplayPlane::assignToDevice(int disp) mPanelOrientation = drm->getPanelOrientation(mDevice); + mForceScaling = DisplayQuery::forceFbScaling(disp); + drm->getDisplayResolution(disp, mDisplayWidth, mDisplayHeight); + + if (mForceScaling) { + mModeInfo.hdisplay = mDisplayWidth; + mModeInfo.vdisplay = mDisplayHeight; + mPosition.x = 0; + mPosition.y = 0; + mPosition.w = mDisplayWidth; + mPosition.h = mDisplayHeight; + } + mDisplayCrop.x = 0; + mDisplayCrop.y = 0; + mDisplayCrop.w = mDisplayWidth; + mDisplayCrop.h = mDisplayHeight; + return true; } diff --git a/include/BufferManager.h b/include/BufferManager.h index c9326bc..20dc634 100644..100755 --- a/include/BufferManager.h +++ b/include/BufferManager.h @@ -59,7 +59,7 @@ public: uint32_t allocGrallocBuffer(uint32_t width, uint32_t height, uint32_t format, uint32_t usage); void freeGrallocBuffer(uint32_t handle); - virtual bool convertRGBToNV12(uint32_t rgbHandle, uint32_t yuvHandle, + virtual bool blitGrallocBuffer(uint32_t srcHandle, uint32_t dstHandle, crop_t& srcCrop, uint32_t async) = 0; protected: virtual DataBuffer* createDataBuffer(gralloc_module_t *module, diff --git a/include/DisplayPlane.h b/include/DisplayPlane.h index 190ef25..b394765 100644..100755 --- a/include/DisplayPlane.h +++ b/include/DisplayPlane.h @@ -146,6 +146,15 @@ protected: uint32_t mUpdateMasks; drmModeModeInfo mModeInfo; int mPanelOrientation; + +protected: + bool mForceScaling; + uint32_t mDisplayWidth; + uint32_t mDisplayHeight; + crop_t mDisplayCrop; + uint32_t mScalingSource; + uint32_t mScalingTarget; + }; } // namespace intel diff --git a/include/DisplayQuery.h b/include/DisplayQuery.h index 185a25d..e3932cc 100644..100755 --- a/include/DisplayQuery.h +++ b/include/DisplayQuery.h @@ -25,6 +25,7 @@ public: static bool isVideoFormat(uint32_t format); static int getOverlayLumaStrideAlignment(uint32_t format); static uint32_t queryNV12Format(); + static bool forceFbScaling(int device); }; } // namespace intel diff --git a/ips/anniedale/AnnOverlayPlane.cpp b/ips/anniedale/AnnOverlayPlane.cpp index 93524fc..dc5f2fd 100755 --- a/ips/anniedale/AnnOverlayPlane.cpp +++ b/ips/anniedale/AnnOverlayPlane.cpp @@ -21,6 +21,7 @@ #include <ips/anniedale/AnnOverlayPlane.h> #include <ips/tangier/TngGrallocBuffer.h> #include <khronos/openmax/OMX_IntelVideoExt.h> +#include <DisplayQuery.h> namespace android { namespace intel { @@ -42,6 +43,38 @@ AnnOverlayPlane::~AnnOverlayPlane() CTRACE(); } +bool AnnOverlayPlane::setDataBuffer(uint32_t handle) +{ + if (handle == 0) { + ELOGTRACE("handle == 0"); + return true; + } + + if (mForceScaling) { + BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); + ssize_t index = mScalingBufferMap.indexOfKey(handle); + if (index < 0) { + mScalingTarget = bm->allocGrallocBuffer( + mSrcCrop.w, + mSrcCrop.h, + DisplayQuery::queryNV12Format(), + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_VIDEO_ENCODER); + if (!mScalingTarget) { + ELOGTRACE("Failed to allocate gralloc buffer."); + return false; + } + mScalingBufferMap.add(handle, mScalingTarget); + } else { + mScalingTarget = mScalingBufferMap.valueAt(index); + } + + mScalingSource = handle; + handle = mScalingTarget; + } + + return DisplayPlane::setDataBuffer(handle); +} + void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& /* zorderConfig */, void *nativeConfig) { @@ -70,6 +103,12 @@ void AnnOverlayPlane::setZOrderConfig(ZOrderConfig& /* zorderConfig */, bool AnnOverlayPlane::reset() { + while (!mScalingBufferMap.isEmpty()) { + uint32_t handle = mScalingBufferMap.valueAt(0); + Hwcomposer::getInstance().getBufferManager()->freeGrallocBuffer(handle); + mScalingBufferMap.removeItemsAt(0); + } + OverlayPlaneBase::reset(); if (mRotationBufProvider) { mRotationBufProvider->reset(); @@ -592,6 +631,14 @@ bool AnnOverlayPlane::flip(void *ctx) RETURN_FALSE_IF_NOT_INIT(); + if (mForceScaling) { + BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); + if (!bm->blitGrallocBuffer(mScalingSource, mScalingTarget, mSrcCrop, 0)) { + ELOGTRACE("Failed to blit RGB buffer to NV12."); + return false; + } + } + if (!DisplayPlane::flip(ctx)) { ELOGTRACE("failed to flip display plane."); return false; diff --git a/ips/anniedale/AnnOverlayPlane.h b/ips/anniedale/AnnOverlayPlane.h index df5f6eb..53235c4 100755 --- a/ips/anniedale/AnnOverlayPlane.h +++ b/ips/anniedale/AnnOverlayPlane.h @@ -32,6 +32,8 @@ public: AnnOverlayPlane(int index, int disp); virtual ~AnnOverlayPlane(); + bool setDataBuffer(uint32_t handle); + virtual void setTransform(int transform); virtual void setZOrderConfig(ZOrderConfig& config, void *nativeConfig); @@ -67,6 +69,9 @@ protected: bool mUseOverlayRotation; // hardware context struct intel_dc_plane_ctx mContext; + +private: + KeyedVector<uint32_t, uint32_t> mScalingBufferMap; }; } // namespace intel diff --git a/ips/anniedale/AnnRGBPlane.cpp b/ips/anniedale/AnnRGBPlane.cpp index 9cb8af3..afc4480 100644..100755 --- a/ips/anniedale/AnnRGBPlane.cpp +++ b/ips/anniedale/AnnRGBPlane.cpp @@ -45,6 +45,30 @@ bool AnnRGBPlane::disable() return enablePlane(false); } +bool AnnRGBPlane::reset() +{ + while (!mScalingBufferMap.isEmpty()) { + uint32_t handle = mScalingBufferMap.valueAt(0); + Hwcomposer::getInstance().getBufferManager()->freeGrallocBuffer(handle); + mScalingBufferMap.removeItemsAt(0); + } + + return DisplayPlane::reset(); +} + +bool AnnRGBPlane::flip(void*) +{ + if (mForceScaling) { + BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); + if (!bm->blitGrallocBuffer(mScalingSource, mScalingTarget, mDisplayCrop, 0)) { + ELOGTRACE("Failed to blit RGB buffer."); + return false; + } + } + + return true; +} + void* AnnRGBPlane::getContext() const { CTRACE(); @@ -59,8 +83,34 @@ void AnnRGBPlane::setZOrderConfig(ZOrderConfig& /* config */, void * /* nativeCo bool AnnRGBPlane::setDataBuffer(uint32_t handle) { if (!handle) { - setFramebufferTarget(handle); - return true; + if (!mForceScaling) { + setFramebufferTarget(handle); + return true; + } else { + ELOGTRACE("Invalid handle while scaling is required."); + return false; + } + } + + if (mForceScaling) { + BufferManager *bm = Hwcomposer::getInstance().getBufferManager(); + ssize_t index = mScalingBufferMap.indexOfKey(handle); + if (index < 0) { + mScalingTarget = bm->allocGrallocBuffer( + mDisplayWidth, + mDisplayHeight, + HAL_PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE); + if (!mScalingTarget) { + ELOGTRACE("Failed to allocate gralloc buffer."); + return false; + } + mScalingBufferMap.add(handle, mScalingTarget); + } else { + mScalingTarget = mScalingBufferMap.valueAt(index); + } + mScalingSource = handle; + handle = mScalingTarget; } TngGrallocBuffer tmpBuf(handle); diff --git a/ips/anniedale/AnnRGBPlane.h b/ips/anniedale/AnnRGBPlane.h index 6c9a46e..76ef53a 100644..100755 --- a/ips/anniedale/AnnRGBPlane.h +++ b/ips/anniedale/AnnRGBPlane.h @@ -34,7 +34,9 @@ public: // hardware operations bool enable(); bool disable(); + bool reset(); bool isDisabled(); + bool flip(void *ctx); void postFlip(); void* getContext() const; @@ -48,6 +50,9 @@ private: void setFramebufferTarget(uint32_t handle); protected: struct intel_dc_plane_ctx mContext; + +private: + KeyedVector<uint32_t, uint32_t> mScalingBufferMap; }; } // namespace intel diff --git a/ips/tangier/TngDisplayQuery.cpp b/ips/tangier/TngDisplayQuery.cpp index e2daa58..13350aa 100644..100755 --- a/ips/tangier/TngDisplayQuery.cpp +++ b/ips/tangier/TngDisplayQuery.cpp @@ -19,6 +19,7 @@ #include <hal_public.h> #include <DisplayQuery.h> #include <khronos/openmax/OMX_IntelVideoExt.h> +#include <Hwcomposer.h> namespace android { @@ -57,6 +58,31 @@ uint32_t DisplayQuery::queryNV12Format() return HAL_PIXEL_FORMAT_NV12; } +bool DisplayQuery::forceFbScaling(int device) +{ + // RGB planes don't support scaling. Panel fitter can be used to scale frame buffer to device's resolution + // if scaling factor is less than 1.5. Otherwise, GPU scaling is needed on RGB buffer, or hardware overlay + // scaling is needed on NV12 buffer + + // this needs to work together with kernel driver. Panel fitter needs to be disabled if scaling factor is greater + // than 1.5 + + uint32_t width, height; + if (!Hwcomposer::getInstance().getDrm()->getDisplayResolution(device, width, height)) { + return false; + } + + if (DEFAULT_DRM_FB_WIDTH / (float)width > 1.5) { + return true; + } + + if (DEFAULT_DRM_FB_HEIGHT / (float)height > 1.5) { + return true; + } + + return false; +} + } // namespace intel } // namespace android diff --git a/platforms/merrifield_plus/PlatfBufferManager.cpp b/platforms/merrifield_plus/PlatfBufferManager.cpp index 9ff12a7..764c47b 100644..100755 --- a/platforms/merrifield_plus/PlatfBufferManager.cpp +++ b/platforms/merrifield_plus/PlatfBufferManager.cpp @@ -58,13 +58,13 @@ BufferMapper* PlatfBufferManager::createBufferMapper(gralloc_module_t *module, buffer); } -bool PlatfBufferManager::convertRGBToNV12(uint32_t rgbHandle, uint32_t yuvHandle, +bool PlatfBufferManager::blitGrallocBuffer(uint32_t srcHandle, uint32_t dstHandle, crop_t& srcCrop, uint32_t async) { IMG_gralloc_module_public_t *imgGrallocModule = (IMG_gralloc_module_public_t *) mGrallocModule; - if (imgGrallocModule->Blit(imgGrallocModule, (buffer_handle_t)rgbHandle, - (buffer_handle_t)yuvHandle, + if (imgGrallocModule->Blit(imgGrallocModule, (buffer_handle_t)srcHandle, + (buffer_handle_t)dstHandle, srcCrop.w, srcCrop.h, srcCrop.x, srcCrop.y, 0, async)) { ELOGTRACE("Blit failed"); @@ -73,5 +73,6 @@ bool PlatfBufferManager::convertRGBToNV12(uint32_t rgbHandle, uint32_t yuvHandle return true; } + } // namespace intel } // namespace android diff --git a/platforms/merrifield_plus/PlatfBufferManager.h b/platforms/merrifield_plus/PlatfBufferManager.h index 0eb8c64..11ff950 100644..100755 --- a/platforms/merrifield_plus/PlatfBufferManager.h +++ b/platforms/merrifield_plus/PlatfBufferManager.h @@ -34,7 +34,7 @@ protected: DataBuffer* createDataBuffer(gralloc_module_t *module, uint32_t handle); BufferMapper* createBufferMapper(gralloc_module_t *module, DataBuffer& buffer); - bool convertRGBToNV12(uint32_t rgbHandle, uint32_t yuvHandle, + bool blitGrallocBuffer(uint32_t srcHandle, uint32_t dstHandle, crop_t& srcCrop, uint32_t async); }; |