initial GL libraries for msm8960
Change-Id: I16451c70a079894ac326d3564d96f1fbafcd4f1b
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
new file mode 100755
index 0000000..79e4256
--- /dev/null
+++ b/liboverlay/Android.mk
@@ -0,0 +1,43 @@
+# Copyright (C) 2008 The Android Open Source Project
+#
+# 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
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
+LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
+LOCAL_SRC_FILES := \
+ overlayLib.cpp \
+ overlayLibUI.cpp \
+LOCAL_CFLAGS:= -DLOG_TAG=\"OverlayLib\"
+
+ifeq ($(TARGET_USE_HDMI_AS_PRIMARY),true)
+LOCAL_CFLAGS += -DHDMI_AS_PRIMARY
+endif
+ifeq ($(TARGET_USES_POST_PROCESSING),true)
+LOCAL_CFLAGS += -DUSES_POST_PROCESSING
+LOCAL_SHARED_LIBRARIES += libmm-abl
+LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/lib/
+endif
+LOCAL_MODULE := liboverlay
+
+#LGE_CHANGE, for userdebug mode
+LOCAL_MODULE_TAGS := optional
+include $(BUILD_SHARED_LIBRARY)
diff --git a/liboverlay/overlayLib.cpp b/liboverlay/overlayLib.cpp
new file mode 100755
index 0000000..fe5c3d3
--- /dev/null
+++ b/liboverlay/overlayLib.cpp
@@ -0,0 +1,2352 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-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 "overlayLib.h"
+#include "gralloc_priv.h"
+
+#define INTERLACE_MASK 0x80
+#define DEBUG_OVERLAY true
+/* Helper functions */
+static inline size_t ALIGN(size_t x, size_t align) {
+ return (x + align-1) & ~(align-1);
+}
+
+using namespace overlay;
+using android::sp;
+using gralloc::IMemAlloc;
+using gralloc::IonController;
+using gralloc::alloc_data;
+
+#ifdef HDMI_AS_PRIMARY
+bool Overlay::sHDMIAsPrimary = true;
+#else
+bool Overlay::sHDMIAsPrimary = false;
+#endif
+
+template <class Type>
+void swapWidthHeight(Type& width, Type& height) {
+ Type tmp = width;
+ width = height;
+ height = tmp;
+}
+
+int overlay::get_mdp_format(int format) {
+ switch (format) {
+ 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_YCbCr_420_SP:
+ return MDP_Y_CRCB_H2V2;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ return MDP_Y_CBCR_H2V2;
+ case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+ return MDP_Y_CRCB_H2V2_TILE;
+ case HAL_PIXEL_FORMAT_YV12:
+ return MDP_Y_CR_CB_GH2V2;
+ default:
+ LOGE("%s: unknown color format [0x%x]", __FUNCTION__, format);
+ return -1;
+ }
+ return -1;
+}
+
+int overlay::get_mdp_orientation(int value) {
+ switch(value) {
+ case 0: return 0;
+ case HAL_TRANSFORM_FLIP_V: return MDP_FLIP_UD;
+ case HAL_TRANSFORM_FLIP_H: return MDP_FLIP_LR;
+ case HAL_TRANSFORM_ROT_90: return MDP_ROT_90;
+ case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V:
+ return MDP_ROT_90|MDP_FLIP_LR;
+ case HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H:
+ return MDP_ROT_90|MDP_FLIP_UD;
+ case HAL_TRANSFORM_ROT_180: return MDP_ROT_180;
+ case HAL_TRANSFORM_ROT_270: return MDP_ROT_270;
+ default:
+ LOGE("%s: invalid rotation value (value = 0x%x",
+ __FUNCTION__, value);
+ return -1;
+ }
+ return -1;
+}
+
+// Rotator - input to output mapping
+int overlay::get_rot_output_format(int format) {
+ switch (format) {
+ case MDP_Y_CRCB_H2V2_TILE:
+ return MDP_Y_CRCB_H2V2;
+ case MDP_Y_CB_CR_H2V2:
+ return MDP_Y_CBCR_H2V2;
+ case MDP_Y_CR_CB_GH2V2:
+ return MDP_Y_CRCB_H2V2;
+ default:
+ return format;
+ }
+ return -1;
+}
+
+// This function normalizes the crop values to be all even
+void overlay::normalize_crop(uint32_t& xy, uint32_t& wh) {
+
+ if (xy & 0x0001) {
+ // x or y is odd, increment it's value
+ xy += 1;
+ // Since we've incremented x(y), we need to decrement
+ // w(h) accordingly
+ if (wh & 0x0001) {
+ // w or h is odd, decrement it by 1, to make it even
+ EVEN_OUT(wh);
+ } else {
+ // w(h) is already even, hence we decrement by 2
+ wh -=2;
+ }
+ } else {
+ EVEN_OUT(wh);
+ }
+}
+
+#define LOG_TAG "OverlayLIB"
+static void reportError(const char* message) {
+ LOGE( "%s", message);
+}
+
+void overlay::dump(mdp_overlay& mOVInfo) {
+ if (!DEBUG_OVERLAY)
+ return;
+ LOGE("mOVInfo:");
+ LOGE("src: width %d height %d format %s user_data[0] %d", mOVInfo.src.width,
+ mOVInfo.src.height, getFormatString(mOVInfo.src.format),
+ mOVInfo.user_data[0]);
+ LOGE("src_rect: x %d y %d w %d h %d", mOVInfo.src_rect.x,
+ mOVInfo.src_rect.y, mOVInfo.src_rect.w, mOVInfo.src_rect.h);
+ LOGE("dst_rect: x %d y %d w %d h %d", mOVInfo.dst_rect.x,
+ mOVInfo.dst_rect.y, mOVInfo.dst_rect.w, mOVInfo.dst_rect.h);
+ LOGE("z_order %d is_fg %d alpha %d transp_mask %d flags %x id %d",
+ mOVInfo.z_order, mOVInfo.is_fg, mOVInfo.alpha, mOVInfo.transp_mask,
+ mOVInfo.flags, mOVInfo.id);
+}
+
+void overlay::dump(msm_rotator_img_info& mRotInfo) {
+ if (!DEBUG_OVERLAY)
+ return;
+ LOGE("mRotInfo:");
+ LOGE("session_id %d dst_x %d dst_y %d rotations %d enable %d",
+ mRotInfo.session_id, mRotInfo.dst_x, mRotInfo.dst_y,
+ mRotInfo.rotations, mRotInfo.enable);
+ LOGE("src: width %d height %d format %s", mRotInfo.src.width,
+ mRotInfo.src.height, getFormatString(mRotInfo.src.format));
+ LOGE("dst: width %d height %d format %s", mRotInfo.dst.width,
+ mRotInfo.dst.height, getFormatString(mRotInfo.src.format));
+ LOGE("src_rect: x %d y %d w %d h %d", mRotInfo.src_rect.x,
+ mRotInfo.src_rect.y, mRotInfo.src_rect.w, mRotInfo.src_rect.h);
+}
+
+const char* overlay::getFormatString(int format){
+ static const char* formats[] = {
+ "MDP_RGB_565",
+ "MDP_XRGB_8888",
+ "MDP_Y_CBCR_H2V2",
+ "MDP_ARGB_8888",
+ "MDP_RGB_888",
+ "MDP_Y_CRCB_H2V2",
+ "MDP_YCRYCB_H2V1",
+ "MDP_Y_CRCB_H2V1",
+ "MDP_Y_CBCR_H2V1",
+ "MDP_RGBA_8888",
+ "MDP_BGRA_8888",
+ "MDP_RGBX_8888",
+ "MDP_Y_CRCB_H2V2_TILE",
+ "MDP_Y_CBCR_H2V2_TILE",
+ "MDP_Y_CR_CB_H2V2",
+ "MDP_Y_CR_CB_GH2V2",
+ "MDP_Y_CB_CR_H2V2",
+ "MDP_Y_CRCB_H1V1",
+ "MDP_Y_CBCR_H1V1",
+ "MDP_IMGTYPE_LIMIT",
+ "MDP_BGR_565",
+ "MDP_FB_FORMAT",
+ "MDP_IMGTYPE_LIMIT2"
+ };
+ return formats[format];
+}
+ZOrderManager* ZOrderManager::sInstance = 0;
+FrameBufferInfo* FrameBufferInfo::sFBInfoInstance = 0;
+
+int ZOrderManager::getZ(int fbnum){
+ int zorder = NO_PIPE;;
+ Mutex::Autolock objLock(mObjMutex);
+ if(mPipesInuse == mMaxPipes) {
+ LOGE("No free pipes available.. inUse = %d ", mPipesInuse);
+ return NO_PIPE;
+ }
+ switch(fbnum) {
+ case FRAMEBUFFER_0:
+ for (int i = 0;i < NUM_CHANNELS; i++) {
+ if(mFB0Pipes[i] == false) {
+ mFB0Pipes[i]= true;
+ zorder = i;
+ break;
+ }
+ }
+ break;
+ case FRAMEBUFFER_1:
+ case FRAMEBUFFER_2:
+ for (int i = 0;i < mMaxPipes; i++) {
+ if(mFB1Pipes[i] == false) {
+ mFB1Pipes[i]= true;
+ zorder = i;
+ break;
+ }
+ }
+ break;
+ default:
+ LOGE("getZ: Invalid framebuffer..");
+ break;
+ }
+ mPipesInuse++;
+ LOGE("getZ: return zorder = %d for fbdev = %d, pipesinUse = %d",
+ zorder, fbnum, mPipesInuse);
+ return zorder;
+}
+
+void ZOrderManager::decZ(int fbnum, int zorder){
+ Mutex::Autolock objLock(mObjMutex);
+ switch(fbnum) {
+ case FRAMEBUFFER_0:
+ LOG_ASSERT(!mFB0Pipes[zorder],"channel with ZOrder does not exist");
+ LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
+ mFB0Pipes[zorder] = false;
+ break;
+ case FRAMEBUFFER_1:
+ case FRAMEBUFFER_2:
+ LOG_ASSERT(!mFB1Pipes[zorder],"channel with ZOrder does not exist");
+ LOGE("decZ: freeing the pipe with zorder = %d for fbdev = %d", zorder, fbnum);
+ mFB1Pipes[zorder] = false;
+ break;
+ default:
+ LOGE("decZ: Invalid framebuffer ");
+ break;
+ }
+ if(mPipesInuse > 0)
+ mPipesInuse--;
+ LOGE("decZ: Pipes in use = %d", mPipesInuse);
+}
+
+bool overlay::isHDMIConnected () {
+ char value[PROPERTY_VALUE_MAX];
+ property_get("hw.hdmiON", value, "0");
+ int isHDMI = atoi(value);
+ return isHDMI ? true : false;
+}
+
+bool overlay::is3DTV() {
+ char is3DTV = '0';
+ FILE *fp = fopen(EDID_3D_INFO_FILE, "r");
+ if (fp) {
+ fread(&is3DTV, 1, 1, fp);
+ fclose(fp);
+ }
+ LOGI("3DTV EDID flag: %c", is3DTV);
+ return (is3DTV == '0') ? false : true;
+}
+
+bool overlay::isPanel3D() {
+ int fd = open("/dev/graphics/fb0", O_RDWR, 0);
+ if (fd < 0) {
+ reportError("Can't open framebuffer 0");
+ return false;
+ }
+ fb_fix_screeninfo finfo;
+ if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ reportError("FBIOGET_FSCREENINFO on fb0 failed");
+ close(fd);
+ fd = -1;
+ return false;
+ }
+ close(fd);
+ return (FB_TYPE_3D_PANEL == finfo.type) ? true : false;
+}
+
+bool overlay::usePanel3D() {
+ if (Overlay::sHDMIAsPrimary)
+ return is3DTV();
+
+ if(!isPanel3D())
+ return false;
+ char value[PROPERTY_VALUE_MAX];
+ property_get("persist.user.panel3D", value, "0");
+ int usePanel3D = atoi(value);
+ return usePanel3D ? true : false;
+}
+
+bool overlay::send3DInfoPacket (unsigned int format3D) {
+ FILE *fp = fopen(FORMAT_3D_FILE, "wb");
+ if (fp) {
+ fprintf(fp, "%d", format3D);
+ fclose(fp);
+ fp = NULL;
+ return true;
+ }
+ LOGE("%s:no sysfs entry for setting 3d mode!", __FUNCTION__);
+ return false;
+}
+
+bool overlay::enableBarrier (unsigned int orientation) {
+ FILE *fp = fopen(BARRIER_FILE, "wb");
+ if (fp) {
+ fprintf(fp, "%d", orientation);
+ fclose(fp);
+ fp = NULL;
+ return true;
+ }
+ LOGE("%s:no sysfs entry for enabling barriers on 3D panel!", __FUNCTION__);
+ return false;
+}
+
+int overlay::getColorFormat(int format)
+{
+ if (format == HAL_PIXEL_FORMAT_YV12)
+ return format;
+ else if (format & INTERLACE_MASK)
+ return format ^ HAL_PIXEL_FORMAT_INTERLACE;
+ else
+ return COLOR_FORMAT(format);
+}
+
+bool overlay::isInterlacedContent(int format)
+{
+ if ((format != HAL_PIXEL_FORMAT_YV12) &&
+ (format & INTERLACE_MASK))
+ return true;
+
+ return false;
+}
+
+unsigned int overlay::getOverlayConfig (unsigned int format3D, bool poll,
+ bool isHDMI) {
+ bool isTV3D = false;
+ unsigned int curState = 0;
+ if (poll)
+ isHDMI = isHDMIConnected();
+ if (isHDMI) {
+ LOGD("%s: HDMI connected... checking the TV type", __FUNCTION__);
+ if (format3D) {
+ if (is3DTV())
+ curState = OV_3D_VIDEO_3D_TV;
+ else
+ curState = OV_3D_VIDEO_2D_TV;
+ } else
+ curState = OV_2D_VIDEO_ON_TV;
+ } else {
+ LOGD("%s: HDMI not connected...", __FUNCTION__);
+ if(format3D) {
+ if (usePanel3D())
+ curState = OV_3D_VIDEO_3D_PANEL;
+ else
+ curState = OV_3D_VIDEO_2D_PANEL;
+ }
+ else
+ curState = OV_2D_VIDEO_ON_PANEL;
+ }
+ return curState;
+}
+
+/* clears any VG pipes allocated to the fb devices */
+int overlay::initOverlay() {
+ msmfb_mixer_info_req req;
+ mdp_mixer_info *minfo = NULL;
+ char name[64];
+ int fd = -1;
+ for(int i = 0; i < NUM_FB_DEVICES; i++) {
+ snprintf(name, 64, FB_DEVICE_TEMPLATE, i);
+ LOGD("initoverlay:: opening the device:: %s", name);
+ fd = open(name, O_RDWR, 0);
+ if(fd < 0) {
+ LOGE("cannot open framebuffer(%d)", i);
+ return -1;
+ }
+ //Get the mixer configuration */
+ req.mixer_num = i;
+ if (ioctl(fd, MSMFB_MIXER_INFO, &req) == -1) {
+ LOGE("ERROR: MSMFB_MIXER_INFO ioctl failed");
+ close(fd);
+ return -1;
+ }
+ minfo = req.info;
+ for (int j = 0; j < req.cnt; j++) {
+ LOGD("ndx=%d num=%d z_order=%d", minfo->pndx, minfo->pnum,
+ minfo->z_order);
+ // except the RGB base layer with z_order of -1, clear any
+ // other pipes connected to mixer.
+ if((minfo->z_order) != -1) {
+ int index = minfo->pndx;
+ LOGD("Unset overlay with index: %d at mixer %d", index, i);
+ if(ioctl(fd, MSMFB_OVERLAY_UNSET, &index) == -1) {
+ LOGE("ERROR: MSMFB_OVERLAY_UNSET failed");
+ close(fd);
+ return -1;
+ }
+ }
+ minfo++;
+ }
+ close(fd);
+ fd = -1;
+ }
+ return 0;
+}
+
+Overlay::Overlay() : mChannelUP(false), mExternalDisplay(false),
+ mS3DFormat(0), mCroppedSrcWidth(0),
+ mCroppedSrcHeight(0), mState(-1) {
+ mOVBufferInfo.width = mOVBufferInfo.height = 0;
+ mOVBufferInfo.format = mOVBufferInfo.size = 0;
+}
+
+Overlay::~Overlay() {
+ closeChannel();
+}
+
+int Overlay::getFBWidth(int channel) const {
+ return objOvCtrlChannel[channel].getFBWidth();
+}
+
+int Overlay::getFBHeight(int channel) const {
+ return objOvCtrlChannel[channel].getFBHeight();
+}
+
+bool Overlay::startChannel(const overlay_buffer_info& info, int fbnum,
+ bool norot, bool uichannel,
+ unsigned int format3D, int channel,
+ int flags, int num_buffers) {
+ int zorder = 0;
+ mCroppedSrcWidth = info.width;
+ mCroppedSrcHeight = info.height;
+ if (format3D)
+ zorder = channel;
+ if (mState == -1)
+ mState = OV_UI_MIRROR_TV;
+
+ mChannelUP = objOvCtrlChannel[channel].startControlChannel(info, fbnum,
+ norot, uichannel,
+ format3D, zorder, flags);
+ if (!mChannelUP) {
+ LOGE("startChannel for fb%d failed", fbnum);
+ return mChannelUP;
+ }
+ bool secure = flags & SECURE_OVERLAY_SESSION;
+ objOvCtrlChannel[channel].setSize(info.size);
+ return objOvDataChannel[channel].startDataChannel(objOvCtrlChannel[channel], fbnum,
+ norot, secure, uichannel, num_buffers);
+}
+
+bool Overlay::closeChannel() {
+
+ if (!mChannelUP)
+ return true;
+
+ if(mS3DFormat) {
+ if (mExternalDisplay)
+ overlay::send3DInfoPacket(0);
+ else if (mState == OV_3D_VIDEO_3D_PANEL) {
+ if (sHDMIAsPrimary)
+ overlay::send3DInfoPacket(0);
+ else
+ enableBarrier(0);
+ }
+ }
+ for (int i = 0; i < NUM_CHANNELS; i++) {
+ objOvCtrlChannel[i].closeControlChannel();
+ objOvDataChannel[i].closeDataChannel();
+ }
+ mChannelUP = false;
+ mS3DFormat = 0;
+ mOVBufferInfo.width = 0;
+ mOVBufferInfo.height = 0;
+ mOVBufferInfo.format = 0;
+ mOVBufferInfo.size = 0;
+ mState = -1;
+ return true;
+}
+
+void Overlay::closeExternalChannel() {
+ if (objOvCtrlChannel[VG1_PIPE].isChannelUP()) {
+ objOvCtrlChannel[VG1_PIPE].closeControlChannel();
+ objOvDataChannel[VG1_PIPE].closeDataChannel();
+ }
+}
+
+bool Overlay::getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel) {
+ return objOvCtrlChannel[channel].getPosition(x, y, w, h);
+}
+
+bool Overlay::getOrientation(int& orientation, int channel) const {
+ return objOvCtrlChannel[channel].getOrientation(orientation);
+}
+
+bool Overlay::setDeviceOrientation(int orientation) {
+ // Use this to calculate the position on HDMI
+ mDevOrientation = orientation;
+ return true;
+}
+
+bool Overlay::setPosition(int x, int y, uint32_t w, uint32_t h) {
+ bool ret = false;
+ overlay_rect secDest;
+ overlay_rect priDest;
+ int currX, currY;
+ uint32_t currW, currH;
+ // Set even destination co-ordinates
+ EVEN_OUT(x); EVEN_OUT(y);
+ EVEN_OUT(w); EVEN_OUT(h);
+ objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
+ priDest.x = x, priDest.y = y;
+ priDest.w = w, priDest.h = h;
+ if(x != currX || y != currY || w != currW || h != currH) {
+ switch (mState) {
+ case OV_UI_MIRROR_TV:
+ case OV_2D_VIDEO_ON_PANEL:
+ case OV_3D_VIDEO_2D_PANEL:
+ return setChannelPosition(x, y, w, h, VG0_PIPE);
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
+ objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
+ mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
+ &priDest, &secDest);
+ } else {
+ objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
+ mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
+ }
+ setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h,
+ VG1_PIPE);
+ return setChannelPosition(x, y, w, h, VG0_PIPE);
+ break;
+ case OV_3D_VIDEO_3D_PANEL:
+ for (int i = 0; i < NUM_CHANNELS; i++) {
+ if (sHDMIAsPrimary)
+ objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat, &secDest);
+ else {
+ if (!objOvCtrlChannel[i].useVirtualFB()) {
+ LOGE("%s: failed virtual fb for channel %d", __FUNCTION__, i);
+ return false;
+ }
+ objOvCtrlChannel[i].getPositionS3D(i, 0x1, &secDest);
+ }
+ if(!setChannelPosition(secDest.x, secDest.y, secDest.w,
+ secDest.h, i)) {
+ LOGE("%s: failed for channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ case OV_3D_VIDEO_2D_TV:
+ case OV_3D_VIDEO_3D_TV:
+ for (int i = 0; i < NUM_CHANNELS; i++) {
+ ret = objOvCtrlChannel[i].getPositionS3D(i, mS3DFormat,
+ &secDest);
+ if (!ret)
+ ret = setChannelPosition(x, y, w, h, i);
+ else
+ ret = setChannelPosition(secDest.x, secDest.y, secDest.w,
+ secDest.h, i);
+ if (!ret) {
+ LOGE("%s: failed for channel %d", __FUNCTION__, i);
+ return ret;
+ }
+ }
+ break;
+ default:
+ LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+ break;
+ }
+ }
+ return true;
+}
+
+bool Overlay::setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel) {
+ return objOvCtrlChannel[channel].setPosition(x, y, w, h);
+}
+
+bool Overlay::updateOverlaySource(const overlay_buffer_info& info, int orientation,
+ int flags) {
+ bool ret = false;
+ int currentFlags = 0;
+
+ bool needUpdateFlags = false;
+ if (objOvCtrlChannel[0].isChannelUP()) {
+ needUpdateFlags = objOvCtrlChannel[0].doFlagsNeedUpdate(flags);
+ }
+
+ bool geometryChanged = true;
+ if (info.width == mOVBufferInfo.width &&
+ info.height == mOVBufferInfo.height &&
+ info.format == mOVBufferInfo.format) {
+ geometryChanged = false;
+ }
+
+ if (sHDMIAsPrimary)
+ needUpdateFlags = false;
+
+ if ((false == needUpdateFlags) && (false == geometryChanged)) {
+ return true;
+ }
+
+ // Disable rotation for the HDMI channels
+ int orientHdmi = 0;
+ int orientPrimary = sHDMIAsPrimary ? 0 : orientation;
+ int orient[2] = {orientPrimary, orientHdmi};
+ // disable waitForVsync on HDMI, since we call the wait ioctl
+ int ovFlagsExternal = 0;
+ int ovFlagsPrimary = sHDMIAsPrimary ? (flags |= WAIT_FOR_VSYNC): flags;
+ int ovFlags[2] = {flags, ovFlagsExternal};
+ switch(mState) {
+ case OV_3D_VIDEO_3D_PANEL:
+ orient[1] = sHDMIAsPrimary ? 0 : orientation;
+ break;
+ case OV_3D_VIDEO_3D_TV:
+ orient[0] = 0;
+ break;
+ default:
+ break;
+ }
+
+ int numChannelsToUpdate = NUM_CHANNELS;
+ if (!geometryChanged) {
+ // Only update the primary channel - we only need to update the
+ // wait/no-wait flags
+ if (objOvCtrlChannel[0].isChannelUP()) {
+ return objOvCtrlChannel[0].updateOverlayFlags(flags);
+ }
+ }
+
+ // Set the overlay source info
+ for (int i = 0; i < NUM_CHANNELS; i++) {
+ if (objOvCtrlChannel[i].isChannelUP()) {
+ ret = objOvCtrlChannel[i].updateOverlaySource(info, orient[i], ovFlags[i]);
+ if (!ret) {
+ LOGE("objOvCtrlChannel[%d].updateOverlaySource failed", i);
+ return false;
+ }
+ objOvCtrlChannel[i].setSize(info.size);
+ ret = objOvDataChannel[i].updateDataChannel(info.size);
+ }
+ }
+ if (ret) {
+ mOVBufferInfo = info;
+ } else
+ LOGE("update failed");
+ return ret;
+}
+
+bool Overlay::getAspectRatioPosition(int w, int h, overlay_rect *rect, int channel) {
+ return objOvCtrlChannel[channel].getAspectRatioPosition(w, h, rect);
+}
+
+int Overlay::getS3DFormat(int format) {
+ // The S3D is part of the HAL_PIXEL_FORMAT_YV12 value. Add
+ // an explicit check for the format
+ if (format == HAL_PIXEL_FORMAT_YV12) {
+ return 0;
+ }
+ int format3D = FORMAT_3D(format);
+ int fIn3D = FORMAT_3D_INPUT(format3D); // MSB 2 bytes are input format
+ int fOut3D = FORMAT_3D_OUTPUT(format3D); // LSB 2 bytes are output format
+ format3D = fIn3D | fOut3D;
+ if (!fIn3D) {
+ format3D |= fOut3D << SHIFT_3D; //Set the input format
+ }
+ if (!fOut3D) {
+ format3D |= fIn3D >> SHIFT_3D; //Set the output format
+ }
+ return format3D;
+}
+
+bool Overlay::setSource(const overlay_buffer_info& info, int orientation,
+ int hdmiConnected, int flags, int num_buffers) {
+ // Separate the color format from the 3D format.
+ // If there is 3D content; the effective format passed by the client is:
+ // effectiveFormat = 3D_IN | 3D_OUT | ColorFormat
+ int newState = mState;
+ bool stateChange = false, ret = true;
+ bool isHDMIStateChange = (mExternalDisplay != hdmiConnected) && (mState != -1);
+ unsigned int format3D = getS3DFormat(info.format);
+ int colorFormat = getColorFormat(info.format);
+ if (isHDMIStateChange || -1 == mState) {
+ // we were mirroring UI. Also HDMI state stored was stale
+ newState = getOverlayConfig (format3D, false, hdmiConnected);
+ stateChange = (mState == newState) ? false : true;
+ }
+
+ if (stateChange) {
+ mExternalDisplay = hdmiConnected;
+ mState = newState;
+ mS3DFormat = format3D;
+ if (mState == OV_3D_VIDEO_2D_PANEL || mState == OV_3D_VIDEO_2D_TV) {
+ LOGI("3D content on 2D display: set the output format as monoscopic");
+ mS3DFormat = FORMAT_3D_INPUT(format3D) | HAL_3D_OUT_MONOSCOPIC_MASK;
+ }
+ // We always enable the rotator for the primary.
+ bool noRot = false;
+ bool uiChannel = false;
+ int fbnum = 0;
+ switch(mState) {
+ case OV_2D_VIDEO_ON_PANEL:
+ if(isHDMIStateChange) {
+ //close HDMI Only
+ closeExternalChannel();
+ break;
+ }
+ case OV_3D_VIDEO_2D_PANEL:
+ closeChannel();
+ return startChannel(info, FRAMEBUFFER_0, noRot, false,
+ mS3DFormat, VG0_PIPE, flags, num_buffers);
+ break;
+ case OV_3D_VIDEO_3D_PANEL:
+ closeChannel();
+ if (sHDMIAsPrimary) {
+ noRot = true;
+ flags |= WAIT_FOR_VSYNC;
+ send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
+ }
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ if(!startChannel(info, FRAMEBUFFER_0, noRot, uiChannel,
+ mS3DFormat, i, flags, num_buffers)) {
+ LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ if(isHDMIStateChange) {
+ //start only HDMI channel
+ noRot = true;
+ bool waitForVsync = true;
+ // External display connected, start corresponding channel
+ // mExternalDisplay will hold the fbnum
+ if(!startChannel(info, mExternalDisplay, noRot, false, mS3DFormat,
+ VG1_PIPE, waitForVsync, num_buffers)) {
+ LOGE("%s:failed to open channel %d", __func__, VG1_PIPE);
+ return false;
+ }
+ int currX, currY;
+ uint32_t currW, currH;
+ overlay_rect priDest;
+ overlay_rect secDest;
+ objOvCtrlChannel[VG0_PIPE].getPosition(currX, currY, currW, currH);
+ priDest.x = currX, priDest.y = currY;
+ priDest.w = currW, priDest.h = currH;
+ if (FrameBufferInfo::getInstance()->canSupportTrueMirroring()) {
+ objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
+ mCroppedSrcWidth, mCroppedSrcHeight, mDevOrientation,
+ &priDest, &secDest);
+ } else {
+ objOvCtrlChannel[VG1_PIPE].getAspectRatioPosition(
+ mCroppedSrcWidth, mCroppedSrcHeight, &secDest);
+ }
+ return setChannelPosition(secDest.x, secDest.y, secDest.w, secDest.h, VG1_PIPE);
+ }
+ case OV_3D_VIDEO_2D_TV:
+ closeChannel();
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ fbnum = i;
+ //start two channels for one for primary and external.
+ if (fbnum) {
+ // Disable rotation for external
+ noRot = true;
+ //set fbnum to hdmiConnected, which holds the ext display
+ fbnum = hdmiConnected;
+ flags &= ~WAIT_FOR_VSYNC;
+ }
+ if(!startChannel(info, fbnum, noRot, false, mS3DFormat,
+ i, flags, num_buffers)) {
+ LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ return true;
+ break;
+ case OV_3D_VIDEO_3D_TV:
+ closeChannel();
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ if(!startChannel(info, FRAMEBUFFER_1, true, false,
+ mS3DFormat, i, flags, num_buffers)) {
+ LOGE("%s:failed to open channel %d", __FUNCTION__, i);
+ return false;
+ }
+ send3DInfoPacket(mS3DFormat & OUTPUT_MASK_3D);
+ }
+ break;
+ default:
+ LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+ break;
+ }
+ } else {
+ ret = updateOverlaySource(info, orientation, flags);
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ return ret;
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+ }
+ return true;
+}
+
+bool Overlay::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
+ if (!mChannelUP) {
+ LOGE("%s: channel not set", __FUNCTION__);
+ return false;
+ }
+ overlay_rect rect, inRect;
+ inRect.x = x; inRect.y = y; inRect.w = w; inRect.h = h;
+ mCroppedSrcWidth = w;
+ mCroppedSrcHeight = h;
+ switch (mState) {
+ case OV_UI_MIRROR_TV:
+ case OV_2D_VIDEO_ON_PANEL:
+ return setChannelCrop(x, y, w, h, VG0_PIPE);
+ break;
+ case OV_3D_VIDEO_2D_PANEL:
+ objOvDataChannel[VG0_PIPE].getCropS3D(&inRect, VG0_PIPE, mS3DFormat, &rect);
+ return setChannelCrop(rect.x, rect.y, rect.w, rect.h, VG0_PIPE);
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ if(!setChannelCrop(x, y, w, h, i)) {
+ LOGE("%s: failed for pipe %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ case OV_3D_VIDEO_3D_PANEL:
+ case OV_3D_VIDEO_2D_TV:
+ case OV_3D_VIDEO_3D_TV:
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ objOvDataChannel[i].getCropS3D(&inRect, i, mS3DFormat, &rect);
+ if(!setChannelCrop(rect.x, rect.y, rect.w, rect.h, i)) {
+ LOGE("%s: failed for pipe %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ default:
+ LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+ break;
+ }
+ return true;
+}
+
+bool Overlay::setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel) {
+ return objOvDataChannel[channel].setCrop(x, y, w, h);
+}
+
+bool Overlay::updateOverlayFlags(int flags) {
+ return objOvCtrlChannel[VG0_PIPE].updateOverlayFlags(flags);
+}
+
+bool Overlay::setTransform(int value) {
+ int barrier = 0;
+ switch (mState) {
+ case OV_UI_MIRROR_TV:
+ case OV_2D_VIDEO_ON_PANEL:
+ case OV_3D_VIDEO_2D_PANEL:
+ return objOvCtrlChannel[VG0_PIPE].setTransform(value);
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ case OV_3D_VIDEO_2D_TV:
+ case OV_3D_VIDEO_3D_TV:
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ if(!objOvCtrlChannel[i].setTransform(value)) {
+ LOGE("%s:failed for channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ case OV_3D_VIDEO_3D_PANEL:
+ switch (value) {
+ case HAL_TRANSFORM_ROT_90:
+ case HAL_TRANSFORM_ROT_270:
+ barrier = BARRIER_LANDSCAPE;
+ break;
+ default:
+ barrier = BARRIER_PORTRAIT;
+ break;
+ if(!enableBarrier(barrier))
+ LOGE("%s:failed to enable barriers for 3D video", __FUNCTION__);
+ }
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ if(!objOvCtrlChannel[i].setTransform(value)) {
+ LOGE("%s:failed for channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ break;
+ default:
+ LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+ break;
+ }
+ return true;
+}
+
+bool Overlay::setFd(int fd, int channel) {
+ return objOvDataChannel[channel].setFd(fd);
+}
+
+bool Overlay::queueBuffer(uint32_t offset, int channel) {
+ return objOvDataChannel[channel].queueBuffer(offset);
+}
+
+bool Overlay::waitForHdmiVsync(int channel) {
+ return objOvDataChannel[channel].waitForHdmiVsync();
+}
+
+bool Overlay::queueBuffer(buffer_handle_t buffer) {
+ private_handle_t const* hnd = reinterpret_cast
+ <private_handle_t const*>(buffer);
+ if (!hnd) {
+ LOGE("Overlay::queueBuffer invalid handle");
+ return false;
+ }
+ const size_t offset = hnd->offset;
+ const int fd = hnd->fd;
+ switch (mState) {
+ case OV_UI_MIRROR_TV:
+ case OV_2D_VIDEO_ON_PANEL:
+ case OV_3D_VIDEO_2D_PANEL:
+ if(!queueBuffer(fd, offset, VG0_PIPE)) {
+ LOGE("%s:failed for channel 0", __FUNCTION__);
+ return false;
+ }
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ case OV_3D_VIDEO_3D_PANEL:
+ case OV_3D_VIDEO_2D_TV:
+ case OV_3D_VIDEO_3D_TV:
+ for (int i=NUM_CHANNELS-1; i>=0; i--) {
+ if(!queueBuffer(fd, offset, i)) {
+ LOGE("%s:failed for channel %d", __FUNCTION__, i);
+ return false;
+ }
+ }
+ //Wait for HDMI done..
+ if(!waitForHdmiVsync(VG1_PIPE)) {
+ LOGE("%s: waitforHdmiVsync failed", __FUNCTION__);
+ return false;
+ }
+ break;
+ default:
+ LOGE("%s:Unknown state %d", __FUNCTION__, mState);
+ break;
+ }
+ return true;
+}
+
+bool Overlay::queueBuffer(int fd, uint32_t offset, int channel) {
+ bool ret = false;
+ ret = setFd(fd, channel);
+ if(!ret) {
+ LOGE("Overlay::queueBuffer channel %d setFd failed", channel);
+ return false;
+ }
+ ret = queueBuffer(offset, channel);
+ if(!ret) {
+ LOGE("Overlay::queueBuffer channel %d queueBuffer failed", channel);
+ return false;
+ }
+ return ret;
+}
+
+OverlayControlChannel::OverlayControlChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
+ mFormat3D(0), mIsChannelUpdated(true) {
+ memset(&mOVInfo, 0, sizeof(mOVInfo));
+ memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
+ memset(&mRotInfo, 0, sizeof(mRotInfo));
+}
+
+
+OverlayControlChannel::~OverlayControlChannel() {
+ closeControlChannel();
+}
+
+bool OverlayControlChannel::getAspectRatioPosition(int w, int h, overlay_rect *rect)
+{
+ int width = w, height = h, x, y;
+ int fbWidth = getFBWidth();
+ int fbHeight = getFBHeight();
+ // width and height for YUV TILE format
+ int tempWidth = w, tempHeight = h;
+ /* Calculate the width and height if it is YUV TILE format*/
+ if(getFormat() == HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED) {
+ tempWidth = w - ( (((w-1)/64 +1)*64) - w);
+ tempHeight = h - ((((h-1)/32 +1)*32) - h);
+ }
+ if (width * fbHeight > fbWidth * height) {
+ height = fbWidth * height / width;
+ EVEN_OUT(height);
+ width = fbWidth;
+ } else if (width * fbHeight < fbWidth * height) {
+ width = fbHeight * width / height;
+ EVEN_OUT(width);
+ height = fbHeight;
+ } else {
+ width = fbWidth;
+ height = fbHeight;
+ }
+ /* Scaling of upto a max of 8 times supported */
+ if(width >(tempWidth * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ width = HW_OVERLAY_MAGNIFICATION_LIMIT * tempWidth;
+ }
+ if(height >(tempHeight*HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ height = HW_OVERLAY_MAGNIFICATION_LIMIT * tempHeight;
+ }
+ if (width > fbWidth) width = fbWidth;
+ if (height > fbHeight) height = fbHeight;
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("hw.actionsafe.width", value, "0");
+ float asWidth = atof(value);
+ property_get("hw.actionsafe.height", value, "0");
+ float asHeight = atof(value);
+ width = width * (1.0f - asWidth / 100.0f);
+ height = height * (1.0f - asHeight / 100.0f);
+
+ x = (fbWidth - width) / 2;
+ y = (fbHeight - height) / 2;
+ rect->x = x;
+ rect->y = y;
+ rect->w = width;
+ rect->h = height;
+ return true;
+}
+
+
+// This function gets the destination position for Seconday display
+// based on the position and aspect ratio of the primary
+bool OverlayControlChannel::getAspectRatioPosition(int w, int h, int orientation,
+ overlay_rect *inRect, overlay_rect *outRect) {
+ float priWidth = FrameBufferInfo::getInstance()->getWidth();
+ float priHeight = FrameBufferInfo::getInstance()->getHeight();
+ float fbWidth = getFBWidth();
+ float fbHeight = getFBHeight();
+ float wRatio = 1.0;
+ float hRatio = 1.0;
+ float xRatio = 1.0;
+ float yRatio = 1.0;
+
+ int xPos = 0;
+ int yPos = 0;
+ int tmp = 0;
+ overlay_rect rect;
+ switch(orientation) {
+ case MDP_ROT_NOP:
+ case MDP_ROT_180:
+ getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
+ xPos = rect.x;
+ yPos = rect.y;
+ fbWidth = rect.w;
+ fbHeight = rect.h;
+
+ if(orientation == MDP_ROT_180) {
+ inRect->x = priWidth - (inRect->x + inRect->w);
+ inRect->y = priHeight - (inRect->y + inRect->h);
+ }
+ break;
+ case MDP_ROT_90:
+ case MDP_ROT_270:
+ if(orientation == MDP_ROT_90) {
+ tmp = inRect->y;
+ inRect->y = priWidth - (inRect->x + inRect->w);
+ inRect->x = tmp;
+ }
+ else if(orientation == MDP_ROT_270) {
+ tmp = inRect->x;
+ inRect->x = priHeight - (inRect->y + inRect->h);
+ inRect->y = tmp;
+ }
+ //Swap the destination width/height
+ swapWidthHeight(inRect->w, inRect->h);
+ // Swap width/height for primary
+ swapWidthHeight(priWidth, priHeight);
+ getAspectRatioPosition((int)priWidth, (int)priHeight, &rect);
+ xPos = rect.x;
+ yPos = rect.y;
+ fbWidth = rect.w;
+ fbHeight = rect.h;
+ break;
+ default:
+ LOGE("In %s: Unknown Orientation", __FUNCTION__);
+ break;
+ }
+ //Calculate the position...
+ xRatio = inRect->x/priWidth;
+ yRatio = inRect->y/priHeight;
+
+ wRatio = inRect->w/priWidth;
+ hRatio = inRect->h/priHeight;
+ outRect->x = (xRatio * fbWidth) + xPos;
+ outRect->y = (yRatio * fbHeight) + yPos;
+
+ outRect->w = (wRatio * fbWidth);
+ outRect->h = hRatio * fbHeight;
+ LOGD("Calculated AS Position for HDMI: X= %d, y = %d w = %d h = %d",
+ outRect->x, outRect->y,outRect->w, outRect->h);
+ return true;
+}
+
+
+bool OverlayControlChannel::getPositionS3D(int channel, int format, overlay_rect *rect) {
+ int wDisp = getFBWidth();
+ int hDisp = getFBHeight();
+ switch (format & OUTPUT_MASK_3D) {
+ case HAL_3D_OUT_SIDE_BY_SIDE_MASK:
+ if (channel == VG0_PIPE) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = wDisp/2;
+ rect->h = hDisp;
+ } else {
+ rect->x = wDisp/2;
+ rect->y = 0;
+ rect->w = wDisp/2;
+ rect->h = hDisp;
+ }
+ break;
+ case HAL_3D_OUT_TOP_BOTTOM_MASK:
+ if (channel == VG0_PIPE) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = wDisp;
+ rect->h = hDisp/2;
+ } else {
+ rect->x = 0;
+ rect->y = hDisp/2;
+ rect->w = wDisp;
+ rect->h = hDisp/2;
+ }
+ break;
+ case HAL_3D_OUT_MONOSCOPIC_MASK:
+ if (channel == VG1_PIPE) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = wDisp;
+ rect->h = hDisp;
+ }
+ else
+ return false;
+ break;
+ case HAL_3D_OUT_INTERLEAVE_MASK:
+ break;
+ default:
+ reportError("Unsupported 3D output format");
+ break;
+ }
+ return true;
+}
+
+bool OverlayControlChannel::openDevices(int fbnum) {
+ if (fbnum < 0)
+ return false;
+
+ char dev_name[64];
+ snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
+ mFD = open(dev_name, O_RDWR, 0);
+ if (mFD < 0) {
+ reportError("Cant open framebuffer ");
+ return false;
+ }
+
+ fb_fix_screeninfo finfo;
+ if (ioctl(mFD, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ reportError("FBIOGET_FSCREENINFO on fb1 failed");
+ close(mFD);
+ mFD = -1;
+ return false;
+ }
+
+ fb_var_screeninfo vinfo;
+ if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ reportError("FBIOGET_VSCREENINFO on fb1 failed");
+ close(mFD);
+ mFD = -1;
+ return false;
+ }
+ mFBWidth = vinfo.xres;
+ mFBHeight = vinfo.yres;
+ mFBbpp = vinfo.bits_per_pixel;
+ mFBystride = finfo.line_length;
+
+ if (!mNoRot) {
+ mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
+ if (mRotFD < 0) {
+ reportError("Cant open rotator device");
+ close(mFD);
+ mFD = -1;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool OverlayControlChannel::setOverlayInformation(const overlay_buffer_info& info,
+ int zorder, int flags, int requestType) {
+ int w = info.width;
+ int h = info.height;
+ int format = info.format;
+
+ mOVInfo.src.width = w;
+ mOVInfo.src.height = h;
+ mOVInfo.src_rect.x = 0;
+ mOVInfo.src_rect.y = 0;
+ mOVInfo.dst_rect.x = 0;
+ mOVInfo.dst_rect.y = 0;
+ mOVInfo.dst_rect.w = w;
+ mOVInfo.dst_rect.h = h;
+ if(format == MDP_Y_CRCB_H2V2_TILE) {
+ if (mNoRot) {
+ mOVInfo.src_rect.w = w - ((((w-1)/64 +1)*64) - w);
+ mOVInfo.src_rect.h = h - ((((h-1)/32 +1)*32) - h);
+ } else {
+ mOVInfo.src_rect.w = w;
+ mOVInfo.src_rect.h = h;
+ mOVInfo.src.width = (((w-1)/64 +1)*64);
+ mOVInfo.src.height = (((h-1)/32 +1)*32);
+ mOVInfo.src_rect.x = mOVInfo.src.width - w;
+ mOVInfo.src_rect.y = mOVInfo.src.height - h;
+ }
+ } else {
+ mOVInfo.src_rect.w = w;
+ mOVInfo.src_rect.h = h;
+ }
+
+ mOVInfo.src.format = format;
+ int dst_w = w;
+ int dst_h = h;
+
+ if (dst_w > mFBWidth) {
+ dst_w = mFBWidth;
+ dst_h = dst_h * mFBWidth / w;
+ }
+ if (dst_h > mFBHeight) {
+ dst_h = mFBHeight;
+ dst_w = dst_w * mFBHeight / h;
+ }
+ mOVInfo.dst_rect.w = dst_w;
+ mOVInfo.dst_rect.h = dst_h;
+ mOVInfo.user_data[0] = 0;
+ if (requestType == NEW_REQUEST) {
+ mOVInfo.id = MSMFB_NEW_REQUEST;
+ mOVInfo.z_order = zorder;
+ mOVInfo.alpha = 0xff;
+ mOVInfo.transp_mask = 0xffffffff;
+ }
+ mOVInfo.flags = 0;
+ setInformationFromFlags(flags, mOVInfo);
+ mOVInfo.dpp.sharp_strength = 0;
+ return true;
+}
+
+void OverlayControlChannel::setInformationFromFlags(int flags, mdp_overlay& ov)
+{
+ if (flags & INTERLACED_CONTENT) {
+ mOVInfo.flags |= MDP_DEINTERLACE;
+ } else {
+ mOVInfo.flags &= ~MDP_DEINTERLACE;
+ }
+
+ if ((flags & WAIT_FOR_VSYNC) == 0)
+ mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
+ else
+ mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
+
+ if(flags & SECURE_OVERLAY_SESSION)
+ mOVInfo.flags |= MDP_SECURE_OVERLAY_SESSION;
+ else
+ mOVInfo.flags &= ~MDP_SECURE_OVERLAY_SESSION;
+
+ //set the default sharpening settings
+ mOVInfo.flags |= MDP_SHARPENING;
+
+ if (flags & DISABLE_FRAMEBUFFER_FETCH)
+ mOVInfo.is_fg = 1;
+ else
+ mOVInfo.is_fg = 0;
+
+ if (flags & OVERLAY_PIPE_SHARE) {
+ mOVInfo.flags |= MDP_OV_PIPE_SHARE;
+ } else {
+ mOVInfo.flags &= ~MDP_OV_PIPE_SHARE;
+ }
+ mOVInfo.dpp.sharp_strength = 0;
+
+}
+
+bool OverlayControlChannel::doFlagsNeedUpdate(int flags) {
+ bool needUpdate = false;
+
+ if ((flags & WAIT_FOR_VSYNC) == 0) {
+ if (!(mOVInfo.flags & MDP_OV_PLAY_NOWAIT)) {
+ needUpdate = true;
+ }
+ }
+ if (flags & WAIT_FOR_VSYNC) {
+ if (mOVInfo.flags & MDP_OV_PLAY_NOWAIT) {
+ needUpdate = true;
+ }
+ }
+
+ if ((flags & DISABLE_FRAMEBUFFER_FETCH) == 0) {
+ if (mOVInfo.is_fg == 1) {
+ needUpdate = true;
+ }
+ }
+ if (flags & DISABLE_FRAMEBUFFER_FETCH) {
+ if (mOVInfo.is_fg == 0) {
+ needUpdate = true;
+ }
+ }
+ return needUpdate;
+}
+
+bool OverlayControlChannel::startOVRotatorSessions(
+ const overlay_buffer_info& info,
+ int requestType) {
+ bool ret = true;
+ int w = info.width;
+ int h = info.height;
+ int format = info.format;
+
+ if (!mNoRot) {
+ mRotInfo.src.format = format;
+ mRotInfo.src.width = w;
+ mRotInfo.src.height = h;
+ mRotInfo.src_rect.w = w;
+ mRotInfo.src_rect.h = h;
+ mRotInfo.dst.width = w;
+ mRotInfo.dst.height = h;
+ if(format == MDP_Y_CRCB_H2V2_TILE) {
+ mRotInfo.src.width = (((w-1)/64 +1)*64);
+ mRotInfo.src.height = (((h-1)/32 +1)*32);
+ mRotInfo.src_rect.w = (((w-1)/64 +1)*64);
+ mRotInfo.src_rect.h = (((h-1)/32 +1)*32);
+ mRotInfo.dst.width = (((w-1)/64 +1)*64);
+ mRotInfo.dst.height = (((h-1)/32 +1)*32);
+ mRotInfo.dst.format = MDP_Y_CRCB_H2V2;
+ }
+ mRotInfo.dst.format = get_rot_output_format(format);
+ mRotInfo.dst_x = 0;
+ mRotInfo.dst_y = 0;
+ mRotInfo.src_rect.x = 0;
+ mRotInfo.src_rect.y = 0;
+ mRotInfo.rotations = 0;
+
+ if (requestType == NEW_REQUEST) {
+ mRotInfo.enable = 0;
+ if(mUIChannel)
+ mRotInfo.enable = 1;
+ mRotInfo.session_id = 0;
+ } else
+ mRotInfo.enable = 1;
+
+ int result = ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo);
+ if (result) {
+ reportError("Rotator session failed");
+ dump(mRotInfo);
+ ret = false;
+ }
+ }
+
+ if (ret && ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+ reportError("startOVRotatorSessions, Overlay set failed");
+ dump(mOVInfo);
+ ret = false;
+ }
+
+ if (!ret)
+ closeControlChannel();
+ else
+ mIsChannelUpdated = true;
+ return ret;
+}
+
+bool OverlayControlChannel::updateOverlaySource(const overlay_buffer_info& info,
+ int orientation, int flags)
+{
+ int colorFormat = getColorFormat(info.format);
+ int hw_format = get_mdp_format(colorFormat);
+ overlay_buffer_info ovBufInfo;
+ ovBufInfo.width = info.width;
+ ovBufInfo.height = info.height;
+ ovBufInfo.format = hw_format;
+
+ if (isInterlacedContent(info.format)) {
+ flags |= INTERLACED_CONTENT;
+ }
+ if (!setOverlayInformation(ovBufInfo, 0, flags,
+ UPDATE_REQUEST))
+ return false;
+
+ return startOVRotatorSessions(ovBufInfo, UPDATE_REQUEST);
+}
+
+bool OverlayControlChannel::startControlChannel(const overlay_buffer_info& info,
+ int fbnum, bool norot,
+ bool uichannel,
+ unsigned int format3D, int zorder,
+ int flags) {
+ int colorFormat = getColorFormat(info.format);
+ mNoRot = norot;
+ mFormat = colorFormat;
+ mUIChannel = uichannel;
+ mFBNum = fbnum;
+ fb_fix_screeninfo finfo;
+ fb_var_screeninfo vinfo;
+ int hw_format;
+
+ // The interlace mask is part of the HAL_PIXEL_FORMAT_YV12 value. Add
+ // an explicit check for the format
+ if (isInterlacedContent(colorFormat)) {
+ flags |= MDP_DEINTERLACE;
+
+ // Get the actual format
+ colorFormat = colorFormat ^ HAL_PIXEL_FORMAT_INTERLACE;
+ }
+ hw_format = get_mdp_format(colorFormat);
+ if (hw_format < 0) {
+ reportError("Unsupported format");
+ return false;
+ }
+
+ mFormat3D = format3D;
+ if ( !mFormat3D || (mFormat3D & HAL_3D_OUT_MONOSCOPIC_MASK) ) {
+ // Set the share bit for sharing the VG pipe
+ flags |= OVERLAY_PIPE_SHARE;
+ }
+ //do not set the PIPE SHARE bit for true mirroring
+ if(uichannel && FrameBufferInfo::getInstance()->canSupportTrueMirroring())
+ flags &= ~OVERLAY_PIPE_SHARE;
+ if (!openDevices(fbnum))
+ return false;
+
+ //get Z order
+ zorder = ZOrderManager::getInstance()->getZ(fbnum);
+ if (zorder == NO_PIPE)
+ return false;
+
+ overlay_buffer_info ovBufInfo;
+ ovBufInfo.width = info.width;
+ ovBufInfo.height = info.height;
+ ovBufInfo.format = hw_format;
+ if (!setOverlayInformation(ovBufInfo, zorder, flags, NEW_REQUEST))
+ return false;
+
+ return startOVRotatorSessions(ovBufInfo, NEW_REQUEST);
+}
+
+bool OverlayControlChannel::closeControlChannel() {
+ if (!isChannelUP())
+ return true;
+
+ if (!mNoRot && mRotFD > 0) {
+ ioctl(mRotFD, MSM_ROTATOR_IOCTL_FINISH, &(mRotInfo.session_id));
+ close(mRotFD);
+ mRotFD = -1;
+ }
+
+ int ovid = mOVInfo.id;
+ ioctl(mFD, MSMFB_OVERLAY_UNSET, &ovid);
+ if (m3DOVInfo.is_3d) {
+ m3DOVInfo.is_3d = 0;
+ ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo);
+ }
+
+ close(mFD);
+
+ if(NO_PIPE != mOVInfo.z_order){
+ ZOrderManager::getInstance()->decZ(mFBNum, mOVInfo.z_order);
+ }
+ memset(&mOVInfo, 0, sizeof(mOVInfo));
+ memset(&mRotInfo, 0, sizeof(mRotInfo));
+ memset(&m3DOVInfo, 0, sizeof(m3DOVInfo));
+
+ mOVInfo.z_order = NO_PIPE;
+ mFD = -1;
+
+ return true;
+}
+
+bool OverlayControlChannel::updateOverlayFlags(int flags) {
+ if ((flags & WAIT_FOR_VSYNC) == 0)
+ mOVInfo.flags |= MDP_OV_PLAY_NOWAIT;
+ else
+ mOVInfo.flags &= ~MDP_OV_PLAY_NOWAIT;
+
+ if (flags & DISABLE_FRAMEBUFFER_FETCH)
+ mOVInfo.is_fg = 1;
+ else
+ mOVInfo.is_fg = 0;
+
+ if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+ LOGE("%s: OVERLAY_SET failed", __FUNCTION__);
+ dump(mOVInfo);
+ return false;
+ }
+ return true;
+}
+
+bool OverlayControlChannel::setPosition(int x, int y, uint32_t w, uint32_t h) {
+
+ if (!isChannelUP() ||
+ (x < 0) || (y < 0) || ((x + w) > mFBWidth) ||
+ ((y + h) > mFBHeight)) {
+ reportError("setPosition failed");
+ LOGW("x %d y %d (x+w) %d (y+h) %d FBWidth %d FBHeight %d", x, y, x+w, y+h,
+ mFBWidth,mFBHeight);
+ return false;
+ }
+ if( x != mOVInfo.dst_rect.x || y != mOVInfo.dst_rect.y ||
+ w != mOVInfo.dst_rect.w || h != mOVInfo.dst_rect.h ) {
+ mdp_overlay ov;
+ ov.id = mOVInfo.id;
+ if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+ reportError("setPosition, overlay GET failed");
+ return false;
+ }
+
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ // can not scale-up 8 times over original source
+ // return false to compose with GPU
+#if 1
+ if(w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ LOGE("[TJ] setPosition : too big width, back to GPU comp %d => %d", ov.src_rect.w, w);
+ return false;
+ }
+ if(h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ LOGE("[TJ] setPosition : too big height, back to GPU comp %d => %d", ov.src_rect.h, h);
+ return false;
+ }
+#else
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ /* Scaling of upto a max of 8 times supported */
+ if(w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
+ x = (mFBWidth - w) / 2;
+ }
+ if(h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
+ y = (mFBHeight - h) / 2;
+ }
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+#endif
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ ov.dst_rect.x = x;
+ ov.dst_rect.y = y;
+ ov.dst_rect.w = w;
+ ov.dst_rect.h = h;
+ if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
+ reportError("setPosition, Overlay SET failed");
+ dump(ov);
+ return false;
+ }
+ mOVInfo = ov;
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ LOGE("setPosition");
+ dump(ov);
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+ }
+ return true;
+}
+
+void OverlayControlChannel::swapOVRotWidthHeight() {
+ int tmp = mOVInfo.src.width;
+ mOVInfo.src.width = mOVInfo.src.height;
+ mOVInfo.src.height = tmp;
+
+ tmp = mOVInfo.src_rect.h;
+ mOVInfo.src_rect.h = mOVInfo.src_rect.w;
+ mOVInfo.src_rect.w = tmp;
+
+ tmp = mRotInfo.dst.width;
+ mRotInfo.dst.width = mRotInfo.dst.height;
+ mRotInfo.dst.height = tmp;
+}
+
+bool OverlayControlChannel::useVirtualFB() {
+ if(!m3DOVInfo.is_3d) {
+ m3DOVInfo.is_3d = 1;
+ mFBWidth *= 2;
+ mFBHeight /= 2;
+ m3DOVInfo.width = mFBWidth;
+ m3DOVInfo.height = mFBHeight;
+ return ioctl(mFD, MSMFB_OVERLAY_3D, &m3DOVInfo) ? false : true;
+ }
+ return true;
+}
+
+bool OverlayControlChannel::setTransform(int value, bool fetch) {
+ if (!isChannelUP()) {
+ LOGE("%s: channel is not up", __FUNCTION__);
+ return false;
+ }
+
+ mdp_overlay ov = mOVInfo;
+ if (fetch && ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+ reportError("setParameter, overlay GET failed");
+ return false;
+ }
+ mOVInfo = ov;
+ if (!mIsChannelUpdated) {
+ int orientation = get_mdp_orientation(value);
+ if (orientation == mOVInfo.user_data[0]) {
+ return true;
+ }
+ }
+ mIsChannelUpdated = false;
+
+ int val = mOVInfo.user_data[0];
+ if (mNoRot)
+ return true;
+
+ int rot = value;
+
+ switch(rot) {
+ case 0:
+ case HAL_TRANSFORM_FLIP_H:
+ case HAL_TRANSFORM_FLIP_V:
+ {
+ if (val == MDP_ROT_90) {
+ int tmp = mOVInfo.src_rect.y;
+ mOVInfo.src_rect.y = mOVInfo.src.width -
+ (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+ mOVInfo.src_rect.x = tmp;
+ swapOVRotWidthHeight();
+ }
+ else if (val == MDP_ROT_270) {
+ int tmp = mOVInfo.src_rect.x;
+ mOVInfo.src_rect.x = mOVInfo.src.height - (
+ mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+ mOVInfo.src_rect.y = tmp;
+ swapOVRotWidthHeight();
+ }
+ break;
+ }
+ case HAL_TRANSFORM_ROT_90:
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
+ {
+ if (val == MDP_ROT_270) {
+ mOVInfo.src_rect.x = mOVInfo.src.width - (
+ mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+ mOVInfo.src_rect.y = mOVInfo.src.height - (
+ mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+ }
+ else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+ int tmp = mOVInfo.src_rect.x;
+ mOVInfo.src_rect.x = mOVInfo.src.height -
+ (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+ mOVInfo.src_rect.y = tmp;
+ swapOVRotWidthHeight();
+ }
+ break;
+ }
+ case HAL_TRANSFORM_ROT_180:
+ {
+ if (val == MDP_ROT_270) {
+ int tmp = mOVInfo.src_rect.y;
+ mOVInfo.src_rect.y = mOVInfo.src.width -
+ (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+ mOVInfo.src_rect.x = tmp;
+ swapOVRotWidthHeight();
+ }
+ else if (val == MDP_ROT_90) {
+ int tmp = mOVInfo.src_rect.x;
+ mOVInfo.src_rect.x = mOVInfo.src.height - (
+ mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+ mOVInfo.src_rect.y = tmp;
+ swapOVRotWidthHeight();
+ }
+ break;
+ }
+ case HAL_TRANSFORM_ROT_270:
+ {
+ if (val == MDP_ROT_90) {
+ mOVInfo.src_rect.y = mOVInfo.src.height -
+ (mOVInfo.src_rect.y + mOVInfo.src_rect.h);
+ mOVInfo.src_rect.x = mOVInfo.src.width -
+ (mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+ }
+ else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
+ int tmp = mOVInfo.src_rect.y;
+ mOVInfo.src_rect.y = mOVInfo.src.width - (
+ mOVInfo.src_rect.x + mOVInfo.src_rect.w);
+ mOVInfo.src_rect.x = tmp;
+ swapOVRotWidthHeight();
+ }
+ break;
+ }
+ default: return false;
+ }
+
+ int mdp_rotation = get_mdp_orientation(rot);
+ if (mdp_rotation == -1)
+ return false;
+
+ mOVInfo.user_data[0] = mdp_rotation;
+ mRotInfo.rotations = mOVInfo.user_data[0];
+
+ /* Rotator always outputs non-tiled formats.
+ If rotator is used, set Overlay input to non-tiled
+ Else, overlay input remains tiled */
+ if (mOVInfo.user_data[0]) {
+ mOVInfo.src.format = get_rot_output_format(mRotInfo.src.format);
+ mRotInfo.enable = 1;
+ }
+ else {
+ //We can switch between rotator ON and OFF. Reset overlay
+ //i/p format whenever this happens
+ if(mRotInfo.dst.format == mOVInfo.src.format)
+ mOVInfo.src.format = mRotInfo.src.format;
+ mRotInfo.enable = 0;
+ //Always enable rotation for UI mirror usecase
+ if(mUIChannel)
+ mRotInfo.enable = 1;
+ }
+
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ // can not scale-up 8 times over original source
+ // return false to compose with GPU
+#if 1
+ if(mOVInfo.dst_rect.w > (mOVInfo.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ LOGE("[TJ] setTransform : too big width, back to GPU comp %d => %d", mOVInfo.src_rect.w, mOVInfo.dst_rect.w);
+ return false;
+ }
+ if(mOVInfo.dst_rect.h > (mOVInfo.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ LOGE("[TJ] setTransform : too big height, back to GPU comp %d => %d", mOVInfo.src_rect.h, mOVInfo.dst_rect.h);
+ return false;
+ }
+#endif
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ //dump(mRotInfo); // TJ
+ if (ioctl(mRotFD, MSM_ROTATOR_IOCTL_START, &mRotInfo)) {
+ reportError("setTransform, rotator start failed");
+ dump(mRotInfo);
+ return false;
+ }
+
+ if ((mOVInfo.user_data[0] == MDP_ROT_90) ||
+ (mOVInfo.user_data[0] == MDP_ROT_270))
+ mOVInfo.flags |= MDP_SOURCE_ROTATED_90;
+ else
+ mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
+
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ LOGE("setTransform"); // TJ
+ dump(mOVInfo); // TJ
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+ reportError("setTransform, overlay set failed");
+ dump(mOVInfo);
+ return false;
+ }
+
+ return true;
+}
+
+bool OverlayControlChannel::getPosition(int& x, int& y,
+ uint32_t& w, uint32_t& h) {
+ if (!isChannelUP())
+ return false;
+ //mOVInfo has the current Overlay Position
+ x = mOVInfo.dst_rect.x;
+ y = mOVInfo.dst_rect.y;
+ w = mOVInfo.dst_rect.w;
+ h = mOVInfo.dst_rect.h;
+
+ return true;
+}
+
+bool OverlayControlChannel::getOrientation(int& orientation) const {
+ if (!isChannelUP())
+ return false;
+ // mOVInfo has the current orientation
+ orientation = mOVInfo.user_data[0];
+ return true;
+}
+bool OverlayControlChannel::getOvSessionID(int& sessionID) const {
+ if (!isChannelUP())
+ return false;
+ sessionID = mOVInfo.id;
+ return true;
+}
+
+bool OverlayControlChannel::getRotSessionID(int& sessionID) const {
+ if (!isChannelUP())
+ return false;
+ sessionID = mRotInfo.session_id;
+ return true;
+}
+
+bool OverlayControlChannel::getSize(int& size) const {
+ if (!isChannelUP())
+ return false;
+ size = mSize;
+ return true;
+}
+
+OverlayDataChannel::OverlayDataChannel() : mNoRot(false), mFD(-1), mRotFD(-1),
+ mPmemFD(-1), mPmemAddr(0), mUpdateDataChannel(false)
+{
+ //XXX: getInstance(false) implies that it should only
+ // use the kernel allocator. Change it to something
+ // more descriptive later.
+ mAlloc = gralloc::IAllocController::getInstance(false);
+}
+
+OverlayDataChannel::~OverlayDataChannel() {
+ closeDataChannel();
+}
+
+bool OverlayDataChannel::startDataChannel(
+ const OverlayControlChannel& objOvCtrlChannel,
+ int fbnum, bool norot, bool secure, bool uichannel,
+ int num_buffers) {
+ int ovid, rotid, size;
+ mNoRot = norot;
+ mSecure = secure;
+ memset(&mOvData, 0, sizeof(mOvData));
+ memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+ memset(&mRotData, 0, sizeof(mRotData));
+ if (objOvCtrlChannel.getOvSessionID(ovid) &&
+ objOvCtrlChannel.getRotSessionID(rotid) &&
+ objOvCtrlChannel.getSize(size)) {
+ return startDataChannel(ovid, rotid, size, fbnum,
+ norot, uichannel, num_buffers);
+ }
+ else
+ return false;
+}
+
+bool OverlayDataChannel::openDevices(int fbnum, bool uichannel, int num_buffers) {
+ if (fbnum < 0)
+ return false;
+ char dev_name[64];
+ snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
+
+ mFD = open(dev_name, O_RDWR, 0);
+ if (mFD < 0) {
+ reportError("Cant open framebuffer ");
+ return false;
+ }
+ if (!mNoRot) {
+ mRotFD = open("/dev/msm_rotator", O_RDWR, 0);
+ if (mRotFD < 0) {
+ reportError("Cant open rotator device");
+ close(mFD);
+ mFD = -1;
+ return false;
+ }
+
+ return mapRotatorMemory(num_buffers, uichannel, NEW_REQUEST);
+ }
+ return true;
+}
+
+bool OverlayDataChannel::mapRotatorMemory(int num_buffers, bool uiChannel, int requestType)
+{
+ mPmemAddr = MAP_FAILED;
+
+ alloc_data data;
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = mPmemOffset * num_buffers;
+ data.align = getpagesize();
+ data.uncached = true;
+
+ int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
+ GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP|
+ GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
+
+ if(mSecure) {
+ allocFlags |= GRALLOC_USAGE_PROTECTED;
+ } else {
+ allocFlags |= GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+ GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
+ if((requestType == NEW_REQUEST) && !uiChannel)
+ allocFlags |= GRALLOC_USAGE_PRIVATE_SMI_HEAP;
+ }
+
+ int err = mAlloc->allocate(data, allocFlags, 0);
+ if(err) {
+ reportError("Cant allocate rotatory memory");
+ close(mFD);
+ mFD = -1;
+ close(mRotFD);
+ mRotFD = -1;
+ return false;
+ }
+ mPmemFD = data.fd;
+ mPmemAddr = data.base;
+ mBufferType = data.allocType;
+
+ // Set this flag if source memory is fb
+ if(uiChannel)
+ mRotData.src.flags |= MDP_MEMORY_ID_TYPE_FB;
+
+ mOvDataRot.data.memory_id = mPmemFD;
+ mRotData.dst.memory_id = mPmemFD;
+ mRotData.dst.offset = 0;
+ mNumBuffers = num_buffers;
+ mCurrentItem = 0;
+ for (int i = 0; i < num_buffers; i++)
+ mRotOffset[i] = i * mPmemOffset;
+
+ return true;
+}
+
+bool OverlayDataChannel::updateDataChannel(int size) {
+ mUpdateDataChannel = true;
+ mNewPmemOffset = size;
+ return true;
+}
+
+bool OverlayDataChannel::startDataChannel(int ovid, int rotid, int size,
+ int fbnum, bool norot,
+ bool uichannel, int num_buffers) {
+ memset(&mOvData, 0, sizeof(mOvData));
+ memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+ memset(&mRotData, 0, sizeof(mRotData));
+ mNoRot = norot;
+ mOvData.data.memory_id = -1;
+ mOvData.id = ovid;
+ mOvDataRot = mOvData;
+ mPmemOffset = size;
+ mRotData.session_id = rotid;
+ mNumBuffers = 0;
+ mCurrentItem = 0;
+
+ return openDevices(fbnum, uichannel, num_buffers);
+}
+
+bool OverlayDataChannel::closeDataChannel() {
+ if (!isChannelUP())
+ return true;
+
+ if (!mNoRot && mRotFD > 0) {
+ sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+ memalloc->free_buffer(mPmemAddr, mPmemOffset * mNumBuffers, 0, mPmemFD);
+ close(mPmemFD);
+ mPmemFD = -1;
+ close(mRotFD);
+ mRotFD = -1;
+ }
+ close(mFD);
+ mFD = -1;
+ memset(&mOvData, 0, sizeof(mOvData));
+ memset(&mOvDataRot, 0, sizeof(mOvDataRot));
+ memset(&mRotData, 0, sizeof(mRotData));
+
+ mNumBuffers = 0;
+ mCurrentItem = 0;
+
+ return true;
+}
+
+bool OverlayDataChannel::setFd(int fd) {
+ mOvData.data.memory_id = fd;
+ return true;
+}
+
+bool OverlayDataChannel::queueBuffer(uint32_t offset) {
+ if ((!isChannelUP()) || mOvData.data.memory_id < 0) {
+ reportError("QueueBuffer failed, either channel is not set or no file descriptor to read from");
+ return false;
+ }
+
+ int oldPmemFD = -1;
+ void* oldPmemAddr = MAP_FAILED;
+ uint32_t oldPmemOffset = -1;
+ bool result;
+ if (!mNoRot) {
+ if (mUpdateDataChannel) {
+ oldPmemFD = mPmemFD;
+ oldPmemAddr = mPmemAddr;
+ oldPmemOffset = mPmemOffset;
+ mPmemOffset = mNewPmemOffset;
+ mNewPmemOffset = -1;
+ // Map the new PMEM memory
+ result = mapRotatorMemory(mNumBuffers, 0, UPDATE_REQUEST);
+ if (!result) {
+ LOGE("queueBuffer: mapRotatorMemory failed");
+ return false;
+ }
+ mUpdateDataChannel = false;
+ }
+ }
+
+ result = queue(offset);
+
+ // Unmap the old PMEM memory after the queueBuffer has returned
+ if (oldPmemFD != -1 && oldPmemAddr != MAP_FAILED) {
+ sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+ memalloc->free_buffer(oldPmemAddr, oldPmemOffset * mNumBuffers, 0, oldPmemFD);
+ oldPmemFD = -1;
+ }
+ return result;
+}
+
+bool OverlayDataChannel::queue(uint32_t offset) {
+ msmfb_overlay_data *odPtr;
+ mOvData.data.offset = offset;
+ odPtr = &mOvData;
+ if (!mNoRot) {
+ mRotData.src.memory_id = mOvData.data.memory_id;
+ mRotData.src.offset = offset;
+ mRotData.dst.offset = (mRotData.dst.offset) ? 0 : mPmemOffset;
+ mRotData.dst.offset = mRotOffset[mCurrentItem];
+ mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
+
+ int result = ioctl(mRotFD,
+ MSM_ROTATOR_IOCTL_ROTATE, &mRotData);
+
+ if (!result) {
+ mOvDataRot.data.offset = (uint32_t) mRotData.dst.offset;
+ odPtr = &mOvDataRot;
+ }
+ }
+
+ if (ioctl(mFD, MSMFB_OVERLAY_PLAY, odPtr)) {
+ reportError("overlay play failed.");
+ return false;
+ }
+
+ return true;
+}
+
+bool OverlayDataChannel::waitForHdmiVsync() {
+ if (!isChannelUP()) {
+ LOGE("%s: channel not up", __FUNCTION__);
+ return false;
+ }
+ if (ioctl(mFD, MSMFB_OVERLAY_PLAY_WAIT, &mOvData)) {
+ LOGE("%s: MSMFB_OVERLAY_PLAY_WAIT failed", __FUNCTION__);
+ return false;
+ }
+ return true;
+}
+
+bool OverlayDataChannel::getCropS3D(overlay_rect *inRect, int channel, int format,
+ overlay_rect *rect) {
+ // for the 3D usecase extract channels from a frame
+ switch (format & INPUT_MASK_3D) {
+ case HAL_3D_IN_SIDE_BY_SIDE_L_R:
+ if(channel == 0) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = inRect->w/2;
+ rect->h = inRect->h;
+ } else {
+ rect->x = inRect->w/2;
+ rect->y = 0;
+ rect->w = inRect->w/2;
+ rect->h = inRect->h;
+ }
+ break;
+ case HAL_3D_IN_SIDE_BY_SIDE_R_L:
+ if(channel == 1) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = inRect->w/2;
+ rect->h = inRect->h;
+ } else {
+ rect->x = inRect->w/2;
+ rect->y = 0;
+ rect->w = inRect->w/2;
+ rect->h = inRect->h;
+ }
+ break;
+ case HAL_3D_IN_TOP_BOTTOM:
+ if(channel == 0) {
+ rect->x = 0;
+ rect->y = 0;
+ rect->w = inRect->w;
+ rect->h = inRect->h/2;
+ } else {
+ rect->x = 0;
+ rect->y = inRect->h/2;
+ rect->w = inRect->w;
+ rect->h = inRect->h/2;
+ }
+ break;
+ case HAL_3D_IN_INTERLEAVE:
+ break;
+ default:
+ reportError("Unsupported 3D format...");
+ break;
+ }
+ return true;
+}
+
+bool OverlayDataChannel::setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h) {
+ if (!isChannelUP()) {
+ reportError("Channel not set");
+ return false;
+ }
+
+ mdp_overlay ov;
+ ov.id = mOvData.id;
+ if (ioctl(mFD, MSMFB_OVERLAY_GET, &ov)) {
+ reportError("setCrop, overlay GET failed");
+ return false;
+ }
+
+ if ((ov.user_data[0] == MDP_ROT_90) ||
+ (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_UD)) ||
+ (ov.user_data[0] == (MDP_ROT_90 | MDP_FLIP_LR))){
+ if (ov.src.width < (y + h))
+ return false;
+
+ uint32_t tmp = x;
+ x = ov.src.width - (y + h);
+ y = tmp;
+
+ tmp = w;
+ w = h;
+ h = tmp;
+ }
+ else if (ov.user_data[0] == MDP_ROT_270) {
+ if (ov.src.height < (x + w))
+ return false;
+
+ uint32_t tmp = y;
+ y = ov.src.height - (x + w);
+ x = tmp;
+
+ tmp = w;
+ w = h;
+ h = tmp;
+ }
+ else if(ov.user_data[0] == MDP_ROT_180) {
+ if ((ov.src.height < (y + h)) || (ov.src.width < ( x + w)))
+ return false;
+
+ x = ov.src.width - (x + w);
+ y = ov.src.height - (y + h);
+ }
+
+
+ normalize_crop(x, w);
+ normalize_crop(y, h);
+
+ if ((ov.src_rect.x == x) &&
+ (ov.src_rect.y == y) &&
+ (ov.src_rect.w == w) &&
+ (ov.src_rect.h == h))
+ return true;
+
+ ov.src_rect.x = x;
+ ov.src_rect.y = y;
+ ov.src_rect.w = w;
+ ov.src_rect.h = h;
+
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+ // can not scale-up 8 times over original source
+ // return false to compose with GPU
+#if 1
+ if(ov.dst_rect.w > (ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ LOGE("[TJ] setCrop : too big width, back to GPU comp %d => %d", ov.src_rect.w, ov.dst_rect.w);
+ return false;
+ }
+ if(ov.dst_rect.h > (ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ LOGE("[TJ] setCrop : too big height, back to GPU comp %d => %d", ov.src_rect.h, ov.dst_rect.h);
+ return false;
+ }
+#else
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ /* Scaling of upto a max of 8 times supported */
+ if(ov.dst_rect.w >(ov.src_rect.w * HW_OVERLAY_MAGNIFICATION_LIMIT)){
+ ov.dst_rect.w = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.w;
+ }
+ if(ov.dst_rect.h >(ov.src_rect.h * HW_OVERLAY_MAGNIFICATION_LIMIT)) {
+ ov.dst_rect.h = HW_OVERLAY_MAGNIFICATION_LIMIT * ov.src_rect.h;
+ }
+// LGE_CHANGE_S, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents {
+#endif
+
+ LOGE("setCrop");
+ dump(ov);
+// LGE_CHANGE_E, [G1_Player][mukyung.jung@lge.com], 20120206, Apply SR 00718706 to fix noise of QCIF contents }
+
+ if (ioctl(mFD, MSMFB_OVERLAY_SET, &ov)) {
+ reportError("setCrop, overlay set error");
+ dump(ov);
+ return false;
+ }
+
+ return true;
+}
+
+/* setVisualParam can be called to set the configuration value of a post
+ * processing feature (HUE,SATURATION,BRIGHTNESS,CONTRAST,SMOOTHING/SHARPENING)
+ * for the first 4, the setting will stay set until the parameter is changed
+ * by another call to setVisualParam with that same paramType */
+void Overlay::setVisualParam(int8_t paramType, float paramValue) {
+ switch (mState) {
+ case OV_UI_MIRROR_TV:
+ case OV_2D_VIDEO_ON_PANEL:
+ case OV_3D_VIDEO_2D_PANEL:
+ // set the parameter value for the given parameter type.
+ if(!objOvCtrlChannel[VG0_PIPE].setVisualParam(paramType, paramValue)) {
+ LOGE("Failed to set param %d for value %f", paramType, paramValue);
+ }
+ break;
+ case OV_2D_VIDEO_ON_TV:
+ case OV_3D_VIDEO_3D_PANEL:
+ case OV_3D_VIDEO_2D_TV:
+ case OV_3D_VIDEO_3D_TV:
+ for (int i=0; i<NUM_CHANNELS; i++) {
+ //setting the value for the given parameter on each pipe (i.e. for
+ //both video pipes)
+ if(!objOvCtrlChannel[i].setVisualParam(paramType, paramValue)) {
+ LOGE("Failed to set param %d for value %f", paramType, paramValue);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* Finalizes the parameter value in the hsic_cfg structure*/
+int OverlayControlChannel::commitVisualParam(int8_t paramType, float paramValue) {
+#ifdef USES_POST_PROCESSING
+ switch(paramType) {
+ case SET_HUE:
+ //API expects param within range -180 - 180
+ CAP_RANGE(paramValue, HUE_RANGE, -HUE_RANGE);
+ hsic_cfg.hue = (int32_t) paramValue;
+ break;
+ case SET_BRIGHTNESS:
+ //API expects param within range -255 - 255
+ CAP_RANGE(paramValue, BRIGHTNESS_RANGE, -BRIGHTNESS_RANGE);
+ hsic_cfg.intensity = (int32_t) paramValue;
+ break;
+ case SET_SATURATION:
+ //API expects param within range -1 - 1
+ CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
+ hsic_cfg.sat = paramValue;
+ break;
+ case SET_CONTRAST:
+ //API expects param within range -1 - 1
+ CAP_RANGE(paramValue, CON_SAT_RANGE, -CON_SAT_RANGE);
+ hsic_cfg.contrast = paramValue;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+#endif
+ return -1;
+}
+
+/* Converts paramValue to the expected range for each paramType, */
+bool OverlayControlChannel::setVisualParam(int8_t paramType, float paramValue)
+{
+ if (!isChannelUP()) {
+ LOGE("%s: Channel not set", __FUNCTION__);
+ return false;
+ }
+
+ bool setFlag = false;
+
+ //Sharpness values range from -128 to 127
+ //Integer values must be converted accordingly
+
+ int8_t value;
+ if (paramType == SET_SHARPNESS) {
+ //binding paramValue to the limits of its range.
+ CAP_RANGE(paramValue, SHARPNESS_RANGE, -SHARPNESS_RANGE);
+ value = paramValue * NUM_SHARPNESS_VALS - (NUM_SHARPNESS_VALS / 2);
+ }
+
+ uint32_t block = MDP_BLOCK_MAX;
+
+ //tranlate mOVInfo.id into block type for pp_conv
+ switch(mOVInfo.id) {
+ case 3:
+ // 3 is the pipe_ndx given when OVERLAY_PIPE_VG1 is used
+ block = MDP_BLOCK_VG_1;
+ break;
+ case 4:
+ // 4 is the pipe_ndx given when OVERLAY_PIPE_VG2 is used
+ block = MDP_BLOCK_VG_2;
+ break;
+ default:
+ LOGE("%s: Invalid HSIC overlay id",__FUNCTION__);
+ }
+
+ //save the paramValue to hsic_cfg
+ commitVisualParam(paramType, paramValue);
+#ifdef USES_POST_PROCESSING
+ //calling our user space library to configure the post processing color
+ //conversion (does Hue, Saturation, Brightness, and Contrast adjustment)
+ display_pp_conv_set_cfg(block, &hsic_cfg);
+#endif
+ mdp_overlay overlay;
+
+ switch(paramType) {
+ case SET_NONE:
+ return true;
+ case SET_SHARPNESS:
+ if (ioctl(mFD, MSMFB_OVERLAY_GET, &overlay)) {
+ reportError("setVisualParam, overlay GET failed");
+ return false;
+ }
+ if (overlay.dpp.sharp_strength != value) {
+ mOVInfo.flags |= MDP_SHARPENING;
+ mOVInfo.dpp.sharp_strength = value;
+ setFlag = true;
+ }
+ break;
+ case RESET_ALL:
+ //set all visual params to a default value
+ //passed in from the app
+ mOVInfo.flags |= MDP_SHARPENING;
+ mOVInfo.dpp.sharp_strength = value;
+ setFlag = true;
+ break;
+ default:
+ return false;
+ }
+ if (setFlag) {
+ if (ioctl(mFD, MSMFB_OVERLAY_SET, &mOVInfo)) {
+ reportError("setVisualParam, overlay set failed");
+ dump(mOVInfo);
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/liboverlay/overlayLib.h b/liboverlay/overlayLib.h
new file mode 100755
index 0000000..65b134c
--- /dev/null
+++ b/liboverlay/overlayLib.h
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2010-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 INCLUDE_OVERLAY_LIB
+#define INCLUDE_OVERLAY_LIB
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+#include <linux/msm_rotator.h>
+#include <linux/android_pmem.h>
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <utils/threads.h>
+#include <utils/RefBase.h>
+#include <alloc_controller.h>
+#include <memalloc.h>
+
+#ifdef USES_POST_PROCESSING
+#include "lib-postproc.h"
+#endif
+
+#define HW_OVERLAY_MAGNIFICATION_LIMIT 8
+#define HW_OVERLAY_MINIFICATION_LIMIT HW_OVERLAY_MAGNIFICATION_LIMIT
+
+#define EVEN_OUT(x) if (x & 0x0001) {x--;}
+#define NO_PIPE -1
+#define VG0_PIPE 0
+#define VG1_PIPE 1
+#define NUM_CHANNELS 2
+#define NUM_FB_DEVICES 3
+#define FRAMEBUFFER_0 0
+#define FRAMEBUFFER_1 1
+#define FRAMEBUFFER_2 2
+#define NUM_SHARPNESS_VALS 256
+#define SHARPNESS_RANGE 1.0f
+#define HUE_RANGE 180
+#define BRIGHTNESS_RANGE 255
+#define CON_SAT_RANGE 1.0f
+#define CAP_RANGE(value,max,min) do { if (value - min < -0.0001)\
+ {value = min;}\
+ else if(value - max > 0.0001)\
+ {value = max;}\
+ } while(0);
+
+enum {
+ HDMI_OFF,
+ HDMI_ON
+};
+
+enum {
+ OVERLAY_CHANNEL_DOWN,
+ OVERLAY_CHANNEL_UP
+};
+
+enum {
+ NEW_REQUEST,
+ UPDATE_REQUEST
+};
+
+enum {
+ WAIT_FOR_VSYNC = 1<<0,
+ DISABLE_FRAMEBUFFER_FETCH = 1<<1,
+ INTERLACED_CONTENT = 1<<2,
+ OVERLAY_PIPE_SHARE = 1<<3,
+ SECURE_OVERLAY_SESSION = 1<<4,
+};
+
+/* ------------------------------- 3D defines ---------------------------------------*/
+// The compound format passed to the overlay is
+// ABCCC where A is the input 3D format,
+// B is the output 3D format
+// CCC is the color format e.g YCbCr420SP YCrCb420SP etc.
+#define FORMAT_3D(x) (x & 0xFF000)
+#define COLOR_FORMAT(x) (x & 0xFFF)
+// in the final 3D format, the MSB 2Bytes are the input format and the
+// LSB 2bytes are the output format. Shift the output byte 12 bits.
+#define SHIFT_OUTPUT_3D 12
+#define FORMAT_3D_OUTPUT(x) ((x & 0xF000) >> SHIFT_OUTPUT_3D)
+#define FORMAT_3D_INPUT(x) (x & 0xF0000)
+#define INPUT_MASK_3D 0xFFFF0000
+#define OUTPUT_MASK_3D 0x0000FFFF
+#define SHIFT_3D 16
+// The output format is the 2MSB bytes. Shift the format by 12 to reflect this
+#define HAL_3D_OUT_SIDE_BY_SIDE_MASK (HAL_3D_OUT_SIDE_BY_SIDE >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_TOP_BOTTOM_MASK (HAL_3D_OUT_TOP_BOTTOM >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_INTERLEAVE_MASK (HAL_3D_OUT_INTERLEAVE >> SHIFT_OUTPUT_3D)
+#define HAL_3D_OUT_MONOSCOPIC_MASK (HAL_3D_OUT_MONOSCOPIC >> SHIFT_OUTPUT_3D)
+
+// 3D panel barrier orientation
+#define BARRIER_LANDSCAPE 1
+#define BARRIER_PORTRAIT 2
+
+#ifdef HDMI_AS_PRIMARY
+#define FORMAT_3D_FILE "/sys/class/graphics/fb0/format_3d"
+#define EDID_3D_INFO_FILE "/sys/class/graphics/fb0/3d_present"
+#else
+#define FORMAT_3D_FILE "/sys/class/graphics/fb1/format_3d"
+#define EDID_3D_INFO_FILE "/sys/class/graphics/fb1/3d_present"
+#endif
+#define BARRIER_FILE "/sys/devices/platform/mipi_novatek.0/enable_3d_barrier"
+/* -------------------------- end 3D defines ----------------------------------------*/
+
+// Struct to hold the buffer info: geometry and size
+struct overlay_buffer_info {
+ int width;
+ int height;
+ int format;
+ int size;
+};
+
+using android::Mutex;
+namespace overlay {
+
+#define FB_DEVICE_TEMPLATE "/dev/graphics/fb%u"
+
+ //Utility Class to query the framebuffer info
+ class FrameBufferInfo {
+ int mFBWidth;
+ int mFBHeight;
+ bool mBorderFillSupported;
+ static FrameBufferInfo *sFBInfoInstance;
+
+ FrameBufferInfo():mFBWidth(0),mFBHeight(0), mBorderFillSupported(false) {
+ char const * const device_name =
+ "/dev/graphics/fb0";
+ int fd = open(device_name, O_RDWR, 0);
+ mdp_overlay ov;
+ memset(&ov, 0, sizeof(ov));
+ if (fd < 0) {
+ LOGE("FrameBufferInfo: Cant open framebuffer ");
+ return;
+ }
+ fb_var_screeninfo vinfo;
+ if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ LOGE("FrameBufferInfo: FBIOGET_VSCREENINFO on fb0 failed");
+ close(fd);
+ fd = -1;
+ return;
+ }
+ ov.id = 1;
+ if(ioctl(fd, MSMFB_OVERLAY_GET, &ov)) {
+ LOGE("FrameBufferInfo: MSMFB_OVERLAY_GET on fb0 failed");
+ close(fd);
+ fd = -1;
+ return;
+ }
+ close(fd);
+ fd = -1;
+ mFBWidth = vinfo.xres;
+ mFBHeight = vinfo.yres;
+ mBorderFillSupported = (ov.flags & MDP_BORDERFILL_SUPPORTED) ?
+ true : false;
+ }
+ public:
+ static FrameBufferInfo* getInstance(){
+ if (!sFBInfoInstance){
+ sFBInfoInstance = new FrameBufferInfo;
+ }
+ return sFBInfoInstance;
+ }
+ int getWidth() const { return mFBWidth; }
+ int getHeight() const { return mFBHeight; }
+ bool canSupportTrueMirroring() const {
+ return mBorderFillSupported; }
+ };
+
+enum {
+ OV_UI_MIRROR_TV = 0,
+ OV_2D_VIDEO_ON_PANEL,
+ OV_2D_VIDEO_ON_TV,
+ OV_3D_VIDEO_2D_PANEL,
+ OV_3D_VIDEO_2D_TV,
+ OV_3D_VIDEO_3D_PANEL,
+ OV_3D_VIDEO_3D_TV
+};
+bool isHDMIConnected();
+bool is3DTV();
+bool isPanel3D();
+bool usePanel3D();
+bool send3DInfoPacket(unsigned int format3D);
+bool enableBarrier(unsigned int orientation);
+unsigned int getOverlayConfig (unsigned int format3D, bool poll = true,
+ bool isHDMI = false);
+int getColorFormat(int format);
+bool isInterlacedContent(int format);
+int get_mdp_format(int format);
+int get_size(int format, int w, int h);
+int get_rot_output_format(int format);
+int get_mdp_orientation(int value);
+void normalize_crop(uint32_t& xy, uint32_t& wh);
+//Initializes the overlay - cleans up any existing overlay pipes
+int initOverlay();
+
+/* Print values being sent to driver in case of ioctl failures
+ These logs are enabled only if DEBUG_OVERLAY is true */
+void dump(msm_rotator_img_info& mRotInfo);
+void dump(mdp_overlay& mOvInfo);
+const char* getFormatString(int format);
+
+ //singleton class to decide the z order of new overlay surfaces
+ class ZOrderManager {
+ bool mFB0Pipes[NUM_CHANNELS];
+ bool mFB1Pipes[NUM_CHANNELS+1]; //FB1 can have 3 pipes
+ int mPipesInuse; // Holds the number of pipes in use
+ int mMaxPipes; // Max number of pipes
+ static ZOrderManager *sInstance;
+ Mutex *mObjMutex;
+ ZOrderManager(){
+ mPipesInuse = 0;
+ // for true mirroring support there can be 3 pipes on secondary
+ mMaxPipes = FrameBufferInfo::getInstance()->canSupportTrueMirroring()?
+ NUM_CHANNELS+1 : NUM_CHANNELS;
+ for (int i = 0; i < NUM_CHANNELS; i++)
+ mFB0Pipes[i] = false;
+ for (int j = 0; j < mMaxPipes; j++)
+ mFB1Pipes[j] = false;
+ mObjMutex = new Mutex();
+ }
+ ~ZOrderManager() {
+ delete sInstance;
+ delete mObjMutex;
+ }
+ public:
+ static ZOrderManager* getInstance(){
+ if (!sInstance){
+ sInstance = new ZOrderManager;
+ }
+ return sInstance;
+ }
+ int getZ(int fbnum);
+ void decZ(int fbnum, int zorder);
+ };
+const int max_num_buffers = 3;
+typedef struct mdp_rect overlay_rect;
+
+class OverlayControlChannel {
+
+enum {
+ SET_NONE = 0,
+ SET_SHARPNESS,
+#ifdef USES_POST_PROCESSING
+ SET_HUE,
+ SET_BRIGHTNESS,
+ SET_SATURATION,
+ SET_CONTRAST,
+#endif
+ RESET_ALL,
+};
+ bool mNoRot;
+ int mFBNum;
+ int mFBWidth;
+ int mFBHeight;
+ int mFBbpp;
+ int mFBystride;
+ int mFormat;
+ int mFD;
+ int mRotFD;
+ int mSize;
+ int mOrientation;
+ unsigned int mFormat3D;
+ bool mUIChannel;
+#ifdef USES_POST_PROCESSING
+ struct display_pp_conv_cfg hsic_cfg;
+#endif
+ mdp_overlay mOVInfo;
+ msm_rotator_img_info mRotInfo;
+ msmfb_overlay_3d m3DOVInfo;
+ bool mIsChannelUpdated;
+ bool openDevices(int fbnum = -1);
+ bool setOverlayInformation(const overlay_buffer_info& info,
+ int zorder = 0, int flags = 0,
+ int requestType = NEW_REQUEST);
+ bool startOVRotatorSessions(const overlay_buffer_info& info, int requestType);
+ void swapOVRotWidthHeight();
+ int commitVisualParam(int8_t paramType, float paramValue);
+ void setInformationFromFlags(int flags, mdp_overlay& ov);
+
+public:
+ OverlayControlChannel();
+ ~OverlayControlChannel();
+ bool startControlChannel(const overlay_buffer_info& info,
+ int fbnum, bool norot = false,
+ bool uichannel = false,
+ unsigned int format3D = 0, int zorder = 0,
+ int flags = 0);
+ bool closeControlChannel();
+ bool setPosition(int x, int y, uint32_t w, uint32_t h);
+ bool setTransform(int value, bool fetch = true);
+ void setSize (int size) { mSize = size; }
+ bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h);
+ bool getOvSessionID(int& sessionID) const;
+ bool getRotSessionID(int& sessionID) const;
+ bool getSize(int& size) const;
+ bool isChannelUP() const { return (mFD > 0); }
+ int getFBWidth() const { return mFBWidth; }
+ int getFBHeight() const { return mFBHeight; }
+ int getFormat3D() const { return mFormat3D; }
+ bool getOrientation(int& orientation) const;
+ bool updateOverlayFlags(int flags);
+ bool getAspectRatioPosition(int w, int h, overlay_rect *rect);
+ // Calculates the aspect ratio for video on HDMI based on primary
+ // aspect ratio used in case of true mirroring
+ bool getAspectRatioPosition(int w, int h, int orientation,
+ overlay_rect *inRect, overlay_rect *outRect);
+ bool getPositionS3D(int channel, int format, overlay_rect *rect);
+ bool updateOverlaySource(const overlay_buffer_info& info, int orientation, int flags);
+ bool getFormat() const { return mFormat; }
+ bool setVisualParam(int8_t paramType, float paramValue);
+ bool useVirtualFB ();
+ bool doFlagsNeedUpdate(int flags);
+};
+
+class OverlayDataChannel {
+
+ bool mNoRot;
+ bool mSecure;
+ int mFD;
+ int mRotFD;
+ int mPmemFD;
+ void* mPmemAddr;
+ uint32_t mPmemOffset;
+ uint32_t mNewPmemOffset;
+ msmfb_overlay_data mOvData;
+ msmfb_overlay_data mOvDataRot;
+ msm_rotator_data_info mRotData;
+ int mRotOffset[max_num_buffers];
+ int mCurrentItem;
+ int mNumBuffers;
+ bool mUpdateDataChannel;
+ android::sp<gralloc::IAllocController> mAlloc;
+ int mBufferType;
+
+ bool openDevices(int fbnum = -1, bool uichannel = false, int num_buffers = 2);
+ bool mapRotatorMemory(int num_buffers, bool uiChannel, int requestType);
+ bool queue(uint32_t offset);
+
+public:
+ OverlayDataChannel();
+ ~OverlayDataChannel();
+ bool startDataChannel(const OverlayControlChannel& objOvCtrlChannel,
+ int fbnum, bool norot = false, bool secure = false,
+ bool uichannel = false, int num_buffers = 2);
+ bool startDataChannel(int ovid, int rotid, int size,
+ int fbnum, bool norot = false, bool uichannel = false,
+ int num_buffers = 2);
+ bool closeDataChannel();
+ bool setFd(int fd);
+ bool queueBuffer(uint32_t offset);
+ bool waitForHdmiVsync();
+ bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+ bool getCropS3D(overlay_rect *inRect, int channel, int format, overlay_rect *rect);
+ bool isChannelUP() const { return (mFD > 0); }
+ bool updateDataChannel(int size);
+};
+
+/*
+ * Overlay class for single thread application
+ * A multiple thread/process application need to use Overlay HAL
+ */
+class Overlay {
+
+ bool mChannelUP;
+ //stores the connected external display Ex: HDMI(1) WFD(2)
+ int mExternalDisplay;
+ unsigned int mS3DFormat;
+ //Actual cropped source width and height of overlay
+ int mCroppedSrcWidth;
+ int mCroppedSrcHeight;
+ overlay_buffer_info mOVBufferInfo;
+ int mState;
+ // Stores the current device orientation
+ int mDevOrientation;
+ OverlayControlChannel objOvCtrlChannel[2];
+ OverlayDataChannel objOvDataChannel[2];
+
+public:
+ Overlay();
+ ~Overlay();
+
+ static bool sHDMIAsPrimary;
+ bool startChannel(const overlay_buffer_info& info, int fbnum, bool norot = false,
+ bool uichannel = false, unsigned int format3D = 0,
+ int channel = 0, int flags = 0,
+ int num_buffers = 2);
+ bool closeChannel();
+ bool setDeviceOrientation(int orientation);
+ bool setPosition(int x, int y, uint32_t w, uint32_t h);
+ bool setTransform(int value);
+ bool setOrientation(int value, int channel = 0);
+ bool setFd(int fd, int channel = 0);
+ bool queueBuffer(uint32_t offset, int channel = 0);
+ bool getPosition(int& x, int& y, uint32_t& w, uint32_t& h, int channel = 0);
+ bool isChannelUP() const { return mChannelUP; }
+ int getFBWidth(int channel = 0) const;
+ int getFBHeight(int channel = 0) const;
+ bool getOrientation(int& orientation, int channel = 0) const;
+ bool queueBuffer(buffer_handle_t buffer);
+ bool setSource(const overlay_buffer_info& info, int orientation, int hdmiConnected,
+ int flags, int numBuffers = 2);
+ bool getAspectRatioPosition(int w, int h, overlay_rect *rect, int channel = 0);
+ bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
+ bool updateOverlayFlags(int flags);
+ void setVisualParam(int8_t paramType, float paramValue);
+ bool waitForHdmiVsync(int channel);
+ int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
+ void closeExternalChannel();
+private:
+ bool setChannelPosition(int x, int y, uint32_t w, uint32_t h, int channel = 0);
+ bool setChannelCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h, int channel);
+ bool queueBuffer(int fd, uint32_t offset, int channel);
+ bool updateOverlaySource(const overlay_buffer_info& info, int orientation, int flags);
+ int getS3DFormat(int format);
+};
+
+struct overlay_shared_data {
+ volatile bool isControlSetup;
+ unsigned int state;
+ int rotid[2];
+ int ovid[2];
+};
+};
+#endif
diff --git a/liboverlay/overlayLibUI.cpp b/liboverlay/overlayLibUI.cpp
new file mode 100755
index 0000000..d3fd80a
--- /dev/null
+++ b/liboverlay/overlayLibUI.cpp
@@ -0,0 +1,482 @@
+/*
+ * Copyright (C) 2008 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 "overlayLibUI.h"
+#include "gralloc_priv.h"
+#define LOG_TAG "OverlayUI"
+
+using android::sp;
+using gralloc::IMemAlloc;
+using gralloc::alloc_data;
+
+namespace {
+/* helper functions */
+void swapOVRotWidthHeight(msm_rotator_img_info& rotInfo,
+ mdp_overlay& ovInfo) {
+ int srcWidth = ovInfo.src.width;
+ ovInfo.src.width = ovInfo.src.height;
+ ovInfo.src.height = srcWidth;
+
+ int srcRectWidth = ovInfo.src_rect.w;
+ ovInfo.src_rect.w = ovInfo.src_rect.h;
+ ovInfo.src_rect.h = srcRectWidth;
+
+ int dstWidth = rotInfo.dst.width;
+ rotInfo.dst.width = rotInfo.dst.height;
+ rotInfo.dst.height = dstWidth;
+}
+
+bool isRGBType(int format) {
+ bool ret = false;
+ switch(format) {
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ case MDP_RGB_565:
+ ret = true;
+ break;
+ default:
+ ret = false;
+ break;
+ }
+ return ret;
+}
+
+int getRGBBpp(int format) {
+ int ret = -1;
+ switch(format) {
+ case MDP_RGBA_8888:
+ case MDP_BGRA_8888:
+ case MDP_RGBX_8888:
+ ret = 4;
+ break;
+ case MDP_RGB_565:
+ ret = 2;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+
+ return ret;
+}
+
+bool turnOFFVSync() {
+ static int swapIntervalPropVal = -1;
+ if (swapIntervalPropVal == -1) {
+ char pval[PROPERTY_VALUE_MAX];
+ property_get("debug.gr.swapinterval", pval, "1");
+ swapIntervalPropVal = atoi(pval);
+ }
+ return (swapIntervalPropVal == 0);
+}
+
+};
+
+namespace overlay {
+
+status_t Display::openDisplay(int fbnum) {
+ if (mFD != NO_INIT)
+ return NO_ERROR;
+
+ status_t ret = NO_INIT;
+ char dev_name[64];
+ snprintf(dev_name, 64, FB_DEVICE_TEMPLATE, fbnum);
+
+ mFD = open(dev_name, O_RDWR, 0);
+ if (mFD < 0) {
+ LOGE("Failed to open FB %d", fbnum);
+ return ret;
+ }
+
+ fb_var_screeninfo vinfo;
+ if (ioctl(mFD, FBIOGET_VSCREENINFO, &vinfo)) {
+ LOGE("FBIOGET_VSCREENINFO on failed on FB %d", fbnum);
+ close(mFD);
+ mFD = NO_INIT;
+ return ret;
+ }
+
+ mFBWidth = vinfo.xres;
+ mFBHeight = vinfo.yres;
+ mFBBpp = vinfo.bits_per_pixel;
+ ret = NO_ERROR;
+
+ return ret;
+}
+
+void Display::closeDisplay() {
+ close(mFD);
+ mFD = NO_INIT;
+}
+
+Rotator::Rotator() : mFD(NO_INIT), mSessionID(NO_INIT), mPmemFD(NO_INIT)
+{
+ mAlloc = gralloc::IAllocController::getInstance(false);
+}
+
+Rotator::~Rotator()
+{
+ closeRotSession();
+}
+
+status_t Rotator::startRotSession(msm_rotator_img_info& rotInfo,
+ int size, int numBuffers) {
+ status_t ret = NO_ERROR;
+ if (mSessionID == NO_INIT && mFD == NO_INIT) {
+ mNumBuffers = numBuffers;
+ mFD = open("/dev/msm_rotator", O_RDWR, 0);
+ if (mFD < 0) {
+ LOGE("Couldnt open rotator device");
+ return NO_INIT;
+ }
+
+ if (ioctl(mFD, MSM_ROTATOR_IOCTL_START, &rotInfo)) {
+ close(mFD);
+ mFD = NO_INIT;
+ return NO_INIT;
+ }
+
+ mSessionID = rotInfo.session_id;
+ alloc_data data;
+ data.base = 0;
+ data.fd = -1;
+ data.offset = 0;
+ data.size = mSize * mNumBuffers;
+ data.align = getpagesize();
+ data.uncached = true;
+
+ int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
+ GRALLOC_USAGE_PRIVATE_WRITEBACK_HEAP |
+ GRALLOC_USAGE_PRIVATE_ADSP_HEAP |
+ GRALLOC_USAGE_PRIVATE_IOMMU_HEAP |
+ GRALLOC_USAGE_PRIVATE_SMI_HEAP |
+ GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
+
+ int err = mAlloc->allocate(data, allocFlags, 0);
+
+ if(err) {
+ LOGE("%s: Can't allocate rotator memory", __func__);
+ closeRotSession();
+ return NO_INIT;
+ }
+ mPmemFD = data.fd;
+ mPmemAddr = data.base;
+ mBufferType = data.allocType;
+
+ mCurrentItem = 0;
+ for (int i = 0; i < mNumBuffers; i++)
+ mRotOffset[i] = i * mSize;
+ ret = NO_ERROR;
+ }
+ return ret;
+}
+
+status_t Rotator::closeRotSession() {
+ if (mSessionID != NO_INIT && mFD != NO_INIT) {
+ ioctl(mFD, MSM_ROTATOR_IOCTL_FINISH, &mSessionID);
+ close(mFD);
+ if (NO_INIT != mPmemFD) {
+ sp<IMemAlloc> memalloc = mAlloc->getAllocator(mBufferType);
+ memalloc->free_buffer(mPmemAddr, mSize * mNumBuffers, 0, mPmemFD);
+ close(mPmemFD);
+ }
+ }
+
+ mFD = NO_INIT;
+ mSessionID = NO_INIT;
+ mPmemFD = NO_INIT;
+ mPmemAddr = MAP_FAILED;
+
+ return NO_ERROR;
+}
+
+status_t Rotator::rotateBuffer(msm_rotator_data_info& rotData) {
+ status_t ret = NO_INIT;
+ if (mSessionID != NO_INIT) {
+ rotData.dst.memory_id = mPmemFD;
+ rotData.dst.offset = mRotOffset[mCurrentItem];
+ rotData.session_id = mSessionID;
+ mCurrentItem = (mCurrentItem + 1) % mNumBuffers;
+ if (ioctl(mFD, MSM_ROTATOR_IOCTL_ROTATE, &rotData)) {
+ LOGE("Rotator failed to rotate");
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+ }
+
+ return ret;
+}
+
+//===================== OverlayUI =================//
+
+OverlayUI::OverlayUI() : mChannelState(CLOSED), mOrientation(NO_INIT),
+ mFBNum(NO_INIT), mZorder(NO_INIT), mWaitForVsync(false), mIsFg(false),
+ mSessionID(NO_INIT), mParamsChanged(false) {
+ memset(&mOvInfo, 0, sizeof(mOvInfo));
+ memset(&mRotInfo, 0, sizeof(mRotInfo));
+}
+
+OverlayUI::~OverlayUI() {
+ closeChannel();
+}
+
+void OverlayUI::setSource(const overlay_buffer_info& info, int orientation) {
+ status_t ret = NO_INIT;
+ int format3D = FORMAT_3D(info.format);
+ int colorFormat = COLOR_FORMAT(info.format);
+ int format = get_mdp_format(colorFormat);
+
+ if (format3D || !isRGBType(format)) {
+ LOGE("%s: Unsupported format", __func__);
+ return;
+ }
+
+ mParamsChanged |= (mSource.width ^ info.width) ||
+ (mSource.height ^ info.height) ||
+ (mSource.format ^ format) ||
+ (mSource.size ^ info.size) ||
+ (mOrientation ^ orientation);
+
+ mSource.width = info.width;
+ mSource.height = info.height;
+ mSource.format = format;
+ mSource.size = info.size;
+ mOrientation = orientation;
+ setupOvRotInfo();
+}
+
+void OverlayUI::setDisplayParams(int fbNum, bool waitForVsync, bool isFg, int
+ zorder, bool isVGPipe) {
+ int flags = 0;
+
+ if(false == waitForVsync)
+ flags |= MDP_OV_PLAY_NOWAIT;
+ else
+ flags &= ~MDP_OV_PLAY_NOWAIT;
+
+ if(isVGPipe)
+ flags |= MDP_OV_PIPE_SHARE;
+ else
+ flags &= ~MDP_OV_PIPE_SHARE;
+
+ if (turnOFFVSync())
+ flags |= MDP_OV_PLAY_NOWAIT;
+
+ mParamsChanged |= (mFBNum ^ fbNum) ||
+ (mOvInfo.is_fg ^ isFg) ||
+ (mOvInfo.flags ^ flags) ||
+ (mOvInfo.z_order ^ zorder);
+
+ mFBNum = fbNum;
+ mOvInfo.is_fg = isFg;
+ mOvInfo.flags = flags;
+ mOvInfo.z_order = zorder;
+
+ mobjDisplay.openDisplay(mFBNum);
+}
+
+void OverlayUI::setPosition(int x, int y, int w, int h) {
+ mParamsChanged |= (mOvInfo.dst_rect.x ^ x) ||
+ (mOvInfo.dst_rect.y ^ y) ||
+ (mOvInfo.dst_rect.w ^ w) ||
+ (mOvInfo.dst_rect.h ^ h);
+
+ mOvInfo.dst_rect.x = x;
+ mOvInfo.dst_rect.y = y;
+ mOvInfo.dst_rect.w = w;
+ mOvInfo.dst_rect.h = h;
+}
+
+void OverlayUI::setCrop(int x, int y, int w, int h) {
+ mParamsChanged |= (mOvInfo.src_rect.x ^ x) ||
+ (mOvInfo.src_rect.y ^ y) ||
+ (mOvInfo.src_rect.w ^ w) ||
+ (mOvInfo.src_rect.h ^ h);
+
+ mOvInfo.src_rect.x = x;
+ mOvInfo.src_rect.y = y;
+ mOvInfo.src_rect.w = w;
+ mOvInfo.src_rect.h = h;
+}
+
+void OverlayUI::setupOvRotInfo() {
+ int w = mSource.width;
+ int h = mSource.height;
+ int format = mSource.format;
+ int srcw = (w + 31) & ~31;
+ int srch = (h + 31) & ~31;
+ mOvInfo.src.width = srcw;
+ mOvInfo.src.height = srch;
+ mOvInfo.src.format = format;
+ mOvInfo.src_rect.w = w;
+ mOvInfo.src_rect.h = h;
+ mOvInfo.alpha = 0xff;
+ mOvInfo.transp_mask = 0xffffffff;
+ mRotInfo.src.format = format;
+ mRotInfo.dst.format = format;
+ mRotInfo.src.width = srcw;
+ mRotInfo.src.height = srch;
+ mRotInfo.src_rect.w = srcw;
+ mRotInfo.src_rect.h = srch;
+ mRotInfo.dst.width = srcw;
+ mRotInfo.dst.height = srch;
+
+ int rot = mOrientation;
+ switch(rot) {
+ case 0:
+ case HAL_TRANSFORM_FLIP_H:
+ case HAL_TRANSFORM_FLIP_V:
+ rot = 0;
+ break;
+ case HAL_TRANSFORM_ROT_90:
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
+ case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V): {
+ int tmp = mOvInfo.src_rect.x;
+ mOvInfo.src_rect.x = mOvInfo.src.height -
+ (mOvInfo.src_rect.y + mOvInfo.src_rect.h);
+ mOvInfo.src_rect.y = tmp;
+ swapOVRotWidthHeight(mRotInfo, mOvInfo);
+ rot = HAL_TRANSFORM_ROT_90;
+ break;
+ }
+ case HAL_TRANSFORM_ROT_180:
+ break;
+ case HAL_TRANSFORM_ROT_270: {
+ int tmp = mOvInfo.src_rect.y;
+ mOvInfo.src_rect.y = mOvInfo.src.width -
+ (mOvInfo.src_rect.x + mOvInfo.src_rect.w);
+ mOvInfo.src_rect.x = tmp;
+ swapOVRotWidthHeight(mRotInfo, mOvInfo);
+ break;
+ }
+ default:
+ break;
+ }
+ int mdp_rotation = overlay::get_mdp_orientation(rot);
+ if (mdp_rotation < 0)
+ mdp_rotation = 0;
+ mOvInfo.user_data[0] = mdp_rotation;
+ mRotInfo.rotations = mOvInfo.user_data[0];
+ if (mdp_rotation)
+ mRotInfo.enable = 1;
+}
+
+status_t OverlayUI::commit() {
+ status_t ret = BAD_VALUE;
+ if(mChannelState != UP)
+ mOvInfo.id = MSMFB_NEW_REQUEST;
+ ret = startOVSession();
+ if (ret == NO_ERROR && mOrientation) {
+ ret = mobjRotator.startRotSession(mRotInfo, mSource.size);
+ }
+ if (ret == NO_ERROR) {
+ mChannelState = UP;
+ } else {
+ LOGE("start channel failed.");
+ }
+ return ret;
+}
+
+status_t OverlayUI::closeChannel() {
+ if( mChannelState != UP ) {
+ return NO_ERROR;
+ }
+ if(NO_ERROR != closeOVSession()) {
+ LOGE("%s: closeOVSession() failed.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ if(NO_ERROR != mobjRotator.closeRotSession()) {
+ LOGE("%s: closeRotSession() failed.", __FUNCTION__);
+ return BAD_VALUE;
+ }
+ mChannelState = CLOSED;
+ mParamsChanged = false;
+ memset(&mOvInfo, 0, sizeof(mOvInfo));
+ memset(&mRotInfo, 0, sizeof(mRotInfo));
+ return NO_ERROR;
+}
+
+status_t OverlayUI::startOVSession() {
+ status_t ret = NO_INIT;
+ ret = mobjDisplay.openDisplay(mFBNum);
+
+ if (ret != NO_ERROR)
+ return ret;
+
+ if(mParamsChanged) {
+ mParamsChanged = false;
+ mdp_overlay ovInfo = mOvInfo;
+ if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_SET, &ovInfo)) {
+ LOGE("Overlay set failed..");
+ ret = BAD_VALUE;
+ } else {
+ mSessionID = ovInfo.id;
+ mOvInfo = ovInfo;
+ ret = NO_ERROR;
+ }
+ }
+ return ret;
+}
+
+status_t OverlayUI::closeOVSession() {
+ status_t ret = NO_ERROR;
+ int err = 0;
+ if(err = ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_UNSET, &mSessionID)) {
+ LOGE("%s: MSMFB_OVERLAY_UNSET failed. (%d)", __FUNCTION__, err);
+ ret = BAD_VALUE;
+ } else {
+ mobjDisplay.closeDisplay();
+ mSessionID = NO_INIT;
+ }
+ return ret;
+}
+
+status_t OverlayUI::queueBuffer(buffer_handle_t buffer) {
+ status_t ret = NO_INIT;
+
+ if (mChannelState != UP)
+ return ret;
+
+ msmfb_overlay_data ovData;
+ memset(&ovData, 0, sizeof(ovData));
+
+ private_handle_t const* hnd = reinterpret_cast
+ <private_handle_t const*>(buffer);
+ ovData.data.memory_id = hnd->fd;
+ ovData.data.offset = hnd->offset;
+ if (mOrientation) {
+ msm_rotator_data_info rotData;
+ memset(&rotData, 0, sizeof(rotData));
+ rotData.src.memory_id = hnd->fd;
+ rotData.src.offset = hnd->offset;
+ if (mobjRotator.rotateBuffer(rotData) != NO_ERROR) {
+ LOGE("Rotator failed.. ");
+ return BAD_VALUE;
+ }
+ ovData.data.memory_id = rotData.dst.memory_id;
+ ovData.data.offset = rotData.dst.offset;
+ }
+ ovData.id = mSessionID;
+ if (ioctl(mobjDisplay.getFD(), MSMFB_OVERLAY_PLAY, &ovData)) {
+ LOGE("Queuebuffer failed ");
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+}
+
+};
diff --git a/liboverlay/overlayLibUI.h b/liboverlay/overlayLibUI.h
new file mode 100644
index 0000000..d16a968
--- /dev/null
+++ b/liboverlay/overlayLibUI.h
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (c) 2011, 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 INCLUDE_OVERLAY_LIB_UI
+#define INCLUDE_OVERLAY_LIB_UI
+
+#include <errno.h>
+
+#include "overlayLib.h"
+
+namespace overlay {
+
+enum channel_state_t { UP, CLOSED, PENDING_CLOSE };
+enum status_t {
+ NO_ERROR,
+ INVALID_OPERATION = -ENOSYS,
+ BAD_VALUE = -EINVAL,
+ NO_INIT = -ENODEV,
+ ALREADY_EXISTS = -EEXIST
+ };
+
+/*
+ * Display class provides following services
+ * Open FB
+ * FB information (Width, Height and Bpp)
+ */
+
+class Display {
+ int mFD;
+ int mFBWidth;
+ int mFBHeight;
+ int mFBBpp;
+ Display(const Display& objDisplay);
+ Display& operator=(const Display& objDisplay);
+
+public:
+ explicit Display() : mFD(NO_INIT) { };
+ ~Display() { close(mFD); };
+ int getFD() const { return mFD; };
+ int getFBWidth() const { return mFBWidth; };
+ int getFBHeight() const { return mFBHeight; };
+ int getFBBpp() const { return mFBBpp; };
+ status_t openDisplay(int fbnum);
+ void closeDisplay();
+};
+
+/*
+ * Rotator class, manages rotation of the buffers
+ * It communicates with Rotator driver, provides following services
+ * Start rotator session
+ * Rotate buffer
+ */
+
+class Rotator {
+ int mFD;
+ int mSessionID;
+ int mPmemFD;
+ void* mPmemAddr;
+ int mRotOffset[max_num_buffers];
+ int mCurrentItem;
+ int mNumBuffers;
+ int mSize;
+ android::sp<gralloc::IAllocController> mAlloc;
+ int mBufferType;
+ Rotator(const Rotator& objROtator);
+ Rotator& operator=(const Rotator& objRotator);
+
+public:
+ explicit Rotator();
+ ~Rotator();
+ status_t startRotSession(msm_rotator_img_info& rotInfo, int size,
+ int numBuffers = max_num_buffers);
+ status_t closeRotSession();
+ status_t rotateBuffer(msm_rotator_data_info& rotData);
+};
+
+/*
+ * Overlay class for Comp. Bypass
+ * We merge control and data channel classes.
+ */
+
+class OverlayUI {
+ channel_state_t mChannelState;
+ overlay_buffer_info mSource;
+ int mZorder;
+ int mOrientation;
+ int mFBNum;
+ bool mWaitForVsync;
+ bool mIsFg;
+ int mSessionID;
+ Display mobjDisplay;
+ Rotator mobjRotator;
+
+ mdp_overlay mOvInfo;
+ msm_rotator_img_info mRotInfo;
+
+ bool mParamsChanged;
+
+ OverlayUI(const OverlayUI& objOverlay);
+ OverlayUI& operator=(const OverlayUI& objOverlay);
+
+ status_t startOVSession();
+ status_t closeOVSession();
+ void setupOvRotInfo();
+
+public:
+
+ enum fbnum_t { FB0, FB1 };
+
+ OverlayUI();
+ ~OverlayUI();
+ void setSource(const overlay_buffer_info& info, int orientation);
+ void setPosition(int x, int y, int w, int h);
+ void setCrop(int x, int y, int w, int h);
+ void setDisplayParams(int fbNum, bool waitForVsync, bool isFg, int zorder,
+ bool isVGPipe);
+ status_t commit();
+ status_t closeChannel();
+ channel_state_t isChannelUP() const { return mChannelState; };
+ int getFBWidth() const { return mobjDisplay.getFBWidth(); };
+ int getFBHeight() const { return mobjDisplay.getFBHeight(); };
+ status_t queueBuffer(buffer_handle_t buffer);
+};
+
+};
+#endif