Merge remote-tracking branch 'caf/jb' into jb
Conflicts: libcopybit/Android.mk libgralloc/Android.mk libgralloc/framebuffer.cpp Change-Id: I61d48a930d840a5edd659527cc2ebbe3ff84ee3b
This commit is contained in:
commit
a91c998940
31
common.mk
Normal file
31
common.mk
Normal file
@ -0,0 +1,31 @@
|
||||
#Common headers
|
||||
common_includes := hardware/qcom/display/libgralloc
|
||||
common_includes += hardware/qcom/display/libgenlock
|
||||
common_includes += hardware/qcom/display/liboverlay
|
||||
common_includes += hardware/qcom/display/libcopybit
|
||||
common_includes += hardware/qcom/display/libqdutils
|
||||
|
||||
ifeq ($(TARGET_USES_POST_PROCESSING),true)
|
||||
common_flags += -DUSES_POST_PROCESSING
|
||||
common_includes += $(TARGET_OUT_HEADERS)/pp/inc
|
||||
endif
|
||||
|
||||
|
||||
#Common libraries external to display HAL
|
||||
common_libs := liblog libutils libcutils libhardware
|
||||
|
||||
#Common C flags
|
||||
common_flags := -DUSE_ION -DDEBUG_CALC_FPS -Wno-missing-field-initializers
|
||||
ifeq ($(ARCH_ARM_HAVE_NEON),true)
|
||||
common_flags += -D__ARM_HAVE_NEON
|
||||
endif
|
||||
|
||||
common_deps :=
|
||||
kernel_includes :=
|
||||
#Kernel includes
|
||||
ifeq ($(call is-vendor-board-platform,QCOM),true)
|
||||
common_deps += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
|
||||
kernel_includes += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
|
||||
endif
|
||||
|
||||
|
@ -12,59 +12,31 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libdl libmemalloc
|
||||
LOCAL_CFLAGS := $(common_flags)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
|
||||
|
||||
ifeq ($(TARGET_USES_C2D_COMPOSITION),true)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libdl libcutils libmemalloc libutils
|
||||
LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_CFLAGS += -DCOPYBIT_Z180=1 -DC2D_SUPPORT_DISPLAY=1
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SRC_FILES := copybit_c2d.cpp software_converter.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
ifneq ($(TARGET_BOARD_PLATFORM),msm7x30)
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),qsd8k)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libmemalloc
|
||||
LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_CFLAGS += -D__ARM_HAVE_NEON -DCOPYBIT_QSD8K=1
|
||||
LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1 -DDEBUG_MDP_ERRORS
|
||||
LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
else
|
||||
include $(CLEAR_VARS)
|
||||
ifeq ($(ARCH_ARM_HAVE_NEON),true)
|
||||
LOCAL_CFLAGS += -D__ARM_HAVE_NEON
|
||||
endif
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),msm7x27a),true)
|
||||
LOCAL_CFLAGS += -DTARGET_7x27A
|
||||
endif
|
||||
ifeq ($(TARGET_GRALLOC_USES_ASHMEM),true)
|
||||
LOCAL_CFLAGS += -DUSE_ASHMEM
|
||||
ifeq ($(TARGET_BOARD_PLATFORM),msm7k),true)
|
||||
LOCAL_CFLAGS += -DTARGET_7x27
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libmemalloc
|
||||
LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
|
||||
LOCAL_MODULE := copybit.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgralloc
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/qcom/display/libgralloc
|
||||
LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
|
||||
LOCAL_SRC_FILES := software_converter.cpp copybit.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
endif
|
||||
|
@ -60,6 +60,7 @@ struct copybit_context_t {
|
||||
int mFD;
|
||||
uint8_t mAlpha;
|
||||
int mFlags;
|
||||
bool mBlitToFB;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -212,6 +213,10 @@ static void set_infos(struct copybit_context_t *dev,
|
||||
req->alpha = dev->mAlpha;
|
||||
req->transp_mask = MDP_TRANSP_NOP;
|
||||
req->flags = dev->mFlags | flags;
|
||||
// check if we are blitting to f/b
|
||||
if (COPYBIT_ENABLE == dev->mBlitToFB) {
|
||||
req->flags |= MDP_MEMORY_ID_TYPE_FB;
|
||||
}
|
||||
#if defined(COPYBIT_QSD8K)
|
||||
req->flags |= MDP_BLEND_FG_PREMULT;
|
||||
#endif
|
||||
@ -229,10 +234,10 @@ static int msm_copybit(struct copybit_context_t *dev, void const *list)
|
||||
#if DEBUG_MDP_ERRORS
|
||||
struct mdp_blit_req_list const* l =
|
||||
(struct mdp_blit_req_list const*)list;
|
||||
for (int i=0 ; i<l->count ; i++) {
|
||||
for (unsigned int i=0 ; i<l->count ; i++) {
|
||||
ALOGE("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
|
||||
" dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
|
||||
" flags=%08lx"
|
||||
" flags=%08x"
|
||||
,
|
||||
i,
|
||||
l->req[i].src.width,
|
||||
@ -322,6 +327,16 @@ static int set_parameter_copybit(
|
||||
ctx->mFlags &= ~0x7;
|
||||
ctx->mFlags |= value & 0x7;
|
||||
break;
|
||||
case COPYBIT_BLIT_TO_FRAMEBUFFER:
|
||||
if (COPYBIT_ENABLE == value) {
|
||||
ctx->mBlitToFB = value;
|
||||
} else if (COPYBIT_DISABLE == value) {
|
||||
ctx->mBlitToFB = value;
|
||||
} else {
|
||||
ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
|
||||
__FUNCTION__, value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
status = -EINVAL;
|
||||
break;
|
||||
@ -391,8 +406,8 @@ static int stretch_copybit(
|
||||
}
|
||||
}
|
||||
|
||||
if (src_rect->l < 0 || src_rect->r > src->w ||
|
||||
src_rect->t < 0 || src_rect->b > src->h) {
|
||||
if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w ||
|
||||
src_rect->t < 0 || (uint32_t)src_rect->b > src->h) {
|
||||
// this is always invalid
|
||||
ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
|
||||
__FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
|
||||
|
@ -52,6 +52,10 @@ enum {
|
||||
|
||||
/* name for copybit_set_parameter */
|
||||
enum {
|
||||
/* Default blit destination is offline buffer */
|
||||
/* clients to set this to '1', if blitting to framebuffer */
|
||||
/* and reset to '0', after calling blit/stretch */
|
||||
COPYBIT_BLIT_TO_FRAMEBUFFER = 0,
|
||||
/* rotation of the source image in degrees (0 to 359) */
|
||||
COPYBIT_ROTATION_DEG = 1,
|
||||
/* plane alpha value */
|
||||
|
@ -1,14 +1,13 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES :=
|
||||
LOCAL_SRC_FILES := genlock.cpp
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"libgenlock\"
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libgenlock
|
||||
|
||||
LOCAL_MODULE := libgenlock
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes)
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"libgenlock\"
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := genlock.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
|
@ -11,49 +11,31 @@
|
||||
# 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.
|
||||
|
||||
#gralloc module
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# HAL module implemenation, not prelinked and stored in
|
||||
# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libmemalloc
|
||||
LOCAL_SHARED_LIBRARIES += libgenlock libqdutils libGLESv1_CM
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/liboverlay/
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils
|
||||
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_CFLAGS := -DLOG_TAG=\"gralloc\" \
|
||||
-DDEBUG_CALC_FPS -Wno-missing-field-initializers
|
||||
LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
|
||||
|
||||
ifeq ($(TARGET_USES_POST_PROCESSING),true)
|
||||
LOCAL_CFLAGS += -DUSES_POST_PROCESSING
|
||||
LOCAL_C_INCLUDES += $(TARGET_OUT_HEADERS)/pp/inc
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_USES_MDP3), true)
|
||||
LOCAL_CFLAGS += -DUSE_MDP3
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_HAVE_HDMI_OUT),true)
|
||||
LOCAL_CFLAGS += -DHDMI_DUAL_DISPLAY
|
||||
LOCAL_SHARED_LIBRARIES += liboverlay
|
||||
endif
|
||||
LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes)
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc libgenlock
|
||||
LOCAL_SHARED_LIBRARIES += libqdutils libGLESv1_CM
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"gralloc\"
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := gpu.cpp gralloc.cpp framebuffer.cpp mapper.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
#MemAlloc Library
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/libqdutils
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
|
||||
LOCAL_SRC_FILES := alloc_controller.cpp
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"memalloc\"
|
||||
LOCAL_MODULE := libmemalloc
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libmemalloc
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes)
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libgenlock
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"memalloc\"
|
||||
LOCAL_SRC_FILES := alloc_controller.cpp
|
||||
ifeq ($(TARGET_USES_PMEM),true)
|
||||
LOCAL_SRC_FILES += pmemalloc.cpp \
|
||||
ashmemalloc.cpp \
|
||||
|
@ -25,11 +25,6 @@
|
||||
#define NO_SURFACEFLINGER_SWAPINTERVAL
|
||||
#define COLOR_FORMAT(x) (x & 0xFFF) // Max range for colorFormats is 0 - FFF
|
||||
|
||||
enum hdmi_mirroring_state {
|
||||
HDMI_NO_MIRRORING,
|
||||
HDMI_UI_MIRRORING,
|
||||
};
|
||||
|
||||
struct private_handle_t;
|
||||
|
||||
enum {
|
||||
@ -54,21 +49,11 @@ struct private_module_t {
|
||||
float ydpi;
|
||||
float fps;
|
||||
uint32_t swapInterval;
|
||||
#if defined(__cplusplus) && defined(HDMI_DUAL_DISPLAY)
|
||||
int orientation;
|
||||
int videoOverlay; // VIDEO_OVERLAY - 2D or 3D
|
||||
int secureVideoOverlay; // VideoOverlay is secure
|
||||
uint32_t currentOffset;
|
||||
int enableHDMIOutput; // holds the type of external display
|
||||
bool trueMirrorSupport;
|
||||
bool exitHDMIUILoop;
|
||||
float actionsafeWidthRatio;
|
||||
float actionsafeHeightRatio;
|
||||
bool hdmiStateChanged;
|
||||
hdmi_mirroring_state hdmiMirroringState;
|
||||
pthread_mutex_t overlayLock;
|
||||
pthread_cond_t overlayPost;
|
||||
#endif
|
||||
bool fbPostDone;
|
||||
pthread_mutex_t fbPostLock;
|
||||
//Condition to inform HWC that fb_post called
|
||||
pthread_cond_t fbPostCond;
|
||||
};
|
||||
|
||||
|
||||
|
@ -43,9 +43,6 @@
|
||||
#include <cutils/properties.h>
|
||||
#include <profiler.h>
|
||||
|
||||
#include "overlay.h"
|
||||
namespace ovutils = overlay::utils;
|
||||
|
||||
#define EVEN_OUT(x) if (x & 0x0001) {x--;}
|
||||
/** min of int a, b */
|
||||
static inline int min(int a, int b) {
|
||||
@ -101,403 +98,6 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
static int closeHDMIChannel(private_module_t* m)
|
||||
{
|
||||
// XXX - when enabling HDMI
|
||||
#if 0
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
if(pTemp != NULL)
|
||||
pTemp->closeChannel();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX - Complete when enabling HDMI
|
||||
#if 0
|
||||
static void getSecondaryDisplayDestinationInfo(private_module_t* m, overlay_rect&
|
||||
rect, int& orientation)
|
||||
{
|
||||
Overlay* pTemp = m->pobjOverlay;
|
||||
int width = pTemp->getFBWidth();
|
||||
int height = pTemp->getFBHeight();
|
||||
int fbwidth = m->info.xres, fbheight = m->info.yres;
|
||||
rect.x = 0; rect.y = 0;
|
||||
rect.w = width; rect.h = height;
|
||||
int rot = m->orientation;
|
||||
switch(rot) {
|
||||
// ROT_0
|
||||
case 0:
|
||||
// ROT_180
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
pTemp->getAspectRatioPosition(fbwidth, fbheight,
|
||||
&rect);
|
||||
if(rot == HAL_TRANSFORM_ROT_180)
|
||||
orientation = HAL_TRANSFORM_ROT_180;
|
||||
else
|
||||
orientation = 0;
|
||||
break;
|
||||
// ROT_90
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
// ROT_270
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
//Calculate the Aspectratio for the UI
|
||||
//in the landscape mode
|
||||
//Width and height will be swapped as there
|
||||
//is rotation
|
||||
pTemp->getAspectRatioPosition(fbheight, fbwidth,
|
||||
&rect);
|
||||
|
||||
if(rot == HAL_TRANSFORM_ROT_90)
|
||||
orientation = HAL_TRANSFORM_ROT_270;
|
||||
else if(rot == HAL_TRANSFORM_ROT_270)
|
||||
orientation = HAL_TRANSFORM_ROT_90;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine overlay state based on whether hardware supports true UI
|
||||
mirroring and whether video is playing or not */
|
||||
static ovutils::eOverlayState getOverlayState(struct private_module_t* module)
|
||||
{
|
||||
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||
|
||||
// Default to existing state
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
|
||||
// Sanity check
|
||||
if (!module) {
|
||||
ALOGE("%s: NULL module", __FUNCTION__);
|
||||
return state;
|
||||
}
|
||||
|
||||
// Check if video is playing or not
|
||||
if (module->videoOverlay) {
|
||||
// Video is playing, check if hardware supports true UI mirroring
|
||||
if (module->trueMirrorSupport) {
|
||||
// True UI mirroring is supported by hardware
|
||||
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||
// Currently playing 2D video
|
||||
state = ovutils::OV_2D_TRUE_UI_MIRROR;
|
||||
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||
// Currently playing M3D video
|
||||
// FIXME: Support M3D true UI mirroring
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||
}
|
||||
} else {
|
||||
// True UI mirroring is not supported by hardware
|
||||
if (ov.getState() == ovutils::OV_2D_VIDEO_ON_PANEL) {
|
||||
// Currently playing 2D video
|
||||
state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
||||
} else if (ov.getState() == ovutils::OV_3D_VIDEO_ON_2D_PANEL) {
|
||||
// Currently playing M3D video
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Video is not playing, true UI mirroring support is irrelevant
|
||||
state = ovutils::OV_UI_MIRROR;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
/* Set overlay state */
|
||||
static void setOverlayState(ovutils::eOverlayState state)
|
||||
{
|
||||
overlay2::Overlay& ov = *(Overlay::getInstance());
|
||||
ov.setState(state);
|
||||
}
|
||||
|
||||
static void *hdmi_ui_loop(void *ptr)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(ptr);
|
||||
while (1) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
while(!(m->hdmiStateChanged))
|
||||
pthread_cond_wait(&(m->overlayPost), &(m->overlayLock));
|
||||
|
||||
m->hdmiStateChanged = false;
|
||||
if (m->exitHDMIUILoop) {
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// No need to mirror UI if HDMI is not on
|
||||
if (!m->enableHDMIOutput) {
|
||||
ALOGE_IF(FB_DEBUG, "%s: hdmi not ON", __FUNCTION__);
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
overlay2::OverlayMgr* ovMgr =
|
||||
overlay2::OverlayMgrSingleton::getOverlayMgr();
|
||||
overlay2::Overlay& ov = ovMgr->ov();
|
||||
|
||||
// Set overlay state
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
|
||||
// Determine the RGB pipe for UI depending on the state
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||
// True UI mirroring state: external RGB pipe is OV_PIPE2
|
||||
dest = ovutils::OV_PIPE2;
|
||||
} else if (state == ovutils::OV_UI_MIRROR) {
|
||||
// UI-only mirroring state: external RGB pipe is OV_PIPE0
|
||||
dest = ovutils::OV_PIPE0;
|
||||
} else {
|
||||
// No UI in this case
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (m->hdmiMirroringState == HDMI_UI_MIRRORING) {
|
||||
int alignedW = ALIGN(m->info.xres, 32);
|
||||
|
||||
private_handle_t const* hnd =
|
||||
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
||||
unsigned int width = alignedW;
|
||||
unsigned int height = hnd->height;
|
||||
unsigned int format = hnd->format;
|
||||
unsigned int size = hnd->size/m->numBuffers;
|
||||
|
||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||
// External display connected during secure video playback
|
||||
// Open secure UI session
|
||||
// NOTE: when external display is already connected and then secure
|
||||
// playback is started, we dont have to do anything
|
||||
if (m->secureVideoOverlay) {
|
||||
ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||
}
|
||||
|
||||
ovutils::Whf whf(width, height, format, size);
|
||||
ovutils::PipeArgs parg(mdpFlags,
|
||||
ovutils::OVERLAY_TRANSFORM_0,
|
||||
whf,
|
||||
ovutils::WAIT,
|
||||
ovutils::ZORDER_0,
|
||||
ovutils::IS_FG_OFF,
|
||||
ovutils::ROT_FLAG_ENABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
bool ret = ov.setSource(pargs, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setSource failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
// we need to communicate m->orientation that will get some
|
||||
// modifications within setParameter func.
|
||||
// FIXME that is ugly.
|
||||
const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM_UI,
|
||||
m->orientation);
|
||||
ov.setParameter(prms, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setParameter failed transform", __FUNCTION__);
|
||||
}
|
||||
|
||||
// x,y,w,h
|
||||
ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
|
||||
ov.setMemoryId(m->framebuffer->fd, dest);
|
||||
ret = ov.setCrop(dcrop, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setCrop failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
ovutils::Dim pdim (m->info.xres,
|
||||
m->info.yres,
|
||||
0,
|
||||
0,
|
||||
m->orientation);
|
||||
ret = ov.setPosition(pdim, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s setPosition failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
if (!ov.commit(dest)) {
|
||||
ALOGE("%s commit fails", __FUNCTION__);
|
||||
}
|
||||
|
||||
ret = ov.queueBuffer(m->currentOffset, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s queueBuffer failed", __FUNCTION__);
|
||||
}
|
||||
} else {
|
||||
setOverlayState(ovutils::OV_CLOSED);
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int fb_videoOverlayStarted(struct framebuffer_device_t* dev, int started)
|
||||
{
|
||||
ALOGE_IF(FB_DEBUG, "%s started=%d", __FUNCTION__, started);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if(started != m->videoOverlay) {
|
||||
m->videoOverlay = started;
|
||||
m->hdmiStateChanged = true;
|
||||
if (!m->trueMirrorSupport) {
|
||||
if (started) {
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
} else if (m->enableHDMIOutput)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else {
|
||||
if (m->videoOverlay == VIDEO_3D_OVERLAY_STARTED) {
|
||||
ALOGE_IF(FB_DEBUG, "3D Video Started, stop mirroring!");
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
}
|
||||
else if (m->enableHDMIOutput) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_enableHDMIOutput(struct framebuffer_device_t* dev, int externaltype)
|
||||
{
|
||||
ALOGE_IF(FB_DEBUG, "%s externaltype=%d", __FUNCTION__, externaltype);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
//Check if true mirroring can be supported
|
||||
m->trueMirrorSupport = ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring();
|
||||
m->enableHDMIOutput = externaltype;
|
||||
if(externaltype) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else {
|
||||
if(!m->videoOverlay)
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
} else if (!externaltype) {
|
||||
// Either HDMI is disconnected or suspend occurred
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
ovutils::eOverlayState state = getOverlayState(m);
|
||||
setOverlayState(state);
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fb_orientationChanged(struct framebuffer_device_t* dev, int orientation)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
neworientation = orientation;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_open_secure_start(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
m->secureVideoOverlay = true;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_open_secure_end(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if (m->enableHDMIOutput) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else if(!m->videoOverlay) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_close_secure_start(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
m->secureVideoOverlay = false;
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int handle_close_secure_end(private_module_t* m) {
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
if (m->enableHDMIOutput) {
|
||||
if (m->trueMirrorSupport) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
} else if(!m->videoOverlay) {
|
||||
m->hdmiMirroringState = HDMI_UI_MIRRORING;
|
||||
}
|
||||
m->hdmiStateChanged = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
}
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* fb_perform - used to add custom event and handle them in fb HAL
|
||||
* Used for external display related functions as of now
|
||||
*/
|
||||
static int fb_perform(struct framebuffer_device_t* dev, int event, int value)
|
||||
{
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
dev->common.module);
|
||||
switch(event) {
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
case EVENT_EXTERNAL_DISPLAY:
|
||||
fb_enableHDMIOutput(dev, value);
|
||||
break;
|
||||
case EVENT_VIDEO_OVERLAY:
|
||||
fb_videoOverlayStarted(dev, value);
|
||||
break;
|
||||
case EVENT_ORIENTATION_CHANGE:
|
||||
fb_orientationChanged(dev, value);
|
||||
break;
|
||||
case EVENT_OVERLAY_STATE_CHANGE:
|
||||
if (value == OVERLAY_STATE_CHANGE_START) {
|
||||
// When state change starts, get a lock on overlay
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
} else if (value == OVERLAY_STATE_CHANGE_END) {
|
||||
// When state change is complete, unlock overlay
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
}
|
||||
break;
|
||||
case EVENT_OPEN_SECURE_START:
|
||||
handle_open_secure_start(m);
|
||||
break;
|
||||
case EVENT_OPEN_SECURE_END:
|
||||
handle_open_secure_end(m);
|
||||
break;
|
||||
case EVENT_CLOSE_SECURE_START:
|
||||
handle_close_secure_start(m);
|
||||
break;
|
||||
case EVENT_CLOSE_SECURE_END:
|
||||
handle_close_secure_end(m);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
ALOGE("In %s: UNKNOWN Event = %d!!!", __FUNCTION__, event);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
{
|
||||
if (private_handle_t::validate(buffer) < 0)
|
||||
@ -511,6 +111,7 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
private_module_t* m =
|
||||
reinterpret_cast<private_module_t*>(dev->common.module);
|
||||
|
||||
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||
genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT);
|
||||
|
||||
@ -520,6 +121,14 @@ static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||
}
|
||||
|
||||
const size_t offset = hnd->base - m->framebuffer->base;
|
||||
// frame ready to be posted, signal so that hwc can update External
|
||||
// display
|
||||
pthread_mutex_lock(&m->fbPostLock);
|
||||
m->currentOffset = offset;
|
||||
m->fbPostDone = true;
|
||||
pthread_cond_signal(&m->fbPostCond);
|
||||
pthread_mutex_unlock(&m->fbPostLock);
|
||||
|
||||
m->info.activate = FB_ACTIVATE_VBL;
|
||||
m->info.yoffset = offset / m->finfo.line_length;
|
||||
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
|
||||
@ -580,11 +189,12 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
info.yoffset = 0;
|
||||
info.activate = FB_ACTIVATE_NOW;
|
||||
|
||||
/* Interpretation of offset for color fields: All offsets are from the right,
|
||||
* inside a "pixel" value, which is exactly 'bits_per_pixel' wide (means: you
|
||||
* can use the offset as right argument to <<). A pixel afterwards is a bit
|
||||
* stream and is written to video memory as that unmodified. This implies
|
||||
* big-endian byte order if bits_per_pixel is greater than 8.
|
||||
/* Interpretation of offset for color fields: All offsets are from the
|
||||
* right, inside a "pixel" value, which is exactly 'bits_per_pixel' wide
|
||||
* (means: you can use the offset as right argument to <<). A pixel
|
||||
* afterwards is a bit stream and is written to video memory as that
|
||||
* unmodified. This implies big-endian byte order if bits_per_pixel is
|
||||
* greater than 8.
|
||||
*/
|
||||
|
||||
if(info.bits_per_pixel == 32) {
|
||||
@ -601,10 +211,11 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
info.transp.offset = 0;
|
||||
info.transp.length = 8;
|
||||
|
||||
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we do
|
||||
* not use the MDP for composition (i.e. hw composition == 0), ask for
|
||||
* RGBA instead of RGBX. */
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0 && atoi(property) == 0)
|
||||
/* Note: the GL driver does not have a r=8 g=8 b=8 a=0 config, so if we
|
||||
* do not use the MDP for composition (i.e. hw composition == 0), ask
|
||||
* for RGBA instead of RGBX. */
|
||||
if (property_get("debug.sf.hw", property, NULL) > 0 &&
|
||||
atoi(property) == 0)
|
||||
module->fbFormat = HAL_PIXEL_FORMAT_RGBX_8888;
|
||||
else if(property_get("debug.composition.type", property, NULL) > 0 &&
|
||||
(strncmp(property, "mdp", 3) == 0))
|
||||
@ -628,7 +239,8 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
}
|
||||
|
||||
//adreno needs 4k aligned offsets. Max hole size is 4096-1
|
||||
int size = roundUpToPageSize(info.yres * info.xres * (info.bits_per_pixel/8));
|
||||
int size = roundUpToPageSize(info.yres * info.xres *
|
||||
(info.bits_per_pixel/8));
|
||||
|
||||
/*
|
||||
* Request NUM_BUFFERS screens (at least 2 for page flipping)
|
||||
@ -739,9 +351,9 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres)*
|
||||
module->numBuffers;
|
||||
module->framebuffer = new private_handle_t(fd, fbSize,
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM,
|
||||
BUFFER_TYPE_UI,
|
||||
module->fbFormat, info.xres, info.yres);
|
||||
private_handle_t::PRIV_FLAGS_USES_PMEM,
|
||||
BUFFER_TYPE_UI,
|
||||
module->fbFormat, info.xres, info.yres);
|
||||
void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (vaddr == MAP_FAILED) {
|
||||
ALOGE("Error mapping the framebuffer (%s)", strerror(errno));
|
||||
@ -749,20 +361,10 @@ int mapFrameBufferLocked(struct private_module_t* module)
|
||||
}
|
||||
module->framebuffer->base = intptr_t(vaddr);
|
||||
memset(vaddr, 0, fbSize);
|
||||
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
/* Overlay for HDMI*/
|
||||
pthread_mutex_init(&(module->overlayLock), NULL);
|
||||
pthread_cond_init(&(module->overlayPost), NULL);
|
||||
module->currentOffset = 0;
|
||||
module->exitHDMIUILoop = false;
|
||||
module->hdmiStateChanged = false;
|
||||
pthread_t hdmiUIThread;
|
||||
pthread_create(&hdmiUIThread, NULL, &hdmi_ui_loop, (void *) module);
|
||||
module->hdmiMirroringState = HDMI_NO_MIRRORING;
|
||||
module->trueMirrorSupport = false;
|
||||
#endif
|
||||
|
||||
module->fbPostDone = false;
|
||||
pthread_mutex_init(&(module->fbPostLock), NULL);
|
||||
pthread_cond_init(&(module->fbPostCond), NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -779,14 +381,6 @@ static int mapFrameBuffer(struct private_module_t* module)
|
||||
static int fb_close(struct hw_device_t *dev)
|
||||
{
|
||||
fb_context_t* ctx = (fb_context_t*)dev;
|
||||
#if defined(HDMI_DUAL_DISPLAY)
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ctx->device.common.module);
|
||||
pthread_mutex_lock(&m->overlayLock);
|
||||
m->exitHDMIUILoop = true;
|
||||
pthread_cond_signal(&(m->overlayPost));
|
||||
pthread_mutex_unlock(&m->overlayLock);
|
||||
#endif
|
||||
if (ctx) {
|
||||
free(ctx);
|
||||
}
|
||||
@ -829,8 +423,10 @@ int fb_device_open(hw_module_t const* module, const char* name,
|
||||
const_cast<float&>(dev->device.xdpi) = m->xdpi;
|
||||
const_cast<float&>(dev->device.ydpi) = m->ydpi;
|
||||
const_cast<float&>(dev->device.fps) = m->fps;
|
||||
const_cast<int&>(dev->device.minSwapInterval) = PRIV_MIN_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.maxSwapInterval) = PRIV_MAX_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.minSwapInterval) =
|
||||
PRIV_MIN_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.maxSwapInterval) =
|
||||
PRIV_MAX_SWAP_INTERVAL;
|
||||
const_cast<int&>(dev->device.numFramebuffers) = m->numBuffers;
|
||||
if (m->finfo.reserved[0] == 0x5444 &&
|
||||
m->finfo.reserved[1] == 0x5055) {
|
||||
|
@ -112,7 +112,7 @@ enum {
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED = 0x7FA30C03,
|
||||
#endif
|
||||
HAL_PIXEL_FORMAT_YCbCr_420_SP = 0x109,
|
||||
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x10A,
|
||||
HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO = 0x7FA30C01,
|
||||
HAL_PIXEL_FORMAT_YCrCb_422_SP = 0x10B,
|
||||
HAL_PIXEL_FORMAT_R_8 = 0x10D,
|
||||
HAL_PIXEL_FORMAT_RG_88 = 0x10E,
|
||||
|
@ -85,8 +85,7 @@ int IonAlloc::alloc_buffer(alloc_data& data)
|
||||
if(data.uncached) {
|
||||
// Use the sync FD to alloc and map
|
||||
// when we need uncached memory
|
||||
// XXX: Change O_SYNC to O_DSYNC when available in bionic
|
||||
ionSyncFd = open(ION_DEVICE, O_RDONLY|O_SYNC);
|
||||
ionSyncFd = open(ION_DEVICE, O_RDONLY|O_DSYNC);
|
||||
if(ionSyncFd < 0) {
|
||||
ALOGE("%s: Failed to open ion device - %s",
|
||||
__FUNCTION__, strerror(errno));
|
||||
|
@ -1,18 +1,15 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_SHARED_LIBRARIES := liblog libcutils libhardware libutils
|
||||
LOCAL_SHARED_LIBRARIES += libEGL liboverlay libgenlock libqdutils
|
||||
LOCAL_SRC_FILES := hwc.cpp \
|
||||
hwc_overlay.cpp \
|
||||
hwc_utils.cpp
|
||||
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libgenlock
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/liboverlay
|
||||
LOCAL_C_INCLUDES += hardware/qcom/display/libqdutils
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).hwcomposer\"
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := hwcomposer.$(TARGET_BOARD_PLATFORM)
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \
|
||||
libqdutils libhardware_legacy libdl libmemalloc
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\"
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \
|
||||
hwc_uimirror.cpp hwc_ext_observer.cpp \
|
||||
hwc_copybit.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -20,9 +20,11 @@
|
||||
|
||||
#include <cutils/log.h>
|
||||
#include <cutils/atomic.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include "hwc_utils.h"
|
||||
#include "hwc_video.h"
|
||||
#include "hwc_uimirror.h"
|
||||
#include "hwc_copybit.h"
|
||||
|
||||
using namespace qhwc;
|
||||
|
||||
@ -65,21 +67,28 @@ static void hwc_registerProcs(struct hwc_composer_device* dev,
|
||||
static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
|
||||
{
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
ctx->overlayInUse = false;
|
||||
|
||||
//Prepare is called after a vsync, so unlock previous buffers here.
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
|
||||
if (LIKELY(list)) {
|
||||
getLayerStats(ctx, list);
|
||||
cleanOverlays(ctx);
|
||||
for (int i=list->numHwLayers-1; i >= 0 ; i--) {
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[i].handle;
|
||||
if (isSkipLayer(&list->hwLayers[i])) {
|
||||
break;
|
||||
} else if(isYuvBuffer(hnd)) {
|
||||
handleYUV(ctx,&list->hwLayers[i]);
|
||||
} else {
|
||||
list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
|
||||
}
|
||||
if(VideoOverlay::prepare(ctx, list)) {
|
||||
ctx->overlayInUse = true;
|
||||
//Nothing here
|
||||
} else if(UIMirrorOverlay::prepare(ctx, list)) {
|
||||
ctx->overlayInUse = true;
|
||||
} else if (0) {
|
||||
//Other features
|
||||
ctx->overlayInUse = true;
|
||||
} else { // Else set this flag to false, otherwise video cases
|
||||
// fail in non-overlay targets.
|
||||
ctx->overlayInUse = false;
|
||||
}
|
||||
CopyBit::prepare(ctx, list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -91,21 +100,18 @@ static int hwc_set(hwc_composer_device_t *dev,
|
||||
int ret = 0;
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
if (LIKELY(list)) {
|
||||
for (size_t i=0; i<list->numHwLayers; i++) {
|
||||
if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
|
||||
continue;
|
||||
} else if (list->hwLayers[i].compositionType == HWC_OVERLAY) {
|
||||
drawLayerUsingOverlay(ctx, &(list->hwLayers[i]));
|
||||
}
|
||||
}
|
||||
//XXX: Handle vsync with FBIO_WAITFORVSYNC ioctl
|
||||
//All other operations (including pan display) should be NOWAIT
|
||||
VideoOverlay::draw(ctx, list);
|
||||
CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
|
||||
EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
|
||||
UIMirrorOverlay::draw(ctx);
|
||||
} else {
|
||||
//XXX: put in a wrapper for non overlay targets
|
||||
setOverlayState(ctx, ovutils::OV_CLOSED);
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
}
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
|
||||
if(!ctx->overlayInUse)
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
453
libhwcomposer/hwc_copybit.cpp
Normal file
453
libhwcomposer/hwc_copybit.cpp
Normal file
@ -0,0 +1,453 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are retained
|
||||
* for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hwc_copybit.h"
|
||||
#include "hwc_copybitEngine.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
|
||||
struct range {
|
||||
int current;
|
||||
int end;
|
||||
};
|
||||
struct region_iterator : public copybit_region_t {
|
||||
|
||||
region_iterator(hwc_region_t region) {
|
||||
mRegion = region;
|
||||
r.end = region.numRects;
|
||||
r.current = 0;
|
||||
this->next = iterate;
|
||||
}
|
||||
|
||||
private:
|
||||
static int iterate(copybit_region_t const * self, copybit_rect_t* rect){
|
||||
if (!self || !rect) {
|
||||
ALOGE("iterate invalid parameters");
|
||||
return 0;
|
||||
}
|
||||
|
||||
region_iterator const* me =
|
||||
static_cast<region_iterator const*>(self);
|
||||
if (me->r.current != me->r.end) {
|
||||
rect->l = me->mRegion.rects[me->r.current].left;
|
||||
rect->t = me->mRegion.rects[me->r.current].top;
|
||||
rect->r = me->mRegion.rects[me->r.current].right;
|
||||
rect->b = me->mRegion.rects[me->r.current].bottom;
|
||||
me->r.current++;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwc_region_t mRegion;
|
||||
mutable range r;
|
||||
};
|
||||
|
||||
// Initialize CopyBit Class Static Mmembers.
|
||||
functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID
|
||||
= NULL;
|
||||
functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL;
|
||||
int CopyBit::sYuvCount = 0;
|
||||
int CopyBit::sYuvLayerIndex = -1;
|
||||
bool CopyBit::sIsModeOn = false;
|
||||
bool CopyBit::sIsLayerSkip = false;
|
||||
void* CopyBit::egl_lib = NULL;
|
||||
|
||||
void CopyBit::updateEglHandles(void* egl_lib)
|
||||
{
|
||||
if(egl_lib != NULL) {
|
||||
*(void **)&CopyBit::LINK_eglGetRenderBufferANDROID =
|
||||
::dlsym(egl_lib, "eglGetRenderBufferANDROID");
|
||||
*(void **)&CopyBit::LINK_eglGetCurrentSurface =
|
||||
::dlsym(egl_lib, "eglGetCurrentSurface");
|
||||
}else {
|
||||
LINK_eglGetCurrentSurface = NULL;
|
||||
LINK_eglGetCurrentSurface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyBit::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
for (int i=list->numHwLayers-1; i >= 0 ; i--) {
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[i].handle;
|
||||
if (isSkipLayer(&list->hwLayers[i])) {
|
||||
break;
|
||||
} else if(canUseCopybit(ctx, list, getYuvCount())
|
||||
&& !ctx->overlayInUse){
|
||||
list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
|
||||
} else {
|
||||
list->hwLayers[i].compositionType = HWC_FRAMEBUFFER;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool CopyBit::draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy,
|
||||
EGLSurface sur){
|
||||
for (size_t i=0; i<list->numHwLayers; i++) {
|
||||
if (list->hwLayers[i].flags & HWC_SKIP_LAYER) {
|
||||
continue;
|
||||
} else if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
|
||||
drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
|
||||
(EGLDisplay)dpy,
|
||||
(EGLSurface)sur,
|
||||
LINK_eglGetRenderBufferANDROID,
|
||||
LINK_eglGetCurrentSurface);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer,
|
||||
EGLDisplay dpy,
|
||||
EGLSurface surface,
|
||||
functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
|
||||
functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
|
||||
{
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
if(!ctx) {
|
||||
ALOGE("%s: null context ", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||
if(!hnd) {
|
||||
ALOGE("%s: invalid handle", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Lock this buffer for read.
|
||||
genlock_lock_type lockType = GENLOCK_READ_LOCK;
|
||||
int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
|
||||
if (GENLOCK_FAILURE == err) {
|
||||
ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
//render buffer
|
||||
EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW);
|
||||
android_native_buffer_t *renderBuffer =
|
||||
(android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface);
|
||||
if (!renderBuffer) {
|
||||
ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__);
|
||||
genlock_unlock_buffer(hnd);
|
||||
return -1;
|
||||
}
|
||||
private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
|
||||
if(!fbHandle) {
|
||||
ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
|
||||
genlock_unlock_buffer(hnd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set the copybit source:
|
||||
copybit_image_t src;
|
||||
src.w = hnd->width;
|
||||
src.h = hnd->height;
|
||||
src.format = hnd->format;
|
||||
src.base = (void *)hnd->base;
|
||||
src.handle = (native_handle_t *)layer->handle;
|
||||
src.horiz_padding = src.w - hnd->width;
|
||||
// Initialize vertical padding to zero for now,
|
||||
// this needs to change to accomodate vertical stride
|
||||
// if needed in the future
|
||||
src.vert_padding = 0;
|
||||
// Remove the srcBufferTransform if any
|
||||
layer->transform = (layer->transform & FINAL_TRANSFORM_MASK);
|
||||
|
||||
// Copybit source rect
|
||||
hwc_rect_t sourceCrop = layer->sourceCrop;
|
||||
copybit_rect_t srcRect = {sourceCrop.left, sourceCrop.top,
|
||||
sourceCrop.right,
|
||||
sourceCrop.bottom};
|
||||
|
||||
// Copybit destination rect
|
||||
hwc_rect_t displayFrame = layer->displayFrame;
|
||||
copybit_rect_t dstRect = {displayFrame.left, displayFrame.top,
|
||||
displayFrame.right,
|
||||
displayFrame.bottom};
|
||||
|
||||
// Copybit dst
|
||||
copybit_image_t dst;
|
||||
dst.w = ALIGN(fbHandle->width,32);
|
||||
dst.h = fbHandle->height;
|
||||
dst.format = fbHandle->format;
|
||||
dst.base = (void *)fbHandle->base;
|
||||
dst.handle = (native_handle_t *)renderBuffer->handle;
|
||||
|
||||
copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
|
||||
|
||||
int32_t screen_w = displayFrame.right - displayFrame.left;
|
||||
int32_t screen_h = displayFrame.bottom - displayFrame.top;
|
||||
int32_t src_crop_width = sourceCrop.right - sourceCrop.left;
|
||||
int32_t src_crop_height = sourceCrop.bottom -sourceCrop.top;
|
||||
|
||||
// Copybit dst
|
||||
float copybitsMaxScale =
|
||||
(float)copybit->get(copybit,COPYBIT_MAGNIFICATION_LIMIT);
|
||||
float copybitsMinScale =
|
||||
(float)copybit->get(copybit,COPYBIT_MINIFICATION_LIMIT);
|
||||
|
||||
if((layer->transform == HWC_TRANSFORM_ROT_90) ||
|
||||
(layer->transform == HWC_TRANSFORM_ROT_270)) {
|
||||
//swap screen width and height
|
||||
int tmp = screen_w;
|
||||
screen_w = screen_h;
|
||||
screen_h = tmp;
|
||||
}
|
||||
private_handle_t *tmpHnd = NULL;
|
||||
|
||||
if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
|
||||
ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
|
||||
screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
|
||||
src_crop_width,screen_w,src_crop_width);
|
||||
genlock_unlock_buffer(hnd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
float dsdx = (float)screen_w/src_crop_width;
|
||||
float dtdy = (float)screen_h/src_crop_height;
|
||||
|
||||
float scaleLimitMax = copybitsMaxScale * copybitsMaxScale;
|
||||
float scaleLimitMin = copybitsMinScale * copybitsMinScale;
|
||||
if(dsdx > scaleLimitMax ||
|
||||
dtdy > scaleLimitMax ||
|
||||
dsdx < 1/scaleLimitMin ||
|
||||
dtdy < 1/scaleLimitMin) {
|
||||
ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \
|
||||
scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
|
||||
scaleLimitMax,1/scaleLimitMin);
|
||||
genlock_unlock_buffer(hnd);
|
||||
return -1;
|
||||
}
|
||||
if(dsdx > copybitsMaxScale ||
|
||||
dtdy > copybitsMaxScale ||
|
||||
dsdx < 1/copybitsMinScale ||
|
||||
dtdy < 1/copybitsMinScale){
|
||||
// The requested scale is out of the range the hardware
|
||||
// can support.
|
||||
ALOGE("%s:%d::Need to scale twice dsdx=%f, dtdy=%f,copybitsMaxScale=%f,\
|
||||
copybitsMinScale=%f,screen_w=%d,screen_h=%d \
|
||||
src_crop_width=%d src_crop_height=%d",__FUNCTION__,__LINE__,
|
||||
dsdx,dtdy,copybitsMaxScale,1/copybitsMinScale,screen_w,screen_h,
|
||||
src_crop_width,src_crop_height);
|
||||
|
||||
//Driver makes width and height as even
|
||||
//that may cause wrong calculation of the ratio
|
||||
//in display and crop.Hence we make
|
||||
//crop width and height as even.
|
||||
src_crop_width = (src_crop_width/2)*2;
|
||||
src_crop_height = (src_crop_height/2)*2;
|
||||
|
||||
int tmp_w = src_crop_width;
|
||||
int tmp_h = src_crop_height;
|
||||
|
||||
if (dsdx > copybitsMaxScale || dtdy > copybitsMaxScale ){
|
||||
tmp_w = src_crop_width*copybitsMaxScale;
|
||||
tmp_h = src_crop_height*copybitsMaxScale;
|
||||
}else if (dsdx < 1/copybitsMinScale ||dtdy < 1/copybitsMinScale ){
|
||||
tmp_w = src_crop_width/copybitsMinScale;
|
||||
tmp_h = src_crop_height/copybitsMinScale;
|
||||
tmp_w = (tmp_w/2)*2;
|
||||
tmp_h = (tmp_h/2)*2;
|
||||
}
|
||||
ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
|
||||
|
||||
int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
|
||||
|
||||
if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
|
||||
copybit_image_t tmp_dst;
|
||||
copybit_rect_t tmp_rect;
|
||||
tmp_dst.w = tmp_w;
|
||||
tmp_dst.h = tmp_h;
|
||||
tmp_dst.format = tmpHnd->format;
|
||||
tmp_dst.handle = tmpHnd;
|
||||
tmp_dst.horiz_padding = src.horiz_padding;
|
||||
tmp_dst.vert_padding = src.vert_padding;
|
||||
tmp_rect.l = 0;
|
||||
tmp_rect.t = 0;
|
||||
tmp_rect.r = tmp_dst.w;
|
||||
tmp_rect.b = tmp_dst.h;
|
||||
//create one clip region
|
||||
hwc_rect tmp_hwc_rect = {0,0,tmp_rect.r,tmp_rect.b};
|
||||
hwc_region_t tmp_hwc_reg = {1,(hwc_rect_t const*)&tmp_hwc_rect};
|
||||
region_iterator tmp_it(tmp_hwc_reg);
|
||||
copybit->set_parameter(copybit,COPYBIT_TRANSFORM,0);
|
||||
// TODO : alpha not defined , fix this
|
||||
// copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
|
||||
// (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
|
||||
err = copybit->stretch(copybit,&tmp_dst, &src, &tmp_rect,
|
||||
&srcRect, &tmp_it);
|
||||
if(err < 0){
|
||||
ALOGE("%s:%d::tmp copybit stretch failed",__FUNCTION__,
|
||||
__LINE__);
|
||||
if(tmpHnd)
|
||||
free_buffer(tmpHnd);
|
||||
genlock_unlock_buffer(hnd);
|
||||
return err;
|
||||
}
|
||||
// copy new src and src rect crop
|
||||
src = tmp_dst;
|
||||
srcRect = tmp_rect;
|
||||
}
|
||||
}
|
||||
// Copybit region
|
||||
hwc_region_t region = layer->visibleRegionScreen;
|
||||
region_iterator copybitRegion(region);
|
||||
|
||||
copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_WIDTH,
|
||||
renderBuffer->width);
|
||||
copybit->set_parameter(copybit, COPYBIT_FRAMEBUFFER_HEIGHT,
|
||||
renderBuffer->height);
|
||||
copybit->set_parameter(copybit, COPYBIT_TRANSFORM,
|
||||
layer->transform);
|
||||
// TODO : alpha not defined , fix this
|
||||
// copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA,
|
||||
// (layer->blending == HWC_BLENDING_NONE) ? -1 : layer->alpha);
|
||||
copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
|
||||
(layer->blending == HWC_BLENDING_PREMULT)?
|
||||
COPYBIT_ENABLE : COPYBIT_DISABLE);
|
||||
copybit->set_parameter(copybit, COPYBIT_DITHER,
|
||||
(dst.format == HAL_PIXEL_FORMAT_RGB_565)?
|
||||
COPYBIT_ENABLE : COPYBIT_DISABLE);
|
||||
copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
|
||||
COPYBIT_ENABLE);
|
||||
err = copybit->stretch(copybit, &dst, &src, &dstRect, &srcRect,
|
||||
©bitRegion);
|
||||
copybit->set_parameter(copybit, COPYBIT_BLIT_TO_FRAMEBUFFER,
|
||||
COPYBIT_DISABLE);
|
||||
|
||||
if(tmpHnd)
|
||||
free_buffer(tmpHnd);
|
||||
|
||||
if(err < 0)
|
||||
ALOGE("%s: copybit stretch failed",__FUNCTION__);
|
||||
|
||||
// Unlock this buffer since copybit is done with it.
|
||||
err = genlock_unlock_buffer(hnd);
|
||||
if (GENLOCK_FAILURE == err) {
|
||||
ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void CopyBit::getLayerResolution(const hwc_layer_t* layer, int& width,
|
||||
int& height)
|
||||
{
|
||||
hwc_rect_t displayFrame = layer->displayFrame;
|
||||
|
||||
width = displayFrame.right - displayFrame.left;
|
||||
height = displayFrame.bottom - displayFrame.top;
|
||||
}
|
||||
|
||||
bool CopyBit::canUseCopybit(hwc_context_t *ctx, const hwc_layer_list_t* list,
|
||||
const int numYUVBuffers)
|
||||
{
|
||||
// XXX : TODO , currently returning false for MDP4 targets,
|
||||
// This has to be modified after adding C2D support.
|
||||
if(ctx->hasOverlay)
|
||||
return false;
|
||||
|
||||
framebuffer_device_t* fbDev = ctx->mFbDevice->getFb();
|
||||
if(!fbDev) {
|
||||
ALOGE("ERROR: canUseCopybit : fb device is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!list)
|
||||
return false;
|
||||
|
||||
// If , couldnt link to adreno library return false.
|
||||
if(LINK_eglGetRenderBufferANDROID == NULL ||
|
||||
LINK_eglGetCurrentSurface == NULL )
|
||||
return false;
|
||||
|
||||
if(!ctx->hasOverlay) {
|
||||
if (numYUVBuffers)
|
||||
return true;
|
||||
}
|
||||
|
||||
int fb_w = fbDev->width;
|
||||
int fb_h = fbDev->height;
|
||||
|
||||
/*
|
||||
* Use copybit only when we need to blit
|
||||
* max 2 full screen sized regions
|
||||
*/
|
||||
|
||||
unsigned int renderArea = 0;
|
||||
|
||||
for(unsigned int i = 0; i < list->numHwLayers; i++ ) {
|
||||
int w, h;
|
||||
getLayerResolution(&list->hwLayers[i], w, h);
|
||||
renderArea += w*h;
|
||||
}
|
||||
|
||||
return (renderArea <= (2 * fb_w * fb_h));
|
||||
}
|
||||
void CopyBit::openEglLibAndGethandle()
|
||||
{
|
||||
egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
|
||||
if (!egl_lib) {
|
||||
return;
|
||||
}
|
||||
updateEglHandles(egl_lib);
|
||||
}
|
||||
void CopyBit::closeEglLib()
|
||||
{
|
||||
if(egl_lib)
|
||||
::dlclose(egl_lib);
|
||||
|
||||
egl_lib = NULL;
|
||||
updateEglHandles(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//CopybitEngine Class functions
|
||||
CopybitEngine* CopybitEngine::sInstance = 0;;
|
||||
|
||||
struct copybit_device_t* CopybitEngine::getEngine() {
|
||||
return sEngine;
|
||||
}
|
||||
CopybitEngine* CopybitEngine::getInstance() {
|
||||
if(sInstance == NULL)
|
||||
sInstance = new CopybitEngine();
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
CopybitEngine::CopybitEngine(){
|
||||
hw_module_t const *module;
|
||||
if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
copybit_open(module, &sEngine);
|
||||
} else {
|
||||
ALOGE("FATAL ERROR: copybit open failed.");
|
||||
}
|
||||
}
|
||||
CopybitEngine::~CopybitEngine()
|
||||
{
|
||||
if(sEngine)
|
||||
{
|
||||
copybit_close(sEngine);
|
||||
sEngine = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}; //namespace qhwc
|
90
libhwcomposer/hwc_copybit.h
Normal file
90
libhwcomposer/hwc_copybit.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are retained
|
||||
* for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HWC_COPYBIT_H
|
||||
#define HWC_COPYBIT_H
|
||||
#include "hwc_utils.h"
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <gralloc_priv.h>
|
||||
#include <gr.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
namespace qhwc {
|
||||
//Feature for using Copybit to display RGB layers.
|
||||
class CopyBit {
|
||||
public:
|
||||
//Sets up members and prepares copybit if conditions are met
|
||||
static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Draws layer if the layer is set for copybit in prepare
|
||||
static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list, EGLDisplay dpy,
|
||||
EGLSurface sur);
|
||||
//Receives data from hwc
|
||||
static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
|
||||
|
||||
static void updateEglHandles(void*);
|
||||
static int drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_t *layer,
|
||||
EGLDisplay dpy, EGLSurface surface,
|
||||
functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
|
||||
functype_eglGetCurrentSurface LINK_eglGetCurrentSurface);
|
||||
static bool canUseCopybit(hwc_context_t* ctx, const hwc_layer_list_t* list,
|
||||
const int numYUVBuffers);
|
||||
static void closeEglLib();
|
||||
static void openEglLibAndGethandle();
|
||||
private:
|
||||
//Marks layer flags if this feature is used
|
||||
static void markFlags(hwc_layer_t *layer);
|
||||
//returns yuv count
|
||||
static int getYuvCount();
|
||||
|
||||
//Number of yuv layers in this drawing round
|
||||
static int sYuvCount;
|
||||
//Index of YUV layer, relevant only if count is 1
|
||||
static int sYuvLayerIndex;
|
||||
//Flags if a yuv layer is animating or below something that is animating
|
||||
static bool sIsLayerSkip;
|
||||
//Flags if this feature is on.
|
||||
static bool sIsModeOn;
|
||||
//handle for adreno lib
|
||||
static void* egl_lib;
|
||||
|
||||
static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID;
|
||||
static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface;
|
||||
|
||||
static void getLayerResolution(const hwc_layer_t* layer, int& width,
|
||||
int& height);
|
||||
|
||||
};
|
||||
|
||||
inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex,
|
||||
bool isYuvLayerSkip) {
|
||||
sYuvCount = yuvCount;
|
||||
sYuvLayerIndex = yuvLayerIndex;
|
||||
sIsLayerSkip = isYuvLayerSkip;
|
||||
}
|
||||
|
||||
inline int CopyBit::getYuvCount() { return sYuvCount; }
|
||||
|
||||
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_COPYBIT_H
|
40
libhwcomposer/hwc_copybitEngine.h
Normal file
40
libhwcomposer/hwc_copybitEngine.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are retained
|
||||
* for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HWC_COPYBIT_ENGINE_H
|
||||
#define HWC_COPYBIT_ENGINE_H
|
||||
|
||||
namespace qhwc {
|
||||
class CopybitEngine {
|
||||
public:
|
||||
~CopybitEngine();
|
||||
// API to get copybit engine(non static)
|
||||
struct copybit_device_t *getEngine();
|
||||
// API to get singleton
|
||||
static CopybitEngine* getInstance();
|
||||
|
||||
private:
|
||||
CopybitEngine();
|
||||
struct copybit_device_t *sEngine;
|
||||
static CopybitEngine* sInstance; // singleton
|
||||
};
|
||||
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_COPYBIT_ENGINE_H
|
446
libhwcomposer/hwc_ext_observer.cpp
Normal file
446
libhwcomposer/hwc_ext_observer.cpp
Normal file
@ -0,0 +1,446 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are
|
||||
* retained for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
#include <media/IAudioPolicyService.h>
|
||||
#include <media/AudioSystem.h>
|
||||
#include <utils/threads.h>
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <linux/msm_mdp.h>
|
||||
#include <linux/fb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#include <hardware_legacy/uevent.h>
|
||||
#include <cutils/properties.h>
|
||||
#include "hwc_utils.h"
|
||||
#include "hwc_ext_observer.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
#define EXT_OBSERVER_DEBUG 1
|
||||
|
||||
#define DEVICE_ROOT "/sys/devices/virtual/graphics"
|
||||
#define DEVICE_NODE "fb1"
|
||||
|
||||
#define SYSFS_CONNECTED DEVICE_ROOT "/" DEVICE_NODE "/connected"
|
||||
#define SYSFS_EDID_MODES DEVICE_ROOT "/" DEVICE_NODE "/edid_modes"
|
||||
#define SYSFS_HPD DEVICE_ROOT "/" DEVICE_NODE "/hpd"
|
||||
|
||||
|
||||
android::sp<ExtDisplayObserver> ExtDisplayObserver::
|
||||
sExtDisplayObserverInstance(0);
|
||||
|
||||
ExtDisplayObserver::ExtDisplayObserver() : Thread(false),
|
||||
fd(-1), mCurrentID(-1), mHwcContext(NULL)
|
||||
{
|
||||
//Enable HPD for HDMI
|
||||
writeHPDOption(1);
|
||||
}
|
||||
|
||||
ExtDisplayObserver::~ExtDisplayObserver() {
|
||||
if (fd > 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
ExtDisplayObserver *ExtDisplayObserver::getInstance() {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s ", __FUNCTION__);
|
||||
if(sExtDisplayObserverInstance.get() == NULL)
|
||||
sExtDisplayObserverInstance = new ExtDisplayObserver();
|
||||
return sExtDisplayObserverInstance.get();
|
||||
}
|
||||
|
||||
void ExtDisplayObserver::setHwcContext(hwc_context_t* hwcCtx) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
|
||||
if(hwcCtx) {
|
||||
mHwcContext = hwcCtx;
|
||||
}
|
||||
return;
|
||||
}
|
||||
void ExtDisplayObserver::onFirstRef() {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s", __FUNCTION__);
|
||||
run("ExtDisplayObserver", ANDROID_PRIORITY_DISPLAY);
|
||||
}
|
||||
|
||||
int ExtDisplayObserver::readyToRun() {
|
||||
//Initialize the uevent
|
||||
uevent_init();
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: success", __FUNCTION__);
|
||||
return android::NO_ERROR;
|
||||
}
|
||||
|
||||
void ExtDisplayObserver::handleUEvent(char* str){
|
||||
int connected = 0;
|
||||
// TODO: check for fb2(WFD) driver also
|
||||
if(!strcasestr(str, DEVICE_NODE))
|
||||
{
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
// Event will be of the form:
|
||||
// change@/devices/virtual/graphics/fb1 ACTION=change
|
||||
// DEVPATH=/devices/virtual/graphics/fb1
|
||||
// SUBSYSTEM=graphics HDCP_STATE=FAIL MAJOR=29
|
||||
// for now just parse the online or offline are important for us.
|
||||
if(!(strncmp(str,"online@",strlen("online@")))) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
|
||||
connected = 1;
|
||||
readResolution();
|
||||
//Get the best mode and set
|
||||
// TODO: DO NOT call this for WFD
|
||||
setResolution(getBestMode());
|
||||
} else if(!(strncmp(str,"offline@",strlen("offline@")))) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: external disp online", __FUNCTION__);
|
||||
connected = 0;
|
||||
close(fd);
|
||||
}
|
||||
setExternalDisplayStatus(connected);
|
||||
}
|
||||
|
||||
bool ExtDisplayObserver::threadLoop()
|
||||
{
|
||||
static char uEventString[1024];
|
||||
memset(uEventString, 0, sizeof(uEventString));
|
||||
int count = uevent_next_event(uEventString, sizeof(uEventString));
|
||||
if(count) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: UeventString: %s len = %d",
|
||||
__FUNCTION__, uEventString, count);
|
||||
handleUEvent(uEventString);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct disp_mode_timing_type {
|
||||
int video_format;
|
||||
|
||||
int active_h;
|
||||
int active_v;
|
||||
|
||||
int front_porch_h;
|
||||
int pulse_width_h;
|
||||
int back_porch_h;
|
||||
|
||||
int front_porch_v;
|
||||
int pulse_width_v;
|
||||
int back_porch_v;
|
||||
|
||||
int pixel_freq;
|
||||
bool interlaced;
|
||||
|
||||
void set_info(struct fb_var_screeninfo &info) const;
|
||||
};
|
||||
|
||||
void disp_mode_timing_type::set_info(struct fb_var_screeninfo &info) const
|
||||
{
|
||||
info.reserved[0] = 0;
|
||||
info.reserved[1] = 0;
|
||||
info.reserved[2] = 0;
|
||||
info.reserved[3] = video_format;
|
||||
|
||||
info.xoffset = 0;
|
||||
info.yoffset = 0;
|
||||
info.xres = active_h;
|
||||
info.yres = active_v;
|
||||
|
||||
info.pixclock = pixel_freq*1000;
|
||||
info.vmode = interlaced ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
|
||||
|
||||
info.right_margin = front_porch_h;
|
||||
info.hsync_len = pulse_width_h;
|
||||
info.left_margin = back_porch_h;
|
||||
info.lower_margin = front_porch_v;
|
||||
info.vsync_len = pulse_width_v;
|
||||
info.upper_margin = back_porch_v;
|
||||
}
|
||||
|
||||
/* Video formates supported by the HDMI Standard */
|
||||
/* Indicates the resolution, pix clock and the aspect ratio */
|
||||
#define m640x480p60_4_3 1
|
||||
#define m720x480p60_4_3 2
|
||||
#define m720x480p60_16_9 3
|
||||
#define m1280x720p60_16_9 4
|
||||
#define m1920x1080i60_16_9 5
|
||||
#define m1440x480i60_4_3 6
|
||||
#define m1440x480i60_16_9 7
|
||||
#define m1920x1080p60_16_9 16
|
||||
#define m720x576p50_4_3 17
|
||||
#define m720x576p50_16_9 18
|
||||
#define m1280x720p50_16_9 19
|
||||
#define m1440x576i50_4_3 21
|
||||
#define m1440x576i50_16_9 22
|
||||
#define m1920x1080p50_16_9 31
|
||||
#define m1920x1080p24_16_9 32
|
||||
#define m1920x1080p25_16_9 33
|
||||
#define m1920x1080p30_16_9 34
|
||||
|
||||
static struct disp_mode_timing_type supported_video_mode_lut[] = {
|
||||
{m640x480p60_4_3, 640, 480, 16, 96, 48, 10, 2, 33, 25200, false},
|
||||
{m720x480p60_4_3, 720, 480, 16, 62, 60, 9, 6, 30, 27030, false},
|
||||
{m720x480p60_16_9, 720, 480, 16, 62, 60, 9, 6, 30, 27030, false},
|
||||
{m1280x720p60_16_9, 1280, 720, 110, 40, 220, 5, 5, 20, 74250, false},
|
||||
{m1920x1080i60_16_9, 1920, 540, 88, 44, 148, 2, 5, 5, 74250, false},
|
||||
{m1440x480i60_4_3, 1440, 240, 38, 124, 114, 4, 3, 15, 27000, true},
|
||||
{m1440x480i60_16_9, 1440, 240, 38, 124, 114, 4, 3, 15, 27000, true},
|
||||
{m1920x1080p60_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 148500, false},
|
||||
{m720x576p50_4_3, 720, 576, 12, 64, 68, 5, 5, 39, 27000, false},
|
||||
{m720x576p50_16_9, 720, 576, 12, 64, 68, 5, 5, 39, 27000, false},
|
||||
{m1280x720p50_16_9, 1280, 720, 440, 40, 220, 5, 5, 20, 74250, false},
|
||||
{m1440x576i50_4_3, 1440, 288, 24, 126, 138, 2, 3, 19, 27000, true},
|
||||
{m1440x576i50_16_9, 1440, 288, 24, 126, 138, 2, 3, 19, 27000, true},
|
||||
{m1920x1080p50_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 148500, false},
|
||||
{m1920x1080p24_16_9, 1920, 1080, 638, 44, 148, 4, 5, 36, 74250, false},
|
||||
{m1920x1080p25_16_9, 1920, 1080, 528, 44, 148, 4, 5, 36, 74250, false},
|
||||
{m1920x1080p30_16_9, 1920, 1080, 88, 44, 148, 4, 5, 36, 74250, false},
|
||||
};
|
||||
int ExtDisplayObserver::parseResolution(char* edidStr, int* edidModes, int len)
|
||||
{
|
||||
char delim = ',';
|
||||
int count = 0;
|
||||
char *start, *end;
|
||||
// EDIDs are string delimited by ','
|
||||
// Ex: 16,4,5,3,32,34,1
|
||||
// Parse this string to get mode(int)
|
||||
start = (char*) edidStr;
|
||||
for(int i=0; i<len; i++) {
|
||||
edidModes[i] = (int) strtol(start, &end, 10);
|
||||
if(*end != delim) {
|
||||
// return as we reached end of string
|
||||
return count;
|
||||
}
|
||||
start = end+1;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
bool ExtDisplayObserver::readResolution()
|
||||
{
|
||||
int hdmiEDIDFile = open(SYSFS_EDID_MODES, O_RDONLY, 0);
|
||||
int len = -1;
|
||||
|
||||
memset(mEDIDs, 0, sizeof(mEDIDs));
|
||||
memset(mEDIDModes, 0, sizeof(mEDIDModes));
|
||||
mModeCount = 0;
|
||||
if (hdmiEDIDFile < 0) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file '%s' not found",
|
||||
__FUNCTION__, SYSFS_EDID_MODES);
|
||||
return false;
|
||||
} else {
|
||||
len = read(hdmiEDIDFile, mEDIDs, sizeof(mEDIDs)-1);
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: EDID string: %s length = %d",
|
||||
__FUNCTION__, mEDIDs, len);
|
||||
if ( len <= 0) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: edid_modes file empty '%s'",
|
||||
__FUNCTION__, SYSFS_EDID_MODES);
|
||||
}
|
||||
else {
|
||||
while (len > 1 && isspace(mEDIDs[len-1]))
|
||||
--len;
|
||||
mEDIDs[len] = 0;
|
||||
}
|
||||
}
|
||||
close(hdmiEDIDFile);
|
||||
if(len > 0) {
|
||||
// GEt EDID modes from the EDID strings
|
||||
mModeCount = parseResolution(mEDIDs, mEDIDModes, len);
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: mModeCount = %d", __FUNCTION__,
|
||||
mModeCount);
|
||||
}
|
||||
|
||||
return (strlen(mEDIDs) > 0);
|
||||
}
|
||||
|
||||
bool ExtDisplayObserver::openFramebuffer()
|
||||
{
|
||||
if (fd == -1) {
|
||||
fd = open("/dev/graphics/fb1", O_RDWR);
|
||||
if (fd < 0)
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: /dev/graphics/fb1 not available"
|
||||
"\n", __FUNCTION__);
|
||||
}
|
||||
return (fd > 0);
|
||||
}
|
||||
|
||||
|
||||
int ExtDisplayObserver::getModeOrder(int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
default:
|
||||
case m1440x480i60_4_3:
|
||||
return 1; // 480i 4:3
|
||||
case m1440x480i60_16_9:
|
||||
return 2; // 480i 16:9
|
||||
case m1440x576i50_4_3:
|
||||
return 3; // i576i 4:3
|
||||
case m1440x576i50_16_9:
|
||||
return 4; // 576i 16:9
|
||||
case m640x480p60_4_3:
|
||||
return 5; // 640x480 4:3
|
||||
case m720x480p60_4_3:
|
||||
return 6; // 480p 4:3
|
||||
case m720x480p60_16_9:
|
||||
return 7; // 480p 16:9
|
||||
case m720x576p50_4_3:
|
||||
return 8; // 576p 4:3
|
||||
case m720x576p50_16_9:
|
||||
return 9; // 576p 16:9
|
||||
case m1920x1080i60_16_9:
|
||||
return 10; // 1080i 16:9
|
||||
case m1280x720p50_16_9:
|
||||
return 11; // 720p@50Hz
|
||||
case m1280x720p60_16_9:
|
||||
return 12; // 720p@60Hz
|
||||
case m1920x1080p24_16_9:
|
||||
return 13; //1080p@24Hz
|
||||
case m1920x1080p25_16_9:
|
||||
return 14; //108-p@25Hz
|
||||
case m1920x1080p30_16_9:
|
||||
return 15; //1080p@30Hz
|
||||
case m1920x1080p50_16_9:
|
||||
return 16; //1080p@50Hz
|
||||
case m1920x1080p60_16_9:
|
||||
return 17; //1080p@60Hz
|
||||
}
|
||||
}
|
||||
|
||||
// Get the best mode for the current HD TV
|
||||
int ExtDisplayObserver::getBestMode() {
|
||||
int bestOrder = 0;
|
||||
int bestMode = m640x480p60_4_3;
|
||||
|
||||
// for all the edid read, get the best mode
|
||||
for(int i = 0; i < mModeCount; i++) {
|
||||
int mode = mEDIDModes[i];
|
||||
int order = getModeOrder(mode);
|
||||
if (order > bestOrder) {
|
||||
bestOrder = order;
|
||||
bestMode = mode;
|
||||
}
|
||||
}
|
||||
return bestMode;
|
||||
}
|
||||
|
||||
inline bool ExtDisplayObserver::isValidMode(int ID)
|
||||
{
|
||||
return ((ID >= m640x480p60_4_3) && (ID <= m1920x1080p30_16_9));
|
||||
}
|
||||
|
||||
void ExtDisplayObserver::setResolution(int ID)
|
||||
{
|
||||
struct fb_var_screeninfo info;
|
||||
if (!openFramebuffer())
|
||||
return;
|
||||
//If its a valid mode and its a new ID - update var_screeninfo
|
||||
if ((isValidMode(ID)) && mCurrentID != ID) {
|
||||
const struct disp_mode_timing_type *mode =
|
||||
&supported_video_mode_lut[0];
|
||||
unsigned count = sizeof(supported_video_mode_lut)/sizeof
|
||||
(*supported_video_mode_lut);
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
const struct disp_mode_timing_type *cur =
|
||||
&supported_video_mode_lut[i];
|
||||
if (cur->video_format == ID)
|
||||
mode = cur;
|
||||
}
|
||||
ioctl(fd, FBIOGET_VSCREENINFO, &info);
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: GET Info<ID=%d %dx%d (%d,%d,%d),"
|
||||
"(%d,%d,%d) %dMHz>", __FUNCTION__,
|
||||
info.reserved[3], info.xres, info.yres,
|
||||
info.right_margin, info.hsync_len, info.left_margin,
|
||||
info.lower_margin, info.vsync_len, info.upper_margin,
|
||||
info.pixclock/1000/1000);
|
||||
mode->set_info(info);
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: SET Info<ID=%d => Info<ID=%d %dx%d"
|
||||
"(%d,%d,%d), (%d,%d,%d) %dMHz>", __FUNCTION__, ID,
|
||||
info.reserved[3], info.xres, info.yres,
|
||||
info.right_margin, info.hsync_len, info.left_margin,
|
||||
info.lower_margin, info.vsync_len, info.upper_margin,
|
||||
info.pixclock/1000/1000);
|
||||
info.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_ALL | FB_ACTIVATE_FORCE;
|
||||
ioctl(fd, FBIOPUT_VSCREENINFO, &info);
|
||||
mCurrentID = ID;
|
||||
}
|
||||
//Powerup
|
||||
ioctl(fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
||||
ioctl(fd, FBIOGET_VSCREENINFO, &info);
|
||||
//Pan_Display
|
||||
ioctl(fd, FBIOPAN_DISPLAY, &info);
|
||||
property_set("hw.hdmiON", "1");
|
||||
}
|
||||
|
||||
|
||||
int ExtDisplayObserver::getExternalDisplay() const
|
||||
{
|
||||
return mExternalDisplay;
|
||||
}
|
||||
|
||||
void ExtDisplayObserver::setExternalDisplayStatus(int connected)
|
||||
{
|
||||
|
||||
hwc_context_t* ctx = mHwcContext;
|
||||
if(ctx) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: status = %d", __FUNCTION__,
|
||||
connected);
|
||||
// Store the external display
|
||||
mExternalDisplay = connected;//(external_display_type)value;
|
||||
//Invalidate
|
||||
hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0];
|
||||
if(!proc) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: HWC proc not registered",
|
||||
__FUNCTION__);
|
||||
} else {
|
||||
/* Trigger redraw */
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: Invalidate !!", __FUNCTION__);
|
||||
proc->invalidate(proc);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool ExtDisplayObserver::writeHPDOption(int userOption) const
|
||||
{
|
||||
bool ret = true;
|
||||
int hdmiHPDFile = open(SYSFS_HPD,O_RDWR, 0);
|
||||
if (hdmiHPDFile < 0) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: state file '%s' not found : ret%d"
|
||||
"err str: %s", __FUNCTION__, SYSFS_HPD, hdmiHPDFile, strerror(errno));
|
||||
ret = false;
|
||||
} else {
|
||||
int err = -1;
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: option = %d", __FUNCTION__,
|
||||
userOption);
|
||||
if(userOption)
|
||||
err = write(hdmiHPDFile, "1", 2);
|
||||
else
|
||||
err = write(hdmiHPDFile, "0" , 2);
|
||||
if (err <= 0) {
|
||||
ALOGD_IF(EXT_OBSERVER_DEBUG, "%s: file write failed '%s'",
|
||||
__FUNCTION__, SYSFS_HPD);
|
||||
ret = false;
|
||||
}
|
||||
close(hdmiHPDFile);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
80
libhwcomposer/hwc_ext_observer.h
Normal file
80
libhwcomposer/hwc_ext_observer.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are
|
||||
* retained for attribution purposes only.
|
||||
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef HWC_EXT_OBSERVER_H
|
||||
#define HWC_EXT_OBSERVER_H
|
||||
|
||||
#include <utils/threads.h>
|
||||
|
||||
struct hwc_context_t;
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
class ExtDisplayObserver : public android::Thread
|
||||
{
|
||||
//Type of external display - OFF, HDMI, WFD
|
||||
enum external_display_type {
|
||||
EXT_TYPE_NONE,
|
||||
EXT_TYPE_HDMI,
|
||||
EXT_TYPE_WIFI
|
||||
};
|
||||
|
||||
// Mirroring state
|
||||
enum external_mirroring_state {
|
||||
EXT_MIRRORING_OFF,
|
||||
EXT_MIRRORING_ON,
|
||||
};
|
||||
public:
|
||||
/*Overrides*/
|
||||
virtual bool threadLoop();
|
||||
virtual int readyToRun();
|
||||
virtual void onFirstRef();
|
||||
|
||||
virtual ~ExtDisplayObserver();
|
||||
static ExtDisplayObserver *getInstance();
|
||||
int getExternalDisplay() const;
|
||||
void setHwcContext(hwc_context_t* hwcCtx);
|
||||
|
||||
private:
|
||||
ExtDisplayObserver();
|
||||
void setExternalDisplayStatus(int connected);
|
||||
bool readResolution();
|
||||
int parseResolution(char* edidStr, int* edidModes, int len);
|
||||
void setResolution(int ID);
|
||||
bool openFramebuffer();
|
||||
bool writeHPDOption(int userOption) const;
|
||||
bool isValidMode(int ID);
|
||||
void handleUEvent(char* str);
|
||||
int getModeOrder(int mode);
|
||||
int getBestMode();
|
||||
|
||||
int fd;
|
||||
int mExternalDisplay;
|
||||
int mCurrentID;
|
||||
char mEDIDs[128];
|
||||
int mEDIDModes[64];
|
||||
int mModeCount;
|
||||
hwc_context_t *mHwcContext;
|
||||
static android::sp<ExtDisplayObserver> sExtDisplayObserverInstance;
|
||||
};
|
||||
|
||||
}; //qhwc
|
||||
// ---------------------------------------------------------------------------
|
||||
#endif //HWC_EXT_OBSERVER_H
|
@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hwc_utils.h"
|
||||
#define FINAL_TRANSFORM_MASK 0x000F
|
||||
|
||||
namespace qhwc {
|
||||
// Determine overlay state based on decoded video info
|
||||
static ovutils::eOverlayState determineOverlayState(hwc_context_t* ctx,
|
||||
uint32_t bypassLayer,
|
||||
uint32_t format)
|
||||
{
|
||||
ovutils::eOverlayState state = ovutils::OV_CLOSED;
|
||||
|
||||
// Sanity check
|
||||
if (!ctx) {
|
||||
ALOGE("%s: NULL ctx", __FUNCTION__);
|
||||
return state;
|
||||
}
|
||||
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
state = ov.getState();
|
||||
|
||||
// If there are any bypassLayers, state is based on number of layers
|
||||
if ((bypassLayer > 0) && (ctx->hdmiEnabled == EXT_TYPE_NONE)) {
|
||||
if (bypassLayer == 1) {
|
||||
state = ovutils::OV_BYPASS_1_LAYER;
|
||||
} else if (bypassLayer == 2) {
|
||||
state = ovutils::OV_BYPASS_2_LAYER;
|
||||
} else if (bypassLayer == 3) {
|
||||
state = ovutils::OV_BYPASS_3_LAYER;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
// RGB is ambiguous for determining overlay state
|
||||
if (ovutils::isRgb(ovutils::getMdpFormat(format))) {
|
||||
return state;
|
||||
}
|
||||
|
||||
// Content type is either 2D or 3D
|
||||
uint32_t fmt3D = 0;//XXX: 3D - ovutils::getS3DFormat(format);
|
||||
|
||||
// Determine state based on the external display, content type, and hw type
|
||||
if (ctx->hdmiEnabled == EXT_TYPE_HDMI) {
|
||||
// External display is HDMI
|
||||
if (fmt3D) {
|
||||
// Content type is 3D
|
||||
if (ovutils::is3DTV()) {
|
||||
// TV panel type is 3D
|
||||
state = ovutils::OV_3D_VIDEO_ON_3D_TV;
|
||||
} else {
|
||||
// TV panel type is 2D
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV;
|
||||
}
|
||||
} else {
|
||||
// Content type is 2D
|
||||
if (ovutils::FrameBufferInfo::getInstance()->supportTrueMirroring()) {
|
||||
// True UI mirroring is supported
|
||||
state = ovutils::OV_2D_TRUE_UI_MIRROR;
|
||||
} else {
|
||||
// True UI mirroring is not supported
|
||||
state = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
||||
}
|
||||
}
|
||||
} else if (ctx->hdmiEnabled == EXT_TYPE_WIFI) {
|
||||
// External display is Wifi (currently unsupported)
|
||||
ALOGE("%s: WIFI external display is unsupported", __FUNCTION__);
|
||||
return state;
|
||||
} else {
|
||||
// No external display (primary panel only)
|
||||
if (fmt3D) {
|
||||
// Content type is 3D
|
||||
if (ovutils::usePanel3D()) {
|
||||
// Primary panel type is 3D
|
||||
state = ovutils::OV_3D_VIDEO_ON_3D_PANEL;
|
||||
} else {
|
||||
// Primary panel type is 2D
|
||||
state = ovutils::OV_3D_VIDEO_ON_2D_PANEL;
|
||||
}
|
||||
} else {
|
||||
// Content type is 2D
|
||||
state = ovutils::OV_2D_VIDEO_ON_PANEL;
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void setOverlayState(hwc_context_t *ctx, ovutils::eOverlayState state)
|
||||
{
|
||||
if (!ctx) {
|
||||
ALOGE("%s: NULL ctx", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
overlay::Overlay *ov = ctx->mOverlay;
|
||||
if (!ov) {
|
||||
ALOGE("%s: NULL OV object", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
ov->setState(state);
|
||||
}
|
||||
|
||||
bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
{
|
||||
bool ret = false;
|
||||
if (LIKELY(ctx->mOverlay)) {
|
||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
||||
|
||||
// Set overlay state
|
||||
ovutils::eOverlayState state = determineOverlayState(ctx, 0, info.format);
|
||||
setOverlayState(ctx, state);
|
||||
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
|
||||
// In the true UI mirroring case, video needs to go to OV_PIPE0 (for
|
||||
// primary) and OV_PIPE1 (for external)
|
||||
if (state == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||
dest = static_cast<ovutils::eDest>(
|
||||
ovutils::OV_PIPE0 | ovutils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// Order order order
|
||||
// setSource - just setting source
|
||||
// setParameter - changes src w/h/f accordingly
|
||||
// setCrop - ROI - that is src_rect
|
||||
// setPosition - need to do scaling
|
||||
// commit - commit changes to mdp driver
|
||||
// queueBuffer - not here, happens when draw is called
|
||||
|
||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
|
||||
ovutils::setMdpFlags(mdpFlags,
|
||||
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||
}
|
||||
|
||||
// FIXME: Use source orientation for TV when source is portrait
|
||||
int transform = layer->transform & FINAL_TRANSFORM_MASK;
|
||||
ovutils::eTransform orient =
|
||||
static_cast<ovutils::eTransform>(transform);
|
||||
|
||||
ovutils::eWait waitFlag = ovutils::NO_WAIT;
|
||||
if (ctx->skipComposition == true) {
|
||||
waitFlag = ovutils::WAIT;
|
||||
}
|
||||
|
||||
ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
|
||||
if (ctx->numHwLayers == 1) {
|
||||
isFgFlag = ovutils::IS_FG_SET;
|
||||
}
|
||||
|
||||
ovutils::PipeArgs parg(mdpFlags,
|
||||
orient,
|
||||
info,
|
||||
waitFlag,
|
||||
ovutils::ZORDER_0,
|
||||
isFgFlag,
|
||||
ovutils::ROT_FLAG_DISABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
ret = ov.setSource(pargs, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s: setSource failed", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, orient);
|
||||
ret = ov.setParameter(prms, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s: setParameter failed transform %x", __FUNCTION__, orient);
|
||||
return ret;
|
||||
}
|
||||
|
||||
hwc_rect_t sourceCrop = layer->sourceCrop;
|
||||
// x,y,w,h
|
||||
ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top, // x, y
|
||||
sourceCrop.right - sourceCrop.left, // w
|
||||
sourceCrop.bottom - sourceCrop.top);// h
|
||||
ret = ov.setCrop(dcrop, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s: setCrop failed", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int orientation = 0;
|
||||
ovutils::Dim dim;
|
||||
hwc_rect_t displayFrame = layer->displayFrame;
|
||||
dim.x = displayFrame.left;
|
||||
dim.y = displayFrame.top;
|
||||
dim.w = (displayFrame.right - displayFrame.left);
|
||||
dim.h = (displayFrame.bottom - displayFrame.top);
|
||||
dim.o = orientation;
|
||||
|
||||
ret = ov.setPosition(dim, dest);
|
||||
if (!ret) {
|
||||
ALOGE("%s: setPosition failed", __FUNCTION__);
|
||||
return ret;
|
||||
}
|
||||
if (!ov.commit(dest)) {
|
||||
ALOGE("%s: commit fails", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
{
|
||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||
|
||||
// Lock this buffer for read.
|
||||
ctx->qbuf->lockAndAdd(hnd);
|
||||
bool ret = true;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
|
||||
// Differentiate between states that need to wait for vsync
|
||||
switch (state) {
|
||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
case ovutils::OV_2D_TRUE_UI_MIRROR:
|
||||
// If displaying on both primary and external, must play each
|
||||
// pipe individually since wait for vsync needs to be done at
|
||||
// the end. Do the following:
|
||||
// - Play external
|
||||
// - Play primary
|
||||
// - Wait for external vsync to be done
|
||||
// NOTE: In these states
|
||||
// - primary VG = OV_PIPE0
|
||||
// - external VG = OV_PIPE1
|
||||
// - external RGB = OV_PIPE2
|
||||
// - Only in true UI mirroring case, played by fb
|
||||
|
||||
// Same FD for both primary and external VG pipes
|
||||
ov.setMemoryId(hnd->fd, static_cast<ovutils::eDest>(
|
||||
ovutils::OV_PIPE0 | ovutils::OV_PIPE1));
|
||||
|
||||
// Play external
|
||||
if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE1)) {
|
||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// Play primary
|
||||
if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// Wait for external vsync to be done
|
||||
if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
|
||||
ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// In most cases, displaying only to one (primary or external)
|
||||
// so use OV_PIPE_ALL since overlay will ignore NullPipes
|
||||
ov.setMemoryId(hnd->fd, ovutils::OV_PIPE_ALL);
|
||||
if (!ov.queueBuffer(hnd->offset, ovutils::OV_PIPE_ALL)) {
|
||||
ALOGE("%s: queueBuffer failed", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
ALOGE("%s: failed", __FUNCTION__);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cleanOverlays(hwc_context_t *ctx )
|
||||
{
|
||||
//XXX: handle for HDMI
|
||||
if(0 == ctx->yuvBufferCount)
|
||||
setOverlayState(ctx, ovutils::OV_CLOSED);
|
||||
}
|
||||
}; //namespace qhwc
|
180
libhwcomposer/hwc_uimirror.cpp
Normal file
180
libhwcomposer/hwc_uimirror.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are
|
||||
* retained for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hwc_uimirror.h"
|
||||
#include "hwc_ext_observer.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
#define HWC_UI_MIRROR 0
|
||||
|
||||
// Function to get the primary device orientation
|
||||
// Loops thru the hardware layers and returns the orientation of the max.
|
||||
// number of layers
|
||||
int getDeviceOrientation(hwc_context_t* ctx, hwc_layer_list_t *list) {
|
||||
int orientation = list->hwLayers[0].transform;
|
||||
if(!ctx) {
|
||||
ALOGD_IF(HWC_UI_MIRROR, "In %s: ctx is NULL!!", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
for(size_t i=0; i <= list->numHwLayers;i++ )
|
||||
{
|
||||
for(size_t j=i+1; j <= list->numHwLayers; j++)
|
||||
{
|
||||
// Should we not check for the video layer orientation as it might
|
||||
// source orientation(?)
|
||||
if(list->hwLayers[i].transform == list->hwLayers[j].transform)
|
||||
{
|
||||
orientation = list->hwLayers[i].transform;
|
||||
}
|
||||
}
|
||||
}
|
||||
return orientation;
|
||||
}
|
||||
|
||||
//Static Members
|
||||
ovutils::eOverlayState UIMirrorOverlay::sState = ovutils::OV_CLOSED;
|
||||
bool UIMirrorOverlay::sIsUiMirroringOn = false;
|
||||
|
||||
|
||||
//Prepare the overlay for the UI mirroring
|
||||
bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
sState = ovutils::OV_CLOSED;
|
||||
sIsUiMirroringOn = false;
|
||||
// If external display is connected
|
||||
if(ctx->mExtDisplayObserver->getExternalDisplay()) {
|
||||
sState = ovutils::OV_UI_MIRROR;
|
||||
configure(ctx, list);
|
||||
}
|
||||
return sIsUiMirroringOn;
|
||||
}
|
||||
|
||||
// Configure
|
||||
bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
{
|
||||
if (LIKELY(ctx->mOverlay)) {
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
// Set overlay state
|
||||
ov.setState(sState);
|
||||
framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
|
||||
if(fbDev) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
fbDev->common.module);
|
||||
int alignedW = ALIGN_TO(m->info.xres, 32);
|
||||
|
||||
private_handle_t const* hnd =
|
||||
reinterpret_cast<private_handle_t const*>(m->framebuffer);
|
||||
unsigned int size = hnd->size/m->numBuffers;
|
||||
ovutils::Whf info(alignedW, hnd->height, hnd->format, size);
|
||||
// Determine the RGB pipe for UI depending on the state
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||
// True UI mirroring state: external RGB pipe is OV_PIPE2
|
||||
dest = ovutils::OV_PIPE2;
|
||||
} else if (sState == ovutils::OV_UI_MIRROR) {
|
||||
// UI-only mirroring state: external RGB pipe is OV_PIPE0
|
||||
dest = ovutils::OV_PIPE0;
|
||||
}
|
||||
|
||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_MEMORY_ID_TYPE_FB;
|
||||
/* - TODO: Secure content
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
|
||||
ovutils::setMdpFlags(mdpFlags,
|
||||
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||
}
|
||||
*/
|
||||
|
||||
ovutils::PipeArgs parg(mdpFlags,
|
||||
info,
|
||||
ovutils::ZORDER_0,
|
||||
ovutils::IS_FG_OFF,
|
||||
ovutils::ROT_FLAG_ENABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
ov.setSource(pargs, dest);
|
||||
|
||||
// x,y,w,h
|
||||
ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
|
||||
ov.setCrop(dcrop, dest);
|
||||
//Get the current orientation on primary panel
|
||||
int transform = getDeviceOrientation(ctx, list);
|
||||
ovutils::eTransform orient =
|
||||
static_cast<ovutils::eTransform>(transform);
|
||||
ov.setTransform(orient, dest);
|
||||
|
||||
ovutils::Dim dim;
|
||||
dim.x = 0;
|
||||
dim.y = 0;
|
||||
dim.w = m->info.xres;
|
||||
dim.h = m->info.yres;
|
||||
ov.setPosition(dim, dest);
|
||||
if (!ov.commit(dest)) {
|
||||
ALOGE("%s: commit fails", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
sIsUiMirroringOn = true;
|
||||
}
|
||||
}
|
||||
return sIsUiMirroringOn;
|
||||
}
|
||||
|
||||
bool UIMirrorOverlay::draw(hwc_context_t *ctx)
|
||||
{
|
||||
if(!sIsUiMirroringOn) {
|
||||
return true;
|
||||
}
|
||||
bool ret = true;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
framebuffer_device_t *fbDev = ctx->mFbDevice->getFb();
|
||||
if(fbDev) {
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
fbDev->common.module);
|
||||
//wait for the fb_post to be called
|
||||
pthread_mutex_lock(&m->fbPostLock);
|
||||
while(m->fbPostDone == false) {
|
||||
pthread_cond_wait(&(m->fbPostCond), &(m->fbPostLock));
|
||||
}
|
||||
pthread_mutex_unlock(&m->fbPostLock);
|
||||
switch (state) {
|
||||
case ovutils::OV_UI_MIRROR:
|
||||
if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
|
||||
ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||
}
|
||||
break;
|
||||
case ovutils::OV_2D_TRUE_UI_MIRROR:
|
||||
if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
|
||||
ovutils::OV_PIPE2)) {
|
||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// TODO:
|
||||
// Call PANDISPLAY ioctl here to kickoff
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
}; //namespace qhwc
|
46
libhwcomposer/hwc_uimirror.h
Normal file
46
libhwcomposer/hwc_uimirror.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Not a Contribution, Apache license notifications and license are
|
||||
* retained for attribution purposes only.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HWC_UIMIRROR_H
|
||||
#define HWC_UIMIRROR_H
|
||||
#include "hwc_utils.h"
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
namespace qhwc {
|
||||
//Feature for Mirroring UI on the External display
|
||||
class UIMirrorOverlay {
|
||||
public:
|
||||
// Sets up members and prepares overlay if conditions are met
|
||||
static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
// Draws layer if this feature is on
|
||||
static bool draw(hwc_context_t *ctx);
|
||||
private:
|
||||
//Configures overlay
|
||||
static bool configure(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//The chosen overlay state.
|
||||
static ovutils::eOverlayState sState;
|
||||
//Flags if this feature is on.
|
||||
static bool sIsUiMirroringOn;
|
||||
};
|
||||
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_UIMIRROR_H
|
@ -17,18 +17,24 @@
|
||||
|
||||
#include "hwc_utils.h"
|
||||
#include "mdp_version.h"
|
||||
|
||||
#include "hwc_video.h"
|
||||
#include "hwc_ext_observer.h"
|
||||
#include "hwc_copybit.h"
|
||||
namespace qhwc {
|
||||
void initContext(hwc_context_t *ctx)
|
||||
{
|
||||
//XXX: target specific initializations here
|
||||
openFramebufferDevice(ctx);
|
||||
ctx->mOverlay = overlay::Overlay::getInstance();
|
||||
ctx->qbuf = new QueuedBufferStore();
|
||||
ctx->mdpVersion = qdutils::MDPVersion::getInstance().getMDPVersion();
|
||||
ctx->hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
|
||||
ALOGI("MDP version: %d",ctx->mdpVersion);
|
||||
|
||||
ctx->mExtDisplayObserver = ExtDisplayObserver::getInstance();
|
||||
ctx->mExtDisplayObserver->setHwcContext(ctx);
|
||||
ctx->mFbDevice = FbDevice::getInstance();
|
||||
ctx->mCopybitEngine = CopybitEngine::getInstance();
|
||||
CopyBit::openEglLibAndGethandle();
|
||||
}
|
||||
|
||||
void closeContext(hwc_context_t *ctx)
|
||||
@ -37,23 +43,20 @@ void closeContext(hwc_context_t *ctx)
|
||||
delete ctx->mOverlay;
|
||||
ctx->mOverlay = NULL;
|
||||
}
|
||||
if(ctx->fbDev) {
|
||||
framebuffer_close(ctx->fbDev);
|
||||
ctx->fbDev = NULL;
|
||||
}
|
||||
|
||||
if(ctx->mCopybitEngine) {
|
||||
delete ctx->mCopybitEngine;
|
||||
ctx->mCopybitEngine = NULL;
|
||||
}
|
||||
if(ctx->mFbDevice) {
|
||||
delete ctx->mFbDevice;
|
||||
ctx->mFbDevice = NULL;
|
||||
}
|
||||
if(ctx->qbuf) {
|
||||
delete ctx->qbuf;
|
||||
ctx->qbuf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Opens Framebuffer device
|
||||
void openFramebufferDevice(hwc_context_t *ctx) {
|
||||
hw_module_t const *module;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
framebuffer_open(module, &(ctx->fbDev));
|
||||
}
|
||||
CopyBit::closeEglLib();
|
||||
}
|
||||
|
||||
void dumpLayer(hwc_layer_t const* l)
|
||||
@ -73,28 +76,120 @@ void dumpLayer(hwc_layer_t const* l)
|
||||
|
||||
void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list)
|
||||
{
|
||||
int yuvBufCount = 0;
|
||||
int layersNotUpdatingCount = 0;
|
||||
for (size_t i=0 ; i<list->numHwLayers; i++) {
|
||||
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
|
||||
//Video specific stats
|
||||
int yuvCount = 0;
|
||||
int yuvLayerIndex = -1;
|
||||
bool isYuvLayerSkip = false;
|
||||
|
||||
for (size_t i = 0; i < list->numHwLayers; i++) {
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[i].handle;
|
||||
|
||||
if (isYuvBuffer(hnd)) {
|
||||
yuvBufCount++;
|
||||
yuvCount++;
|
||||
yuvLayerIndex = i;
|
||||
//Animating
|
||||
if (isSkipLayer(&list->hwLayers[i])) {
|
||||
isYuvLayerSkip = true;
|
||||
}
|
||||
} else if (isSkipLayer(&list->hwLayers[i])) { //Popups
|
||||
//If video layer is below a skip layer
|
||||
if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) {
|
||||
isYuvLayerSkip = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Number of video/camera layers drawable with overlay
|
||||
ctx->yuvBufferCount = yuvBufCount;
|
||||
|
||||
VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
|
||||
CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
|
||||
|
||||
ctx->numHwLayers = list->numHwLayers;
|
||||
return;
|
||||
}
|
||||
|
||||
void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
{
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)layer->handle;
|
||||
//XXX: Handle targets not using overlay
|
||||
if(prepareOverlay(ctx, layer)) {
|
||||
layer->compositionType = HWC_OVERLAY;
|
||||
layer->hints |= HWC_HINT_CLEAR_FB;
|
||||
//Crops source buffer against destination and FB boundaries
|
||||
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
||||
const int fbWidth, const int fbHeight) {
|
||||
|
||||
int& crop_x = crop.left;
|
||||
int& crop_y = crop.top;
|
||||
int& crop_r = crop.right;
|
||||
int& crop_b = crop.bottom;
|
||||
int crop_w = crop.right - crop.left;
|
||||
int crop_h = crop.bottom - crop.top;
|
||||
|
||||
int& dst_x = dst.left;
|
||||
int& dst_y = dst.top;
|
||||
int& dst_r = dst.right;
|
||||
int& dst_b = dst.bottom;
|
||||
int dst_w = dst.right - dst.left;
|
||||
int dst_h = dst.bottom - dst.top;
|
||||
|
||||
if(dst_x < 0) {
|
||||
float scale_x = crop_w * 1.0f / dst_w;
|
||||
float diff_factor = (scale_x * abs(dst_x));
|
||||
crop_x = crop_x + (int)diff_factor;
|
||||
crop_w = crop_r - crop_x;
|
||||
|
||||
dst_x = 0;
|
||||
dst_w = dst_r - dst_x;;
|
||||
}
|
||||
if(dst_r > fbWidth) {
|
||||
float scale_x = crop_w * 1.0f / dst_w;
|
||||
float diff_factor = scale_x * (dst_r - fbWidth);
|
||||
crop_r = crop_r - diff_factor;
|
||||
crop_w = crop_r - crop_x;
|
||||
|
||||
dst_r = fbWidth;
|
||||
dst_w = dst_r - dst_x;
|
||||
}
|
||||
if(dst_y < 0) {
|
||||
float scale_y = crop_h * 1.0f / dst_h;
|
||||
float diff_factor = scale_y * abs(dst_y);
|
||||
crop_y = crop_y + diff_factor;
|
||||
crop_h = crop_b - crop_y;
|
||||
|
||||
dst_y = 0;
|
||||
dst_h = dst_b - dst_y;
|
||||
}
|
||||
if(dst_b > fbHeight) {
|
||||
float scale_y = crop_h * 1.0f / dst_h;
|
||||
float diff_factor = scale_y * (dst_b - fbHeight);
|
||||
crop_b = crop_b - diff_factor;
|
||||
crop_h = crop_b - crop_y;
|
||||
|
||||
dst_b = fbHeight;
|
||||
dst_h = dst_b - dst_y;
|
||||
}
|
||||
}
|
||||
|
||||
//FbDevice class functions
|
||||
FbDevice* FbDevice::sInstance = 0;;
|
||||
struct framebuffer_device_t* FbDevice::getFb() {
|
||||
return sFb;
|
||||
}
|
||||
|
||||
FbDevice* FbDevice::getInstance() {
|
||||
if(sInstance == NULL)
|
||||
sInstance = new FbDevice();
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
FbDevice::FbDevice(){
|
||||
hw_module_t const *module;
|
||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
|
||||
framebuffer_open(module, &sFb);
|
||||
} else {
|
||||
ALOGE("FATAL ERROR: framebuffer open failed.");
|
||||
}
|
||||
}
|
||||
FbDevice::~FbDevice()
|
||||
{
|
||||
if(sFb)
|
||||
{
|
||||
framebuffer_close(sFb);
|
||||
sFb = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
};//namespace
|
||||
|
@ -26,12 +26,16 @@
|
||||
#include <string.h>
|
||||
#include <fb_priv.h>
|
||||
#include <overlay.h>
|
||||
#include <copybit.h>
|
||||
#include <hwc_copybitEngine.h>
|
||||
#include <genlock.h>
|
||||
#include "hwc_qbuf.h"
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#define ALIGN(x, align) (((x) + ((align)-1)) & ~((align)-1))
|
||||
#define ALIGN_TO(x, align) (((x) + ((align)-1)) & ~((align)-1))
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
#define FINAL_TRANSFORM_MASK 0x000F
|
||||
|
||||
struct hwc_context_t;
|
||||
namespace qhwc {
|
||||
@ -41,16 +45,24 @@ enum external_display_type {
|
||||
EXT_TYPE_HDMI,
|
||||
EXT_TYPE_WIFI
|
||||
};
|
||||
enum HWCCompositionType {
|
||||
HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by
|
||||
// Surfaceflinger
|
||||
HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay
|
||||
HWC_USE_COPYBIT // This layer is to be handled by copybit
|
||||
};
|
||||
|
||||
|
||||
class ExtDisplayObserver;
|
||||
// -----------------------------------------------------------------------------
|
||||
// Utility functions - implemented in hwc_utils.cpp
|
||||
void dumpLayer(hwc_layer_t const* l);
|
||||
void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list);
|
||||
void handleYUV(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
void initContext(hwc_context_t *ctx);
|
||||
void closeContext(hwc_context_t *ctx);
|
||||
void openFramebufferDevice(hwc_context_t *ctx);
|
||||
//Crops source buffer against destination and FB boundaries
|
||||
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
||||
const int fbWidth, const int fbHeight);
|
||||
|
||||
// Inline utility functions
|
||||
static inline bool isSkipLayer(const hwc_layer_t* l) {
|
||||
@ -66,28 +78,30 @@ static inline bool isYuvBuffer(const private_handle_t* hnd) {
|
||||
static inline bool isBufferLocked(const private_handle_t* hnd) {
|
||||
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
// Copybit specific - inline or implemented in hwc_copybit.cpp
|
||||
typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
|
||||
EGLDisplay dpy,
|
||||
EGLSurface draw);
|
||||
typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Overlay specific functions - inline or implemented in hwc_overlay.cpp
|
||||
bool prepareOverlay(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
//XXX: Refine draw functions
|
||||
bool drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
//XXX: Refine
|
||||
void cleanOverlays(hwc_context_t *ctx );
|
||||
void setOverlayState(hwc_context_t* ctx, ovutils::eOverlayState state);
|
||||
// Singleton for Framebuffer device
|
||||
class FbDevice{
|
||||
public:
|
||||
~FbDevice();
|
||||
// API to get Fb device(non static)
|
||||
struct framebuffer_device_t *getFb();
|
||||
// API to get singleton
|
||||
static FbDevice* getInstance();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Copybit specific functions - inline or implemented in hwc_copybit.cpp
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// HDMI specific functions - inline or implemented in hwc_hdmi.cpp
|
||||
|
||||
|
||||
|
||||
} //qhwc namespace
|
||||
private:
|
||||
FbDevice();
|
||||
struct framebuffer_device_t *sFb;
|
||||
static FbDevice* sInstance; // singleton
|
||||
};
|
||||
|
||||
}; //qhwc namespace
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
@ -95,25 +109,25 @@ void setOverlayState(hwc_context_t* ctx, ovutils::eOverlayState state);
|
||||
// This structure contains overall state
|
||||
struct hwc_context_t {
|
||||
hwc_composer_device_t device;
|
||||
// Layer variables
|
||||
int yuvBufferCount;
|
||||
int hdmiEnabled;
|
||||
int numHwLayers;
|
||||
int mdpVersion;
|
||||
bool hasOverlay;
|
||||
bool skipComposition;
|
||||
int overlayInUse;
|
||||
|
||||
//Framebuffer device
|
||||
framebuffer_device_t *fbDev;
|
||||
qhwc::FbDevice* mFbDevice;
|
||||
|
||||
//Copybit Engine
|
||||
qhwc::CopybitEngine* mCopybitEngine;
|
||||
|
||||
//Overlay object - NULL for non overlay devices
|
||||
overlay::Overlay *mOverlay;
|
||||
|
||||
//QueuedBufferStore to hold buffers for overlay
|
||||
qhwc::QueuedBufferStore *qbuf;
|
||||
|
||||
// External display related information
|
||||
qhwc::ExtDisplayObserver*mExtDisplayObserver;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif //HWC_UTILS_H
|
||||
|
245
libhwcomposer/hwc_video.cpp
Normal file
245
libhwcomposer/hwc_video.cpp
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hwc_video.h"
|
||||
#include "hwc_ext_observer.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
#define FINAL_TRANSFORM_MASK 0x000F
|
||||
#define VIDEO_DEBUG 0
|
||||
|
||||
//Static Members
|
||||
ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
|
||||
int VideoOverlay::sYuvCount = 0;
|
||||
int VideoOverlay::sYuvLayerIndex = -1;
|
||||
bool VideoOverlay::sIsModeOn = false;
|
||||
bool VideoOverlay::sIsLayerSkip = false;
|
||||
|
||||
//Cache stats, figure out the state, config overlay
|
||||
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
sIsModeOn = false;
|
||||
if(!ctx->hasOverlay) {
|
||||
ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
chooseState(ctx);
|
||||
//if the state chosen above is CLOSED, skip this block.
|
||||
if(sState != ovutils::OV_CLOSED) {
|
||||
if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) {
|
||||
markFlags(&list->hwLayers[sYuvLayerIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
|
||||
"IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount,
|
||||
sYuvLayerIndex, sIsModeOn, sIsLayerSkip);
|
||||
|
||||
return sIsModeOn;
|
||||
}
|
||||
|
||||
void VideoOverlay::chooseState(hwc_context_t *ctx) {
|
||||
ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
|
||||
ovutils::getStateString(sState));
|
||||
|
||||
ovutils::eOverlayState newState = ovutils::OV_CLOSED;
|
||||
//TODO check if device supports overlay and hdmi
|
||||
|
||||
//Support 1 video layer
|
||||
if(sYuvCount == 1) {
|
||||
//Skip on primary, display on ext.
|
||||
if(sIsLayerSkip && ctx->mExtDisplayObserver->getExternalDisplay()) {
|
||||
//TODO
|
||||
//VIDEO_ON_TV_ONLY
|
||||
} else if(sIsLayerSkip) { //skip on primary, no ext
|
||||
newState = ovutils::OV_CLOSED;
|
||||
} else if(ctx->mExtDisplayObserver->getExternalDisplay()) {
|
||||
//display on both
|
||||
newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
||||
} else { //display on primary only
|
||||
newState = ovutils::OV_2D_VIDEO_ON_PANEL;
|
||||
}
|
||||
}
|
||||
sState = newState;
|
||||
ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
|
||||
ovutils::getStateString(sState));
|
||||
}
|
||||
|
||||
void VideoOverlay::markFlags(hwc_layer_t *layer) {
|
||||
switch(sState) {
|
||||
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
layer->compositionType = HWC_OVERLAY;
|
||||
layer->hints |= HWC_HINT_CLEAR_FB;
|
||||
break;
|
||||
//TODO
|
||||
//case ovutils::OV_2D_VIDEO_ON_TV:
|
||||
//just break, dont update flags.
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *layer)
|
||||
{
|
||||
if (LIKELY(ctx->mOverlay)) {
|
||||
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
// Set overlay state
|
||||
ov.setState(sState);
|
||||
|
||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
||||
|
||||
//TODO change this based on state.
|
||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||
|
||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
|
||||
ovutils::setMdpFlags(mdpFlags,
|
||||
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||
}
|
||||
|
||||
ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
|
||||
if (ctx->numHwLayers == 1) {
|
||||
isFgFlag = ovutils::IS_FG_SET;
|
||||
}
|
||||
|
||||
ovutils::PipeArgs parg(mdpFlags,
|
||||
info,
|
||||
ovutils::ZORDER_0,
|
||||
isFgFlag,
|
||||
ovutils::ROT_FLAG_DISABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
ov.setSource(pargs, dest);
|
||||
|
||||
hwc_rect_t sourceCrop = layer->sourceCrop;
|
||||
// x,y,w,h
|
||||
ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
|
||||
sourceCrop.right - sourceCrop.left,
|
||||
sourceCrop.bottom - sourceCrop.top);
|
||||
//Only for External
|
||||
ov.setCrop(dcrop, ovutils::OV_PIPE1);
|
||||
|
||||
// FIXME: Use source orientation for TV when source is portrait
|
||||
//Only for External
|
||||
ov.setTransform(0, dest);
|
||||
|
||||
ovutils::Dim dpos;
|
||||
hwc_rect_t displayFrame = layer->displayFrame;
|
||||
dpos.x = displayFrame.left;
|
||||
dpos.y = displayFrame.top;
|
||||
dpos.w = (displayFrame.right - displayFrame.left);
|
||||
dpos.h = (displayFrame.bottom - displayFrame.top);
|
||||
|
||||
//Only for External
|
||||
ov.setPosition(dpos, ovutils::OV_PIPE1);
|
||||
|
||||
//Calculate the rect for primary based on whether the supplied position
|
||||
//is within or outside bounds.
|
||||
const int fbWidth =
|
||||
ovutils::FrameBufferInfo::getInstance()->getWidth();
|
||||
const int fbHeight =
|
||||
ovutils::FrameBufferInfo::getInstance()->getHeight();
|
||||
|
||||
if( displayFrame.left < 0 ||
|
||||
displayFrame.top < 0 ||
|
||||
displayFrame.right > fbWidth ||
|
||||
displayFrame.bottom > fbHeight) {
|
||||
|
||||
calculate_crop_rects(sourceCrop, displayFrame, fbWidth, fbHeight);
|
||||
|
||||
//Update calculated width and height
|
||||
dcrop.w = sourceCrop.right - sourceCrop.left;
|
||||
dcrop.h = sourceCrop.bottom - sourceCrop.top;
|
||||
|
||||
dpos.w = displayFrame.right - displayFrame.left;
|
||||
dpos.h = displayFrame.bottom - displayFrame.top;
|
||||
}
|
||||
|
||||
//Only for Primary
|
||||
ov.setCrop(dcrop, ovutils::OV_PIPE0);
|
||||
|
||||
int transform = layer->transform & FINAL_TRANSFORM_MASK;
|
||||
ovutils::eTransform orient =
|
||||
static_cast<ovutils::eTransform>(transform);
|
||||
ov.setTransform(orient, ovutils::OV_PIPE0);
|
||||
|
||||
ov.setPosition(dpos, ovutils::OV_PIPE0);
|
||||
|
||||
//Both prim and external
|
||||
if (!ov.commit(dest)) {
|
||||
ALOGE("%s: commit fails", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
sIsModeOn = true;
|
||||
}
|
||||
return sIsModeOn;
|
||||
}
|
||||
|
||||
bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
{
|
||||
if(!sIsModeOn || sYuvLayerIndex == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[sYuvLayerIndex].handle;
|
||||
|
||||
// Lock this buffer for read.
|
||||
ctx->qbuf->lockAndAdd(hnd);
|
||||
bool ret = true;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
|
||||
switch (state) {
|
||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case ovutils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
// Play external
|
||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
|
||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// Play primary
|
||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// Wait for external vsync to be done
|
||||
if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
|
||||
ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// In most cases, displaying only to one (primary or external)
|
||||
// so use OV_PIPE_ALL since overlay will ignore NullPipes
|
||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE_ALL)) {
|
||||
ALOGE("%s: queueBuffer failed", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
}; //namespace qhwc
|
67
libhwcomposer/hwc_video.h
Normal file
67
libhwcomposer/hwc_video.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HWC_VIDEO_H
|
||||
#define HWC_VIDEO_H
|
||||
#include "hwc_utils.h"
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
namespace qhwc {
|
||||
//Feature for using overlay to display videos.
|
||||
class VideoOverlay {
|
||||
public:
|
||||
//Sets up members and prepares overlay if conditions are met
|
||||
static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Draws layer if this feature is on
|
||||
static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Receives data from hwc
|
||||
static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
|
||||
private:
|
||||
//Choose an appropriate overlay state based on conditions
|
||||
static void chooseState(hwc_context_t *ctx);
|
||||
//Configures overlay
|
||||
static bool configure(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
//Marks layer flags if this feature is used
|
||||
static void markFlags(hwc_layer_t *layer);
|
||||
//returns yuv count
|
||||
static int getYuvCount();
|
||||
|
||||
//The chosen overlay state.
|
||||
static ovutils::eOverlayState sState;
|
||||
//Number of yuv layers in this drawing round
|
||||
static int sYuvCount;
|
||||
//Index of YUV layer, relevant only if count is 1
|
||||
static int sYuvLayerIndex;
|
||||
//Flags if a yuv layer is animating or below something that is animating
|
||||
static bool sIsLayerSkip;
|
||||
//Flags if this feature is on.
|
||||
static bool sIsModeOn;
|
||||
};
|
||||
|
||||
inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex,
|
||||
bool isYuvLayerSkip) {
|
||||
sYuvCount = yuvCount;
|
||||
sYuvLayerIndex = yuvLayerIndex;
|
||||
sIsLayerSkip = isYuvLayerSkip;
|
||||
}
|
||||
|
||||
inline int VideoOverlay::getYuvCount() { return sYuvCount; }
|
||||
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_VIDEO_H
|
@ -1,11 +1,13 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
LOCAL_SHARED_LIBRARIES += libcutils
|
||||
LOCAL_SHARED_LIBRARIES += libutils
|
||||
LOCAL_SHARED_LIBRARIES += libmemalloc
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
|
||||
LOCAL_MODULE := liboverlay
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libmemalloc
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"overlay\"
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := \
|
||||
overlay.cpp \
|
||||
overlayCtrl.cpp \
|
||||
@ -14,7 +16,4 @@ LOCAL_SRC_FILES := \
|
||||
overlayRotator.cpp \
|
||||
overlayTransitions.cpp
|
||||
|
||||
LOCAL_CFLAGS:= -DLOG_TAG=\"overlay2\"
|
||||
LOCAL_MODULE := liboverlay
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
@ -76,7 +76,7 @@ bool getOverlay(int fd, mdp_overlay& ov);
|
||||
bool play(int fd, msmfb_overlay_data& od);
|
||||
|
||||
/* MSMFB_OVERLAY_PLAY_WAIT */
|
||||
bool playWait(int fd, msmfb_overlay_data& od);
|
||||
bool waitForVsync(int fd, msmfb_overlay_data& od);
|
||||
|
||||
/* MSMFB_OVERLAY_3D */
|
||||
bool set3D(int fd, msmfb_overlay_3d& ov);
|
||||
@ -102,96 +102,108 @@ void dump(const char* const s, const fb_var_screeninfo& vinfo);
|
||||
//---------------Inlines -------------------------------------
|
||||
|
||||
inline bool getFScreenInfo(int fd, fb_fix_screeninfo& finfo) {
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
|
||||
ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%d", errno);
|
||||
if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
|
||||
ALOGE("Failed to call ioctl FBIOGET_FSCREENINFO err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool getVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
|
||||
ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%d", errno);
|
||||
if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
|
||||
ALOGE("Failed to call ioctl FBIOGET_VSCREENINFO err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool setVScreenInfo(int fd, fb_var_screeninfo& vinfo) {
|
||||
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) {
|
||||
ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%d", errno);
|
||||
if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
|
||||
ALOGE("Failed to call ioctl FBIOPUT_VSCREENINFO err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool startRotator(int fd, msm_rotator_img_info& rot) {
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) == -1){
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%d", errno);
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_START, &rot) < 0){
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_START err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool rotate(int fd, msm_rotator_data_info& rot) {
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) == -1) {
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%d", errno);
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_ROTATE, &rot) < 0) {
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_ROTATE err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool setOverlay(int fd, mdp_overlay& ov) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%d", errno);
|
||||
if (ioctl(fd, MSMFB_OVERLAY_SET, &ov) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_SET err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool endRotator(int fd, int sessionId) {
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) == -1) {
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%d", errno);
|
||||
if (ioctl(fd, MSM_ROTATOR_IOCTL_FINISH, &sessionId) < 0) {
|
||||
ALOGE("Failed to call ioctl MSM_ROTATOR_IOCTL_FINISH err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool unsetOverlay(int fd, int ovId) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%d", errno);
|
||||
if (ioctl(fd, MSMFB_OVERLAY_UNSET, &ovId) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_UNSET err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool getOverlay(int fd, mdp_overlay& ov) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%d", errno);
|
||||
if (ioctl(fd, MSMFB_OVERLAY_GET, &ov) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_GET err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool play(int fd, msmfb_overlay_data& od) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%d", errno);
|
||||
if (ioctl(fd, MSMFB_OVERLAY_PLAY, &od) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool playWait(int fd, msmfb_overlay_data& od) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%d", errno);
|
||||
inline bool waitForVsync(int fd, msmfb_overlay_data& od) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_PLAY_WAIT, &od) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_PLAY_WAIT err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool set3D(int fd, msmfb_overlay_3d& ov) {
|
||||
if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) == -1) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%d", errno);
|
||||
if (ioctl(fd, MSMFB_OVERLAY_3D, &ov) < 0) {
|
||||
ALOGE("Failed to call ioctl MSMFB_OVERLAY_3D err=%s",
|
||||
strerror(errno));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -262,7 +274,6 @@ inline void dump(const char* const s, const fb_var_screeninfo& vinfo) {
|
||||
s, vinfo.xres, vinfo.yres);
|
||||
}
|
||||
|
||||
|
||||
} // mdp_wrapper
|
||||
|
||||
} // overlay
|
||||
|
@ -31,10 +31,8 @@
|
||||
#include "overlayImpl.h"
|
||||
#include "overlay.h"
|
||||
|
||||
// MDP related FIXME move to state
|
||||
#include "overlayMdp.h"
|
||||
#include "overlayCtrlData.h"
|
||||
#include "overlayRotator.h"
|
||||
|
||||
namespace overlay {
|
||||
|
||||
@ -42,64 +40,16 @@ Overlay::Overlay(): mOv(0) {
|
||||
}
|
||||
|
||||
Overlay::~Overlay() {
|
||||
if(mState.state() == utils::OV_CLOSED) return;
|
||||
close();
|
||||
mOv = mState.handleEvent(utils::OV_CLOSED, mOv);
|
||||
delete mOv;
|
||||
mOv = 0;
|
||||
}
|
||||
|
||||
bool Overlay::open() {
|
||||
// We need an empty open to just open the bare minimum for business
|
||||
return true;
|
||||
}
|
||||
|
||||
void Overlay::reset(){
|
||||
if(mOv && !mOv->close()) {
|
||||
ALOGE("%s Overlay failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
delete mOv;
|
||||
mOv = 0;
|
||||
}
|
||||
|
||||
bool Overlay::close()
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_CLOSED:
|
||||
// try to close any partially opened items
|
||||
break;
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
case utils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
case utils::OV_UI_MIRROR:
|
||||
case utils::OV_2D_TRUE_UI_MIRROR:
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
mOv = mState.handleEvent(utils::OV_CLOSED, mOv);
|
||||
this->reset();
|
||||
break;
|
||||
default:
|
||||
OVASSERT(false, "close Unknown state %d", st);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::commit(utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -125,13 +75,12 @@ bool Overlay::commit(utils::eDest dest)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::queueBuffer(uint32_t offset,
|
||||
bool Overlay::queueBuffer(int fd, uint32_t offset,
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -145,39 +94,7 @@ bool Overlay::queueBuffer(uint32_t offset,
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
if(!mOv->queueBuffer(offset, dest)) {
|
||||
ALOGE("Overlay %s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::dequeueBuffer(void*& buf,
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
case utils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
case utils::OV_UI_MIRROR:
|
||||
case utils::OV_2D_TRUE_UI_MIRROR:
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
if(!mOv->dequeueBuffer(buf, dest)) {
|
||||
if(!mOv->queueBuffer(fd, offset, dest)) {
|
||||
ALOGE("Overlay %s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
@ -194,7 +111,6 @@ bool Overlay::waitForVsync(utils::eDest dest)
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -226,7 +142,6 @@ bool Overlay::setCrop(const utils::Dim& d,
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -257,7 +172,6 @@ bool Overlay::setPosition(const utils::Dim& d,
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -282,13 +196,13 @@ bool Overlay::setPosition(const utils::Dim& d,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Overlay::setParameter(const utils::Params& param,
|
||||
|
||||
bool Overlay::setTransform(const int orient,
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eTransform transform =
|
||||
static_cast<utils::eTransform>(orient);
|
||||
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
@ -302,7 +216,7 @@ bool Overlay::setParameter(const utils::Params& param,
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
if(!mOv->setParameter(param, dest)) {
|
||||
if(!mOv->setTransform(transform, dest)) {
|
||||
ALOGE("Overlay %s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
@ -313,25 +227,19 @@ bool Overlay::setParameter(const utils::Params& param,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
utils::eDest dest)
|
||||
{
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::PipeArgs margs[utils::MAX_PIPES] = {
|
||||
args[0], args[1], args[2] };
|
||||
utils::eOverlayState st = mState.state();
|
||||
|
||||
switch (st) {
|
||||
case utils::OV_CLOSED:
|
||||
// if we get setSource when we are closed, then
|
||||
// we will assume tranistion to OV_2D_VIDEO_ON_PANEL
|
||||
// returns overlay
|
||||
mOv = mState.handle_closed(utils::OV_2D_VIDEO_ON_PANEL);
|
||||
if (!mOv) {
|
||||
ALOGE("Overlay %s failed", __FUNCTION__);
|
||||
this->reset(); // cleanup
|
||||
return false;
|
||||
}
|
||||
ALOGE("Overlay %s failed, state is OV_CLOSED, set state first",
|
||||
__FUNCTION__);
|
||||
return false;
|
||||
break;
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL:
|
||||
@ -339,25 +247,15 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
// no tweaking
|
||||
break;
|
||||
case utils::OV_3D_VIDEO_ON_3D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_TV:
|
||||
margs[utils::CHANNEL_1].zorder = utils::ZORDER_1;
|
||||
break;
|
||||
//TODO set zorder for channel 1 as 1 in 3D pipe
|
||||
case utils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
// If displaying on both, external VG pipe set to be no wait
|
||||
margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
|
||||
break;
|
||||
case utils::OV_2D_TRUE_UI_MIRROR:
|
||||
// Set zorder -- external VG pipe (video) gets 0, RGB pipe (UI) gets 1
|
||||
margs[utils::CHANNEL_1].zorder = utils::ZORDER_0;
|
||||
margs[utils::CHANNEL_2].zorder = utils::ZORDER_1;
|
||||
// External VG (video) and RGB (UI) pipe set to be no wait
|
||||
margs[utils::CHANNEL_0].wait = utils::WAIT;
|
||||
margs[utils::CHANNEL_1].wait = utils::NO_WAIT;
|
||||
margs[utils::CHANNEL_2].wait = utils::NO_WAIT;
|
||||
// TODO Set zorder, external VG pipe (video) gets 0, RGB pipe (UI) gets 1
|
||||
break;
|
||||
default:
|
||||
OVASSERT(false, "%s Unknown state %d", __FUNCTION__, st);
|
||||
@ -371,39 +269,12 @@ bool Overlay::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
|
||||
return true;
|
||||
}
|
||||
void Overlay::setMemoryId(int id, utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME that one needs to move to the state machine class
|
||||
utils::eOverlayState st = mState.state();
|
||||
switch (st) {
|
||||
case utils::OV_2D_VIDEO_ON_PANEL:
|
||||
case utils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_PANEL:
|
||||
case utils::OV_3D_VIDEO_ON_3D_TV:
|
||||
case utils::OV_3D_VIDEO_ON_2D_PANEL_2D_TV:
|
||||
case utils::OV_UI_MIRROR:
|
||||
case utils::OV_2D_TRUE_UI_MIRROR:
|
||||
case utils::OV_BYPASS_1_LAYER:
|
||||
case utils::OV_BYPASS_2_LAYER:
|
||||
case utils::OV_BYPASS_3_LAYER:
|
||||
mOv->setMemoryId(id, dest);
|
||||
break;
|
||||
default:
|
||||
OVASSERT(false, "setMemId Unknown state %d", st);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Overlay::dump() const
|
||||
{
|
||||
OVASSERT(mOv,
|
||||
"%s Overlay and Rotator should be init at this point",
|
||||
__FUNCTION__);
|
||||
// FIXME dump tate object, factory
|
||||
ALOGE("== Dump Overlay start ==");
|
||||
mState.dump();
|
||||
mOv->dump();
|
||||
@ -426,30 +297,4 @@ Overlay* Overlay::getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**** NullPipe ****/
|
||||
|
||||
bool NullPipe::open(RotatorBase*) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "NullPipe open");
|
||||
return true;
|
||||
}
|
||||
bool NullPipe::close() { return true; }
|
||||
bool NullPipe::commit() { return true; }
|
||||
bool NullPipe::start(const utils::PipeArgs&) { return true; }
|
||||
bool NullPipe::setCrop(const utils::Dim&) { return true; }
|
||||
bool NullPipe::setPosition(const utils::Dim&) { return true; }
|
||||
bool NullPipe::setParameter(const utils::Params&) { return true; }
|
||||
bool NullPipe::setSource(const utils::PipeArgs&) { return true; }
|
||||
bool NullPipe::queueBuffer(uint32_t offset) { return true; }
|
||||
bool NullPipe::dequeueBuffer(void*&) { return true; }
|
||||
bool NullPipe::waitForVsync() { return true; }
|
||||
void NullPipe::setMemoryId(int) {}
|
||||
// NullPipe will return by val here as opposed to other Pipes.
|
||||
utils::PipeArgs NullPipe::getArgs() const { return utils::PipeArgs(); }
|
||||
utils::eOverlayPipeType NullPipe::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_NULL;
|
||||
}
|
||||
void NullPipe::dump() const {
|
||||
ALOGE("== NullPipe (null) start/end ==");
|
||||
}
|
||||
|
||||
} // overlay
|
||||
|
@ -43,31 +43,22 @@ public:
|
||||
|
||||
/* Overlay related func */
|
||||
|
||||
/* We need an empty open to just open the bare minimum for
|
||||
* business. */
|
||||
bool open();
|
||||
|
||||
/* close rotator, state, overlayimpl*/
|
||||
bool close();
|
||||
|
||||
/* Following is the same as the pure virt interface in ov impl */
|
||||
|
||||
bool commit(utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
|
||||
bool queueBuffer(uint32_t offset,
|
||||
bool setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool dequeueBuffer(void*& buf,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool waitForVsync(utils::eDest dest = utils::OV_PIPE1);
|
||||
bool setCrop(const utils::Dim& d,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool setTransform(const int orientation,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool setPosition(const utils::Dim& dim,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool setParameter(const utils::Params& param,
|
||||
bool commit(utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
|
||||
bool queueBuffer(int fd, uint32_t offset,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
bool waitForVsync(utils::eDest dest = utils::OV_PIPE1);
|
||||
|
||||
void dump() const;
|
||||
|
||||
/* state related functions */
|
||||
|
@ -18,14 +18,14 @@
|
||||
#include <cutils/properties.h>
|
||||
#include "overlayCtrlData.h"
|
||||
#include "fb_priv.h"
|
||||
#include "gralloc_priv.h" //for interlace
|
||||
|
||||
namespace overlay{
|
||||
|
||||
bool Ctrl::open(uint32_t fbnum,
|
||||
RotatorBase* rot) {
|
||||
// MDP/FD open
|
||||
if(!mMdp.open(fbnum)) {
|
||||
ALOGE("Ctrl failed to open fbnum=%d", fbnum);
|
||||
bool Ctrl::init(uint32_t fbnum) {
|
||||
// MDP/FD init
|
||||
if(!mMdp.init(fbnum)) {
|
||||
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -34,127 +34,12 @@ bool Ctrl::open(uint32_t fbnum,
|
||||
return false;
|
||||
}
|
||||
|
||||
OVASSERT(rot, "rot is null");
|
||||
mRot = rot;
|
||||
// rot should be already opened
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ctrl::start(const utils::PipeArgs& args)
|
||||
{
|
||||
int colorFormat = utils::getColorFormat(args.whf.format);
|
||||
utils::eMdpFlags flags = args.mdpFlags;
|
||||
|
||||
//XXX: Support for interlaced content
|
||||
if (0) {
|
||||
|
||||
setMdpFlags(flags, utils::OV_MDP_DEINTERLACE);
|
||||
|
||||
// Get the actual format
|
||||
colorFormat = args.whf.format ^ HAL_PIXEL_FORMAT_INTERLACE;
|
||||
}
|
||||
utils::Whf hwwhf(args.whf);
|
||||
int fmt = utils::getMdpFormat(colorFormat);
|
||||
// FIXME format should probably be int and not uint
|
||||
if (fmt < 0) {
|
||||
ALOGE("Ctrl failed getMdpFormat unsopported "
|
||||
"colorFormat=%d format=%d flags=%d",
|
||||
colorFormat, fmt, flags);
|
||||
return false;
|
||||
}
|
||||
hwwhf.format = fmt;
|
||||
|
||||
// devices should be already opened
|
||||
// (by calling open earlier in the flow)
|
||||
|
||||
const utils::PipeArgs newargs(flags, // mdp flags
|
||||
args.orientation, // trans
|
||||
hwwhf,
|
||||
args.wait,
|
||||
args.zorder,
|
||||
args.isFg,
|
||||
args.rotFlags);
|
||||
if (!setInfo(newargs)) {
|
||||
ALOGE("Ctrl failed to setInfo mdpflags=%d wait=%d zorder=%d",
|
||||
newargs.mdpFlags, newargs.wait, newargs.zorder);
|
||||
hwwhf.dump();
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME, can we remove that and have it in
|
||||
// setSource only when source changed?
|
||||
if(!mRot->start(newargs)) {
|
||||
ALOGE("Ctrl failed to start Rotation session");
|
||||
return false;
|
||||
}
|
||||
|
||||
// if geom is different, we need to prepare a new rot buffers.
|
||||
// remap on demand when the current orientation is 90,180, etc.
|
||||
// and the prev orientation was 0. It means we go from orient
|
||||
if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
|
||||
ALOGE("%s Error in remapping", __FUNCTION__);
|
||||
}
|
||||
|
||||
if(!mMdp.set()) {
|
||||
ALOGE("Ctrl start failed set overlay");
|
||||
return false;
|
||||
}
|
||||
|
||||
// cache the src to be the current mCrop vals
|
||||
mCrop.w = hwwhf.w;
|
||||
mCrop.h = hwwhf.h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void Ctrl::updateSource(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
utils::ScreenInfo& info)
|
||||
{
|
||||
mMdp.updateSource(r, args, info);
|
||||
}
|
||||
|
||||
bool Ctrl::setSource(const utils::PipeArgs& args)
|
||||
{
|
||||
mMdp.setWait(args.wait);
|
||||
|
||||
utils::PipeArgs newargs(args);
|
||||
utils::Whf whf(args.whf);
|
||||
// check geom change
|
||||
if(mOvBufInfo != whf) {
|
||||
// whf.format is given as HAL, that is why it is
|
||||
// needed to be MDP fmt.
|
||||
whf.format = utils::getColorFormat(whf.format);
|
||||
int fmt = utils::getMdpFormat(whf.format);
|
||||
OVASSERT(-1 != fmt, "Ctrl setSource format is -1");
|
||||
whf.format = fmt;
|
||||
newargs.whf = whf;
|
||||
updateSource(mRot, newargs, mInfo);
|
||||
mMdp.setUserData(0);
|
||||
if(!mRot->start(newargs)) {
|
||||
ALOGE("%s failed start rot", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if geom is different, we need to prepare a new rot buffers.
|
||||
// remap on demand when the current orientation is 90,180, etc.
|
||||
// and the prev orientation was 0. It means we go from orient
|
||||
if(!mRot->remap(utils::ROT_NUM_BUFS, newargs)) {
|
||||
ALOGE("%s Error in remapping", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
|
||||
// needed for setSource
|
||||
mOrient = args.orientation;
|
||||
|
||||
// cache last whf from gralloc hnd
|
||||
mOvBufInfo = args.whf;
|
||||
|
||||
// orign impl is returning false here
|
||||
// because they will close the overlay and reopen it.
|
||||
// New design would not do that.
|
||||
return true;
|
||||
return mMdp.setSource(args);
|
||||
}
|
||||
|
||||
bool Ctrl::setPosition(const utils::Dim& dim)
|
||||
@ -172,41 +57,21 @@ bool Ctrl::setPosition(const utils::Dim& dim)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ctrl::setParameter(const utils::Params& p)
|
||||
bool Ctrl::setTransform(const utils::eTransform& orient, const bool& rotUsed)
|
||||
{
|
||||
if (utils::OVERLAY_TRANSFORM == p.param &&
|
||||
p.value == mMdp.getUserData()) {
|
||||
// nothing to do here
|
||||
return true;
|
||||
}
|
||||
|
||||
utils::eTransform trns = static_cast<utils::eTransform>(p.value);
|
||||
switch (p.param) {
|
||||
case utils::OVERLAY_DITHER:
|
||||
// nothing here today
|
||||
ALOGE("Ctrl setParameter OVERLAY_DITHER not impl");
|
||||
return true;
|
||||
case utils::OVERLAY_TRANSFORM:
|
||||
if(!mRot->overlayTransform(mMdp, trns)) {
|
||||
ALOGE("Ctrl setParameter failed Rot overlayTransform");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ALOGE("Ctrl setParameter unknown param %d", p.param);
|
||||
return false;
|
||||
if(!mMdp.setTransform(orient, rotUsed)) {
|
||||
ALOGE("Ctrl setTransform failed for Mdp");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Ctrl::setCrop(const utils::Dim& d)
|
||||
{
|
||||
// FIXME check channel validity
|
||||
if(!mMdp.setCrop(d)) {
|
||||
ALOGE("Data setCrop failed in MDP setCrop");
|
||||
return false;
|
||||
}
|
||||
mCrop = d;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -224,11 +89,9 @@ utils::Dim Ctrl::getAspectRatio(const utils::Whf& whf) const
|
||||
}
|
||||
if (inWhf.w * fbHeight > fbWidth * inWhf.h) {
|
||||
inWhf.h = fbWidth * inWhf.h / inWhf.w;
|
||||
utils::even_out(inWhf.h);
|
||||
inWhf.w = fbWidth;
|
||||
} else if (inWhf.w * fbHeight < fbWidth * inWhf.h) {
|
||||
inWhf.w = fbHeight * inWhf.w / inWhf.h;
|
||||
utils::even_out(inWhf.w);
|
||||
inWhf.h = fbHeight;
|
||||
} else {
|
||||
inWhf.w = fbWidth;
|
||||
@ -339,10 +202,8 @@ utils::Dim Ctrl::getAspectRatio(const utils::Dim& dim) const {
|
||||
|
||||
void Ctrl::dump() const {
|
||||
ALOGE("== Dump Ctrl start ==");
|
||||
ALOGE("orient=%d", mOrient);
|
||||
mInfo.dump("mInfo");
|
||||
mMdp.dump();
|
||||
mRot->dump();
|
||||
ALOGE("== Dump Ctrl end ==");
|
||||
}
|
||||
|
||||
|
@ -38,65 +38,40 @@ namespace ovutils = overlay::utils;
|
||||
|
||||
namespace overlay {
|
||||
|
||||
// FIXME make int to be uint32 whenever possible
|
||||
|
||||
class RotatorBase;
|
||||
|
||||
/*
|
||||
* FIXME do we want rot to be template parameter?
|
||||
* It's already using inheritance...
|
||||
*
|
||||
* Sequence to use:
|
||||
* open
|
||||
* init
|
||||
* start
|
||||
* setXXX
|
||||
* close
|
||||
*
|
||||
* Can call setRot anytime to replace rotator on-the-fly
|
||||
* */
|
||||
class Ctrl : utils::NoCopy {
|
||||
public:
|
||||
|
||||
/* ctor */
|
||||
explicit Ctrl();
|
||||
|
||||
/* dtor close */
|
||||
~Ctrl();
|
||||
|
||||
/* should open devices? or start()? */
|
||||
bool open(uint32_t fbnum, RotatorBase* rot);
|
||||
|
||||
/* init fd etc*/
|
||||
bool init(uint32_t fbnum);
|
||||
/* close underlying mdp */
|
||||
bool close();
|
||||
|
||||
/* Invoke methods for opening underlying devices
|
||||
* flags - PIPE SHARED
|
||||
* wait - WAIT, NO_WAIT */
|
||||
bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* Dynamically set rotator*/
|
||||
void setRot(RotatorBase* rot);
|
||||
|
||||
/* set mdp posision using dim */
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
|
||||
/* set param using Params (param,value pair) */
|
||||
bool setParameter(const utils::Params& p);
|
||||
|
||||
/* set source using whf, orient and wait flag */
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
|
||||
/* set crop info and pass it down to mdp */
|
||||
bool setCrop(const utils::Dim& d);
|
||||
|
||||
/* set orientation */
|
||||
bool setTransform(const utils::eTransform& p, const bool&);
|
||||
/* set mdp position using dim */
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
/* mdp set overlay/commit changes */
|
||||
bool commit();
|
||||
|
||||
/* ctrl id */
|
||||
int getId() const;
|
||||
int getPipeId() const;
|
||||
/* ctrl fd */
|
||||
int getFd() const;
|
||||
bool getRotSessId(int& id) const;
|
||||
utils::Dim getAspectRatio(const utils::Whf& whf) const;
|
||||
utils::Dim getAspectRatio(const utils::Dim& dim) const;
|
||||
|
||||
@ -113,40 +88,14 @@ private:
|
||||
/* Retrieve screen info from underlying mdp */
|
||||
bool getScreenInfo(utils::ScreenInfo& info);
|
||||
|
||||
/* calls underlying mdp set info */
|
||||
bool setInfo(const utils::PipeArgs& args);
|
||||
|
||||
/* given whf, update src */
|
||||
void updateSource(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
utils::ScreenInfo& info);
|
||||
|
||||
// mdp ctrl struct(info e.g.)
|
||||
MdpCtrl mMdp;
|
||||
|
||||
// Rotator
|
||||
RotatorBase* mRot;
|
||||
|
||||
/* Cache cropped value */
|
||||
utils::Dim mCrop;
|
||||
|
||||
/* Screen info */
|
||||
utils::ScreenInfo mInfo;
|
||||
|
||||
/* orientation cache FIXME */
|
||||
utils::eTransform mOrient;
|
||||
|
||||
/* Cache last known whfz.
|
||||
* That would help us compare to a previous
|
||||
* source that was submitted */
|
||||
utils::Whf mOvBufInfo;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* MDP = DataMdp, ROT = CtrlMdp usually since Rotator<>
|
||||
* is instansiated with Ctrl data structure.
|
||||
* */
|
||||
class Data : utils::NoCopy {
|
||||
public:
|
||||
/* init, reset */
|
||||
@ -155,44 +104,30 @@ public:
|
||||
/* calls close */
|
||||
~Data();
|
||||
|
||||
/* should open devices? or start()? */
|
||||
bool open(uint32_t fbnum, RotatorBase* rot);
|
||||
/* init fd etc */
|
||||
bool init(uint32_t fbnum);
|
||||
|
||||
/* calls underlying mdp close */
|
||||
bool close();
|
||||
|
||||
/* set the rotator */
|
||||
void setRot(RotatorBase* rot);
|
||||
|
||||
/* set memory id in the mdp struct */
|
||||
void setMemoryId(int id);
|
||||
|
||||
/* set overlay id in the mdp struct */
|
||||
void setId(int id);
|
||||
/* set overlay pipe id in the mdp struct */
|
||||
void setPipeId(int id);
|
||||
|
||||
/* get overlay id in the mdp struct */
|
||||
int getId() const;
|
||||
int getPipeId() const;
|
||||
|
||||
/* queue buffer to the overlay */
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
|
||||
/* wait for vsync to be done */
|
||||
bool waitForVsync();
|
||||
|
||||
/* sump the state of the obj */
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
/* play wrapper */
|
||||
bool play();
|
||||
|
||||
/* playWait wrapper */
|
||||
bool playWait();
|
||||
|
||||
// mdp data struct
|
||||
MdpData mMdp;
|
||||
|
||||
// Rotator
|
||||
RotatorBase* mRot;
|
||||
};
|
||||
|
||||
/* This class just creates a Ctrl Data pair to be used by a pipe.
|
||||
@ -207,7 +142,7 @@ struct CtrlData {
|
||||
|
||||
//-------------Inlines-------------------------------
|
||||
|
||||
inline Ctrl::Ctrl() : mRot(0), mOrient(utils::OVERLAY_TRANSFORM_0) {
|
||||
inline Ctrl::Ctrl() {
|
||||
mMdp.reset();
|
||||
}
|
||||
|
||||
@ -216,7 +151,6 @@ inline Ctrl::~Ctrl() {
|
||||
}
|
||||
|
||||
inline bool Ctrl::close() {
|
||||
// do not close the rotator
|
||||
if(!mMdp.close())
|
||||
return false;
|
||||
return true;
|
||||
@ -238,70 +172,37 @@ inline bool Ctrl::getScreenInfo(utils::ScreenInfo& info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Ctrl::setInfo(const utils::PipeArgs& args)
|
||||
{
|
||||
// FIXME set flags, zorder and wait separtly
|
||||
if(!mMdp.setInfo(mRot, args, mInfo)){
|
||||
ALOGE("Ctrl failed to setInfo wait=%d mdpflags=%d "
|
||||
"zorder=%d", args.wait, args.mdpFlags, args.zorder);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline int Ctrl::getId() const {
|
||||
// FIXME check channel up?
|
||||
return mMdp.getId();
|
||||
inline int Ctrl::getPipeId() const {
|
||||
return mMdp.getPipeId();
|
||||
}
|
||||
|
||||
inline int Ctrl::getFd() const {
|
||||
// FIXME check channel up?
|
||||
return mMdp.getFd();
|
||||
}
|
||||
|
||||
inline bool Ctrl::getRotSessId(int& id) const {
|
||||
// FIXME check channel up?
|
||||
// should be -1 in case of no rot session active
|
||||
id = mRot->getSessId();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline utils::ScreenInfo Ctrl::getScreenInfo() const {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
inline utils::Dim Ctrl::getCrop() const {
|
||||
return mCrop;
|
||||
return mMdp.getSrcRectDim();
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline Data::Data() : mRot(0) {
|
||||
inline Data::Data() {
|
||||
mMdp.reset();
|
||||
}
|
||||
|
||||
inline Data::~Data() { close(); }
|
||||
|
||||
inline void Data::setRot(RotatorBase* rot) { mRot = rot; }
|
||||
inline void Data::setPipeId(int id) { mMdp.setPipeId(id); }
|
||||
|
||||
inline void Data::setMemoryId(int id) { mMdp.setMemoryId(id); }
|
||||
inline int Data::getPipeId() const { return mMdp.getPipeId(); }
|
||||
|
||||
// really a reqid
|
||||
inline void Data::setId(int id) { mMdp.setId(id); }
|
||||
|
||||
inline int Data::getId() const { return mMdp.getId(); }
|
||||
|
||||
inline bool Data::open(uint32_t fbnum,
|
||||
RotatorBase* rot) {
|
||||
if(!mMdp.open(fbnum)) {
|
||||
ALOGE("Data cannot open mdp");
|
||||
inline bool Data::init(uint32_t fbnum) {
|
||||
if(!mMdp.init(fbnum)) {
|
||||
ALOGE("Data cannot init mdp");
|
||||
return false;
|
||||
}
|
||||
|
||||
OVASSERT(rot, "rot is null");
|
||||
mRot = rot;
|
||||
|
||||
// rotator should be already opened here
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -313,49 +214,22 @@ inline bool Data::close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Data::queueBuffer(uint32_t offset) {
|
||||
// FIXME asserts on state validity
|
||||
|
||||
mMdp.setOffset(offset);
|
||||
mRot->setRotDataSrcMemId(mMdp.getMemoryId());
|
||||
// will play if succeeded
|
||||
if(!mRot->prepareQueueBuf(offset)) {
|
||||
ALOGE("Data failed to prepareQueueBuf");
|
||||
return false;
|
||||
}
|
||||
// Play can go either from mdp or rot
|
||||
if(!this->play()){
|
||||
ALOGE("Data error in MDP/ROT play");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
inline bool Data::queueBuffer(int fd, uint32_t offset) {
|
||||
return mMdp.play(fd, offset);
|
||||
}
|
||||
|
||||
inline bool Data::waitForVsync() {
|
||||
|
||||
// Call mdp playWait
|
||||
if(!this->playWait()){
|
||||
ALOGE("Error in MDP playWait");
|
||||
// Call mdp waitForVsync
|
||||
if(!mMdp.waitForVsync()){
|
||||
ALOGE("Error in MDP %s", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Data::play() {
|
||||
int fd = mMdp.getFd();
|
||||
return mRot->enabled() ? mRot->play(fd) : mMdp.play();
|
||||
}
|
||||
|
||||
inline bool Data::playWait() {
|
||||
return mMdp.playWait();
|
||||
}
|
||||
|
||||
inline void Data::dump() const {
|
||||
ALOGE("== Dump Data MDP start ==");
|
||||
mMdp.dump();
|
||||
mRot->dump();
|
||||
ALOGE("== Dump Data MDP end ==");
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,6 @@
|
||||
#include "overlayUtils.h"
|
||||
#include "overlayRotator.h"
|
||||
|
||||
// FIXME make int to be uint32 whenever possible
|
||||
|
||||
namespace overlay {
|
||||
|
||||
// Interface only. No member, no definiton (except ~ which can
|
||||
@ -44,8 +42,8 @@ public:
|
||||
/* empty dtor. can be =0 with cpp impl*/
|
||||
virtual ~OverlayImplBase() {}
|
||||
|
||||
/* Open pipe/rot for one dest */
|
||||
virtual bool openPipe(RotatorBase* rot, utils::eDest dest) = 0;
|
||||
/* Init pipe/rot for one dest */
|
||||
virtual bool initPipe(RotatorBase* rot, utils::eDest dest) = 0;
|
||||
|
||||
/* Close pipe/rot for all specified dest */
|
||||
virtual bool closePipe(utils::eDest dest) = 0;
|
||||
@ -53,12 +51,10 @@ public:
|
||||
/* Copy specified pipe/rot from ov passed in (used by state machine only) */
|
||||
virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest) = 0;
|
||||
|
||||
/* TODO open func customized for RGBx pipes */
|
||||
|
||||
/* Open all pipes
|
||||
* To open just one pipe, use openPipe()
|
||||
/* Init all pipes
|
||||
* To init just one pipe, use initPipe()
|
||||
* */
|
||||
virtual bool open(RotatorBase* rot0,
|
||||
virtual bool init(RotatorBase* rot0,
|
||||
RotatorBase* rot1,
|
||||
RotatorBase* rot2) = 0;
|
||||
|
||||
@ -72,12 +68,8 @@ public:
|
||||
* */
|
||||
virtual bool commit(utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* Queue buffer with offset*/
|
||||
virtual bool queueBuffer(uint32_t offset,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* For RGBx pipes, dequeue buffer (that is fb chunk)*/
|
||||
virtual bool dequeueBuffer(void*& buf,
|
||||
/* Queue buffer with fd from an offset*/
|
||||
virtual bool queueBuffer(int fd, uint32_t offset,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* Wait for vsync to be done on dest */
|
||||
@ -93,16 +85,13 @@ public:
|
||||
|
||||
/* Set parameters - usually needed for Rotator, but would
|
||||
* be passed down the stack as well */
|
||||
virtual bool setParameter(const utils::Params& param,
|
||||
virtual bool setTransform(const utils::eTransform& param,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* Set new source including orientation */
|
||||
virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES],
|
||||
utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* set memory id to the underlying pipes */
|
||||
virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL) = 0;
|
||||
|
||||
/* Get the overlay pipe type */
|
||||
virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const = 0;
|
||||
|
||||
@ -112,22 +101,21 @@ public:
|
||||
|
||||
class NullPipe {
|
||||
public:
|
||||
/* TODO open func customized for RGBx pipes */
|
||||
bool open(RotatorBase* rot);
|
||||
bool close();
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool commit();
|
||||
bool setCrop(const utils::Dim& d);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool waitForVsync();
|
||||
void setMemoryId(int id);
|
||||
utils::PipeArgs getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
bool init(RotatorBase* rot) { return true; }
|
||||
bool close() { return true; }
|
||||
bool start(const utils::PipeArgs& args) { return true; }
|
||||
bool commit() { return true; }
|
||||
bool setCrop(const utils::Dim& d) { return true; }
|
||||
bool setPosition(const utils::Dim& dim) { return true; }
|
||||
bool setTransform(const utils::eTransform& param) { return true; }
|
||||
bool setSource(const utils::PipeArgs& args) { return true; }
|
||||
bool queueBuffer(int fd, uint32_t offset) { return true; }
|
||||
bool waitForVsync() { return true; }
|
||||
// NullPipe will return by val here as opposed to other Pipes.
|
||||
utils::eOverlayPipeType getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_NULL;
|
||||
}
|
||||
void dump() const {}
|
||||
};
|
||||
|
||||
/*
|
||||
@ -143,7 +131,6 @@ public:
|
||||
|
||||
/* ctor */
|
||||
OverlayImpl();
|
||||
OverlayImpl(P0* p0, P1* p1, P2* p2);
|
||||
|
||||
/*
|
||||
* Comments of the below functions are the same as the one
|
||||
@ -151,12 +138,11 @@ public:
|
||||
* */
|
||||
virtual ~OverlayImpl();
|
||||
|
||||
virtual bool openPipe(RotatorBase* rot, utils::eDest dest);
|
||||
virtual bool initPipe(RotatorBase* rot, utils::eDest dest);
|
||||
virtual bool closePipe(utils::eDest dest);
|
||||
virtual bool copyOvPipe(OverlayImplBase* ov, utils::eDest dest);
|
||||
|
||||
/* TODO open func customized for RGBx pipes */
|
||||
virtual bool open(RotatorBase* rot0,
|
||||
virtual bool init(RotatorBase* rot0,
|
||||
RotatorBase* rot1,
|
||||
RotatorBase* rot2);
|
||||
virtual bool close();
|
||||
@ -165,16 +151,13 @@ public:
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool setPosition(const utils::Dim& dim,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool setParameter(const utils::Params& param,
|
||||
virtual bool setTransform(const utils::eTransform& param,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool setSource(const utils::PipeArgs[utils::MAX_PIPES],
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool queueBuffer(uint32_t offset,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool dequeueBuffer(void*& buf,
|
||||
virtual bool queueBuffer(int fd, uint32_t offset,
|
||||
utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual bool waitForVsync(utils::eDest dest = utils::OV_PIPE1);
|
||||
virtual void setMemoryId(int id, utils::eDest dest = utils::OV_PIPE_ALL);
|
||||
virtual utils::eOverlayPipeType getOvPipeType(utils::eDest dest) const;
|
||||
virtual void dump() const;
|
||||
|
||||
@ -197,74 +180,97 @@ private:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------Inlines and Template defn---------------------------------
|
||||
|
||||
/**** OverlayImpl ****/
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
OverlayImpl<P0, P1, P2>::OverlayImpl() :
|
||||
mPipe0(new P0), mPipe1(new P1), mPipe2(new P2),
|
||||
mPipe0(0), mPipe1(0), mPipe2(0),
|
||||
mRotP0(0), mRotP1(0), mRotP2(0)
|
||||
{}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
OverlayImpl<P0, P1, P2>::OverlayImpl(P0* p0, P1* p1, P2* p2) :
|
||||
mPipe0(p0), mPipe1(p1), mPipe2(p2),
|
||||
mRotP0(0), mRotP1(0), mRotP2(0)
|
||||
{}
|
||||
{
|
||||
//Do not create a pipe here.
|
||||
//Either initPipe can create a pipe OR
|
||||
//copyOvPipe can assign a pipe.
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
OverlayImpl<P0, P1, P2>::~OverlayImpl()
|
||||
{
|
||||
// no op in the meantime. needed to be clean
|
||||
// since state machine will do delete. so we
|
||||
// do not want to close/delete pipes here
|
||||
//Do not delete pipes.
|
||||
//closePipe will close and delete.
|
||||
}
|
||||
|
||||
/* Open only one pipe/rot pair per call */
|
||||
/* Init only one pipe/rot pair per call */
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::openPipe(RotatorBase* rot, utils::eDest dest)
|
||||
bool OverlayImpl<P0, P1, P2>::initPipe(RotatorBase* rot, utils::eDest dest)
|
||||
{
|
||||
OVASSERT(rot, "%s: OverlayImpl rot is null", __FUNCTION__);
|
||||
OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
|
||||
__FUNCTION__, dest);
|
||||
|
||||
// Need to down case rotator to mdp one.
|
||||
// we assume p0/p1/p2/px all use the _same_ underlying mdp structure.
|
||||
// FIXME STATIC_ASSERT here
|
||||
|
||||
bool ret = true;
|
||||
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "Open pipe0");
|
||||
ret = mPipe0->open(rot);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "init pipe0");
|
||||
|
||||
mRotP0 = rot;
|
||||
ret = mRotP0->init();
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe0 failed to open", __FUNCTION__);
|
||||
ALOGE("%s: OverlayImpl rot0 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
mPipe0 = new P0();
|
||||
OVASSERT(mPipe0, "%s: OverlayImpl pipe0 is null", __FUNCTION__);
|
||||
ret = mPipe0->init(rot);
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe0 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "Open pipe1");
|
||||
ret = mPipe1->open(rot);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "init pipe1");
|
||||
|
||||
mRotP1 = rot;
|
||||
ret = mRotP1->init();
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe1 failed to open", __FUNCTION__);
|
||||
ALOGE("%s: OverlayImpl rot1 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
mPipe1 = new P1();
|
||||
OVASSERT(mPipe1, "%s: OverlayImpl pipe1 is null", __FUNCTION__);
|
||||
ret = mPipe1->init(rot);
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe1 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "Open pipe2");
|
||||
ret = mPipe2->open(rot);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "init pipe2");
|
||||
|
||||
mRotP2 = rot;
|
||||
ret = mRotP2->init();
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe2 failed to open", __FUNCTION__);
|
||||
ALOGE("%s: OverlayImpl rot2 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
mPipe2 = new P2();
|
||||
OVASSERT(mPipe2, "%s: OverlayImpl pipe2 is null", __FUNCTION__);
|
||||
ret = mPipe2->init(rot);
|
||||
if(!ret) {
|
||||
ALOGE("%s: OverlayImpl pipe2 failed to init", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -356,44 +362,48 @@ bool OverlayImpl<P0, P1, P2>::copyOvPipe(OverlayImplBase* ov,
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
mPipe0 = ovimpl->mPipe0;
|
||||
mRotP0 = ovimpl->mRotP0;
|
||||
ovimpl->mPipe0 = 0;
|
||||
ovimpl->mRotP0 = 0;
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
mPipe1 = ovimpl->mPipe1;
|
||||
mRotP1 = ovimpl->mRotP1;
|
||||
ovimpl->mPipe1 = 0;
|
||||
ovimpl->mRotP1 = 0;
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
mPipe2 = ovimpl->mPipe2;
|
||||
mRotP2 = ovimpl->mRotP2;
|
||||
ovimpl->mPipe2 = 0;
|
||||
ovimpl->mRotP2 = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TODO open func customized for RGBx pipes */
|
||||
|
||||
/* Open all pipes/rot */
|
||||
/* Init all pipes/rot */
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::open(RotatorBase* rot0,
|
||||
bool OverlayImpl<P0, P1, P2>::init(RotatorBase* rot0,
|
||||
RotatorBase* rot1,
|
||||
RotatorBase* rot2)
|
||||
{
|
||||
if (!this->openPipe(rot0, utils::OV_PIPE0)) {
|
||||
if (!this->initPipe(rot0, utils::OV_PIPE0)) {
|
||||
if (!this->close()) {
|
||||
ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->openPipe(rot1, utils::OV_PIPE1)) {
|
||||
if (!this->initPipe(rot1, utils::OV_PIPE1)) {
|
||||
if (!this->close()) {
|
||||
ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this->openPipe(rot2, utils::OV_PIPE2)) {
|
||||
if (!this->initPipe(rot2, utils::OV_PIPE2)) {
|
||||
if (!this->close()) {
|
||||
ALOGE("%s: failed to close at least one pipe", __FUNCTION__);
|
||||
}
|
||||
@ -509,7 +519,7 @@ bool OverlayImpl<P0, P1, P2>::setPosition(const utils::Dim& d,
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::setParameter(const utils::Params& param,
|
||||
bool OverlayImpl<P0, P1, P2>::setTransform(const utils::eTransform& param,
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mPipe0 && mPipe1 && mPipe2,
|
||||
@ -517,21 +527,21 @@ bool OverlayImpl<P0, P1, P2>::setParameter(const utils::Params& param,
|
||||
__FUNCTION__, mPipe0, mPipe1, mPipe2);
|
||||
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
if(!mPipe0->setParameter(param)) {
|
||||
if(!mPipe0->setTransform(param)) {
|
||||
ALOGE("OverlayImpl p0 failed to setparam");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
if(!mPipe1->setParameter(param)) {
|
||||
if(!mPipe1->setTransform(param)) {
|
||||
ALOGE("OverlayImpl p1 failed to setparam");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
if(!mPipe2->setParameter(param)) {
|
||||
if(!mPipe2->setTransform(param)) {
|
||||
ALOGE("OverlayImpl p2 failed to setparam");
|
||||
return false;
|
||||
}
|
||||
@ -541,7 +551,8 @@ bool OverlayImpl<P0, P1, P2>::setParameter(const utils::Params& param,
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::setSource(const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
bool OverlayImpl<P0, P1, P2>::setSource(
|
||||
const utils::PipeArgs args[utils::MAX_PIPES],
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mPipe0 && mPipe1 && mPipe2,
|
||||
@ -573,28 +584,29 @@ bool OverlayImpl<P0, P1, P2>::setSource(const utils::PipeArgs args[utils::MAX_PI
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::queueBuffer(uint32_t offset, utils::eDest dest)
|
||||
bool OverlayImpl<P0, P1, P2>::queueBuffer(int fd, uint32_t offset,
|
||||
utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mPipe0 && mPipe1 && mPipe2,
|
||||
"%s: Pipes are null p0=%p p1=%p p2=%p",
|
||||
__FUNCTION__, mPipe0, mPipe1, mPipe2);
|
||||
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
if(!mPipe0->queueBuffer(offset)) {
|
||||
if(!mPipe0->queueBuffer(fd, offset)) {
|
||||
ALOGE("OverlayImpl p0 failed to queueBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
if(!mPipe1->queueBuffer(offset)) {
|
||||
if(!mPipe1->queueBuffer(fd, offset)) {
|
||||
ALOGE("OverlayImpl p1 failed to queueBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
if(!mPipe2->queueBuffer(offset)) {
|
||||
if(!mPipe2->queueBuffer(fd, offset)) {
|
||||
ALOGE("OverlayImpl p2 failed to queueBuffer");
|
||||
return false;
|
||||
}
|
||||
@ -603,37 +615,6 @@ bool OverlayImpl<P0, P1, P2>::queueBuffer(uint32_t offset, utils::eDest dest)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::dequeueBuffer(void*& buf, utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mPipe0 && mPipe1 && mPipe2,
|
||||
"%s: Pipes are null p0=%p p1=%p p2=%p",
|
||||
__FUNCTION__, mPipe0, mPipe1, mPipe2);
|
||||
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
if(!mPipe0->dequeueBuffer(buf)) {
|
||||
ALOGE("OverlayImpl p0 failed to dequeueBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
if(!mPipe1->dequeueBuffer(buf)) {
|
||||
ALOGE("OverlayImpl p1 failed to dequeueBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
if(!mPipe2->dequeueBuffer(buf)) {
|
||||
ALOGE("OverlayImpl p2 failed to dequeueBuffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
bool OverlayImpl<P0, P1, P2>::waitForVsync(utils::eDest dest)
|
||||
{
|
||||
@ -666,27 +647,8 @@ bool OverlayImpl<P0, P1, P2>::waitForVsync(utils::eDest dest)
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
void OverlayImpl<P0, P1, P2>::setMemoryId(int id, utils::eDest dest)
|
||||
{
|
||||
OVASSERT(mPipe0 && mPipe1 && mPipe2,
|
||||
"%s: Pipes are null p0=%p p1=%p p2=%p",
|
||||
__FUNCTION__, mPipe0, mPipe1, mPipe2);
|
||||
|
||||
if (utils::OV_PIPE0 & dest) {
|
||||
mPipe0->setMemoryId(id);
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE1 & dest) {
|
||||
mPipe1->setMemoryId(id);
|
||||
}
|
||||
|
||||
if (utils::OV_PIPE2 & dest) {
|
||||
mPipe2->setMemoryId(id);
|
||||
}
|
||||
}
|
||||
|
||||
template <class P0, class P1, class P2>
|
||||
utils::eOverlayPipeType OverlayImpl<P0, P1, P2>::getOvPipeType(utils::eDest dest) const
|
||||
utils::eOverlayPipeType OverlayImpl<P0, P1, P2>::getOvPipeType(
|
||||
utils::eDest dest) const
|
||||
{
|
||||
OVASSERT(utils::isValidDest(dest), "%s: OverlayImpl invalid dest=%d",
|
||||
__FUNCTION__, dest);
|
||||
|
@ -23,11 +23,11 @@
|
||||
|
||||
namespace ovutils = overlay::utils;
|
||||
namespace overlay {
|
||||
bool MdpCtrl::open(uint32_t fbnum) {
|
||||
// FD open
|
||||
bool MdpCtrl::init(uint32_t fbnum) {
|
||||
// FD init
|
||||
if(!utils::openDev(mFd, fbnum,
|
||||
Res::devTemplate, O_RDWR)){
|
||||
ALOGE("Ctrl failed to open fbnum=%d", fbnum);
|
||||
Res::fbPath, O_RDWR)){
|
||||
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -36,12 +36,15 @@ bool MdpCtrl::open(uint32_t fbnum) {
|
||||
void MdpCtrl::reset() {
|
||||
utils::memset0(mOVInfo);
|
||||
utils::memset0(mLkgo);
|
||||
mOVInfo.id = -1;
|
||||
mLkgo.id = -1;
|
||||
mOVInfo.id = MSMFB_NEW_REQUEST;
|
||||
mLkgo.id = MSMFB_NEW_REQUEST;
|
||||
mOrientation = utils::OVERLAY_TRANSFORM_0;
|
||||
mRotUsed = false;
|
||||
}
|
||||
|
||||
bool MdpCtrl::close() {
|
||||
if(-1 == static_cast<int>(mOVInfo.id)) return true;
|
||||
if(MSMFB_NEW_REQUEST == static_cast<int>(mOVInfo.id))
|
||||
return true;
|
||||
if(!mdp_wrapper::unsetOverlay(mFd.getFD(), mOVInfo.id)) {
|
||||
ALOGE("MdpCtrl close error in unset");
|
||||
return false;
|
||||
@ -53,6 +56,86 @@ bool MdpCtrl::close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setSource(const utils::PipeArgs& args) {
|
||||
|
||||
setSrcWhf(args.whf);
|
||||
|
||||
//TODO These are hardcoded. Can be moved out of setSource.
|
||||
mOVInfo.alpha = 0xff;
|
||||
mOVInfo.transp_mask = 0xffffffff;
|
||||
|
||||
//TODO These calls should ideally be a part of setPipeParams API
|
||||
setFlags(args.mdpFlags);
|
||||
setZ(args.zorder);
|
||||
setIsFg(args.isFg);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setCrop(const utils::Dim& d) {
|
||||
setSrcRectDim(d);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setPosition(const overlay::utils::Dim& d,
|
||||
int fbw, int fbh)
|
||||
{
|
||||
ovutils::Dim dim(d);
|
||||
ovutils::Dim ovsrcdim = getSrcRectDim();
|
||||
// Scaling of upto a max of 20 times supported
|
||||
if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){
|
||||
dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w;
|
||||
dim.x = (fbw - dim.w) / 2;
|
||||
}
|
||||
if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) {
|
||||
dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h;
|
||||
dim.y = (fbh - dim.h) / 2;
|
||||
}
|
||||
|
||||
setDstRectDim(dim);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setTransform(const utils::eTransform& orient,
|
||||
const bool& rotUsed) {
|
||||
mOrientation = orient;
|
||||
int rot = utils::getMdpOrient(orient);
|
||||
setUserData(rot);
|
||||
//Rotator can be requested by client even if layer has 0 orientation.
|
||||
mRotUsed = rotUsed;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdpCtrl::doTransform() {
|
||||
adjustSrcWhf(mRotUsed);
|
||||
setRotationFlags();
|
||||
//180 will be H + V
|
||||
//270 will be H + V + 90
|
||||
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_H) {
|
||||
overlayTransFlipH();
|
||||
}
|
||||
if(mOrientation & utils::OVERLAY_TRANSFORM_FLIP_V) {
|
||||
overlayTransFlipV();
|
||||
}
|
||||
if(mOrientation & utils::OVERLAY_TRANSFORM_ROT_90) {
|
||||
overlayTransRot90();
|
||||
}
|
||||
}
|
||||
|
||||
bool MdpCtrl::set() {
|
||||
//deferred calcs, so APIs could be called in any order.
|
||||
doTransform();
|
||||
if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
|
||||
ALOGE("MdpCtrl failed to setOverlay, restoring last known "
|
||||
"good ov info");
|
||||
mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
|
||||
mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
|
||||
this->restore();
|
||||
return false;
|
||||
}
|
||||
this->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::getScreenInfo(overlay::utils::ScreenInfo& info) {
|
||||
fb_fix_screeninfo finfo;
|
||||
if (!mdp_wrapper::getFScreenInfo(mFd.getFD(), finfo)) {
|
||||
@ -81,193 +164,24 @@ bool MdpCtrl::get() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// that is the second part of original setParameter function
|
||||
void MdpCtrl::setSrcFormat(const utils::Whf& whf) {
|
||||
|
||||
//By default mdp src format is the same as buffer's
|
||||
mOVInfo.src.format = whf.format;
|
||||
|
||||
//If rotation is used and input formats are tiled then output of rotator is
|
||||
//non-tiled.
|
||||
// FIXME mRotInfo.enable = 1; for enable
|
||||
if (getUserData()) { // if rotations enabled in MdpCtrl
|
||||
if (whf.format == MDP_Y_CRCB_H2V2_TILE)
|
||||
mOVInfo.src.format = MDP_Y_CRCB_H2V2;
|
||||
else if (whf.format == MDP_Y_CBCR_H2V2_TILE)
|
||||
mOVInfo.src.format = MDP_Y_CBCR_H2V2;
|
||||
return;
|
||||
//Adjust width, height, format if rotator is used.
|
||||
void MdpCtrl::adjustSrcWhf(const bool& rotUsed) {
|
||||
if(rotUsed) {
|
||||
utils::Whf whf = getSrcWhf();
|
||||
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
|
||||
whf.format == MDP_Y_CBCR_H2V2_TILE) {
|
||||
whf.w = utils::alignup(whf.w, 64);
|
||||
whf.h = utils::alignup(whf.h, 32);
|
||||
}
|
||||
//For example: If original format is tiled, rotator outputs non-tiled,
|
||||
//so update mdp's src fmt to that.
|
||||
whf.format = utils::getRotOutFmt(whf.format);
|
||||
setSrcWhf(whf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool MdpCtrl::set() {
|
||||
if(!this->ovChanged()) {
|
||||
return true; // nothing todo here.
|
||||
}
|
||||
|
||||
if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
|
||||
ALOGE("MdpCtrl failed to setOverlay, restoring last known "
|
||||
"good ov info");
|
||||
mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
|
||||
mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
|
||||
this->restore();
|
||||
// FIXME, do we need to set the old one?
|
||||
return false;
|
||||
}
|
||||
this->save();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setPosition(const overlay::utils::Dim& d,
|
||||
int fbw, int fbh)
|
||||
{
|
||||
// Validatee against FB size
|
||||
if(!d.check(fbw, fbh)) {
|
||||
ALOGE("MdpCtrl setPosition failed dest dim violate screen limits");
|
||||
return false;
|
||||
}
|
||||
|
||||
ovutils::Dim dim(d);
|
||||
ovutils::Dim ovsrcdim = getSrcRectDim();
|
||||
// Scaling of upto a max of 8 times supported
|
||||
if(dim.w >(ovsrcdim.w * ovutils::HW_OV_MAGNIFICATION_LIMIT)){
|
||||
dim.w = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.w;
|
||||
dim.x = (fbw - dim.w) / 2;
|
||||
}
|
||||
if(dim.h >(ovsrcdim.h * ovutils::HW_OV_MAGNIFICATION_LIMIT)) {
|
||||
dim.h = ovutils::HW_OV_MAGNIFICATION_LIMIT * ovsrcdim.h;
|
||||
dim.y = (fbh - dim.h) / 2;
|
||||
}
|
||||
|
||||
//dim.even_out();
|
||||
setDstRectDim(dim);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdpCtrl::updateSource(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
const utils::ScreenInfo& info) {
|
||||
utils::Whf whf(args.whf);
|
||||
mOVInfo.src.width = whf.w;
|
||||
mOVInfo.src.height = whf.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 = whf.w;
|
||||
mOVInfo.dst_rect.h = whf.h;
|
||||
mOVInfo.src.format = whf.format;
|
||||
|
||||
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
|
||||
(whf.format == MDP_Y_CBCR_H2V2_TILE)) {
|
||||
// passing by value, setInfo fills it and return by val
|
||||
mOVInfo = r->setInfo(args, mOVInfo);
|
||||
} else {
|
||||
mOVInfo.src_rect.w = whf.w;
|
||||
mOVInfo.src_rect.h = whf.h;
|
||||
}
|
||||
|
||||
if (whf.w > info.mFBWidth)
|
||||
mOVInfo.dst_rect.w = info.mFBWidth;
|
||||
if (whf.h > info.mFBHeight)
|
||||
mOVInfo.dst_rect.h = info.mFBHeight;
|
||||
mSize = whf.size;
|
||||
}
|
||||
|
||||
|
||||
bool MdpCtrl::setInfo(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
const utils::ScreenInfo& info)
|
||||
{
|
||||
// new request
|
||||
utils::Whf whf(args.whf);
|
||||
mOVInfo.id = MSMFB_NEW_REQUEST;
|
||||
|
||||
updateSource(r, args, info);
|
||||
|
||||
setUserData(0);
|
||||
mOVInfo.alpha = 0xff;
|
||||
mOVInfo.transp_mask = 0xffffffff;
|
||||
setZ(args.zorder);
|
||||
setFlags(args.mdpFlags);
|
||||
setWait(args.wait);
|
||||
setIsFg(args.isFg);
|
||||
mSize = whf.size;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpCtrl::setCrop(const utils::Dim& cdim) {
|
||||
utils::Dim d(cdim);
|
||||
const utils::Whf ovwhf = getSrcWhf();
|
||||
int udata = getUserData();
|
||||
switch(udata) {
|
||||
case MDP_ROT_NOP:
|
||||
break; // nothing to do here
|
||||
case MDP_ROT_90:
|
||||
case MDP_ROT_90 | MDP_FLIP_UD:
|
||||
case MDP_ROT_90 | MDP_FLIP_LR:
|
||||
{
|
||||
if (ovwhf.w < (d.y + d.h)) {
|
||||
ALOGE("MdpCtrl setCrop failed ROT 90 udata=%d",
|
||||
udata);
|
||||
d.dump();
|
||||
this->dump();
|
||||
return false;
|
||||
}
|
||||
uint32_t tmp = d.x;
|
||||
d.x = ovwhf.w - (d.y + d.h);
|
||||
d.y = tmp;
|
||||
utils::swap(d.w, d.h);
|
||||
}break;
|
||||
case MDP_ROT_270:
|
||||
{
|
||||
if (ovwhf.h < (d.x + d.w)) {
|
||||
ALOGE("MdpCtrl setCrop failed ROT 270 udata=%d",
|
||||
udata);
|
||||
d.dump();
|
||||
this->dump();
|
||||
return false;
|
||||
}
|
||||
uint32_t tmp = d.y;
|
||||
d.y = ovwhf.h - (d.x + d.w);
|
||||
d.x = tmp;
|
||||
utils::swap(d.w, d.h);
|
||||
}break;
|
||||
case MDP_ROT_180:
|
||||
{
|
||||
if ((ovwhf.h < (d.y + d.h)) ||
|
||||
(ovwhf.w < ( d.x + d.w))) {
|
||||
ALOGE("MdpCtrl setCrop failed ROT 180 udata=%d",
|
||||
udata);
|
||||
d.dump();
|
||||
this->dump();
|
||||
return false;
|
||||
}
|
||||
d.x = ovwhf.w - (d.x + d.w);
|
||||
d.y = ovwhf.h - (d.y + d.h);
|
||||
}break;
|
||||
default:
|
||||
if(!(udata & (MDP_FLIP_UD | MDP_FLIP_LR))) {
|
||||
ALOGE("MdpCtrl setCrop unknown rot %d", udata);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(getSrcRectDim() == d) {
|
||||
return true; // Nothing to do here
|
||||
}
|
||||
|
||||
utils::normalizeCrop(d.x, d.w);
|
||||
utils::normalizeCrop(d.y, d.h);
|
||||
|
||||
setSrcRectDim(d);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdpCtrl::dump() const {
|
||||
ALOGE("== Dump MdpCtrl start ==");
|
||||
ALOGE("size=%d", mSize);
|
||||
mFd.dump();
|
||||
mdp_wrapper::dump("mOVInfo", mOVInfo);
|
||||
ALOGE("== Dump MdpCtrl end ==");
|
||||
|
@ -22,12 +22,9 @@
|
||||
|
||||
#include "overlayUtils.h"
|
||||
#include "mdpWrapper.h"
|
||||
#include "overlayRotator.h"
|
||||
|
||||
namespace overlay{
|
||||
|
||||
class RotatorBase;
|
||||
|
||||
/*
|
||||
* Mdp Ctrl holds corresponding fd and MDP related struct.
|
||||
* It is simple wrapper to MDP services
|
||||
@ -40,20 +37,20 @@ public:
|
||||
/* dtor close */
|
||||
~MdpCtrl();
|
||||
|
||||
/* Open underlying device using fbnum */
|
||||
bool open(uint32_t fbnum);
|
||||
/* init underlying device using fbnum */
|
||||
bool init(uint32_t fbnum);
|
||||
|
||||
/* unset overlay, reset and close fd */
|
||||
bool close();
|
||||
|
||||
/* reset and set ov id to -1*/
|
||||
/* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
|
||||
void reset();
|
||||
|
||||
/* get orient / user_data[0] */
|
||||
int getOrient() const;
|
||||
|
||||
/* returns session id */
|
||||
int getId() const;
|
||||
int getPipeId() const;
|
||||
|
||||
/* returns the fd associated to ctrl*/
|
||||
int getFd() const;
|
||||
@ -64,29 +61,15 @@ public:
|
||||
/* overlay get */
|
||||
bool get();
|
||||
|
||||
/* returns flags from mdp structure.
|
||||
* Flags are WAIT/NOWAIT/PIPE SHARED*/
|
||||
/* returns flags from mdp structure */
|
||||
int getFlags() const;
|
||||
|
||||
/* set flags to mdp structure */
|
||||
void setFlags(int f);
|
||||
|
||||
/* code taken from OverlayControlChannel::setOverlayInformation */
|
||||
bool setInfo(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
const utils::ScreenInfo& info);
|
||||
|
||||
/* given whf, update src */
|
||||
void updateSource(RotatorBase* r,
|
||||
const utils::PipeArgs& args,
|
||||
const utils::ScreenInfo& info);
|
||||
|
||||
/* set z order */
|
||||
void setZ(utils::eZorder z);
|
||||
|
||||
/* set Wait/nowait */
|
||||
void setWait(utils::eWait wait);
|
||||
|
||||
/* set isFg flag */
|
||||
void setIsFg(utils::eIsFg isFg);
|
||||
|
||||
@ -102,8 +85,8 @@ public:
|
||||
/* set src whf */
|
||||
void setSrcWhf(const utils::Whf& whf);
|
||||
|
||||
/* set source format based on rot info */
|
||||
void setSrcFormat(const utils::Whf& whf);
|
||||
/* adjust source width height format based on rot info */
|
||||
void adjustSrcWhf(const bool& rotUsed);
|
||||
|
||||
/* swap src w/h*/
|
||||
void swapSrcWH();
|
||||
@ -128,7 +111,7 @@ public:
|
||||
void setUserData(int v);
|
||||
|
||||
/* return true if current overlay is different
|
||||
* than lask known good overlay */
|
||||
* than last known good overlay */
|
||||
bool ovChanged() const;
|
||||
|
||||
/* save mOVInfo to be last known good ov*/
|
||||
@ -137,6 +120,9 @@ public:
|
||||
/* restore last known good ov to be the current */
|
||||
void restore();
|
||||
|
||||
/* Sets the source total width, height, format */
|
||||
bool setSource(const utils::PipeArgs& pargs);
|
||||
|
||||
/*
|
||||
* Sets ROI, the unpadded region, for source buffer.
|
||||
* Should be called before a setPosition, for small clips.
|
||||
@ -144,6 +130,8 @@ public:
|
||||
*/
|
||||
bool setCrop(const utils::Dim& d);
|
||||
|
||||
bool setTransform(const utils::eTransform& orient, const bool& rotUsed);
|
||||
|
||||
/* given a dim and w/h, set overlay dim */
|
||||
bool setPosition(const utils::Dim& dim, int w, int h);
|
||||
|
||||
@ -152,8 +140,19 @@ public:
|
||||
|
||||
/* dump state of the object */
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
|
||||
/* helper functions for overlayTransform */
|
||||
void doTransform();
|
||||
void overlayTransFlipH();
|
||||
void overlayTransFlipV();
|
||||
void overlayTransRot90();
|
||||
|
||||
utils::eTransform mOrientation; //Holds requested orientation
|
||||
bool mRotUsed; //whether rotator should be used even if requested
|
||||
//orientation is 0.
|
||||
|
||||
/* last good known ov info */
|
||||
mdp_overlay mLkgo;
|
||||
|
||||
@ -162,9 +161,6 @@ private:
|
||||
|
||||
/* FD for the mdp fbnum */
|
||||
OvFD mFd;
|
||||
|
||||
/* cached size FIXME do we need it? */
|
||||
uint32_t mSize;
|
||||
};
|
||||
|
||||
|
||||
@ -201,8 +197,8 @@ public:
|
||||
/* dtor close*/
|
||||
~MdpData();
|
||||
|
||||
/* open FD */
|
||||
bool open(uint32_t fbnum);
|
||||
/* init FD */
|
||||
bool init(uint32_t fbnum);
|
||||
|
||||
/* memset0 the underlying mdp object */
|
||||
void reset();
|
||||
@ -210,29 +206,23 @@ public:
|
||||
/* close fd, and reset */
|
||||
bool close();
|
||||
|
||||
/* Set FD / memid */
|
||||
void setMemoryId(int id);
|
||||
|
||||
/* set id of mdp data */
|
||||
void setId(int id);
|
||||
void setPipeId(int id);
|
||||
|
||||
/* return ses id of data */
|
||||
int getId() const;
|
||||
int getPipeId() const;
|
||||
|
||||
/* get underlying fd*/
|
||||
int getFd() const;
|
||||
|
||||
/* get memory_id */
|
||||
int getMemoryId() const;
|
||||
|
||||
/* set offset in underlying mdp obj */
|
||||
void setOffset(uint32_t o);
|
||||
int getSrcMemoryId() const;
|
||||
|
||||
/* calls wrapper play */
|
||||
bool play();
|
||||
bool play(int fd, uint32_t offset);
|
||||
|
||||
/* calls wrapper playWait */
|
||||
bool playWait();
|
||||
/* calls wrapper waitForVsync */
|
||||
bool waitForVsync();
|
||||
|
||||
/* dump state of the object */
|
||||
void dump() const;
|
||||
@ -247,21 +237,22 @@ private:
|
||||
|
||||
//--------------Inlines---------------------------------
|
||||
namespace utils {
|
||||
inline bool openDev(OvFD& fd, int fb,
|
||||
const char* const s,
|
||||
int flags) {
|
||||
return overlay::open(fd, fb, Res::devTemplate, O_RDWR);
|
||||
}
|
||||
inline bool openDev(OvFD& fd, int fbnum,
|
||||
const char* const devpath,
|
||||
int flags) {
|
||||
return overlay::open(fd, fbnum, devpath, flags);
|
||||
}
|
||||
}
|
||||
namespace {
|
||||
// just a helper func for common operations x-(y+z)
|
||||
int compute(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return x-(y+z);
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void init(T& t) {
|
||||
memset(&t, 0, sizeof(T));
|
||||
}
|
||||
|
||||
///// MdpCtrl //////
|
||||
|
||||
inline MdpCtrl::MdpCtrl() : mSize(0) {
|
||||
inline MdpCtrl::MdpCtrl() {
|
||||
reset();
|
||||
}
|
||||
|
||||
@ -273,7 +264,7 @@ inline int MdpCtrl::getOrient() const {
|
||||
return getUserData();
|
||||
}
|
||||
|
||||
inline int MdpCtrl::getId() const {
|
||||
inline int MdpCtrl::getPipeId() const {
|
||||
return mOVInfo.id;
|
||||
}
|
||||
|
||||
@ -293,10 +284,6 @@ inline void MdpCtrl::setZ(overlay::utils::eZorder z) {
|
||||
mOVInfo.z_order = z;
|
||||
}
|
||||
|
||||
inline void MdpCtrl::setWait(overlay::utils::eWait wait) {
|
||||
mOVInfo.flags = utils::setWait(wait, mOVInfo.flags);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::setIsFg(overlay::utils::eIsFg isFg) {
|
||||
mOVInfo.is_fg = isFg;
|
||||
}
|
||||
@ -310,27 +297,25 @@ inline bool MdpCtrl::ovChanged() const {
|
||||
}
|
||||
|
||||
inline void MdpCtrl::save() {
|
||||
if(static_cast<ssize_t>(mOVInfo.id) == -1) {
|
||||
if(static_cast<ssize_t>(mOVInfo.id) == MSMFB_NEW_REQUEST) {
|
||||
ALOGE("MdpCtrl current ov has id -1, will not save");
|
||||
// FIXME dump both?
|
||||
return;
|
||||
}
|
||||
mLkgo = mOVInfo;
|
||||
}
|
||||
|
||||
inline void MdpCtrl::restore() {
|
||||
if(static_cast<ssize_t>(mLkgo.id) == -1) {
|
||||
if(static_cast<ssize_t>(mLkgo.id) == MSMFB_NEW_REQUEST) {
|
||||
ALOGE("MdpCtrl Lkgo ov has id -1, will not restore");
|
||||
// FIXME dump both?
|
||||
return;
|
||||
}
|
||||
mOVInfo = mLkgo;
|
||||
}
|
||||
|
||||
inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
|
||||
return utils::Whf(mOVInfo.src.width,
|
||||
mOVInfo.src.height,
|
||||
mOVInfo.src.format);
|
||||
return utils::Whf( mOVInfo.src.width,
|
||||
mOVInfo.src.height,
|
||||
mOVInfo.src.format);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
|
||||
@ -340,10 +325,10 @@ inline void MdpCtrl::setSrcWhf(const overlay::utils::Whf& whf) {
|
||||
}
|
||||
|
||||
inline overlay::utils::Dim MdpCtrl::getSrcRectDim() const {
|
||||
return utils::Dim(mOVInfo.src_rect.x,
|
||||
mOVInfo.src_rect.y,
|
||||
mOVInfo.src_rect.w,
|
||||
mOVInfo.src_rect.h);
|
||||
return utils::Dim( mOVInfo.src_rect.x,
|
||||
mOVInfo.src_rect.y,
|
||||
mOVInfo.src_rect.w,
|
||||
mOVInfo.src_rect.h);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
|
||||
@ -354,10 +339,10 @@ inline void MdpCtrl::setSrcRectDim(const overlay::utils::Dim d) {
|
||||
}
|
||||
|
||||
inline overlay::utils::Dim MdpCtrl::getDstRectDim() const {
|
||||
return utils::Dim(mOVInfo.dst_rect.x,
|
||||
mOVInfo.dst_rect.y,
|
||||
mOVInfo.dst_rect.w,
|
||||
mOVInfo.dst_rect.h);
|
||||
return utils::Dim( mOVInfo.dst_rect.x,
|
||||
mOVInfo.dst_rect.y,
|
||||
mOVInfo.dst_rect.w,
|
||||
mOVInfo.dst_rect.h);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::setDstRectDim(const overlay::utils::Dim d) {
|
||||
@ -379,14 +364,46 @@ inline void MdpCtrl::setRotationFlags() {
|
||||
mOVInfo.flags &= ~MDP_SOURCE_ROTATED_90;
|
||||
}
|
||||
|
||||
|
||||
inline void MdpCtrl::swapSrcWH() {
|
||||
utils::swap(mOVInfo.src.width,
|
||||
mOVInfo.src.height); }
|
||||
mOVInfo.src.height);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::swapSrcRectWH() {
|
||||
utils::swap(mOVInfo.src_rect.h,
|
||||
mOVInfo.src_rect.w); }
|
||||
utils::swap(mOVInfo.src_rect.w,
|
||||
mOVInfo.src_rect.h);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::overlayTransFlipH()
|
||||
{
|
||||
utils::Dim d = getSrcRectDim();
|
||||
utils::Whf whf = getSrcWhf();
|
||||
d.x = compute(whf.w, d.x, d.w);
|
||||
setSrcRectDim(d);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::overlayTransFlipV()
|
||||
{
|
||||
utils::Dim d = getSrcRectDim();
|
||||
utils::Whf whf = getSrcWhf();
|
||||
d.y = compute(whf.h, d.y, d.h);
|
||||
setSrcRectDim(d);
|
||||
}
|
||||
|
||||
inline void MdpCtrl::overlayTransRot90()
|
||||
{
|
||||
utils::Dim d = getSrcRectDim();
|
||||
utils::Whf whf = getSrcWhf();
|
||||
int tmp = d.x;
|
||||
d.x = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
d.y = tmp;
|
||||
setSrcRectDim(d);
|
||||
swapSrcWH();
|
||||
swapSrcRectWH();
|
||||
}
|
||||
|
||||
|
||||
/////// MdpCtrl3D //////
|
||||
|
||||
@ -434,10 +451,10 @@ inline MdpData::MdpData() { reset(); }
|
||||
|
||||
inline MdpData::~MdpData() { close(); }
|
||||
|
||||
inline bool MdpData::open(uint32_t fbnum) {
|
||||
// FD open
|
||||
if(!utils::openDev(mFd, fbnum, Res::devTemplate, O_RDWR)){
|
||||
ALOGE("Ctrl failed to open fbnum=%d", fbnum);
|
||||
inline bool MdpData::init(uint32_t fbnum) {
|
||||
// FD init
|
||||
if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){
|
||||
ALOGE("Ctrl failed to init fbnum=%d", fbnum);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -457,28 +474,29 @@ inline bool MdpData::close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void MdpData::setMemoryId(int id) { mOvData.data.memory_id = id; }
|
||||
inline int MdpData::getMemoryId() const { return mOvData.data.memory_id; }
|
||||
inline int MdpData::getSrcMemoryId() const { return mOvData.data.memory_id; }
|
||||
|
||||
inline void MdpData::setId(int id) { mOvData.id = id; }
|
||||
inline void MdpData::setPipeId(int id) { mOvData.id = id; }
|
||||
|
||||
inline int MdpData::getId() const { return mOvData.id; }
|
||||
inline int MdpData::getPipeId() const { return mOvData.id; }
|
||||
|
||||
inline int MdpData::getFd() const { return mFd.getFD(); }
|
||||
|
||||
inline void MdpData::setOffset(uint32_t o) { mOvData.data.offset = o; }
|
||||
|
||||
inline bool MdpData::play() {
|
||||
inline bool MdpData::play(int fd, uint32_t offset) {
|
||||
mOvData.data.memory_id = fd;
|
||||
mOvData.data.offset = offset;
|
||||
if(!mdp_wrapper::play(mFd.getFD(), mOvData)){
|
||||
ALOGE("MdpData failed to play");
|
||||
dump();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool MdpData::playWait() {
|
||||
if(!mdp_wrapper::playWait(mFd.getFD(), mOvData)){
|
||||
ALOGE("MdpData failed to playWait");
|
||||
inline bool MdpData::waitForVsync() {
|
||||
if(!mdp_wrapper::waitForVsync(mFd.getFD(), mOvData)){
|
||||
ALOGE("%s failed", __FUNCTION__);
|
||||
dump();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
@ -54,7 +54,7 @@ public:
|
||||
|
||||
/* Use libgralloc to retrieve fd, base addr, alloc type */
|
||||
bool open(uint32_t numbufs,
|
||||
uint32_t bufSz, int flags = O_RDWR);
|
||||
uint32_t bufSz, bool isSecure);
|
||||
|
||||
/* close fd. assign base address to invalid*/
|
||||
bool close();
|
||||
@ -115,14 +115,17 @@ inline OvMem::OvMem() {
|
||||
inline OvMem::~OvMem() { }
|
||||
|
||||
inline bool OvMem::open(uint32_t numbufs,
|
||||
uint32_t bufSz, int flags)
|
||||
uint32_t bufSz, bool isSecure)
|
||||
{
|
||||
alloc_data data;
|
||||
//XXX: secure buffers and IOMMU heap
|
||||
int allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP |
|
||||
GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
|
||||
int err = 0;
|
||||
int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
|
||||
if(isSecure) {
|
||||
allocFlags |= GRALLOC_USAGE_PRIVATE_MM_HEAP;
|
||||
allocFlags |= GRALLOC_USAGE_PRIVATE_DO_NOT_MAP;
|
||||
allocFlags |= GRALLOC_USAGE_PRIVATE_CP_BUFFER;
|
||||
}
|
||||
|
||||
int err = 0;
|
||||
OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
|
||||
|
||||
mBufSz = bufSz;
|
||||
@ -138,6 +141,7 @@ inline bool OvMem::open(uint32_t numbufs,
|
||||
err = mAlloc->allocate(data, allocFlags, 0);
|
||||
if (err != 0) {
|
||||
ALOGE("OvMem: error allocating memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
mFd = data.fd;
|
||||
@ -159,6 +163,7 @@ inline bool OvMem::close()
|
||||
ret = memalloc->free_buffer(mBaseAddr, mBufSz * mNumBuffers, 0, mFd);
|
||||
if (ret != 0) {
|
||||
ALOGE("OvMem: error freeing buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
mFd = -1;
|
||||
@ -166,7 +171,7 @@ inline bool OvMem::close()
|
||||
mAllocType = 0;
|
||||
mBufSz = 0;
|
||||
mNumBuffers = 0;
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool OvMem::valid() const
|
||||
@ -196,8 +201,9 @@ inline uint32_t OvMem::numBufs() const
|
||||
|
||||
inline void OvMem::dump() const
|
||||
{
|
||||
ALOGE("%s: fd=%d addr=%p type=%d bufsz=%u",
|
||||
__FUNCTION__, mFd, mBaseAddr, mAllocType, mBufSz);
|
||||
ALOGE("== Dump OvMem start ==");
|
||||
ALOGE("fd=%d addr=%p type=%d bufsz=%u", mFd, mBaseAddr, mAllocType, mBufSz);
|
||||
ALOGE("== Dump OvMem end ==");
|
||||
}
|
||||
|
||||
} // overlay
|
||||
|
@ -17,72 +17,110 @@
|
||||
|
||||
#include "overlayRotator.h"
|
||||
#include "overlayUtils.h"
|
||||
#include "overlayMdp.h"
|
||||
|
||||
namespace ovutils = overlay::utils;
|
||||
|
||||
namespace overlay {
|
||||
|
||||
namespace utils {
|
||||
inline mdp_overlay setInfoNullRot(const utils::PipeArgs& args,
|
||||
const mdp_overlay& o)
|
||||
{
|
||||
mdp_overlay ov = o;
|
||||
utils::Whf whf(args.whf);
|
||||
utils::Dim d(utils::getSrcRectDim(ov));
|
||||
|
||||
d.w = whf.w - (utils::alignup(whf.w, 64) - whf.w);
|
||||
d.h = whf.h - (utils::alignup(whf.h, 32) - whf.h);
|
||||
utils::setSrcRectDim(ov, d);
|
||||
return ov;
|
||||
int IRotatorHw::getRotatorHwType() {
|
||||
//TODO figure out based on ioctl
|
||||
return TYPE_MDP;
|
||||
}
|
||||
|
||||
inline mdp_overlay setInfoRot(const utils::PipeArgs& args,
|
||||
const mdp_overlay& o)
|
||||
{
|
||||
/* If there are no orientation, then we use setInfoRot
|
||||
* That is even if we are a real rotator object (not null)
|
||||
* Note, that if args.rotFlags are ENABLED
|
||||
* it means we would still like to have rot
|
||||
* even though it is ROT_0 */
|
||||
if(OVERLAY_TRANSFORM_0 == args.orientation &&
|
||||
utils::ROT_FLAG_ENABLED != args.rotFlags) {
|
||||
return setInfoNullRot(args, o);
|
||||
bool RotMem::close() {
|
||||
bool ret = true;
|
||||
for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
|
||||
// skip current, and if valid, close
|
||||
if(m[i].valid()) {
|
||||
if(m[i].close() == false) {
|
||||
ALOGE("%s error in closing rot mem %d", __FUNCTION__, i);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mdp_overlay ov = o;
|
||||
utils::Whf whf(args.whf);
|
||||
utils::Dim d(utils::getSrcRectDim(ov));
|
||||
d.w = whf.w;
|
||||
d.h = whf.h;
|
||||
utils::Whf localwhf (utils::getSrcWhf(ov));
|
||||
localwhf.w = utils::alignup(whf.w, 64);
|
||||
localwhf.h = utils::alignup(whf.h, 32);
|
||||
d.x = localwhf.w - whf.w;
|
||||
d.y = localwhf.h - whf.h;
|
||||
utils::setSrcRectDim(ov, d);
|
||||
utils::setSrcWhf(ov, localwhf);
|
||||
return ov;
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // utils
|
||||
|
||||
bool MdpRot::open()
|
||||
bool MdpRot::init()
|
||||
{
|
||||
if(!mFd.open(Res::rotPath, O_RDWR)){
|
||||
ALOGE("MdpRot failed to open %s", Res::rotPath);
|
||||
ALOGE("MdpRot failed to init %s", Res::rotPath);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdpRot::setSource(const overlay::utils::Whf& awhf) {
|
||||
utils::Whf whf(awhf);
|
||||
|
||||
mRotImgInfo.src.format = whf.format;
|
||||
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
|
||||
whf.format == MDP_Y_CBCR_H2V2_TILE) {
|
||||
whf.w = utils::alignup(awhf.w, 64);
|
||||
whf.h = utils::alignup(awhf.h, 32);
|
||||
}
|
||||
|
||||
mRotImgInfo.src.width = whf.w;
|
||||
mRotImgInfo.src.height = whf.h;
|
||||
|
||||
mRotImgInfo.src_rect.w = whf.w;
|
||||
mRotImgInfo.src_rect.h = whf.h;
|
||||
|
||||
mRotImgInfo.dst.width = whf.w;
|
||||
mRotImgInfo.dst.height = whf.h;
|
||||
|
||||
mBufSize = awhf.size;
|
||||
}
|
||||
|
||||
void MdpRot::setFlags(const utils::eMdpFlags& flags) {
|
||||
mRotImgInfo.secure = 0;
|
||||
if(flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
|
||||
mRotImgInfo.secure = 1;
|
||||
}
|
||||
|
||||
void MdpRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
|
||||
{
|
||||
mOrientation = rot;
|
||||
int r = utils::getMdpOrient(rot);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
|
||||
setRotations(r);
|
||||
setDisable();
|
||||
if(rotUsed) {
|
||||
setEnable();
|
||||
}
|
||||
}
|
||||
|
||||
void MdpRot::doTransform() {
|
||||
switch(mOrientation) {
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_H:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90_FLIP_V:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_270:
|
||||
utils::swap(mRotImgInfo.dst.width, mRotImgInfo.dst.height);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MdpRot::commit() {
|
||||
doTransform();
|
||||
if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
|
||||
ALOGE("MdpRot commit failed");
|
||||
dump();
|
||||
return false;
|
||||
}
|
||||
mRotDataInfo.session_id = mRotImgInfo.session_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
|
||||
{
|
||||
OvMem mem;
|
||||
|
||||
OVASSERT(MAP_FAILED == mem.addr(), "MAP failed in open_i");
|
||||
|
||||
if(!mem.open(numbufs, bufsz)){
|
||||
if(!mem.open(numbufs, bufsz, mRotImgInfo.secure)){
|
||||
ALOGE("%s: Failed to open", __func__);
|
||||
mem.close();
|
||||
return false;
|
||||
@ -91,25 +129,12 @@ bool MdpRot::open_i(uint32_t numbufs, uint32_t bufsz)
|
||||
OVASSERT(MAP_FAILED != mem.addr(), "MAP failed");
|
||||
OVASSERT(mem.getFD() != -1, "getFd is -1");
|
||||
|
||||
mData.data.memory_id = mem.getFD();
|
||||
mRotDataInfo.dst.memory_id = mem.getFD();
|
||||
mRotDataInfo.dst.offset = 0;
|
||||
mMem.curr().m = mem;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpRot::RotMem::close() {
|
||||
bool ret = true;
|
||||
for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
|
||||
// skip current, and if valid, close
|
||||
if(m[i].valid() && (m[i].close() != 0)) {
|
||||
ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MdpRot::close() {
|
||||
bool success = true;
|
||||
if(mFd.valid() && (getSessId() > 0)) {
|
||||
@ -131,300 +156,78 @@ bool MdpRot::close() {
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MdpRot::unmapNonCurrent() {
|
||||
bool ret = true;
|
||||
for(uint32_t i=0; i < RotMem::MAX_ROT_MEM; ++i) {
|
||||
// skip current, and if valid, close
|
||||
if(i != mMem._curr % RotMem::MAX_ROT_MEM &&
|
||||
mMem.m[i].valid() &&
|
||||
!mMem.m[i].close()) {
|
||||
ALOGE("%s error in closing prev rot mem %d", __FUNCTION__, i);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MdpRot::remap(uint32_t numbufs,
|
||||
const utils::PipeArgs& args) {
|
||||
bool MdpRot::remap(uint32_t numbufs) {
|
||||
// if current size changed, remap
|
||||
if(args.whf.size == mMem.curr().size()) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, args.whf.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// remap only if we have orientation.
|
||||
// If rotFlags are ENABLED, it means we need rotation bufs
|
||||
// even when orientation is 0
|
||||
if(utils::OVERLAY_TRANSFORM_0 == args.orientation &&
|
||||
utils::ROT_FLAG_ENABLED != args.rotFlags) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: orientation=%d, rotFlags=%d",
|
||||
__FUNCTION__, args.orientation, args.rotFlags);
|
||||
if(mBufSize == mMem.curr().size()) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: same size %d", __FUNCTION__, mBufSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: size changed - remapping", __FUNCTION__);
|
||||
OVASSERT(!mMem.prev().valid(), "Prev should not be valid");
|
||||
|
||||
// remap and have the current to be the new one.
|
||||
// ++mMem will make curr to be prev, and prev will be curr
|
||||
++mMem;
|
||||
if(!open_i(numbufs, args.whf.size)) {
|
||||
if(!open_i(numbufs, mBufSize)) {
|
||||
ALOGE("%s Error could not open", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
OVASSERT(numbufs <= ROT_MAX_BUF_OFFSET,
|
||||
"Numbufs %d > ROT_MAX_BUF_OFFSET", numbufs);
|
||||
for (uint32_t i = 0; i < numbufs; ++i) {
|
||||
mMem.curr().mRotOffset[i] = i * args.whf.size;
|
||||
mMem.curr().mRotOffset[i] = i * mBufSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MdpRot::start() {
|
||||
if(!overlay::mdp_wrapper::startRotator(mFd.getFD(), mRotImgInfo)) {
|
||||
ALOGE("MdpRot start failed");
|
||||
this->dump();
|
||||
return false;
|
||||
}
|
||||
mRotDataInfo.session_id = mRotImgInfo.session_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MdpRot::reset() {
|
||||
ovutils::memset0(mRotImgInfo);
|
||||
ovutils::memset0(mRotDataInfo);
|
||||
ovutils::memset0(mData);
|
||||
ovutils::memset0(mMem.curr().mRotOffset);
|
||||
ovutils::memset0(mMem.prev().mRotOffset);
|
||||
mMem.curr().mCurrOffset = 0;
|
||||
mMem.prev().mCurrOffset = 0;
|
||||
isSrcFB = false;
|
||||
mBufSize = 0;
|
||||
mOrientation = utils::OVERLAY_TRANSFORM_0;
|
||||
}
|
||||
|
||||
bool MdpRot::prepareQueueBuf(uint32_t offset) {
|
||||
// FIXME if it fails, what happens to the above current item?
|
||||
bool MdpRot::queueBuffer(int fd, uint32_t offset) {
|
||||
if(enabled()) {
|
||||
OVASSERT(mMem.curr().m.numBufs(),
|
||||
"prepareQueueBuf numbufs is 0");
|
||||
|
||||
// If the rotator source is FB
|
||||
if(isSrcFB) {
|
||||
mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB;
|
||||
}
|
||||
|
||||
mRotDataInfo.src.memory_id = fd;
|
||||
mRotDataInfo.src.offset = offset;
|
||||
|
||||
remap(RotMem::Mem::ROT_NUM_BUFS);
|
||||
OVASSERT(mMem.curr().m.numBufs(),
|
||||
"queueBuffer numbufs is 0");
|
||||
mRotDataInfo.dst.offset =
|
||||
mMem.curr().mRotOffset[mMem.curr().mCurrOffset];
|
||||
mMem.curr().mCurrOffset =
|
||||
(mMem.curr().mCurrOffset + 1) % mMem.curr().m.numBufs();
|
||||
|
||||
if(!overlay::mdp_wrapper::rotate(mFd.getFD(), mRotDataInfo)) {
|
||||
ALOGE("MdpRot failed rotate");
|
||||
dump();
|
||||
return false;
|
||||
}
|
||||
mData.data.offset = mRotDataInfo.dst.offset;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool MdpRot::play(int fd) {
|
||||
if(!overlay::mdp_wrapper::play(fd, mData)) {
|
||||
ALOGE("MdpRot failed to play with fd=%d", fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the prev mem is valid, we need to close
|
||||
if(mMem.prev().valid()) {
|
||||
// FIXME FIXME FIXME if no wait for vsync the above
|
||||
// play will return immediatly and might cause
|
||||
// tearing when prev.close is called.
|
||||
if(!mMem.prev().close()) {
|
||||
ALOGE("%s error in closing prev rot mem", __FUNCTION__);
|
||||
// if the prev mem is valid, we need to close
|
||||
if(mMem.prev().valid()) {
|
||||
// FIXME if no wait for vsync the above
|
||||
// play will return immediatly and might cause
|
||||
// tearing when prev.close is called.
|
||||
if(!mMem.prev().close()) {
|
||||
ALOGE("%s error in closing prev rot mem", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
///// Null Rot ////
|
||||
|
||||
mdp_overlay NullRotator::setInfo(
|
||||
const utils::PipeArgs& args,
|
||||
const mdp_overlay& o) {
|
||||
return utils::setInfoNullRot(args, o);
|
||||
}
|
||||
|
||||
///// Rotator ////
|
||||
|
||||
mdp_overlay Rotator::setInfo(
|
||||
const utils::PipeArgs& args,
|
||||
const mdp_overlay& o)
|
||||
{
|
||||
return utils::setInfoRot(args, o);
|
||||
}
|
||||
|
||||
bool Rotator::overlayTransform(MdpCtrl& mdp,
|
||||
utils::eTransform& rot)
|
||||
{
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rot);
|
||||
switch(int(rot)) {
|
||||
case 0:
|
||||
case HAL_TRANSFORM_FLIP_H:
|
||||
case HAL_TRANSFORM_FLIP_V:
|
||||
overlayTransFlipHV(mdp, rot);
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_H):
|
||||
case (HAL_TRANSFORM_ROT_90|HAL_TRANSFORM_FLIP_V):
|
||||
overlayTransFlipRot90(mdp, rot);
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
overlayTransFlipRot180(mdp);
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
overlayTransFlipRot270(mdp);
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s: Error due to unknown rot value %d", __FUNCTION__, rot);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* everything below is rotation related */
|
||||
int r = utils::getMdpOrient(rot);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: r=%d", __FUNCTION__, r);
|
||||
if (r == -1) {
|
||||
ALOGE("Ctrl setParameter rot it -1");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Need to have both in sync
|
||||
mdp.setUserData(r);
|
||||
this->setRotations(r);
|
||||
this->setDisable();
|
||||
if(r) {
|
||||
this->setEnable();
|
||||
}
|
||||
|
||||
/* set src format using rotation info
|
||||
* e.g. (12-->5 in case of rotation) */
|
||||
mdp.setSrcFormat(this->getSrcWhf());
|
||||
|
||||
// based on 90/270 set flags
|
||||
mdp.setRotationFlags();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Rotator::overlayTransFlipHV(MdpCtrl& mdp,
|
||||
utils::eTransform& rot)
|
||||
{
|
||||
int val = mdp.getUserData();
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
|
||||
utils::Dim d = mdp.getSrcRectDim();
|
||||
utils::Whf whf = mdp.getSrcWhf();
|
||||
if (val == MDP_ROT_90) {
|
||||
int tmp = d.y;
|
||||
d.y = compute(whf.w,
|
||||
d.x,
|
||||
d.w);
|
||||
d.x = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
else if (val == MDP_ROT_270) {
|
||||
int tmp = d.x;
|
||||
d.x = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
d.y = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
}
|
||||
|
||||
void Rotator::overlayTransFlipRot90(MdpCtrl& mdp,
|
||||
utils::eTransform& rot)
|
||||
{
|
||||
int val = mdp.getUserData();
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
|
||||
utils::Dim d = mdp.getSrcRectDim();
|
||||
utils::Whf whf = mdp.getSrcWhf();
|
||||
if (val == MDP_ROT_270) {
|
||||
d.x = compute(whf.w,
|
||||
d.x,
|
||||
d.w);
|
||||
d.y = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
}
|
||||
else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
|
||||
int tmp = d.x;
|
||||
d.x = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
d.y = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
}
|
||||
|
||||
void Rotator::overlayTransFlipRot180(MdpCtrl& mdp)
|
||||
{
|
||||
int val = mdp.getUserData();
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
|
||||
utils::Dim d = mdp.getSrcRectDim();
|
||||
utils::Whf whf = mdp.getSrcWhf();
|
||||
if (val == MDP_ROT_270) {
|
||||
int tmp = d.y;
|
||||
d.y = compute(whf.w,
|
||||
d.x,
|
||||
d.w);
|
||||
d.x = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
else if (val == MDP_ROT_90) {
|
||||
int tmp = d.x;
|
||||
d.x = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
d.y = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
}
|
||||
|
||||
void Rotator::overlayTransFlipRot270(MdpCtrl& mdp)
|
||||
{
|
||||
int val = mdp.getUserData();
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: prev=%d", __FUNCTION__, val);
|
||||
utils::Dim d = mdp.getSrcRectDim();
|
||||
utils::Whf whf = mdp.getSrcWhf();
|
||||
if (val == MDP_ROT_90) {
|
||||
d.y = compute(whf.h,
|
||||
d.y,
|
||||
d.h);
|
||||
d.x = compute(whf.w,
|
||||
d.x,
|
||||
d.w);
|
||||
}
|
||||
else if (val == MDP_ROT_NOP || val == MDP_ROT_180) {
|
||||
int tmp = d.y;
|
||||
d.y = compute(whf.w,
|
||||
d.x,
|
||||
d.w);
|
||||
d.x = tmp;
|
||||
mdp.setSrcRectDim(d);
|
||||
utils::swapOVRotWidthHeight(mRot, mdp);
|
||||
}
|
||||
}
|
||||
|
||||
void MdpRot::dump() const {
|
||||
ALOGE("== Dump MdpRot start ==");
|
||||
mFd.dump();
|
||||
mMem.curr().m.dump();
|
||||
mdp_wrapper::dump("mRotImgInfo", mRotImgInfo);
|
||||
mdp_wrapper::dump("mRotDataInfo", mRotDataInfo);
|
||||
mdp_wrapper::dump("mData", mData);
|
||||
ALOGE("== Dump MdpRot end ==");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
||||
* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
@ -27,8 +27,8 @@
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef OVERLAY_ROTATOR_H
|
||||
#define OVERLAY_ROTATOR_H
|
||||
#ifndef OVERlAY_ROTATOR_H
|
||||
#define OVERlAY_ROTATOR_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -37,158 +37,111 @@
|
||||
#include "overlayMem.h"
|
||||
|
||||
namespace overlay {
|
||||
class MdpCtrl;
|
||||
|
||||
class IRotatorHw;
|
||||
/*
|
||||
* MDP rot holds MDP's rotation related structures.
|
||||
*
|
||||
* */
|
||||
class MdpRot {
|
||||
public:
|
||||
/* ctor */
|
||||
explicit MdpRot();
|
||||
|
||||
/* open fd for rotator. map bufs is defered */
|
||||
bool open();
|
||||
|
||||
/* remap rot buffers */
|
||||
bool remap(uint32_t numbufs, const utils::PipeArgs& args);
|
||||
|
||||
/* Unmap everything that is not current */
|
||||
bool unmapNonCurrent();
|
||||
|
||||
/* close fd, mem */
|
||||
bool close();
|
||||
|
||||
/* reset underlying data, basically memset 0 */
|
||||
void reset();
|
||||
|
||||
/* calls underlying wrappers to start rotator */
|
||||
bool start();
|
||||
|
||||
/* start underlying but use given whf and flags */
|
||||
bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* start underlying but use given whf and flags.
|
||||
* Has the ability to parameterize the dst fmt */
|
||||
template <int ROT_OUT_FMT>
|
||||
bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* assign memory id to mdp structure */
|
||||
void setDataMemId(int fd);
|
||||
void setRotDataSrcMemId(int fd);
|
||||
|
||||
/* Mark src as FB (non-ION) */
|
||||
void setSrcFB(bool);
|
||||
|
||||
/* get dst (for offset and memory id) non-virt */
|
||||
int getDstMemId() const;
|
||||
uint32_t getDstOffset() const;
|
||||
|
||||
/* set enable/disable flag */
|
||||
void setEnable();
|
||||
void setDisable();
|
||||
bool enabled() const;
|
||||
|
||||
/* set rotator flag*/
|
||||
void setRotations(uint32_t r);
|
||||
|
||||
/* set the req data id in mData */
|
||||
void setDataReqId(int id);
|
||||
|
||||
/* swap rot info dst w/h */
|
||||
void swapDstWH();
|
||||
|
||||
/* returns a copy of src whf */
|
||||
utils::Whf getSrcWhf() const;
|
||||
|
||||
/* setup rotator data before queue buf calls
|
||||
* call play if rotate call succeed. return false if failed */
|
||||
bool prepareQueueBuf(uint32_t offset);
|
||||
|
||||
/* call play on mdp*/
|
||||
bool play(int fd);
|
||||
|
||||
/* set src whf */
|
||||
void setSrcWhf(const utils::Whf& whf);
|
||||
|
||||
/* returns rotator session id */
|
||||
int getSessId() const;
|
||||
|
||||
/* dump the state of the object */
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
bool open_i(uint32_t numbufs, uint32_t bufsz);
|
||||
|
||||
/* max buf no for offset */
|
||||
enum { ROT_MAX_BUF_OFFSET = 2 };
|
||||
/* rot info*/
|
||||
msm_rotator_img_info mRotImgInfo;
|
||||
/* rot data */
|
||||
msm_rotator_data_info mRotDataInfo;
|
||||
/* data needed for rotator */
|
||||
msmfb_overlay_data mData;
|
||||
/* rotator fd */
|
||||
OvFD mFd;
|
||||
/* Array of memory map for rotator
|
||||
* The array enable us to change rot buffers/mapping
|
||||
* on the fly*/
|
||||
struct RotMem {
|
||||
enum {MAX_ROT_MEM = 2};
|
||||
struct Mem {
|
||||
Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); }
|
||||
bool valid() { return m.valid(); }
|
||||
bool close() { return m.close(); }
|
||||
uint32_t size() const { return m.bufSz(); }
|
||||
/* rotator data info dst offset */
|
||||
uint32_t mRotOffset[ROT_MAX_BUF_OFFSET];
|
||||
/* current offset slot from mRotOffset */
|
||||
uint32_t mCurrOffset;
|
||||
OvMem m;
|
||||
};
|
||||
RotMem() : _curr(0) {}
|
||||
Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
|
||||
const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
|
||||
Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
|
||||
RotMem& operator++() { ++_curr; return *this; }
|
||||
bool close();
|
||||
uint32_t _curr;
|
||||
Mem m[MAX_ROT_MEM];
|
||||
} mMem;
|
||||
bool isSrcFB;
|
||||
};
|
||||
|
||||
/*
|
||||
* RotatorBase. No memebers, just interface.
|
||||
* ~ can also be =0 with empty impl in cpp.
|
||||
* RotatorBase. No members, just interface.
|
||||
* can also be =0 with empty impl in cpp.
|
||||
* */
|
||||
class RotatorBase {
|
||||
public:
|
||||
/* Most of the below are No op funcs for RotatorBase */
|
||||
virtual ~RotatorBase() {}
|
||||
virtual bool open() = 0;
|
||||
virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args) = 0;
|
||||
virtual bool init() = 0;
|
||||
virtual bool close() = 0;
|
||||
virtual bool start(const utils::PipeArgs& args) = 0;
|
||||
virtual bool start() = 0;
|
||||
virtual mdp_overlay setInfo(const utils::PipeArgs& args,
|
||||
const mdp_overlay& o) = 0;
|
||||
virtual bool overlayTransform(MdpCtrl& mdp,
|
||||
utils::eTransform& rot) = 0;
|
||||
virtual void setSrcWhf(const utils::Whf& wfh) = 0;
|
||||
virtual utils::Whf getSrcWhf() const = 0;
|
||||
virtual void setRotations(uint32_t r) = 0;
|
||||
virtual void setDataReqId(int id) = 0;
|
||||
virtual bool prepareQueueBuf(uint32_t offset) = 0;
|
||||
virtual bool play(int fd) = 0;
|
||||
virtual void setSource(const utils::Whf& wfh) = 0;
|
||||
virtual void setFlags(const utils::eMdpFlags& flags) = 0;
|
||||
virtual void setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed) = 0;
|
||||
virtual bool commit() = 0;
|
||||
virtual bool queueBuffer(int fd, uint32_t offset) = 0;
|
||||
|
||||
virtual void setEnable() = 0;
|
||||
virtual void setDisable() = 0;
|
||||
virtual void setRotations(uint32_t r) = 0;
|
||||
virtual void setSrcFB() = 0;
|
||||
|
||||
virtual bool enabled() const = 0;
|
||||
virtual void setDataMemId(int fd) = 0;
|
||||
virtual void setRotDataSrcMemId(int fd) = 0;
|
||||
virtual void setSrcFB(bool) = 0;
|
||||
virtual int getSessId() const = 0;
|
||||
virtual int getDstMemId() const = 0;
|
||||
virtual uint32_t getDstOffset() const = 0;
|
||||
virtual void dump() const = 0;
|
||||
|
||||
protected:
|
||||
//Hardware specific rotator impl.
|
||||
IRotatorHw *mRot;
|
||||
};
|
||||
|
||||
/*
|
||||
* Rotator Hw Interface. Any hardware specific implementation should inherit
|
||||
* from this.
|
||||
*/
|
||||
class IRotatorHw {
|
||||
public:
|
||||
/* Most of the below are No op funcs for RotatorBase */
|
||||
virtual ~IRotatorHw() {}
|
||||
/* init fd for rotator. map bufs is defered */
|
||||
virtual bool init() = 0;
|
||||
/* close fd, mem */
|
||||
virtual bool close() = 0;
|
||||
/* set src */
|
||||
virtual void setSource(const utils::Whf& wfh) = 0;
|
||||
/* set mdp flags, will use only stuff necessary for rotator */
|
||||
virtual void setFlags(const utils::eMdpFlags& flags) = 0;
|
||||
/* Set rotation and calculate */
|
||||
virtual void setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed) = 0;
|
||||
/* calls underlying wrappers to start rotator */
|
||||
virtual bool commit() = 0;
|
||||
/* Lazy buffer allocation. queue buffer */
|
||||
virtual bool queueBuffer(int fd, uint32_t offset) = 0;
|
||||
/* set enable/disable flag */
|
||||
virtual void setEnable() = 0;
|
||||
virtual void setDisable() = 0;
|
||||
/* set rotator flag*/
|
||||
virtual void setRotations(uint32_t r) = 0;
|
||||
/* Mark src as FB (non-ION) */
|
||||
virtual void setSrcFB() = 0;
|
||||
/* Retusn true if rotator enabled */
|
||||
virtual bool enabled() const = 0;
|
||||
/* returns rotator session id */
|
||||
virtual int getSessId() const = 0;
|
||||
/* get dst (for offset and memory id) non-virt */
|
||||
virtual int getDstMemId() const = 0;
|
||||
virtual uint32_t getDstOffset() const = 0;
|
||||
/* dump the state of the object */
|
||||
virtual void dump() const = 0;
|
||||
|
||||
enum { TYPE_MDP, TYPE_MDSS };
|
||||
/*Returns rotator h/w type */
|
||||
static int getRotatorHwType();
|
||||
};
|
||||
|
||||
/*
|
||||
* Actual Rotator impl.
|
||||
* */
|
||||
class Rotator : public RotatorBase
|
||||
{
|
||||
public:
|
||||
explicit Rotator();
|
||||
virtual ~Rotator();
|
||||
virtual bool init();
|
||||
virtual bool close();
|
||||
virtual void setSource(const utils::Whf& wfh);
|
||||
virtual void setFlags(const utils::eMdpFlags& flags);
|
||||
virtual void setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed);
|
||||
virtual bool commit();
|
||||
virtual void setRotations(uint32_t r);
|
||||
virtual void setSrcFB();
|
||||
virtual int getDstMemId() const;
|
||||
virtual uint32_t getDstOffset() const;
|
||||
virtual void setEnable();
|
||||
virtual void setDisable();
|
||||
virtual bool enabled () const;
|
||||
virtual int getSessId() const;
|
||||
virtual bool queueBuffer(int fd, uint32_t offset);
|
||||
virtual void dump() const;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -198,357 +151,217 @@ class NullRotator : public RotatorBase {
|
||||
public:
|
||||
/* Most of the below are No op funcs for RotatorBase */
|
||||
virtual ~NullRotator();
|
||||
virtual bool open();
|
||||
virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args);
|
||||
virtual bool init();
|
||||
virtual bool close();
|
||||
virtual bool start(const utils::PipeArgs& args);
|
||||
virtual bool start();
|
||||
/* null rotator behavior should set info in a specific way */
|
||||
virtual mdp_overlay setInfo(const utils::PipeArgs& args,
|
||||
const mdp_overlay& o);
|
||||
virtual bool overlayTransform(MdpCtrl& o,
|
||||
utils::eTransform& rot);
|
||||
virtual void setSrcWhf(const utils::Whf& wfh);
|
||||
virtual utils::Whf getSrcWhf() const;
|
||||
virtual void setSource(const utils::Whf& wfh);
|
||||
virtual void setFlags(const utils::eMdpFlags& flags);
|
||||
virtual void setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed);
|
||||
virtual bool commit();
|
||||
virtual void setRotations(uint32_t r);
|
||||
virtual void setDataReqId(int id);
|
||||
virtual bool prepareQueueBuf(uint32_t offset);
|
||||
virtual bool play(int fd);
|
||||
virtual bool queueBuffer(int fd, uint32_t offset);
|
||||
virtual void setEnable();
|
||||
virtual void setDisable();
|
||||
virtual bool enabled () const;
|
||||
virtual void setDataMemId(int fd);
|
||||
virtual void setRotDataSrcMemId(int fd);
|
||||
virtual void setSrcFB(bool);
|
||||
virtual void setSrcFB();
|
||||
virtual int getSessId() const;
|
||||
virtual int getDstMemId() const;
|
||||
virtual uint32_t getDstOffset() const;
|
||||
virtual void dump() const;
|
||||
};
|
||||
|
||||
/*
|
||||
Manages the case where new rotator memory needs to be
|
||||
allocated, before previous is freed, due to resolution change etc. If we make
|
||||
rotator memory to be always max size, irrespctive of source resolution then
|
||||
we don't need this RotMem wrapper. The inner class is sufficient.
|
||||
*/
|
||||
struct RotMem {
|
||||
// Max rotator memory allocations
|
||||
enum { MAX_ROT_MEM = 2};
|
||||
|
||||
//Manages the rotator buffer offsets.
|
||||
struct Mem {
|
||||
Mem() : mCurrOffset(0) {utils::memset0(mRotOffset); }
|
||||
bool valid() { return m.valid(); }
|
||||
bool close() { return m.close(); }
|
||||
uint32_t size() const { return m.bufSz(); }
|
||||
// Max rotator buffers
|
||||
enum { ROT_NUM_BUFS = 2 };
|
||||
// rotator data info dst offset
|
||||
uint32_t mRotOffset[ROT_NUM_BUFS];
|
||||
// current offset slot from mRotOffset
|
||||
uint32_t mCurrOffset;
|
||||
OvMem m;
|
||||
};
|
||||
|
||||
RotMem() : _curr(0) {}
|
||||
Mem& curr() { return m[_curr % MAX_ROT_MEM]; }
|
||||
const Mem& curr() const { return m[_curr % MAX_ROT_MEM]; }
|
||||
Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
|
||||
RotMem& operator++() { ++_curr; return *this; }
|
||||
bool close();
|
||||
uint32_t _curr;
|
||||
Mem m[MAX_ROT_MEM];
|
||||
};
|
||||
|
||||
/*
|
||||
* Rotator impl.
|
||||
* MDP rot holds MDP's rotation related structures.
|
||||
*
|
||||
* */
|
||||
class Rotator : public RotatorBase
|
||||
{
|
||||
class MdpRot : public IRotatorHw {
|
||||
public:
|
||||
/* construct underlying object */
|
||||
explicit Rotator();
|
||||
|
||||
/* close underlying rot */
|
||||
virtual ~Rotator();
|
||||
|
||||
/* calls underlying open */
|
||||
virtual bool open();
|
||||
|
||||
/* remap rot buffers */
|
||||
virtual bool remap(uint32_t numbufs, const utils::PipeArgs& args);
|
||||
|
||||
/* calls underlying close */
|
||||
virtual bool close();
|
||||
|
||||
/* calls underlying start */
|
||||
virtual bool start();
|
||||
|
||||
/* calls underlying start with whf and flags */
|
||||
virtual bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* non virtual - calls underlying start with whf and flags.
|
||||
* Has the ability to parameterize the dst */
|
||||
template <int ROT_OUT_FMT>
|
||||
bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* Unmap everything that is not current */
|
||||
bool unmapNonCurrent();
|
||||
|
||||
/* set info using whf and given mdp */
|
||||
virtual mdp_overlay setInfo(const utils::PipeArgs& args,
|
||||
const mdp_overlay& o);
|
||||
|
||||
/* transform function for the MDP */
|
||||
virtual bool overlayTransform(MdpCtrl& mdp,
|
||||
utils::eTransform& rot);
|
||||
|
||||
/* set src whf */
|
||||
virtual void setSrcWhf(const utils::Whf& wfh);
|
||||
|
||||
/* set Rotations */
|
||||
virtual void setRotations(uint32_t r);
|
||||
|
||||
/* set the req data id in mData */
|
||||
virtual void setDataReqId(int id);
|
||||
|
||||
/* set memory_id */
|
||||
virtual void setDataMemId(int fd);
|
||||
virtual void setRotDataSrcMemId(int fd);
|
||||
|
||||
/* Mark the src for rotator as FB. usually set by UI mirroing cases */
|
||||
virtual void setSrcFB(bool);
|
||||
|
||||
/* get dst (for offset and memory id) non-virt */
|
||||
explicit MdpRot();
|
||||
~MdpRot();
|
||||
bool init();
|
||||
bool close();
|
||||
void setSource(const utils::Whf& whf);
|
||||
virtual void setFlags(const utils::eMdpFlags& flags);
|
||||
void setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed);
|
||||
bool commit();
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
void setEnable();
|
||||
void setDisable();
|
||||
void setRotations(uint32_t r);
|
||||
void setSrcFB();
|
||||
bool enabled() const;
|
||||
int getSessId() const;
|
||||
int getDstMemId() const;
|
||||
uint32_t getDstOffset() const;
|
||||
void dump() const;
|
||||
|
||||
/* set enable/disable flag */
|
||||
virtual void setEnable();
|
||||
virtual void setDisable();
|
||||
virtual bool enabled () const;
|
||||
|
||||
/* return rotator sess id */
|
||||
virtual int getSessId() const;
|
||||
|
||||
/* return a copy of src whf*/
|
||||
virtual utils::Whf getSrcWhf() const;
|
||||
|
||||
/* prepare rot for queue buf*/
|
||||
virtual bool prepareQueueBuf(uint32_t offset);
|
||||
|
||||
/* call play on mdp*/
|
||||
virtual bool play(int fd);
|
||||
|
||||
/* dump the state of the object */
|
||||
virtual void dump() const;
|
||||
private:
|
||||
/* helper functions for overlayTransform */
|
||||
void overlayTransFlipHV(MdpCtrl& mdp,
|
||||
utils::eTransform& rot);
|
||||
void overlayTransFlipRot90(MdpCtrl& mdp,
|
||||
utils::eTransform& rot);
|
||||
void overlayTransFlipRot180(MdpCtrl& mdp);
|
||||
void overlayTransFlipRot270(MdpCtrl& mdp);
|
||||
/* remap rot buffers */
|
||||
bool remap(uint32_t numbufs);
|
||||
bool open_i(uint32_t numbufs, uint32_t bufsz);
|
||||
/* Deferred transform calculations */
|
||||
void doTransform();
|
||||
/* reset underlying data, basically memset 0 */
|
||||
void reset();
|
||||
|
||||
/* underlying rotator MDP object */
|
||||
MdpRot mRot;
|
||||
/* rot info*/
|
||||
msm_rotator_img_info mRotImgInfo;
|
||||
/* rot data */
|
||||
msm_rotator_data_info mRotDataInfo;
|
||||
/* Orientation */
|
||||
utils::eTransform mOrientation;
|
||||
/* rotator fd */
|
||||
OvFD mFd;
|
||||
/* Rotator memory manager */
|
||||
RotMem mMem;
|
||||
/* Single Rotator buffer size */
|
||||
uint32_t mBufSize;
|
||||
};
|
||||
|
||||
|
||||
//--------------inlines------------------------------------
|
||||
//// MdpRot ////
|
||||
inline MdpRot::MdpRot() { reset(); }
|
||||
inline bool MdpRot::start(const utils::PipeArgs& args) {
|
||||
return this->start<utils::ROT_OUT_FMT_DEFAULT>(args);
|
||||
|
||||
///// Rotator /////
|
||||
inline Rotator::Rotator() {
|
||||
int type = IRotatorHw::getRotatorHwType();
|
||||
if(type == IRotatorHw::TYPE_MDP) {
|
||||
mRot = new MdpRot(); //will do reset
|
||||
} else if(type == IRotatorHw::TYPE_MDSS) {
|
||||
//TODO create mdss specific rotator
|
||||
} else {
|
||||
ALOGE("%s Unknown h/w type %d", __FUNCTION__, type);
|
||||
}
|
||||
}
|
||||
inline Rotator::~Rotator() {
|
||||
delete mRot; //will do close
|
||||
}
|
||||
inline bool Rotator::init() {
|
||||
if(!mRot->init()) {
|
||||
ALOGE("Rotator::init failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool Rotator::close() {
|
||||
return mRot->close();
|
||||
}
|
||||
inline void Rotator::setSource(const utils::Whf& whf) {
|
||||
mRot->setSource(whf);
|
||||
}
|
||||
inline void Rotator::setFlags(const utils::eMdpFlags& flags) {
|
||||
mRot->setFlags(flags);
|
||||
}
|
||||
inline void Rotator::setTransform(const utils::eTransform& rot,
|
||||
const bool& rotUsed)
|
||||
{
|
||||
mRot->setTransform(rot, rotUsed);
|
||||
}
|
||||
inline bool Rotator::commit() {
|
||||
return mRot->commit();
|
||||
}
|
||||
inline void Rotator::setEnable(){ mRot->setEnable(); }
|
||||
inline void Rotator::setDisable(){ mRot->setDisable(); }
|
||||
inline bool Rotator::enabled() const { return mRot->enabled(); }
|
||||
inline void Rotator::setSrcFB() { mRot->setSrcFB(); }
|
||||
inline int Rotator::getDstMemId() const {
|
||||
return mRot->getDstMemId();
|
||||
}
|
||||
inline uint32_t Rotator::getDstOffset() const {
|
||||
return mRot->getDstOffset();
|
||||
}
|
||||
inline void Rotator::setRotations(uint32_t rot) {
|
||||
mRot->setRotations (rot);
|
||||
}
|
||||
inline int Rotator::getSessId() const {
|
||||
return mRot->getSessId();
|
||||
}
|
||||
inline void Rotator::dump() const {
|
||||
ALOGE("== Dump Rotator start ==");
|
||||
mRot->dump();
|
||||
ALOGE("== Dump Rotator end ==");
|
||||
}
|
||||
inline bool Rotator::queueBuffer(int fd, uint32_t offset) {
|
||||
return mRot->queueBuffer(fd, offset);
|
||||
}
|
||||
|
||||
inline void MdpRot::setDataMemId(int fd) { mData.data.memory_id = fd; }
|
||||
inline void MdpRot::setRotDataSrcMemId(int fd) {
|
||||
mRotDataInfo.src.memory_id = fd; }
|
||||
|
||||
///// Null Rotator /////
|
||||
inline NullRotator::~NullRotator() {}
|
||||
inline bool NullRotator::init() { return true; }
|
||||
inline bool NullRotator::close() { return true; }
|
||||
inline bool NullRotator::commit() { return true; }
|
||||
inline void NullRotator::setSource(const utils::Whf& wfh) {}
|
||||
inline void NullRotator::setFlags(const utils::eMdpFlags& flags) {}
|
||||
inline void NullRotator::setTransform(const utils::eTransform& rot, const bool&)
|
||||
{}
|
||||
inline void NullRotator::setRotations(uint32_t) {}
|
||||
inline void NullRotator::setEnable() {}
|
||||
inline void NullRotator::setDisable() {}
|
||||
inline bool NullRotator::enabled() const { return false; }
|
||||
inline int NullRotator::getSessId() const { return -1; }
|
||||
inline bool NullRotator::queueBuffer(int fd, uint32_t offset) { return true; }
|
||||
inline void NullRotator::setSrcFB() {}
|
||||
inline int NullRotator::getDstMemId() const { return -1; }
|
||||
inline uint32_t NullRotator::getDstOffset() const { return 0;}
|
||||
inline void NullRotator::dump() const {
|
||||
ALOGE("== Dump NullRotator dump (null) start/end ==");
|
||||
}
|
||||
|
||||
|
||||
//// MdpRot ////
|
||||
inline MdpRot::MdpRot() { reset(); }
|
||||
inline MdpRot::~MdpRot() { close(); }
|
||||
inline void MdpRot::setEnable() { mRotImgInfo.enable = 1; }
|
||||
inline void MdpRot::setDisable() { mRotImgInfo.enable = 0; }
|
||||
inline bool MdpRot::enabled() const { return mRotImgInfo.enable; }
|
||||
|
||||
inline void MdpRot::setRotations(uint32_t r) { mRotImgInfo.rotations = r; }
|
||||
inline void MdpRot::setDataReqId(int id) { mData.id = id; }
|
||||
inline void MdpRot::swapDstWH() {
|
||||
overlay::utils::swap(mRotImgInfo.dst.width,
|
||||
mRotImgInfo.dst.height); }
|
||||
|
||||
inline overlay::utils::Whf MdpRot::getSrcWhf() const {
|
||||
return overlay::utils::Whf(mRotImgInfo.src.width,
|
||||
mRotImgInfo.src.height,
|
||||
mRotImgInfo.src.format);
|
||||
}
|
||||
|
||||
inline int MdpRot::getDstMemId() const {
|
||||
return mRotDataInfo.dst.memory_id;
|
||||
}
|
||||
inline uint32_t MdpRot::getDstOffset() const {
|
||||
return mRotDataInfo.dst.offset;
|
||||
}
|
||||
|
||||
inline void MdpRot::setSrcWhf(const overlay::utils::Whf& whf) {
|
||||
mRotImgInfo.src.width = whf.w;
|
||||
mRotImgInfo.src.height = whf.h;
|
||||
mRotImgInfo.src.format = whf.format;
|
||||
}
|
||||
|
||||
inline int MdpRot::getSessId() const { return mRotImgInfo.session_id; }
|
||||
|
||||
inline void MdpRot::setSrcFB(bool mark) { isSrcFB = mark; }
|
||||
|
||||
///// Null Rotator /////
|
||||
inline NullRotator::~NullRotator() {}
|
||||
inline bool NullRotator::open() {
|
||||
return true; }
|
||||
inline bool NullRotator::remap(uint32_t numbufs,
|
||||
const utils::PipeArgs& args){
|
||||
return true; }
|
||||
inline bool NullRotator::close() { return true; }
|
||||
inline bool NullRotator::start(const utils::PipeArgs& args)
|
||||
{ return true; }
|
||||
|
||||
inline bool NullRotator::start() { return true; }
|
||||
inline bool NullRotator::overlayTransform(MdpCtrl& o,
|
||||
utils::eTransform& rot)
|
||||
{ return true; }
|
||||
inline void NullRotator::setSrcWhf(const overlay::utils::Whf& wfh) {}
|
||||
inline void NullRotator::setRotations(uint32_t) {}
|
||||
inline void NullRotator::setDataReqId(int id) {}
|
||||
inline void NullRotator::setEnable() {}
|
||||
inline void NullRotator::setDisable() {}
|
||||
inline bool NullRotator::enabled() const { return false; }
|
||||
inline int NullRotator::getSessId() const { return -1; }
|
||||
inline overlay::utils::Whf NullRotator::getSrcWhf() const {
|
||||
return overlay::utils::Whf(); }
|
||||
inline bool NullRotator::prepareQueueBuf(uint32_t offset)
|
||||
{ return true; }
|
||||
inline bool NullRotator::play(int fd)
|
||||
{ return true; }
|
||||
inline void NullRotator::setDataMemId(int fd) {}
|
||||
inline void NullRotator::setRotDataSrcMemId(int fd) {}
|
||||
inline void NullRotator::setSrcFB(bool) {}
|
||||
inline void NullRotator::dump() const {
|
||||
ALOGE("== Dump NullRotator dump (null) start/end ==");
|
||||
}
|
||||
|
||||
///// Rotator /////
|
||||
inline Rotator::Rotator() { }
|
||||
|
||||
inline Rotator::~Rotator() {
|
||||
mRot.close(); // also will do reset
|
||||
}
|
||||
|
||||
inline bool Rotator::open() {
|
||||
if(!mRot.open()) {
|
||||
ALOGE("Rotator::open failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int ROT_OUT_FMT>
|
||||
inline bool Rotator::start(const utils::PipeArgs& args) {
|
||||
return mRot.start<ROT_OUT_FMT>(args);
|
||||
}
|
||||
|
||||
inline bool Rotator::remap(uint32_t numbufs,
|
||||
const utils::PipeArgs& args){
|
||||
if(!mRot.remap(numbufs, args)) {
|
||||
ALOGE("%s failed", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool Rotator::close() {
|
||||
return mRot.close();
|
||||
}
|
||||
|
||||
inline bool Rotator::start() {
|
||||
return mRot.start();
|
||||
}
|
||||
|
||||
inline bool Rotator::start(const utils::PipeArgs& args) {
|
||||
return mRot.start(args);
|
||||
}
|
||||
|
||||
inline bool Rotator::unmapNonCurrent() {
|
||||
return mRot.unmapNonCurrent();
|
||||
}
|
||||
|
||||
inline void Rotator::setEnable(){ mRot.setEnable(); }
|
||||
inline void Rotator::setDisable(){ mRot.setDisable(); }
|
||||
inline bool Rotator::enabled() const { return mRot.enabled(); }
|
||||
inline void Rotator::setDataMemId(int fd) {
|
||||
mRot.setDataMemId(fd); }
|
||||
|
||||
inline void Rotator::setRotDataSrcMemId(int fd) {
|
||||
mRot.setRotDataSrcMemId(fd);
|
||||
}
|
||||
|
||||
inline void Rotator::setSrcFB(bool mark) { mRot.setSrcFB(mark); }
|
||||
|
||||
inline int Rotator::getDstMemId() const {
|
||||
return mRot.getDstMemId();
|
||||
}
|
||||
inline uint32_t Rotator::getDstOffset() const {
|
||||
return mRot.getDstOffset();
|
||||
}
|
||||
|
||||
inline void Rotator::setDataReqId(int id) {
|
||||
mRot.setDataReqId(id);
|
||||
}
|
||||
|
||||
inline void Rotator::setSrcWhf(
|
||||
const overlay::utils::Whf& whf) {
|
||||
mRot.setSrcWhf(whf);
|
||||
}
|
||||
|
||||
inline void Rotator::setRotations(uint32_t rot) {
|
||||
mRot.setRotations (rot);
|
||||
}
|
||||
|
||||
inline int Rotator::getSessId() const {
|
||||
return mRot.getSessId(); }
|
||||
|
||||
inline void Rotator::dump() const {
|
||||
ALOGE("== Dump Rotator start ==");
|
||||
mRot.dump();
|
||||
ALOGE("== Dump Rotator end ==");
|
||||
}
|
||||
|
||||
inline overlay::utils::Whf Rotator::getSrcWhf() const {
|
||||
return mRot.getSrcWhf(); }
|
||||
|
||||
inline bool Rotator::prepareQueueBuf(uint32_t offset)
|
||||
{
|
||||
return mRot.prepareQueueBuf(offset);
|
||||
}
|
||||
|
||||
inline bool Rotator::play(int fd)
|
||||
{
|
||||
return mRot.play(fd);
|
||||
}
|
||||
|
||||
template <int ROT_OUT_FMT>
|
||||
bool MdpRot::start(const utils::PipeArgs& args) {
|
||||
// Do nothing when no orientation
|
||||
if(utils::OVERLAY_TRANSFORM_0 == args.orientation &&
|
||||
utils::ROT_FLAG_ENABLED != args.rotFlags) {
|
||||
return true;
|
||||
}
|
||||
utils::Whf whf(args.whf);
|
||||
mRotImgInfo.src.format = whf.format;
|
||||
mRotImgInfo.src.width = whf.w;
|
||||
mRotImgInfo.src.height = whf.h;
|
||||
mRotImgInfo.src_rect.w = whf.w;
|
||||
mRotImgInfo.src_rect.h = whf.h;
|
||||
mRotImgInfo.dst.width = whf.w;
|
||||
mRotImgInfo.dst.height = whf.h;
|
||||
if(whf.format == MDP_Y_CRCB_H2V2_TILE ||
|
||||
whf.format == MDP_Y_CBCR_H2V2_TILE) {
|
||||
mRotImgInfo.src.width = utils::alignup(whf.w, 64);
|
||||
mRotImgInfo.src.height = utils::alignup(whf.h, 32);
|
||||
mRotImgInfo.src_rect.w = utils::alignup(whf.w, 64);
|
||||
mRotImgInfo.src_rect.h = utils::alignup(whf.h, 32);
|
||||
mRotImgInfo.dst.width = utils::alignup(whf.w, 64);
|
||||
mRotImgInfo.dst.height = utils::alignup(whf.h, 32);
|
||||
mRotImgInfo.dst.format = MDP_Y_CRCB_H2V2;
|
||||
}
|
||||
// either utils::getRotOutFmt(whf.format); or supplied fmt
|
||||
// utils::RotOutFmt<ROT_OUT_FMT_DEFAULT>::fmt;
|
||||
mRotImgInfo.dst.format = utils::RotOutFmt<ROT_OUT_FMT>::fmt(whf.format);
|
||||
mRotImgInfo.dst_x = 0;
|
||||
mRotImgInfo.dst_y = 0;
|
||||
mRotImgInfo.src_rect.x = 0;
|
||||
mRotImgInfo.src_rect.y = 0;
|
||||
mRotImgInfo.rotations = 0;
|
||||
// ROT_FLAG_DISABLED / ENABLED
|
||||
// Refer to overlayUtils.h eRotFlags
|
||||
// for more info
|
||||
mRotImgInfo.enable = args.rotFlags;
|
||||
mRotImgInfo.session_id = mRotImgInfo.session_id ?
|
||||
mRotImgInfo.session_id : 0;
|
||||
|
||||
return start();
|
||||
inline void MdpRot::setSrcFB() {
|
||||
mRotDataInfo.src.flags |= MDP_MEMORY_ID_TYPE_FB;
|
||||
}
|
||||
|
||||
} // overlay
|
||||
|
||||
namespace {
|
||||
// just a helper func for Rotator common operations x-(y+z)
|
||||
int compute(uint32_t x, uint32_t y, uint32_t z) {
|
||||
return x-(y+z);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // OVERLAY_ROTATOR_H
|
||||
#endif // OVERlAY_ROTATOR_H
|
||||
|
@ -34,22 +34,16 @@
|
||||
#include "overlayImpl.h"
|
||||
#include "overlayRotator.h"
|
||||
#include "pipes/overlayGenPipe.h"
|
||||
#include "pipes/overlayBypassPipe.h"
|
||||
#include "pipes/overlayHdmiPipe.h"
|
||||
#include "pipes/overlayVideoExtPipe.h"
|
||||
#include "pipes/overlayUIMirrorPipe.h"
|
||||
#include "pipes/overlay3DPipe.h"
|
||||
|
||||
// FIXME make int to be uint32 whenever possible
|
||||
|
||||
namespace overlay {
|
||||
|
||||
/*
|
||||
* Used by Overlay class. Invokes each event
|
||||
* */
|
||||
|
||||
/* TODO case of RGBx will call mOv open with diff
|
||||
* params customized for RGBx pipes */
|
||||
|
||||
class OverlayState : utils::NoCopy {
|
||||
public:
|
||||
/**/
|
||||
@ -153,11 +147,11 @@ template <> struct StateTraits<utils::OV_2D_VIDEO_ON_PANEL>
|
||||
template <> struct StateTraits<utils::OV_2D_VIDEO_ON_PANEL_TV>
|
||||
{
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
|
||||
typedef overlay::HdmiPipe pipe1;
|
||||
typedef overlay::VideoExtPipe pipe1;
|
||||
typedef overlay::NullPipe pipe2; // place holder
|
||||
|
||||
typedef Rotator rot0;
|
||||
typedef NullRotator rot1;
|
||||
typedef Rotator rot1;
|
||||
typedef NullRotator rot2;
|
||||
|
||||
typedef overlay::OverlayImpl<pipe0, pipe1> ovimpl;
|
||||
@ -231,11 +225,11 @@ template <> struct StateTraits<utils::OV_UI_MIRROR>
|
||||
template <> struct StateTraits<utils::OV_2D_TRUE_UI_MIRROR>
|
||||
{
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
|
||||
typedef overlay::HdmiPipe pipe1;
|
||||
typedef overlay::VideoExtPipe pipe1;
|
||||
typedef overlay::UIMirrorPipe pipe2;
|
||||
|
||||
typedef Rotator rot0;
|
||||
typedef NullRotator rot1;
|
||||
typedef Rotator rot1;
|
||||
typedef Rotator rot2;
|
||||
|
||||
typedef overlay::OverlayImpl<pipe0, pipe1, pipe2> ovimpl;
|
||||
@ -243,7 +237,7 @@ template <> struct StateTraits<utils::OV_2D_TRUE_UI_MIRROR>
|
||||
|
||||
template <> struct StateTraits<utils::OV_BYPASS_1_LAYER>
|
||||
{
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::WAIT, utils::ZORDER_0> pipe0;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
|
||||
typedef overlay::NullPipe pipe1; // place holder
|
||||
typedef overlay::NullPipe pipe2; // place holder
|
||||
|
||||
@ -256,8 +250,8 @@ template <> struct StateTraits<utils::OV_BYPASS_1_LAYER>
|
||||
|
||||
template <> struct StateTraits<utils::OV_BYPASS_2_LAYER>
|
||||
{
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::NO_WAIT, utils::ZORDER_0> pipe0;
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_OFF, utils::WAIT, utils::ZORDER_1> pipe1;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe1;
|
||||
typedef overlay::NullPipe pipe2; // place holder
|
||||
|
||||
typedef NullRotator rot0;
|
||||
@ -269,9 +263,9 @@ template <> struct StateTraits<utils::OV_BYPASS_2_LAYER>
|
||||
|
||||
template <> struct StateTraits<utils::OV_BYPASS_3_LAYER>
|
||||
{
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_SET, utils::NO_WAIT, utils::ZORDER_0> pipe0;
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_VG, utils::IS_FG_OFF, utils::NO_WAIT, utils::ZORDER_1> pipe1;
|
||||
typedef overlay::BypassPipe<utils::OV_MDP_PIPE_RGB, utils::IS_FG_OFF, utils::WAIT, utils::ZORDER_2> pipe2;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe0;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe1;
|
||||
typedef overlay::GenericPipe<utils::PRIMARY> pipe2;
|
||||
|
||||
typedef NullRotator rot0;
|
||||
typedef NullRotator rot1;
|
||||
@ -310,8 +304,8 @@ inline OverlayImplBase* handle_closed_to_xxx()
|
||||
RotatorBase* rot0 = new typename StateTraits<STATE>::rot0;
|
||||
RotatorBase* rot1 = new typename StateTraits<STATE>::rot1;
|
||||
RotatorBase* rot2 = new typename StateTraits<STATE>::rot2;
|
||||
if(!ov->open(rot0, rot1, rot2)) {
|
||||
ALOGE("Overlay failed to open in state %d", STATE);
|
||||
if(!ov->init(rot0, rot1, rot2)) {
|
||||
ALOGE("Overlay failed to init in state %d", STATE);
|
||||
return 0;
|
||||
}
|
||||
return ov;
|
||||
@ -329,7 +323,7 @@ inline OverlayImplBase* handle_xxx_to_closed(OverlayImplBase* ov)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Hard transitions from any state to any state will close and then open */
|
||||
/* Hard transitions from any state to any state will close and then init */
|
||||
template <int STATE>
|
||||
inline OverlayImplBase* handle_xxx_to_xxx(OverlayImplBase* ov)
|
||||
{
|
||||
@ -392,6 +386,7 @@ inline OverlayImplBase* OverlayState::handleEvent(utils::eOverlayState newState,
|
||||
|
||||
// FIXME, how to communicate bad transition?
|
||||
// Should we have bool returned from transition func?
|
||||
// This is also a very good interview question.
|
||||
|
||||
return newov;
|
||||
}
|
||||
|
@ -42,12 +42,12 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel(
|
||||
|
||||
// Create new ovimpl based on new state
|
||||
typedef StateTraits<utils::OV_2D_VIDEO_ON_PANEL> NewState;
|
||||
OverlayImplBase* newov = new NewState::ovimpl;
|
||||
OverlayImplBase* newov = new NewState::ovimpl();
|
||||
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (GenericPipe)
|
||||
@ -55,10 +55,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__);
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (NullPipe)
|
||||
@ -66,10 +66,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__);
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -77,10 +77,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DPanel(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -106,7 +106,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV(
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (GenericPipe)
|
||||
@ -114,21 +114,21 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (HdmiPipe)
|
||||
if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__);
|
||||
// pipe1/rot1 (VideoExtPipe)
|
||||
if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -136,10 +136,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_2DTV(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -162,21 +162,22 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel(
|
||||
typedef StateTraits<utils::OV_3D_VIDEO_ON_2D_PANEL> NewState;
|
||||
OverlayImplBase* newov = new NewState::ovimpl;
|
||||
|
||||
//===========================================================
|
||||
//=================================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
// - If pipe matches, copy from previous into new ovimpl.
|
||||
// (which also makes previous pipe ref 0, so nobody can use)
|
||||
// - Otherwise init pipe for new ovimpl and delete from previous
|
||||
//=================================================================
|
||||
|
||||
// pipe0/rot0 (M3DPrimaryPipe)
|
||||
if (ov->getOvPipeType(utils::OV_PIPE0) == utils::OV_PIPE_TYPE_M3D_PRIMARY) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (NullPipe)
|
||||
@ -184,10 +185,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -195,10 +196,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DPanel(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -224,7 +225,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV(
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (M3DPrimaryPipe)
|
||||
@ -232,10 +233,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (M3DPrimaryPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (M3DExtPipe)
|
||||
@ -243,10 +244,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (M3DExtPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (M3DExtPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (M3DExtPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -254,10 +255,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_3D_2DTV(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -283,7 +284,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror(
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (GenericPipe)
|
||||
@ -291,21 +292,21 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (GenericPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (GenericPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (GenericPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (HdmiPipe)
|
||||
if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_HDMI) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (HdmiPipe)", __FUNCTION__);
|
||||
// pipe1/rot1 (VideoExtPipe)
|
||||
if (ov->getOvPipeType(utils::OV_PIPE1) == utils::OV_PIPE_TYPE_VIDEO_EXT) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (VideoExtPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (HdmiPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (VideoExtPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (UIMirrorPipe)
|
||||
@ -313,10 +314,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_2D_trueUI_Mirror(
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (UIMirrorPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (UIMirrorPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (UIMirrorPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -341,7 +342,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov)
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (BypassPipe)
|
||||
@ -349,10 +350,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (NullPipe)
|
||||
@ -360,10 +361,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -371,10 +372,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass1(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -399,7 +400,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov)
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (BypassPipe)
|
||||
@ -407,10 +408,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (BypassPipe)
|
||||
@ -418,10 +419,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (NullPipe)
|
||||
@ -429,10 +430,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass2(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (NullPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (NullPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (NullPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
@ -457,7 +458,7 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov)
|
||||
//===========================================================
|
||||
// For each pipe:
|
||||
// - If pipe matches, copy from previous into new ovimpl
|
||||
// - Otherwise open for new and delete from previous ovimpl
|
||||
// - Otherwise init for new and delete from previous ovimpl
|
||||
//===========================================================
|
||||
|
||||
// pipe0/rot0 (BypassPipe)
|
||||
@ -465,10 +466,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe0 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE0);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe0 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe0 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot0 = new NewState::rot0;
|
||||
ov->closePipe(utils::OV_PIPE0);
|
||||
newov->openPipe(rot0, utils::OV_PIPE0);
|
||||
newov->initPipe(rot0, utils::OV_PIPE0);
|
||||
}
|
||||
|
||||
// pipe1/rot1 (BypassPipe)
|
||||
@ -476,10 +477,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe1 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE1);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe1 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe1 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot1 = new NewState::rot1;
|
||||
ov->closePipe(utils::OV_PIPE1);
|
||||
newov->openPipe(rot1, utils::OV_PIPE1);
|
||||
newov->initPipe(rot1, utils::OV_PIPE1);
|
||||
}
|
||||
|
||||
// pipe2/rot2 (BypassPipe)
|
||||
@ -487,10 +488,10 @@ OverlayImplBase* OverlayState::handle_xxx_to_bypass3(OverlayImplBase* ov)
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Copy pipe2 (BypassPipe)", __FUNCTION__);
|
||||
newov->copyOvPipe(ov, utils::OV_PIPE2);
|
||||
} else {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: Open pipe2 (BypassPipe)", __FUNCTION__);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: init pipe2 (BypassPipe)", __FUNCTION__);
|
||||
RotatorBase* rot2 = new NewState::rot2;
|
||||
ov->closePipe(utils::OV_PIPE2);
|
||||
newov->openPipe(rot2, utils::OV_PIPE2);
|
||||
newov->initPipe(rot2, utils::OV_PIPE2);
|
||||
}
|
||||
|
||||
// All pipes are copied or deleted so no more need for previous ovimpl
|
||||
|
@ -70,7 +70,7 @@ struct IOFile {
|
||||
namespace overlay {
|
||||
|
||||
//----------From class Res ------------------------------
|
||||
const char* const Res::devTemplate = "/dev/graphics/fb%u";
|
||||
const char* const Res::fbPath = "/dev/graphics/fb%u";
|
||||
const char* const Res::rotPath = "/dev/msm_rotator";
|
||||
const char* const Res::format3DFile =
|
||||
"/sys/class/graphics/fb1/format_3d";
|
||||
@ -92,7 +92,7 @@ FrameBufferInfo::FrameBufferInfo() {
|
||||
OvFD mFd;
|
||||
|
||||
// Use open defined in overlayFD file to open fd for fb0
|
||||
if(!overlay::open(mFd, 0, Res::devTemplate)) {
|
||||
if(!overlay::open(mFd, 0, Res::fbPath)) {
|
||||
ALOGE("FrameBufferInfo: failed to open fd");
|
||||
return;
|
||||
}
|
||||
@ -142,45 +142,13 @@ int FrameBufferInfo::getHeight() const {
|
||||
}
|
||||
|
||||
bool FrameBufferInfo::supportTrueMirroring() const {
|
||||
return mBorderFillSupported;
|
||||
char value[PROPERTY_VALUE_MAX] = {0};
|
||||
property_get("hw.trueMirrorSupported", value, "0");
|
||||
int trueMirroringSupported = atoi(value);
|
||||
return (trueMirroringSupported && mBorderFillSupported);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------
|
||||
uint32_t getSize(const Whf& whf) {
|
||||
int aligned_height=0, pitch=0;
|
||||
|
||||
uint32_t size = whf.w * whf.h;
|
||||
switch (whf.format) {
|
||||
case MDP_RGBA_8888:
|
||||
case MDP_BGRA_8888:
|
||||
case MDP_RGBX_8888:
|
||||
size *= 4;
|
||||
break;
|
||||
case MDP_RGB_565:
|
||||
case MDP_Y_CBCR_H2V1:
|
||||
size *= 2;
|
||||
break;
|
||||
case MDP_Y_CBCR_H2V2:
|
||||
case MDP_Y_CRCB_H2V2:
|
||||
size = (size * 3) / 2;
|
||||
break;
|
||||
case MDP_Y_CRCB_H2V2_TILE:
|
||||
case MDP_Y_CBCR_H2V2_TILE:
|
||||
aligned_height = align(whf.h , 32);
|
||||
pitch = align(whf.w, 128);
|
||||
size = pitch * aligned_height;
|
||||
size = align(size, 8192);
|
||||
|
||||
aligned_height = align(whf.h >> 1, 32);
|
||||
size += pitch * aligned_height;
|
||||
size = align(size, 8192);
|
||||
break;
|
||||
default:
|
||||
ALOGE("getSize unknown format %d", whf.format);
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
int getMdpFormat(int format) {
|
||||
switch (format) {
|
||||
@ -205,18 +173,25 @@ int getMdpFormat(int format) {
|
||||
case HAL_PIXEL_FORMAT_YV12:
|
||||
return MDP_Y_CR_CB_H2V2;
|
||||
default:
|
||||
ALOGE("Error getMdpFormat format=%d", format);
|
||||
ALOGE("Error getMdpFormat format=0x%x", format);
|
||||
return -1;
|
||||
}
|
||||
// not reached
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool isHDMIConnected () {
|
||||
char value[PROPERTY_VALUE_MAX] = {0};
|
||||
property_get("hw.hdmiON", value, "0");
|
||||
int isHDMI = atoi(value);
|
||||
return isHDMI ? true : false;
|
||||
//Set by client as HDMI/WFD
|
||||
void setExtType(const int& type) {
|
||||
if(type != HDMI && type != WFD) {
|
||||
ALOGE("%s: Unrecognized type %d", __func__, type);
|
||||
return;
|
||||
}
|
||||
sExtType = type;
|
||||
}
|
||||
|
||||
//Return External panel type set by client.
|
||||
int getExtType() {
|
||||
return sExtType;
|
||||
}
|
||||
|
||||
bool is3DTV() {
|
||||
@ -229,7 +204,7 @@ bool is3DTV() {
|
||||
|
||||
bool isPanel3D() {
|
||||
OvFD fd;
|
||||
if(!overlay::open(fd, 0 /*fb*/, Res::devTemplate)){
|
||||
if(!overlay::open(fd, 0 /*fb*/, Res::fbPath)){
|
||||
ALOGE("isPanel3D Can't open framebuffer 0");
|
||||
return false;
|
||||
}
|
||||
@ -299,39 +274,6 @@ uint32_t getS3DFormat(uint32_t fmt) {
|
||||
return fmt3D;
|
||||
}
|
||||
|
||||
void normalizeCrop(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);
|
||||
}
|
||||
}
|
||||
|
||||
void scale(mdp_overlay& ov)
|
||||
{
|
||||
/* Scaling of upto a max of 8 times supported */
|
||||
overlay::utils::Dim dst(overlay::utils::getDstRectDim(ov));
|
||||
overlay::utils::Dim src(overlay::utils::getSrcRectDim(ov));
|
||||
if(dst.w >(src.w * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) {
|
||||
dst.w = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.w;
|
||||
}
|
||||
if(dst.h >(src.h * overlay::utils::HW_OV_MAGNIFICATION_LIMIT)) {
|
||||
dst.h = overlay::utils::HW_OV_MAGNIFICATION_LIMIT * src.h;
|
||||
}
|
||||
|
||||
setDstRectDim(dst, ov);
|
||||
}
|
||||
|
||||
} // utils
|
||||
|
||||
} // overlay
|
||||
|
@ -35,14 +35,14 @@
|
||||
#include <fcntl.h> // open, O_RDWR, etc
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/gralloc.h> // buffer_handle_t
|
||||
#include <linux/msm_mdp.h> // MDP_OV_PLAY_NOWAIT etc ...
|
||||
#include <linux/msm_mdp.h> // flags
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include "gralloc_priv.h" //for interlace
|
||||
/*
|
||||
*
|
||||
* Collection of utilities functions/structs/enums etc...
|
||||
@ -70,12 +70,6 @@ class Overlay;
|
||||
namespace utils {
|
||||
struct Whf;
|
||||
struct Dim;
|
||||
template <class T>
|
||||
inline void even_out(T& x) { if (x & 0x0001) --x; }
|
||||
|
||||
inline uint32_t getBit(uint32_t x, uint32_t mask) {
|
||||
return (x & mask);
|
||||
}
|
||||
|
||||
inline uint32_t setBit(uint32_t x, uint32_t mask) {
|
||||
return (x | mask);
|
||||
@ -89,7 +83,7 @@ inline uint32_t clrBit(uint32_t x, uint32_t mask) {
|
||||
* and assignment operator private
|
||||
*
|
||||
* Usage:
|
||||
* * class SomeClass : utils::NoCopy {...};
|
||||
* class SomeClass : utils::NoCopy {...};
|
||||
*/
|
||||
class NoCopy {
|
||||
protected:
|
||||
@ -147,7 +141,14 @@ enum { BARRIER_LAND = 1,
|
||||
BARRIER_PORT = 2 };
|
||||
|
||||
inline uint32_t format3D(uint32_t x) { return x & 0xFF000; }
|
||||
inline uint32_t colorFormat(uint32_t x) { return x & 0xFFF; }
|
||||
inline uint32_t colorFormat(uint32_t fmt) {
|
||||
/*TODO enable this block only if format has interlace / 3D info in top bits.
|
||||
if(fmt & INTERLACE_MASK) {
|
||||
fmt = fmt ^ HAL_PIXEL_FORMAT_INTERLACE;
|
||||
}
|
||||
fmt = fmt & 0xFFF;*/
|
||||
return fmt;
|
||||
}
|
||||
inline uint32_t format3DOutput(uint32_t x) {
|
||||
return (x & 0xF000) >> SHIFT_OUT_3D; }
|
||||
inline uint32_t format3DInput(uint32_t x) { return x & 0xF0000; }
|
||||
@ -160,12 +161,15 @@ bool usePanel3D();
|
||||
bool send3DInfoPacket (uint32_t fmt);
|
||||
bool enableBarrier (uint32_t orientation);
|
||||
uint32_t getS3DFormat(uint32_t fmt);
|
||||
|
||||
template <int CHAN>
|
||||
bool getPositionS3D(const Whf& whf, Dim& out);
|
||||
bool getPositionS3D(const Whf& whf, Dim& out);
|
||||
|
||||
template <int CHAN>
|
||||
bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt);
|
||||
bool getCropS3D(const Dim& in, Dim& out, uint32_t fmt);
|
||||
|
||||
template <class Type>
|
||||
void swapWidthHeight(Type& width, Type& height);
|
||||
void swapWidthHeight(Type& width, Type& height);
|
||||
|
||||
struct Dim {
|
||||
Dim () : x(0), y(0),
|
||||
@ -193,13 +197,6 @@ struct Dim {
|
||||
return !operator==(d);
|
||||
}
|
||||
|
||||
void even_out() {
|
||||
utils::even_out(x);
|
||||
utils::even_out(y);
|
||||
utils::even_out(w);
|
||||
utils::even_out(h);
|
||||
}
|
||||
|
||||
void dump() const;
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
@ -227,26 +224,12 @@ struct Whf {
|
||||
void dump() const;
|
||||
uint32_t w;
|
||||
uint32_t h;
|
||||
// FIXME need to be int32_t ?
|
||||
uint32_t format;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
enum { MAX_PATH_LEN = 256 };
|
||||
|
||||
enum eParams {
|
||||
OVERLAY_DITHER,
|
||||
OVERLAY_TRANSFORM,
|
||||
OVERLAY_TRANSFORM_UI
|
||||
};
|
||||
|
||||
struct Params{
|
||||
Params(eParams p, int v) : param(p), value(v) {}
|
||||
eParams param;
|
||||
int value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rotator flags: not to be confused with orientation flags.
|
||||
* Ususally, you want to open the rotator to make sure it is
|
||||
@ -267,19 +250,6 @@ enum eRotFlags {
|
||||
ROT_FLAG_ENABLED = 1 // needed in rot
|
||||
};
|
||||
|
||||
/* Used for rotator open.
|
||||
* FIXME that is default, might be configs */
|
||||
enum { ROT_NUM_BUFS = 2 };
|
||||
|
||||
/* Wait/No wait for waiting for vsync
|
||||
* WAIT - wait for vsync, ignore fb (no need to compose w/ fb)
|
||||
* NO_WAIT - do not wait for vsync and return immediatly since
|
||||
* we need to run composition code */
|
||||
enum eWait {
|
||||
WAIT,
|
||||
NO_WAIT
|
||||
};
|
||||
|
||||
/* The values for is_fg flag for control alpha and transp
|
||||
* IS_FG_OFF means is_fg = 0
|
||||
* IS_FG_SET means is_fg = 1
|
||||
@ -298,15 +268,17 @@ enum eMdpFlags {
|
||||
OV_MDP_FLAGS_NONE = 0,
|
||||
OV_MDP_PIPE_SHARE = MDP_OV_PIPE_SHARE,
|
||||
OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
|
||||
OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT,
|
||||
OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION
|
||||
OV_MDP_PLAY_NOWAIT = MDP_OV_PLAY_NOWAIT, //deprecated
|
||||
OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
|
||||
OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
|
||||
OV_MDP_MEMORY_ID_TYPE_FB = MDP_MEMORY_ID_TYPE_FB,
|
||||
};
|
||||
|
||||
enum eOverlayPipeType {
|
||||
OV_PIPE_TYPE_NULL,
|
||||
OV_PIPE_TYPE_BYPASS,
|
||||
OV_PIPE_TYPE_GENERIC,
|
||||
OV_PIPE_TYPE_HDMI,
|
||||
OV_PIPE_TYPE_VIDEO_EXT,
|
||||
OV_PIPE_TYPE_M3D_EXTERNAL,
|
||||
OV_PIPE_TYPE_M3D_PRIMARY,
|
||||
OV_PIPE_TYPE_RGB,
|
||||
@ -327,24 +299,12 @@ enum eMdpPipeType {
|
||||
OV_MDP_PIPE_VG
|
||||
};
|
||||
|
||||
/* Corresponds to pipes in eDest */
|
||||
enum eChannel {
|
||||
CHANNEL_0,
|
||||
CHANNEL_1,
|
||||
CHANNEL_2
|
||||
};
|
||||
|
||||
// Max pipes via overlay (VG0, VG1, RGB1)
|
||||
enum { MAX_PIPES = 3 };
|
||||
|
||||
/* Used to identify destination channels and
|
||||
* also 3D channels e.g. when in 3D mode with 2
|
||||
* pipes opened and it is used in get crop/pos 3D
|
||||
*
|
||||
* PLEASE NOTE : DO NOT USE eDest FOR ARRAYS
|
||||
* i.e. args[OV_PIPE1] since it is a BIT MASK
|
||||
* use CHANNELS enum instead. Each OV_PIPEX is
|
||||
* not specific to a display (primary/external).
|
||||
* */
|
||||
enum eDest {
|
||||
OV_PIPE0 = 1 << 0,
|
||||
@ -356,65 +316,51 @@ enum eDest {
|
||||
/* values for copybit_set_parameter(OVERLAY_TRANSFORM) */
|
||||
enum eTransform {
|
||||
/* No rot */
|
||||
OVERLAY_TRANSFORM_0 = 0x0,
|
||||
/* flip source image horizontally */
|
||||
OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
|
||||
/* flip source image vertically */
|
||||
OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
|
||||
/* rotate source image 90 degrees */
|
||||
OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
|
||||
OVERLAY_TRANSFORM_0 = 0x0,
|
||||
/* flip source image horizontally 0x1 */
|
||||
OVERLAY_TRANSFORM_FLIP_H = HAL_TRANSFORM_FLIP_H,
|
||||
/* flip source image vertically 0x2 */
|
||||
OVERLAY_TRANSFORM_FLIP_V = HAL_TRANSFORM_FLIP_V,
|
||||
/* rotate source image 180 degrees
|
||||
* It is basically bit-or-ed H | V == 0x3 */
|
||||
OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
|
||||
OVERLAY_TRANSFORM_ROT_180 = HAL_TRANSFORM_ROT_180,
|
||||
/* rotate source image 90 degrees 0x4 */
|
||||
OVERLAY_TRANSFORM_ROT_90 = HAL_TRANSFORM_ROT_90,
|
||||
/* rotate source image 90 degrees and flip horizontally 0x5 */
|
||||
OVERLAY_TRANSFORM_ROT_90_FLIP_H = HAL_TRANSFORM_ROT_90 |
|
||||
HAL_TRANSFORM_FLIP_H,
|
||||
/* rotate source image 90 degrees and flip vertically 0x6 */
|
||||
OVERLAY_TRANSFORM_ROT_90_FLIP_V = HAL_TRANSFORM_ROT_90 |
|
||||
HAL_TRANSFORM_FLIP_V,
|
||||
/* rotate source image 270 degrees
|
||||
* Basically 180 | 90 == 0x7 */
|
||||
OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
|
||||
OVERLAY_TRANSFORM_ROT_270 = HAL_TRANSFORM_ROT_270,
|
||||
/* rotate invalid like in Transform.h */
|
||||
OVERLAY_TRANSFORM_INV = 0x80
|
||||
};
|
||||
|
||||
/* offset and fd are play info */
|
||||
struct PlayInfo {
|
||||
PlayInfo() : fd(-1), offset(0) {}
|
||||
PlayInfo(int _fd, uint32_t _offset) :
|
||||
fd(_fd), offset(_offset) {}
|
||||
bool operator==(const PlayInfo& p) {
|
||||
return (fd == p.fd && offset == p.offset);
|
||||
}
|
||||
int fd;
|
||||
uint32_t offset;
|
||||
OVERLAY_TRANSFORM_INV = 0x80
|
||||
};
|
||||
|
||||
// Used to consolidate pipe params
|
||||
struct PipeArgs {
|
||||
PipeArgs() : mdpFlags(OV_MDP_FLAGS_NONE),
|
||||
orientation(OVERLAY_TRANSFORM_0),
|
||||
wait(NO_WAIT),
|
||||
zorder(Z_SYSTEM_ALLOC),
|
||||
isFg(IS_FG_OFF),
|
||||
rotFlags(ROT_FLAG_DISABLED){
|
||||
}
|
||||
|
||||
PipeArgs(eMdpFlags f, eTransform o,
|
||||
Whf _whf, eWait w,
|
||||
PipeArgs(eMdpFlags f, Whf _whf,
|
||||
eZorder z, eIsFg fg, eRotFlags r) :
|
||||
mdpFlags(f),
|
||||
orientation(o),
|
||||
whf(_whf),
|
||||
wait(w),
|
||||
zorder(z),
|
||||
isFg(fg),
|
||||
rotFlags(r) {
|
||||
}
|
||||
|
||||
eMdpFlags mdpFlags; // for mdp_overlay flags PIPE_SHARE, NO_WAIT, etc
|
||||
eTransform orientation; // FIXME docs
|
||||
eMdpFlags mdpFlags; // for mdp_overlay flags
|
||||
Whf whf;
|
||||
eWait wait; // flags WAIT/NO_WAIT
|
||||
eZorder zorder; // stage number
|
||||
eIsFg isFg; // control alpha & transp
|
||||
eRotFlags rotFlags;
|
||||
PlayInfo play;
|
||||
};
|
||||
|
||||
enum eOverlayState{
|
||||
@ -464,21 +410,13 @@ enum {
|
||||
WFD = 2
|
||||
};
|
||||
|
||||
//TODO Make this a part of some appropriate class
|
||||
static int sExtType = HDMI; //HDMI or WFD
|
||||
|
||||
//Set by client as HDMI/WFD
|
||||
static inline void setExtType(const int& type) {
|
||||
if(type != HDMI || type != WFD) {
|
||||
ALOGE("%s: Unrecognized type %d", __func__, type);
|
||||
return;
|
||||
}
|
||||
sExtType = type;
|
||||
}
|
||||
|
||||
void setExtType(const int& type);
|
||||
//Return External panel type set by client.
|
||||
static inline int getExtType() {
|
||||
return sExtType;
|
||||
}
|
||||
int getExtType();
|
||||
|
||||
|
||||
//Gets the FB number for the external type.
|
||||
//As of now, HDMI always has fb1, WFD could use fb1 or fb2
|
||||
@ -503,6 +441,7 @@ static int getFBForPanel(int panel) { // PRIMARY OR EXTERNAL
|
||||
}
|
||||
|
||||
// number of rgb pipes bufs (max)
|
||||
|
||||
// 2 for rgb0/1 double bufs
|
||||
enum { RGB_PIPE_NUM_BUFS = 2 };
|
||||
|
||||
@ -524,52 +463,17 @@ int getRotOutFmt(uint32_t format);
|
||||
* rotation is 90, 180 etc
|
||||
* It returns MDP related enum/define that match rot+flip*/
|
||||
int getMdpOrient(eTransform rotation);
|
||||
uint32_t getSize(const Whf& whf);
|
||||
uint32_t getSizeByMdp(const Whf& whf);
|
||||
const char* getFormatString(uint32_t format);
|
||||
const char* getStateString(eOverlayState state);
|
||||
|
||||
inline int setWait(eWait wait, int flags) {
|
||||
return (wait == WAIT) ?
|
||||
flags &= ~MDP_OV_PLAY_NOWAIT :
|
||||
flags |= MDP_OV_PLAY_NOWAIT;
|
||||
}
|
||||
/* possible overlay formats libhardware/include/hardware/hardware.h */
|
||||
enum eFormat {
|
||||
OVERLAY_FORMAT_RGBA_8888 = HAL_PIXEL_FORMAT_RGBA_8888,
|
||||
OVERLAY_FORMAT_RGB_565 = HAL_PIXEL_FORMAT_RGB_565,
|
||||
OVERLAY_FORMAT_BGRA_8888 = HAL_PIXEL_FORMAT_BGRA_8888,
|
||||
OVERLAY_FORMAT_YCbYCr_422_I = 0x14,
|
||||
OVERLAY_FORMAT_CbYCrY_422_I = 0x16,
|
||||
OVERLAY_FORMAT_DEFAULT = 99 // The actual color format is
|
||||
// determined by the overlay
|
||||
};
|
||||
|
||||
// Cannot use HW_OVERLAY_MAGNIFICATION_LIMIT, since at the time
|
||||
// of integration, HW_OVERLAY_MAGNIFICATION_LIMIT was a define
|
||||
enum { HW_OV_MAGNIFICATION_LIMIT = 20,
|
||||
HW_OV_MINIFICATION_LIMIT = 8
|
||||
};
|
||||
|
||||
inline bool rotated(int orie) {
|
||||
return (orie == OVERLAY_TRANSFORM_ROT_90 ||
|
||||
orie == OVERLAY_TRANSFORM_ROT_270);
|
||||
}
|
||||
|
||||
/* used by crop funcs in order to
|
||||
* normalizes the crop values to be all even */
|
||||
void normalizeCrop(uint32_t& xy, uint32_t& wh);
|
||||
|
||||
template <class T>
|
||||
inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); }
|
||||
|
||||
template <class ROT, class MDP>
|
||||
inline void swapOVRotWidthHeight(ROT& rot, MDP& mdp)
|
||||
{
|
||||
mdp.swapSrcWH();
|
||||
mdp.swapSrcRectWH();
|
||||
rot.swapDstWH();
|
||||
}
|
||||
inline void memset0(T& t) { ::memset(&t, 0, sizeof(T)); }
|
||||
|
||||
template <class T> inline void swap ( T& a, T& b )
|
||||
{
|
||||
@ -587,35 +491,6 @@ inline int align(int value, int a) {
|
||||
return a ? ((value + (a-1)) & ~(a-1)) : value;
|
||||
}
|
||||
|
||||
|
||||
template <class MDP>
|
||||
inline utils::Dim getSrcRectDim(const MDP& ov) {
|
||||
return utils::Dim(ov.src_rect.x,
|
||||
ov.src_rect.y,
|
||||
ov.src_rect.w,
|
||||
ov.src_rect.h);
|
||||
}
|
||||
|
||||
template <class MDP>
|
||||
inline utils::Whf getSrcWhf(const MDP& ov) {
|
||||
return utils::Whf(ov.src.width,
|
||||
ov.src.height,
|
||||
ov.src.format);
|
||||
}
|
||||
template <class MDP>
|
||||
inline void setSrcRectDim(MDP& ov, const utils::Dim& d) {
|
||||
ov.src_rect.x = d.x;
|
||||
ov.src_rect.y = d.y;
|
||||
ov.src_rect.w = d.w;
|
||||
ov.src_rect.h = d.h;
|
||||
}
|
||||
template <class MDP>
|
||||
inline void setSrcWhf(MDP& ov, const utils::Whf& whf) {
|
||||
ov.src.width = whf.w;
|
||||
ov.src.height = whf.h;
|
||||
ov.src.format = whf.format;
|
||||
}
|
||||
|
||||
enum eRotOutFmt {
|
||||
ROT_OUT_FMT_DEFAULT,
|
||||
ROT_OUT_FMT_Y_CRCB_H2V2
|
||||
@ -691,21 +566,30 @@ inline const char* getFormatString(uint32_t format){
|
||||
"MDP_RGB_565",
|
||||
"MDP_XRGB_8888",
|
||||
"MDP_Y_CBCR_H2V2",
|
||||
"MDP_Y_CBCR_H2V2_ADRENO",
|
||||
"MDP_ARGB_8888",
|
||||
"MDP_RGB_888",
|
||||
"MDP_Y_CRCB_H2V2",
|
||||
"MDP_YCRYCB_H2V1",
|
||||
"MDP_Y_CRCB_H2V1",
|
||||
"MDP_Y_CBCR_H2V1",
|
||||
"MDP_Y_CRCB_H1V2",
|
||||
"MDP_Y_CBCR_H1V2",
|
||||
"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_IMGTYPE_LIMIT",
|
||||
"MDP_Y_CRCB_H1V1",
|
||||
"MDP_Y_CBCR_H1V1",
|
||||
"MDP_YCRCB_H1V1",
|
||||
"MDP_YCBCR_H1V1",
|
||||
"MDP_BGR_565",
|
||||
"MDP_IMGTYPE_LIMIT",
|
||||
"MDP_RGB_BORDERFILL",
|
||||
"MDP_FB_FORMAT",
|
||||
"MDP_IMGTYPE_LIMIT2"
|
||||
};
|
||||
@ -746,15 +630,6 @@ inline const char* getStateString(eOverlayState state){
|
||||
return "BAD_STATE";
|
||||
}
|
||||
|
||||
inline uint32_t getSizeByMdp(const Whf& whf) {
|
||||
Whf _whf(whf);
|
||||
int fmt = getMdpFormat(whf.format);
|
||||
OVASSERT(-1 != fmt, "getSizeByMdp error in format %d",
|
||||
whf.format);
|
||||
_whf.format = fmt;
|
||||
return getSize(_whf);
|
||||
}
|
||||
|
||||
inline void Whf::dump() const {
|
||||
ALOGE("== Dump WHF w=%d h=%d f=%d s=%d start/end ==",
|
||||
w, h, format, size);
|
||||
@ -766,21 +641,21 @@ inline void Dim::dump() const {
|
||||
|
||||
inline int getMdpOrient(eTransform rotation) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "%s: rot=%d", __FUNCTION__, rotation);
|
||||
switch(int(rotation))
|
||||
switch(rotation)
|
||||
{
|
||||
case OVERLAY_TRANSFORM_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;
|
||||
case OVERLAY_TRANSFORM_FLIP_V: return MDP_FLIP_UD;
|
||||
case OVERLAY_TRANSFORM_FLIP_H: return MDP_FLIP_LR;
|
||||
case OVERLAY_TRANSFORM_ROT_90: return MDP_ROT_90;
|
||||
case OVERLAY_TRANSFORM_ROT_90_FLIP_V:
|
||||
return MDP_ROT_90 | MDP_FLIP_UD;
|
||||
case OVERLAY_TRANSFORM_ROT_90_FLIP_H:
|
||||
return MDP_ROT_90 | MDP_FLIP_LR;
|
||||
case OVERLAY_TRANSFORM_ROT_180: return MDP_ROT_180;
|
||||
case OVERLAY_TRANSFORM_ROT_270: return MDP_ROT_270;
|
||||
default:
|
||||
ALOGE("%s: invalid rotation value (value = 0x%x",
|
||||
__FUNCTION__, rotation);
|
||||
ALOGE("%s: invalid rotation value (value = 0x%x",
|
||||
__FUNCTION__, rotation);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -801,28 +676,11 @@ inline int getRotOutFmt(uint32_t format) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<>
|
||||
struct RotOutFmt<ROT_OUT_FMT_DEFAULT>
|
||||
{
|
||||
static inline int fmt(uint32_t format) {
|
||||
return getRotOutFmt(format);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RotOutFmt<ROT_OUT_FMT_Y_CRCB_H2V2>
|
||||
{
|
||||
static inline int fmt(uint32_t) {
|
||||
return MDP_Y_CRCB_H2V2;
|
||||
}
|
||||
};
|
||||
|
||||
inline uint32_t getColorFormat(uint32_t format)
|
||||
{
|
||||
//XXX: Earlier this used to mask the format
|
||||
//to check for interlaced or 3D. Just return
|
||||
//the format now
|
||||
return format;
|
||||
return (format == HAL_PIXEL_FORMAT_YV12) ?
|
||||
format : colorFormat(format);
|
||||
}
|
||||
|
||||
// FB0
|
||||
@ -937,43 +795,6 @@ inline void ScreenInfo::dump(const char* const s) const {
|
||||
s, mFBWidth, mFBHeight, mFBbpp, mFBystride);
|
||||
}
|
||||
|
||||
inline void setSrcRectDim(const overlay::utils::Dim d,
|
||||
mdp_overlay& ov) {
|
||||
ov.src_rect.x = d.x;
|
||||
ov.src_rect.y = d.y;
|
||||
ov.src_rect.w = d.w;
|
||||
ov.src_rect.h = d.h;
|
||||
}
|
||||
|
||||
inline void setDstRectDim(const overlay::utils::Dim d,
|
||||
mdp_overlay& ov) {
|
||||
ov.dst_rect.x = d.x;
|
||||
ov.dst_rect.y = d.y;
|
||||
ov.dst_rect.w = d.w;
|
||||
ov.dst_rect.h = d.h;
|
||||
}
|
||||
|
||||
inline overlay::utils::Whf getSrcWhf(const mdp_overlay& ov) {
|
||||
return overlay::utils::Whf(ov.src.width,
|
||||
ov.src.height,
|
||||
ov.src.format);
|
||||
}
|
||||
|
||||
inline overlay::utils::Dim getSrcRectDim(const mdp_overlay& ov) {
|
||||
return overlay::utils::Dim(ov.src_rect.x,
|
||||
ov.src_rect.y,
|
||||
ov.src_rect.w,
|
||||
ov.src_rect.h);
|
||||
}
|
||||
|
||||
inline overlay::utils::Dim getDstRectDim(const mdp_overlay& ov) {
|
||||
return overlay::utils::Dim(ov.dst_rect.x,
|
||||
ov.dst_rect.y,
|
||||
ov.dst_rect.w,
|
||||
ov.dst_rect.h);
|
||||
}
|
||||
|
||||
|
||||
} // namespace utils ends
|
||||
|
||||
//--------------------Class Res stuff (namespace overlay only) -----------
|
||||
@ -981,7 +802,7 @@ inline overlay::utils::Dim getDstRectDim(const mdp_overlay& ov) {
|
||||
class Res {
|
||||
public:
|
||||
// /dev/graphics/fb%u
|
||||
static const char* const devTemplate;
|
||||
static const char* const fbPath;
|
||||
// /dev/msm_rotator
|
||||
static const char* const rotPath;
|
||||
// /sys/class/graphics/fb1/format_3d
|
||||
@ -1060,7 +881,9 @@ inline OvFD::OvFD() : mFD (INVAL) {
|
||||
mPath[0] = 0;
|
||||
}
|
||||
|
||||
inline OvFD::~OvFD() { /* no op in the meantime */ }
|
||||
inline OvFD::~OvFD() {
|
||||
//no op since copy() can be used to share fd, in 3d cases.
|
||||
}
|
||||
|
||||
inline bool OvFD::open(const char* const dev, int flags)
|
||||
{
|
||||
|
@ -50,20 +50,15 @@ public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit M3DExtPipe();
|
||||
~M3DExtPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& d);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
@ -87,20 +82,15 @@ public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit M3DPrimaryPipe();
|
||||
~M3DPrimaryPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& d);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
@ -124,20 +114,15 @@ public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit S3DExtPipe();
|
||||
~S3DExtPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& d);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
@ -161,20 +146,15 @@ public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit S3DPrimaryPipe();
|
||||
~S3DPrimaryPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& d);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
@ -197,10 +177,10 @@ inline M3DExtPipe<CHAN>::M3DExtPipe() : mM3Dfmt(0) {}
|
||||
template <int CHAN>
|
||||
inline M3DExtPipe<CHAN>::~M3DExtPipe() { close(); }
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe open");
|
||||
if(!mM3d.open(rot)) {
|
||||
ALOGE("3Dpipe failed to open");
|
||||
inline bool M3DExtPipe<CHAN>::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "M3DExtPipe init");
|
||||
if(!mM3d.init(rot)) {
|
||||
ALOGE("3Dpipe failed to init");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -212,15 +192,9 @@ inline bool M3DExtPipe<CHAN>::close() {
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::commit() { return mM3d.commit(); }
|
||||
template <int CHAN>
|
||||
inline void M3DExtPipe<CHAN>::setId(int id) { mM3d.setId(id); }
|
||||
template <int CHAN>
|
||||
inline void M3DExtPipe<CHAN>::setMemoryId(int id) { mM3d.setMemoryId(id); }
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::queueBuffer(uint32_t offset) {
|
||||
return mM3d.queueBuffer(offset); }
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::dequeueBuffer(void*& buf) {
|
||||
return mM3d.dequeueBuffer(buf); }
|
||||
inline bool M3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
|
||||
return mM3d.queueBuffer(fd, offset);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::waitForVsync() {
|
||||
return mM3d.waitForVsync(); }
|
||||
@ -233,14 +207,7 @@ inline bool M3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
|
||||
}
|
||||
return mM3d.setCrop(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::start(const utils::PipeArgs& args) {
|
||||
if(!mM3d.start(args)) {
|
||||
ALOGE("M3DExtPipe start failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::setPosition(const utils::Dim& d) {
|
||||
utils::Dim _dim;
|
||||
@ -258,8 +225,8 @@ inline bool M3DExtPipe<CHAN>::setPosition(const utils::Dim& d) {
|
||||
return mM3d.setPosition(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::setParameter(const utils::Params& param) {
|
||||
return mM3d.setParameter(param);
|
||||
inline bool M3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
|
||||
return mM3d.setTransform(param);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args)
|
||||
@ -267,19 +234,9 @@ inline bool M3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args)
|
||||
// extract 3D fmt
|
||||
mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
|
||||
utils::HAL_3D_OUT_MONOS_MASK;
|
||||
if(mM3d.isClosed()){
|
||||
if(!this->start(args)) {
|
||||
ALOGE("M3DExtPipe setSource failed to start");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mM3d.setSource(args);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline const utils::PipeArgs& M3DExtPipe<CHAN>::getArgs() const {
|
||||
return mM3d.getArgs();
|
||||
}
|
||||
template <int CHAN>
|
||||
inline utils::eOverlayPipeType M3DExtPipe<CHAN>::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_M3D_EXTERNAL;
|
||||
}
|
||||
@ -296,10 +253,10 @@ inline M3DPrimaryPipe<CHAN>::M3DPrimaryPipe() : mM3Dfmt(0) {}
|
||||
template <int CHAN>
|
||||
inline M3DPrimaryPipe<CHAN>::~M3DPrimaryPipe() { close(); }
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe open");
|
||||
if(!mM3d.open(rot)) {
|
||||
ALOGE("3Dpipe failed to open");
|
||||
inline bool M3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "M3DPrimaryPipe init");
|
||||
if(!mM3d.init(rot)) {
|
||||
ALOGE("3Dpipe failed to init");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -311,15 +268,9 @@ inline bool M3DPrimaryPipe<CHAN>::close() {
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::commit() { return mM3d.commit(); }
|
||||
template <int CHAN>
|
||||
inline void M3DPrimaryPipe<CHAN>::setId(int id) { mM3d.setId(id); }
|
||||
template <int CHAN>
|
||||
inline void M3DPrimaryPipe<CHAN>::setMemoryId(int id) { mM3d.setMemoryId(id); }
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::queueBuffer(uint32_t offset) {
|
||||
return mM3d.queueBuffer(offset); }
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::dequeueBuffer(void*& buf) {
|
||||
return mM3d.dequeueBuffer(buf); }
|
||||
inline bool M3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
|
||||
return mM3d.queueBuffer(fd, offset);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::waitForVsync() {
|
||||
return mM3d.waitForVsync(); }
|
||||
@ -333,20 +284,12 @@ inline bool M3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
|
||||
return mM3d.setCrop(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::start(const utils::PipeArgs& args) {
|
||||
if(!mM3d.start(args)) {
|
||||
ALOGE("M3DPrimaryPipe start failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d) {
|
||||
return mM3d.setPosition(d);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::setParameter(const utils::Params& param) {
|
||||
return mM3d.setParameter(param);
|
||||
inline bool M3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
|
||||
return mM3d.setTransform(param);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool M3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
|
||||
@ -354,19 +297,9 @@ inline bool M3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
|
||||
// extract 3D fmt
|
||||
mM3Dfmt = utils::format3DInput(utils::getS3DFormat(args.whf.format)) |
|
||||
utils::HAL_3D_OUT_MONOS_MASK;
|
||||
if (mM3d.isClosed()) {
|
||||
if (!this->start(args)) {
|
||||
ALOGE("M3DPrimaryPipe setSource failed to start");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mM3d.setSource(args);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline const utils::PipeArgs& M3DPrimaryPipe<CHAN>::getArgs() const {
|
||||
return mM3d.getArgs();
|
||||
}
|
||||
template <int CHAN>
|
||||
inline utils::eOverlayPipeType M3DPrimaryPipe<CHAN>::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_M3D_PRIMARY;
|
||||
}
|
||||
@ -382,10 +315,10 @@ inline S3DExtPipe<CHAN>::S3DExtPipe() : mS3Dfmt(0) {}
|
||||
template <int CHAN>
|
||||
inline S3DExtPipe<CHAN>::~S3DExtPipe() { close(); }
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe open");
|
||||
if(!mS3d.open(rot)) {
|
||||
ALOGE("3Dpipe failed to open");
|
||||
inline bool S3DExtPipe<CHAN>::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "S3DExtPipe init");
|
||||
if(!mS3d.init(rot)) {
|
||||
ALOGE("3Dpipe failed to init");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -400,16 +333,9 @@ inline bool S3DExtPipe<CHAN>::close() {
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::commit() { return mS3d.commit(); }
|
||||
template <int CHAN>
|
||||
inline void S3DExtPipe<CHAN>::setId(int id) { mS3d.setId(id); }
|
||||
template <int CHAN>
|
||||
inline void S3DExtPipe<CHAN>::setMemoryId(int id) { mS3d.setMemoryId(id); }
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::queueBuffer(uint32_t offset) {
|
||||
//this->dump();
|
||||
return mS3d.queueBuffer(offset); }
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::dequeueBuffer(void*& buf) {
|
||||
return mS3d.dequeueBuffer(buf); }
|
||||
inline bool S3DExtPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
|
||||
return mS3d.queueBuffer(fd, offset);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::waitForVsync() {
|
||||
return mS3d.waitForVsync(); }
|
||||
@ -423,20 +349,6 @@ inline bool S3DExtPipe<CHAN>::setCrop(const utils::Dim& d) {
|
||||
return mS3d.setCrop(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::start(const utils::PipeArgs& args) {
|
||||
OVASSERT(mS3Dfmt, "S3DExtPipe mS3Dfmt should not be 0 here");
|
||||
if(!mS3d.start(args)) {
|
||||
ALOGE("S3DExtPipe start failed");
|
||||
return false;
|
||||
}
|
||||
uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK;
|
||||
if(!utils::send3DInfoPacket(fmt)){
|
||||
ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::setPosition(const utils::Dim& d)
|
||||
{
|
||||
utils::Dim _dim;
|
||||
@ -450,25 +362,15 @@ inline bool S3DExtPipe<CHAN>::setPosition(const utils::Dim& d)
|
||||
return mS3d.setPosition(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::setParameter(const utils::Params& param) {
|
||||
return mS3d.setParameter(param);
|
||||
inline bool S3DExtPipe<CHAN>::setTransform(const utils::eTransform& param) {
|
||||
return mS3d.setTransform(param);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DExtPipe<CHAN>::setSource(const utils::PipeArgs& args) {
|
||||
mS3Dfmt = utils::getS3DFormat(args.whf.format);
|
||||
if(mS3d.isClosed()){
|
||||
if(!this->start(args)) {
|
||||
ALOGE("S3DExtPipe setSource failed to start");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mS3d.setSource(args);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline const utils::PipeArgs& S3DExtPipe<CHAN>::getArgs() const {
|
||||
return mS3d.getArgs();
|
||||
}
|
||||
template <int CHAN>
|
||||
inline utils::eOverlayPipeType S3DExtPipe<CHAN>::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_S3D_EXTERNAL;
|
||||
}
|
||||
@ -484,10 +386,10 @@ inline S3DPrimaryPipe<CHAN>::S3DPrimaryPipe() : mS3Dfmt(0) {}
|
||||
template <int CHAN>
|
||||
inline S3DPrimaryPipe<CHAN>::~S3DPrimaryPipe() { close(); }
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe open");
|
||||
if(!mS3d.open(rot)) {
|
||||
ALOGE("3Dpipe failed to open");
|
||||
inline bool S3DPrimaryPipe<CHAN>::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "S3DPrimaryPipe init");
|
||||
if(!mS3d.init(rot)) {
|
||||
ALOGE("3Dpipe failed to init");
|
||||
return false;
|
||||
}
|
||||
// set the ctrl fd
|
||||
@ -502,18 +404,20 @@ inline bool S3DPrimaryPipe<CHAN>::close() {
|
||||
mCtrl3D.close();
|
||||
return mS3d.close();
|
||||
}
|
||||
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::commit() { return mS3d.commit(); }
|
||||
inline bool S3DPrimaryPipe<CHAN>::commit() {
|
||||
uint32_t fmt = mS3Dfmt & utils::OUTPUT_3D_MASK;
|
||||
if(!utils::send3DInfoPacket(fmt)){
|
||||
ALOGE("Error S3DExtPipe start error send3DInfoPacket %d", fmt);
|
||||
return false;
|
||||
}
|
||||
return mS3d.commit();
|
||||
}
|
||||
template <int CHAN>
|
||||
inline void S3DPrimaryPipe<CHAN>::setId(int id) { mS3d.setId(id); }
|
||||
template <int CHAN>
|
||||
inline void S3DPrimaryPipe<CHAN>::setMemoryId(int id) { mS3d.setMemoryId(id); }
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::queueBuffer(uint32_t offset) {
|
||||
return mS3d.queueBuffer(offset); }
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::dequeueBuffer(void*& buf) {
|
||||
return mS3d.dequeueBuffer(buf); }
|
||||
inline bool S3DPrimaryPipe<CHAN>::queueBuffer(int fd, uint32_t offset) {
|
||||
return mS3d.queueBuffer(fd, offset);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::waitForVsync() {
|
||||
return mS3d.waitForVsync(); }
|
||||
@ -527,14 +431,6 @@ inline bool S3DPrimaryPipe<CHAN>::setCrop(const utils::Dim& d) {
|
||||
return mS3d.setCrop(_dim);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::start(const utils::PipeArgs& args) {
|
||||
if(!mS3d.start(args)) {
|
||||
ALOGE("S3DPrimaryPipe start failed");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d)
|
||||
{
|
||||
utils::Whf fbwhf(mS3d.getScreenInfo().mFBWidth,
|
||||
@ -562,47 +458,35 @@ inline bool S3DPrimaryPipe<CHAN>::setPosition(const utils::Dim& d)
|
||||
* So the easiest way to achieve it, is to make sure FB0 is having it before
|
||||
* setParam is running */
|
||||
template <>
|
||||
inline bool S3DPrimaryPipe<utils::OV_PIPE0>::setParameter(
|
||||
const utils::Params& param) {
|
||||
if(utils::OVERLAY_TRANSFORM == param.param){
|
||||
uint32_t barrier=0;
|
||||
switch(param.value) {
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
barrier = utils::BARRIER_LAND;
|
||||
break;
|
||||
default:
|
||||
barrier = utils::BARRIER_PORT;
|
||||
break;
|
||||
}
|
||||
if(!utils::enableBarrier(barrier)) {
|
||||
ALOGE("S3DPrimaryPipe setParameter failed to enable barrier");
|
||||
}
|
||||
inline bool S3DPrimaryPipe<utils::OV_PIPE0>::setTransform(
|
||||
const utils::eTransform& param) {
|
||||
uint32_t barrier=0;
|
||||
switch(param) {
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_270:
|
||||
barrier = utils::BARRIER_LAND;
|
||||
break;
|
||||
default:
|
||||
barrier = utils::BARRIER_PORT;
|
||||
break;
|
||||
}
|
||||
return mS3d.setParameter(param);
|
||||
if(!utils::enableBarrier(barrier)) {
|
||||
ALOGE("S3DPrimaryPipe setTransform failed to enable barrier");
|
||||
}
|
||||
return mS3d.setTransform(param);
|
||||
}
|
||||
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::setParameter(const utils::Params& param) {
|
||||
return mS3d.setParameter(param);
|
||||
inline bool S3DPrimaryPipe<CHAN>::setTransform(const utils::eTransform& param) {
|
||||
return mS3d.setTransform(param);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline bool S3DPrimaryPipe<CHAN>::setSource(const utils::PipeArgs& args)
|
||||
{
|
||||
mS3Dfmt = utils::getS3DFormat(args.whf.format);
|
||||
if(mS3d.isClosed()){
|
||||
if(!this->start(args)) {
|
||||
ALOGE("S3DPrimaryPipe setSource failed to start");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return mS3d.setSource(args);
|
||||
}
|
||||
template <int CHAN>
|
||||
inline const utils::PipeArgs& S3DPrimaryPipe<CHAN>::getArgs() const {
|
||||
return mS3d.getArgs();
|
||||
}
|
||||
template <int CHAN>
|
||||
inline utils::eOverlayPipeType S3DPrimaryPipe<CHAN>::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_S3D_PRIMARY;
|
||||
}
|
||||
|
@ -1,213 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef OVERLAY_BYPASS_PIPE_H
|
||||
#define OVERLAY_BYPASS_PIPE_H
|
||||
|
||||
#include "overlayGenPipe.h"
|
||||
#include "overlayUtils.h"
|
||||
#include "overlayCtrlData.h"
|
||||
#include "overlayMdp.h"
|
||||
#include "overlayRotator.h"
|
||||
|
||||
namespace overlay {
|
||||
|
||||
/* A specific impl of GenericPipe
|
||||
* Whenever needed to have a pass through - we do it.
|
||||
* If there is a special need for a different behavior - do it here
|
||||
* PipeType = 0 (RGB), 1 (VG) */
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
class BypassPipe : utils::NoCopy {
|
||||
public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit BypassPipe();
|
||||
~BypassPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& dim);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
overlay::GenericPipe<ovutils::PRIMARY> mBypass;
|
||||
};
|
||||
|
||||
//------------------Inlines and Templates---------------------
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline BypassPipe<PipeType, IsFg, Wait, Zorder>::BypassPipe() {}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline BypassPipe<PipeType, IsFg, Wait, Zorder>::~BypassPipe() {
|
||||
close();
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "BypassPipe open");
|
||||
return mBypass.open(rot);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::close() {
|
||||
return mBypass.close();
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::commit() {
|
||||
return mBypass.commit();
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::setId(int id) {
|
||||
mBypass.setId(id);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::setMemoryId(int id) {
|
||||
mBypass.setMemoryId(id);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::queueBuffer(
|
||||
uint32_t offset) {
|
||||
return mBypass.queueBuffer(offset);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::dequeueBuffer(
|
||||
void*& buf) {
|
||||
return mBypass.dequeueBuffer(buf);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::waitForVsync() {
|
||||
return mBypass.waitForVsync();
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setCrop(
|
||||
const utils::Dim& dim) {
|
||||
return mBypass.setCrop(dim);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::start(
|
||||
const utils::PipeArgs& args) {
|
||||
return mBypass.start(args);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setPosition(
|
||||
const utils::Dim& dim) {
|
||||
return mBypass.setPosition(dim);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setParameter(
|
||||
const utils::Params& param) {
|
||||
return mBypass.setParameter(param);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline bool BypassPipe<PipeType, IsFg, Wait, Zorder>::setSource(
|
||||
const utils::PipeArgs& args) {
|
||||
utils::PipeArgs arg(args);
|
||||
|
||||
// Stride aligned to 32
|
||||
arg.whf.w = utils::align(arg.whf.w, 32);
|
||||
arg.whf.h = utils::align(arg.whf.h, 32);
|
||||
|
||||
// VG or RG pipe
|
||||
if (PipeType == utils::OV_MDP_PIPE_VG) {
|
||||
setMdpFlags(arg.mdpFlags, utils::OV_MDP_PIPE_SHARE);
|
||||
}
|
||||
|
||||
// Set is_fg flag
|
||||
arg.isFg = IsFg;
|
||||
|
||||
// Wait or no wait
|
||||
arg.wait = Wait;
|
||||
|
||||
// Z-order
|
||||
arg.zorder = Zorder;
|
||||
|
||||
return mBypass.setSource(arg);
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline const utils::PipeArgs& BypassPipe<PipeType, IsFg, Wait,
|
||||
Zorder>::getArgs() const {
|
||||
return mBypass.getArgs();
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline utils::eOverlayPipeType BypassPipe<PipeType, IsFg, Wait,
|
||||
Zorder>::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_BYPASS;
|
||||
}
|
||||
|
||||
template <utils::eMdpPipeType PipeType, utils::eIsFg IsFg, utils::eWait Wait,
|
||||
utils::eZorder Zorder>
|
||||
inline void BypassPipe<PipeType, IsFg, Wait, Zorder>::dump() const {
|
||||
ALOGE("Bypass VG Pipe");
|
||||
mBypass.dump();
|
||||
}
|
||||
|
||||
} // overlay
|
||||
|
||||
#endif // OVERLAY_BYPASS_PIPE_H
|
@ -34,65 +34,38 @@
|
||||
#include "overlayRotator.h"
|
||||
#include "overlayCtrlData.h"
|
||||
|
||||
// FIXME make int to be uint32 whenever possible
|
||||
|
||||
namespace overlay {
|
||||
|
||||
template <int PANEL>
|
||||
class GenericPipe : utils::NoCopy {
|
||||
public:
|
||||
/* ctor init */
|
||||
/* ctor */
|
||||
explicit GenericPipe();
|
||||
|
||||
/* dtor close */
|
||||
/* dtor */
|
||||
~GenericPipe();
|
||||
|
||||
/* CTRL/DATA/ROT open */
|
||||
bool open(RotatorBase* rot);
|
||||
|
||||
/* CTRL/DATA init. Not owning rotator, will not init it */
|
||||
bool init(RotatorBase* rot);
|
||||
/* CTRL/DATA close. Not owning rotator, will not close it */
|
||||
bool close();
|
||||
|
||||
/* Control APIs */
|
||||
/* set source using whf, orient and wait flag */
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
/* set crop a.k.a the region of interest */
|
||||
bool setCrop(const utils::Dim& d);
|
||||
/* set orientation*/
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
/* set mdp posision using dim */
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
/* commit changes to the overlay "set"*/
|
||||
bool commit();
|
||||
|
||||
/* "Data" related interface */
|
||||
|
||||
/* set ID directly to data channel */
|
||||
void setId(int id);
|
||||
|
||||
/* Set FD / memid */
|
||||
void setMemoryId(int id);
|
||||
|
||||
/* Data APIs */
|
||||
/* queue buffer to the overlay */
|
||||
bool queueBuffer(uint32_t offset);
|
||||
|
||||
/* dequeue buffer to the overlay NOTSUPPORTED */
|
||||
bool dequeueBuffer(void*& buf);
|
||||
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
/* wait for vsync to be done */
|
||||
bool waitForVsync();
|
||||
|
||||
/* set crop data FIXME setROI (Region Of Intrest) */
|
||||
bool setCrop(const utils::Dim& d);
|
||||
|
||||
/* "Ctrl" related interface */
|
||||
|
||||
/*
|
||||
* Start a session, opens the rotator
|
||||
* FIXME, we might want to open the rotator separately
|
||||
*/
|
||||
bool start(const utils::PipeArgs& args);
|
||||
|
||||
/* set mdp posision using dim */
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
|
||||
/* set param using Params (param,value pair) */
|
||||
bool setParameter(const utils::Params& param);
|
||||
|
||||
/* set source using whf, orient and wait flag */
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
|
||||
/* return cached startup args */
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
|
||||
@ -123,33 +96,33 @@ public:
|
||||
/* dump the state of the object */
|
||||
void dump() const;
|
||||
private:
|
||||
/* set Closed channel */
|
||||
/* set Closed pipe */
|
||||
bool setClosed();
|
||||
// kick off rotator.
|
||||
bool startRotator();
|
||||
|
||||
/* Ctrl/Data aggregator */
|
||||
CtrlData mCtrlData;
|
||||
|
||||
/* caching startup params. useful when need
|
||||
* to have the exact copy of that pipe.
|
||||
* For example when HDMI is connected, and we would
|
||||
* like to open/start the pipe with the args */
|
||||
utils::PipeArgs mArgs;
|
||||
|
||||
/* rotator mdp base
|
||||
* Can point to NullRotator or to Rotator*/
|
||||
RotatorBase* mRot;
|
||||
|
||||
/* my flags */
|
||||
enum { CLOSED = 1<<0 };
|
||||
uint32_t mFlags;
|
||||
//Whether rotator is used for 0-rot or otherwise
|
||||
bool mRotUsed;
|
||||
|
||||
/* Pipe open or closed */
|
||||
enum ePipeState {
|
||||
CLOSED,
|
||||
OPEN
|
||||
};
|
||||
ePipeState pipeState;
|
||||
};
|
||||
|
||||
//------------------------Inlines and Templates ----------------------
|
||||
|
||||
template <int PANEL>
|
||||
GenericPipe<PANEL>::GenericPipe() : mRot(0), mFlags(CLOSED) {}
|
||||
GenericPipe<PANEL>::GenericPipe() : mRot(0), mRotUsed(false),
|
||||
pipeState(CLOSED) {
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
GenericPipe<PANEL>::~GenericPipe() {
|
||||
@ -157,33 +130,42 @@ GenericPipe<PANEL>::~GenericPipe() {
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
bool GenericPipe<PANEL>::open(RotatorBase* rot)
|
||||
bool GenericPipe<PANEL>::init(RotatorBase* rot)
|
||||
{
|
||||
ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
|
||||
OVASSERT(rot, "rot is null");
|
||||
// open ctrl and data
|
||||
|
||||
// init ctrl and data
|
||||
uint32_t fbnum = utils::getFBForPanel(PANEL);
|
||||
ALOGE_IF(DEBUG_OVERLAY, "GenericPipe open");
|
||||
if(!mCtrlData.ctrl.open(fbnum, rot)) {
|
||||
ALOGE("GenericPipe failed to open ctrl");
|
||||
|
||||
if(!mCtrlData.ctrl.init(fbnum)) {
|
||||
ALOGE("GenericPipe failed to init ctrl");
|
||||
return false;
|
||||
}
|
||||
if(!mCtrlData.data.open(fbnum, rot)) {
|
||||
ALOGE("GenericPipe failed to open data");
|
||||
|
||||
if(!mCtrlData.data.init(fbnum)) {
|
||||
ALOGE("GenericPipe failed to init data");
|
||||
return false;
|
||||
}
|
||||
|
||||
//Cache the rot ref. Ownership is with OverlayImpl.
|
||||
mRot = rot;
|
||||
|
||||
// NOTE: we won't have the flags as non CLOSED since we
|
||||
// consider the pipe opened for business only when we call
|
||||
// start()
|
||||
mRotUsed = false;
|
||||
|
||||
// NOTE:init() on the rot is called by OverlayImpl
|
||||
// Pipes only have to worry about using rot, and not init or close.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
bool GenericPipe<PANEL>::close() {
|
||||
if(isClosed()) return true;
|
||||
if(isClosed())
|
||||
return true;
|
||||
|
||||
bool ret = true;
|
||||
|
||||
if(!mCtrlData.ctrl.close()) {
|
||||
ALOGE("GenericPipe failed to close ctrl");
|
||||
ret = false;
|
||||
@ -192,153 +174,118 @@ bool GenericPipe<PANEL>::close() {
|
||||
ALOGE("GenericPipe failed to close data");
|
||||
ret = false;
|
||||
}
|
||||
|
||||
// NOTE:close() on the rot is called by OverlayImpl
|
||||
// Pipes only have to worry about using rot, and not init or close.
|
||||
|
||||
setClosed();
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::commit(){
|
||||
OVASSERT(isOpen(), "State is closed, cannot commit");
|
||||
return mCtrlData.ctrl.commit();
|
||||
inline bool GenericPipe<PANEL>::setSource(
|
||||
const utils::PipeArgs& args)
|
||||
{
|
||||
utils::PipeArgs newargs(args);
|
||||
//Interlace video handling.
|
||||
if(newargs.whf.format & INTERLACE_MASK) {
|
||||
setMdpFlags(newargs.mdpFlags, utils::OV_MDP_DEINTERLACE);
|
||||
}
|
||||
utils::Whf whf(newargs.whf);
|
||||
//Extract HAL format from lower bytes. Deinterlace if interlaced.
|
||||
whf.format = utils::getColorFormat(whf.format);
|
||||
//Get MDP equivalent of HAL format.
|
||||
whf.format = utils::getMdpFormat(whf.format);
|
||||
newargs.whf = whf;
|
||||
|
||||
//Cache if user wants 0-rotation
|
||||
mRotUsed = newargs.rotFlags & utils::ROT_FLAG_ENABLED;
|
||||
mRot->setSource(newargs.whf);
|
||||
mRot->setFlags(newargs.mdpFlags);
|
||||
return mCtrlData.ctrl.setSource(newargs);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline void GenericPipe<PANEL>::setMemoryId(int id) {
|
||||
OVASSERT(isOpen(), "State is closed, cannot setMemoryId");
|
||||
mCtrlData.data.setMemoryId(id);
|
||||
inline bool GenericPipe<PANEL>::setCrop(
|
||||
const overlay::utils::Dim& d) {
|
||||
return mCtrlData.ctrl.setCrop(d);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline void GenericPipe<PANEL>::setId(int id) {
|
||||
mCtrlData.data.setId(id); }
|
||||
inline bool GenericPipe<PANEL>::setTransform(
|
||||
const utils::eTransform& orient)
|
||||
{
|
||||
//Rotation could be enabled by user for zero-rot or the layer could have
|
||||
//some transform. Mark rotation enabled in either case.
|
||||
mRotUsed |= (orient != utils::OVERLAY_TRANSFORM_0);
|
||||
mRot->setTransform(orient, mRotUsed);
|
||||
|
||||
return mCtrlData.ctrl.setTransform(orient, mRotUsed);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setPosition(const utils::Dim& d)
|
||||
{
|
||||
return mCtrlData.ctrl.setPosition(d);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::commit() {
|
||||
bool ret = false;
|
||||
//If wanting to use rotator, start it.
|
||||
if(mRotUsed) {
|
||||
if(!mRot->commit()) {
|
||||
ALOGE("GenPipe Rotator commit failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ret = mCtrlData.ctrl.commit();
|
||||
pipeState = ret ? OPEN : CLOSED;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::queueBuffer(int fd, uint32_t offset) {
|
||||
//TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private.
|
||||
OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
|
||||
int pipeId = mCtrlData.ctrl.getPipeId();
|
||||
OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
|
||||
// set pipe id from ctrl to data
|
||||
mCtrlData.data.setPipeId(pipeId);
|
||||
|
||||
int finalFd = fd;
|
||||
uint32_t finalOffset = offset;
|
||||
//If rotator is to be used, queue to it, so it can ROTATE.
|
||||
if(mRotUsed) {
|
||||
if(!mRot->queueBuffer(fd, offset)) {
|
||||
ALOGE("GenPipe Rotator play failed");
|
||||
return false;
|
||||
}
|
||||
//Configure MDP's source buffer as the current output buffer of rotator
|
||||
if(mRot->getDstMemId() != -1) {
|
||||
finalFd = mRot->getDstMemId();
|
||||
finalOffset = mRot->getDstOffset();
|
||||
} else {
|
||||
//Could be -1 for NullRotator, if queue above succeeds.
|
||||
//Need an actual rotator. Modify overlay State Traits.
|
||||
//Not fatal, keep queuing to MDP without rotation.
|
||||
ALOGE("Null rotator in use, where an actual is required");
|
||||
}
|
||||
}
|
||||
return mCtrlData.data.queueBuffer(finalFd, finalOffset);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline int GenericPipe<PANEL>::getCtrlFd() const {
|
||||
return mCtrlData.ctrl.getFd();
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setCrop(
|
||||
const overlay::utils::Dim& d) {
|
||||
OVASSERT(isOpen(), "State is closed, cannot setCrop");
|
||||
return mCtrlData.ctrl.setCrop(d);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
bool GenericPipe<PANEL>::start(const utils::PipeArgs& args)
|
||||
{
|
||||
/* open before your start control rotator */
|
||||
uint32_t sz = args.whf.size; //utils::getSizeByMdp(args.whf);
|
||||
OVASSERT(sz, "GenericPipe sz=%d", sz);
|
||||
if(!mRot->open()) {
|
||||
ALOGE("GenericPipe start failed to open rot");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mCtrlData.ctrl.start(args)){
|
||||
ALOGE("GenericPipe failed to start");
|
||||
return false;
|
||||
}
|
||||
|
||||
int ctrlId = mCtrlData.ctrl.getId();
|
||||
OVASSERT(-1 != ctrlId, "Ctrl ID should not be -1");
|
||||
// set ID requeset to assoc ctrl to data
|
||||
setId(ctrlId);
|
||||
// set ID request to assoc MDP data to ROT MDP data
|
||||
mRot->setDataReqId(mCtrlData.data.getId());
|
||||
|
||||
// cache the args for future reference.
|
||||
mArgs = args;
|
||||
|
||||
// we got here so we are open+start and good to go
|
||||
mFlags = 0; // clear flags from CLOSED
|
||||
// TODO make it more robust when more flags
|
||||
// are added
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline const utils::PipeArgs& GenericPipe<PANEL>::getArgs() const
|
||||
{
|
||||
return mArgs;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
bool GenericPipe<PANEL>::startRotator() {
|
||||
// kick off rotator
|
||||
if(!mRot->start()) {
|
||||
ALOGE("GenericPipe failed to start rotator");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::queueBuffer(uint32_t offset) {
|
||||
OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
|
||||
return mCtrlData.data.queueBuffer(offset);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::dequeueBuffer(void*&) {
|
||||
OVASSERT(isOpen(), "State is closed, cannot dequeueBuffer");
|
||||
// can also set error to NOTSUPPORTED in the future
|
||||
return false;
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::waitForVsync() {
|
||||
OVASSERT(isOpen(), "State is closed, cannot waitForVsync");
|
||||
|
||||
return mCtrlData.data.waitForVsync();
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setPosition(const utils::Dim& dim)
|
||||
{
|
||||
OVASSERT(isOpen(), "State is closed, cannot setPosition");
|
||||
return mCtrlData.ctrl.setPosition(dim);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setParameter(
|
||||
const utils::Params& param)
|
||||
{
|
||||
OVASSERT(isOpen(), "State is closed, cannot setParameter");
|
||||
// Currently setParameter would start rotator
|
||||
if(!mCtrlData.ctrl.setParameter(param)) {
|
||||
ALOGE("GenericPipe failed to setparam");
|
||||
return false;
|
||||
}
|
||||
// if rot flags are ENABLED it means we would always
|
||||
// like to have rot. Even with 0 rot. (solves tearing)
|
||||
if(utils::ROT_FLAG_ENABLED == mArgs.rotFlags) {
|
||||
mRot->setEnable();
|
||||
}
|
||||
return startRotator();
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setSource(
|
||||
const utils::PipeArgs& args)
|
||||
{
|
||||
// cache the recent args.
|
||||
mArgs = args;
|
||||
// setSource is the 1st thing that is being called on a pipe.
|
||||
// If pipe is closed, we should start everything.
|
||||
// we assume it is being opened with the correct FDs.
|
||||
if(isClosed()) {
|
||||
if(!this->start(args)) {
|
||||
ALOGE("GenericPipe setSource failed to start");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return mCtrlData.ctrl.setSource(args);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline utils::Dim GenericPipe<PANEL>::getAspectRatio(
|
||||
const utils::Whf& whf) const
|
||||
@ -374,7 +321,7 @@ template <int PANEL>
|
||||
void GenericPipe<PANEL>::dump() const
|
||||
{
|
||||
ALOGE("== Dump Generic pipe start ==");
|
||||
ALOGE("flags=0x%x", mFlags);
|
||||
ALOGE("pipe state = %d", (int)pipeState);
|
||||
OVASSERT(mRot, "GenericPipe should have a valid Rot");
|
||||
mCtrlData.ctrl.dump();
|
||||
mCtrlData.data.dump();
|
||||
@ -384,20 +331,20 @@ void GenericPipe<PANEL>::dump() const
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::isClosed() const {
|
||||
return utils::getBit(mFlags, CLOSED);
|
||||
return (pipeState == CLOSED);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::isOpen() const {
|
||||
return !isClosed();
|
||||
return (pipeState == OPEN);
|
||||
}
|
||||
|
||||
template <int PANEL>
|
||||
inline bool GenericPipe<PANEL>::setClosed() {
|
||||
return utils::setBit(mFlags, CLOSED);
|
||||
pipeState = CLOSED;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} //namespace overlay
|
||||
|
||||
#endif // OVERLAY_GENERIC_PIPE_H
|
||||
|
@ -46,74 +46,61 @@ public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit UIMirrorPipe();
|
||||
~UIMirrorPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& dim);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
overlay::GenericPipe<ovutils::EXTERNAL> mUI;
|
||||
utils::eTransform mPrimFBOr; //Primary FB's orientation
|
||||
};
|
||||
|
||||
//----------------------------Inlines -----------------------------
|
||||
|
||||
inline UIMirrorPipe::UIMirrorPipe() {}
|
||||
inline UIMirrorPipe::UIMirrorPipe() { mPrimFBOr = utils::OVERLAY_TRANSFORM_0; }
|
||||
inline UIMirrorPipe::~UIMirrorPipe() { close(); }
|
||||
inline bool UIMirrorPipe::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "UIMirrorPipe open");
|
||||
bool ret = mUI.open(rot);
|
||||
//If source to rotator is framebuffer, which is the case we UI Mirror pipe,
|
||||
//we need to inform driver during playback. Since FB does not use ION.
|
||||
rot->setSrcFB(true);
|
||||
inline bool UIMirrorPipe::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "UIMirrorPipe init");
|
||||
bool ret = mUI.init(rot);
|
||||
//If source to rotator is FB, which is the case with UI Mirror pipe,
|
||||
//we need to inform driver during playback, since FB does not use ION.
|
||||
rot->setSrcFB();
|
||||
return ret;
|
||||
}
|
||||
inline bool UIMirrorPipe::close() { return mUI.close(); }
|
||||
inline bool UIMirrorPipe::commit() { return mUI.commit(); }
|
||||
inline void UIMirrorPipe::setId(int id) { mUI.setId(id); }
|
||||
inline void UIMirrorPipe::setMemoryId(int id) { mUI.setMemoryId(id); }
|
||||
inline bool UIMirrorPipe::queueBuffer(uint32_t offset) {
|
||||
return mUI.queueBuffer(offset); }
|
||||
inline bool UIMirrorPipe::dequeueBuffer(void*& buf) {
|
||||
return mUI.dequeueBuffer(buf); }
|
||||
inline bool UIMirrorPipe::queueBuffer(int fd, uint32_t offset) {
|
||||
return mUI.queueBuffer(fd, offset);
|
||||
}
|
||||
inline bool UIMirrorPipe::waitForVsync() {
|
||||
return mUI.waitForVsync(); }
|
||||
inline bool UIMirrorPipe::setCrop(const utils::Dim& dim) {
|
||||
return mUI.setCrop(dim); }
|
||||
inline bool UIMirrorPipe::start(const utils::PipeArgs& args) {
|
||||
if(!mUI.start(args)) {
|
||||
ALOGE("%s failed to start", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) {
|
||||
|
||||
inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) {
|
||||
ovutils::Dim pdim;
|
||||
switch (dim.o) {
|
||||
case 0:
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
//using utils::eTransform;
|
||||
switch (mPrimFBOr) {
|
||||
case utils::OVERLAY_TRANSFORM_0:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_180:
|
||||
{
|
||||
ovutils::Whf whf(dim.x, dim.y, 0);
|
||||
ovutils::Whf whf(dim.w, dim.h, 0);
|
||||
pdim = mUI.getAspectRatio(whf);
|
||||
break;
|
||||
}
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90:
|
||||
case utils::OVERLAY_TRANSFORM_ROT_270:
|
||||
{
|
||||
// Calculate the Aspectratio for the UI in the landscape mode
|
||||
// Width and height will be swapped as there is rotation
|
||||
ovutils::Whf whf(dim.y, dim.x, 0);
|
||||
ovutils::Whf whf(dim.h, dim.w, 0);
|
||||
pdim = mUI.getAspectRatio(whf);
|
||||
break;
|
||||
}
|
||||
@ -121,43 +108,43 @@ inline bool UIMirrorPipe::setPosition(const utils::Dim& dim) {
|
||||
ALOGE("%s: Unknown orientation %d", __FUNCTION__, dim.o);
|
||||
return false;
|
||||
}
|
||||
|
||||
ovutils::even_out(pdim.x);
|
||||
ovutils::even_out(pdim.y);
|
||||
ovutils::even_out(pdim.w);
|
||||
ovutils::even_out(pdim.h);
|
||||
return mUI.setPosition(pdim);
|
||||
}
|
||||
inline bool UIMirrorPipe::setParameter(const utils::Params& param) {
|
||||
|
||||
OVASSERT(utils::OVERLAY_TRANSFORM_UI == param.param,
|
||||
"%p Expecting OVERLAY_TRANSFORM_UI", __FUNCTION__);
|
||||
inline bool UIMirrorPipe::setTransform(const utils::eTransform& param) {
|
||||
|
||||
int orientation = param.value;
|
||||
//Cache the primary FB orientation, since the TV's will be 0, we need this
|
||||
//info to translate later.
|
||||
mPrimFBOr = param;
|
||||
utils::eTransform transform = param;
|
||||
|
||||
// Figure out orientation to transform to
|
||||
switch (param.value) {
|
||||
case 0:
|
||||
orientation = 0;
|
||||
switch (param) {
|
||||
case utils::OVERLAY_TRANSFORM_0:
|
||||
transform = utils::OVERLAY_TRANSFORM_0;
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_180:
|
||||
orientation = HAL_TRANSFORM_ROT_180;
|
||||
case utils::OVERLAY_TRANSFORM_ROT_180:
|
||||
//If prim FB is drawn 180 rotated, rotate by additional 180 to make
|
||||
//it to 0, which is TV's orientation.
|
||||
transform = utils::OVERLAY_TRANSFORM_ROT_180;
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_90:
|
||||
orientation = HAL_TRANSFORM_ROT_270;
|
||||
case utils::OVERLAY_TRANSFORM_ROT_90:
|
||||
//If prim FB is drawn 90 rotated, rotate by additional 270 to make
|
||||
//it to 0, which is TV's orientation.
|
||||
transform = utils::OVERLAY_TRANSFORM_ROT_270;
|
||||
break;
|
||||
case HAL_TRANSFORM_ROT_270:
|
||||
orientation = HAL_TRANSFORM_ROT_90;
|
||||
case utils::OVERLAY_TRANSFORM_ROT_270:
|
||||
//If prim FB is drawn 270 rotated, rotate by additional 90 to make
|
||||
//it to 0, which is TV's orientation.
|
||||
transform = utils::OVERLAY_TRANSFORM_ROT_90;
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s: Unknown orientation %d", __FUNCTION__, param.value);
|
||||
ALOGE("%s: Unknown orientation %d", __FUNCTION__,
|
||||
static_cast<int>(param));
|
||||
return false;
|
||||
}
|
||||
|
||||
ovutils::eTransform transform =
|
||||
static_cast<ovutils::eTransform>(orientation);
|
||||
const ovutils::Params prms (ovutils::OVERLAY_TRANSFORM, transform);
|
||||
return mUI.setParameter(prms);
|
||||
return mUI.setTransform(transform);
|
||||
}
|
||||
|
||||
inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) {
|
||||
@ -175,9 +162,6 @@ inline bool UIMirrorPipe::setSource(const utils::PipeArgs& args) {
|
||||
|
||||
return mUI.setSource(arg);
|
||||
}
|
||||
inline const utils::PipeArgs& UIMirrorPipe::getArgs() const {
|
||||
return mUI.getArgs();
|
||||
}
|
||||
inline utils::eOverlayPipeType UIMirrorPipe::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_UI_MIRROR;
|
||||
}
|
||||
|
@ -27,8 +27,8 @@
|
||||
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef OVERLAY_HDMI_PIPE_H
|
||||
#define OVERLAY_HDMI_PIPE_H
|
||||
#ifndef OVERLAY_VIDEO_EXT_PIPE_H
|
||||
#define OVERLAY_VIDEO_EXT_PIPE_H
|
||||
|
||||
#include "overlayGenPipe.h"
|
||||
#include "overlayUtils.h"
|
||||
@ -41,88 +41,79 @@ namespace overlay {
|
||||
/* A specific impl of GenericPipe
|
||||
* Whenever needed to have a pass through - we do it.
|
||||
* If there is a special need for a different behavior - do it here */
|
||||
class HdmiPipe : utils::NoCopy {
|
||||
class VideoExtPipe : utils::NoCopy {
|
||||
public:
|
||||
/* Please look at overlayGenPipe.h for info */
|
||||
explicit HdmiPipe();
|
||||
~HdmiPipe();
|
||||
bool open(RotatorBase* rot);
|
||||
explicit VideoExtPipe();
|
||||
~VideoExtPipe();
|
||||
bool init(RotatorBase* rot);
|
||||
bool close();
|
||||
bool commit();
|
||||
void setId(int id);
|
||||
void setMemoryId(int id);
|
||||
bool queueBuffer(uint32_t offset);
|
||||
bool dequeueBuffer(void*& buf);
|
||||
bool queueBuffer(int fd, uint32_t offset);
|
||||
bool waitForVsync();
|
||||
bool setCrop(const utils::Dim& dim);
|
||||
bool start(const utils::PipeArgs& args);
|
||||
bool setPosition(const utils::Dim& dim);
|
||||
bool setParameter(const utils::Params& param);
|
||||
bool setTransform(const utils::eTransform& param);
|
||||
bool setSource(const utils::PipeArgs& args);
|
||||
const utils::PipeArgs& getArgs() const;
|
||||
utils::eOverlayPipeType getOvPipeType() const;
|
||||
void dump() const;
|
||||
private:
|
||||
overlay::GenericPipe<ovutils::EXTERNAL> mHdmi;
|
||||
overlay::GenericPipe<ovutils::EXTERNAL> mVideoExt;
|
||||
};
|
||||
|
||||
//------------------Inlines -----------------------------
|
||||
|
||||
inline HdmiPipe::HdmiPipe() {}
|
||||
inline HdmiPipe::~HdmiPipe() { close(); }
|
||||
inline bool HdmiPipe::open(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "HdmiPipe open");
|
||||
return mHdmi.open(rot);
|
||||
inline VideoExtPipe::VideoExtPipe() {}
|
||||
inline VideoExtPipe::~VideoExtPipe() { close(); }
|
||||
inline bool VideoExtPipe::init(RotatorBase* rot) {
|
||||
ALOGE_IF(DEBUG_OVERLAY, "VideoExtPipe init");
|
||||
return mVideoExt.init(rot);
|
||||
}
|
||||
inline bool HdmiPipe::close() { return mHdmi.close(); }
|
||||
inline bool HdmiPipe::commit() { return mHdmi.commit(); }
|
||||
inline void HdmiPipe::setId(int id) { mHdmi.setId(id); }
|
||||
inline void HdmiPipe::setMemoryId(int id) { mHdmi.setMemoryId(id); }
|
||||
inline bool HdmiPipe::queueBuffer(uint32_t offset) {
|
||||
return mHdmi.queueBuffer(offset); }
|
||||
inline bool HdmiPipe::dequeueBuffer(void*& buf) {
|
||||
return mHdmi.dequeueBuffer(buf); }
|
||||
inline bool HdmiPipe::waitForVsync() {
|
||||
return mHdmi.waitForVsync(); }
|
||||
inline bool HdmiPipe::setCrop(const utils::Dim& dim) {
|
||||
return mHdmi.setCrop(dim); }
|
||||
inline bool HdmiPipe::start(const utils::PipeArgs& args) {
|
||||
return mHdmi.start(args); }
|
||||
inline bool HdmiPipe::setPosition(const utils::Dim& dim)
|
||||
inline bool VideoExtPipe::close() { return mVideoExt.close(); }
|
||||
inline bool VideoExtPipe::commit() { return mVideoExt.commit(); }
|
||||
inline bool VideoExtPipe::queueBuffer(int fd, uint32_t offset) {
|
||||
return mVideoExt.queueBuffer(fd, offset);
|
||||
}
|
||||
inline bool VideoExtPipe::waitForVsync() {
|
||||
return mVideoExt.waitForVsync();
|
||||
}
|
||||
inline bool VideoExtPipe::setCrop(const utils::Dim& dim) {
|
||||
return mVideoExt.setCrop(dim);
|
||||
}
|
||||
inline bool VideoExtPipe::setPosition(const utils::Dim& dim)
|
||||
{
|
||||
utils::Dim d;
|
||||
// Need to change dim to aspect ratio
|
||||
if (utils::FrameBufferInfo::getInstance()->supportTrueMirroring()) {
|
||||
// Use dim info to calculate aspect ratio for true UI mirroring
|
||||
d = mHdmi.getAspectRatio(dim);
|
||||
d = mVideoExt.getAspectRatio(dim);
|
||||
} else {
|
||||
// Use cached crop data to get aspect ratio
|
||||
utils::Dim crop = mHdmi.getCrop();
|
||||
utils::Dim crop = mVideoExt.getCrop();
|
||||
utils::Whf whf(crop.w, crop.h, 0);
|
||||
d = mHdmi.getAspectRatio(whf);
|
||||
d = mVideoExt.getAspectRatio(whf);
|
||||
}
|
||||
ALOGE_IF(DEBUG_OVERLAY, "Calculated aspect ratio for HDMI: x=%d, y=%d, w=%d, h=%d, o=%d",
|
||||
ALOGE_IF(DEBUG_OVERLAY, "Calculated aspect ratio for EXT: x=%d, y=%d, w=%d,"
|
||||
"h=%d, o=%d",
|
||||
d.x, d.y, d.w, d.h, d.o);
|
||||
return mHdmi.setPosition(d);
|
||||
return mVideoExt.setPosition(d);
|
||||
}
|
||||
inline bool HdmiPipe::setParameter(const utils::Params& param) {
|
||||
return mHdmi.setParameter(param); }
|
||||
inline bool HdmiPipe::setSource(const utils::PipeArgs& args) {
|
||||
inline bool VideoExtPipe::setTransform(const utils::eTransform& param) {
|
||||
return mVideoExt.setTransform(param);
|
||||
}
|
||||
inline bool VideoExtPipe::setSource(const utils::PipeArgs& args) {
|
||||
utils::PipeArgs arg(args);
|
||||
return mHdmi.setSource(arg);
|
||||
return mVideoExt.setSource(arg);
|
||||
}
|
||||
inline const utils::PipeArgs& HdmiPipe::getArgs() const {
|
||||
return mHdmi.getArgs();
|
||||
inline utils::eOverlayPipeType VideoExtPipe::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_VIDEO_EXT;
|
||||
}
|
||||
inline utils::eOverlayPipeType HdmiPipe::getOvPipeType() const {
|
||||
return utils::OV_PIPE_TYPE_HDMI;
|
||||
}
|
||||
inline void HdmiPipe::dump() const {
|
||||
ALOGE("HDMI Pipe");
|
||||
mHdmi.dump();
|
||||
inline void VideoExtPipe::dump() const {
|
||||
ALOGE("Video Ext Pipe");
|
||||
mVideoExt.dump();
|
||||
}
|
||||
|
||||
|
||||
} // overlay
|
||||
|
||||
#endif // OVERLAY_HDMI_PIPE_H
|
||||
#endif // OVERLAY_VIDEO_EXT_PIPE_H
|
@ -1,11 +1,12 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp
|
||||
LOCAL_SHARED_LIBRARIES := libutils libcutils
|
||||
LOCAL_C_INCLUDES := hardware/qcom/display/libgralloc
|
||||
|
||||
LOCAL_CFLAGS += -DDEBUG_CALC_FPS
|
||||
LOCAL_MODULE := libqdutils
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_MODULE := libqdutils
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs)
|
||||
LOCAL_C_INCLUDES := $(common_includes) $(kernel_includes)
|
||||
LOCAL_CFLAGS := $(common_flags)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := profiler.cpp mdp_version.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -1,26 +1,22 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
include $(LOCAL_PATH)/../common.mk
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
|
||||
LOCAL_SHARED_LIBRARIES := libutils libcutils libGLESv2 libhwui
|
||||
LOCAL_MODULE := libtilerenderer
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_C_INCLUDES := \
|
||||
frameworks/base/include/utils \
|
||||
frameworks/base/libs/hwui \
|
||||
external/skia/include/core \
|
||||
external/skia/include/effects \
|
||||
external/skia/include/images \
|
||||
external/skia/src/ports \
|
||||
external/skia/include/utils \
|
||||
hardware/libhardware/include/hardware \
|
||||
frameworks/base/opengl/include/GLES2
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
frameworks/base/include/utils \
|
||||
frameworks/base/libs/hwui \
|
||||
external/skia/include/core \
|
||||
external/skia/include/effects \
|
||||
external/skia/include/images \
|
||||
external/skia/src/ports \
|
||||
external/skia/include/utils \
|
||||
hardware/libhardware/include/hardware \
|
||||
frameworks/base/opengl/include/GLES2
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
tilerenderer.cpp
|
||||
|
||||
LOCAL_MODULE := libtilerenderer
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
LOCAL_SHARED_LIBRARIES := $(common_libs) libGLESv2 libhwui
|
||||
LOCAL_SRC_FILES := tilerenderer.cpp
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user