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:
Andrew Sutherland 2012-07-24 12:18:55 -05:00
commit a91c998940
47 changed files with 3313 additions and 3818 deletions

31
common.mk Normal file
View 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

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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 \

View File

@ -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;
};

View File

@ -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) {

View File

@ -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,

View File

@ -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));

View File

@ -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)

View File

@ -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;
}

View 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,
&copybitRegion);
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

View 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

View 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

View 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;
}
};

View 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

View File

@ -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

View 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

View 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

View File

@ -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

View File

@ -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
View 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
View 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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 ==");
}

View File

@ -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 ==");
}

View File

@ -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);

View File

@ -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 ==");

View File

@ -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;

View File

@ -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

View File

@ -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 ==");
}
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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