hwc: hwc 1.1 implementation
Bug: 7124159 --External disabled --MDP comp coded but disabled. --Videos via overlay, so that secure videos can work. Change-Id: Ie48b264143d5e4237ab9724e28930e3f68ba49ee Signed-off-by: Iliyan Malchev <malchev@google.com>
This commit is contained in:
committed by
Iliyan Malchev
parent
52fc4cdb4d
commit
3e858ebde3
@@ -94,11 +94,6 @@ void ExternalDisplay::getEDIDModes(int *out) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExternalDisplay::getExternalDisplay() const {
|
|
||||||
Mutex::Autolock lock(mExtDispLock);
|
|
||||||
return mExternalDisplay;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExternalDisplay::~ExternalDisplay()
|
ExternalDisplay::~ExternalDisplay()
|
||||||
{
|
{
|
||||||
closeFrameBuffer();
|
closeFrameBuffer();
|
||||||
@@ -249,6 +244,9 @@ bool ExternalDisplay::openFramebuffer()
|
|||||||
if (mFd < 0)
|
if (mFd < 0)
|
||||||
ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__);
|
ALOGE("%s: /dev/graphics/fb1 not available", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
if(mHwcContext) {
|
||||||
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
|
||||||
|
}
|
||||||
return (mFd > 0);
|
return (mFd > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,6 +257,9 @@ bool ExternalDisplay::closeFrameBuffer()
|
|||||||
ret = close(mFd);
|
ret = close(mFd);
|
||||||
mFd = -1;
|
mFd = -1;
|
||||||
}
|
}
|
||||||
|
if(mHwcContext) {
|
||||||
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].fd = mFd;
|
||||||
|
}
|
||||||
return (ret == 0);
|
return (ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,11 +412,10 @@ void ExternalDisplay::setExternalDisplay(int connected)
|
|||||||
//Get the best mode and set
|
//Get the best mode and set
|
||||||
// TODO: DO NOT call this for WFD
|
// TODO: DO NOT call this for WFD
|
||||||
setResolution(getBestMode());
|
setResolution(getBestMode());
|
||||||
|
setDpyAttr();
|
||||||
//enable hdmi vsync
|
//enable hdmi vsync
|
||||||
enableHDMIVsync(connected);
|
|
||||||
} else {
|
} else {
|
||||||
// Disable the hdmi vsync
|
// Disable the hdmi vsync
|
||||||
enableHDMIVsync(connected);
|
|
||||||
closeFrameBuffer();
|
closeFrameBuffer();
|
||||||
resetInfo();
|
resetInfo();
|
||||||
}
|
}
|
||||||
@@ -424,9 +424,9 @@ void ExternalDisplay::setExternalDisplay(int connected)
|
|||||||
const char* prop = (connected) ? "1" : "0";
|
const char* prop = (connected) ? "1" : "0";
|
||||||
// set system property
|
// set system property
|
||||||
property_set("hw.hdmiON", prop);
|
property_set("hw.hdmiON", prop);
|
||||||
/* Trigger redraw */
|
//Inform SF
|
||||||
ALOGD_IF(DEBUG, "%s: Invalidate !!", __FUNCTION__);
|
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive = false;
|
||||||
ctx->proc->invalidate(ctx->proc);
|
ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL, connected);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -458,7 +458,7 @@ bool ExternalDisplay::writeHPDOption(int userOption) const
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExternalDisplay::commit()
|
bool ExternalDisplay::post()
|
||||||
{
|
{
|
||||||
if(mFd == -1) {
|
if(mFd == -1) {
|
||||||
return false;
|
return false;
|
||||||
@@ -470,16 +470,73 @@ bool ExternalDisplay::commit()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExternalDisplay::enableHDMIVsync(int enable)
|
void ExternalDisplay::setDpyAttr() {
|
||||||
{
|
int width = 0, height = 0, fps = 0;
|
||||||
if(mFd > 0) {
|
getAttrForMode(width, height, fps);
|
||||||
int ret = ioctl(mFd, MSMFB_OVERLAY_VSYNC_CTRL, &enable);
|
if(mHwcContext) {
|
||||||
if (ret<0) {
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = width;
|
||||||
ALOGE("%s: enabling HDMI vsync failed, str: %s", __FUNCTION__,
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = height;
|
||||||
strerror(errno));
|
mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].vsync_period = 1000000000l /
|
||||||
}
|
fps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalDisplay::getAttrForMode(int& width, int& height,
|
||||||
|
int& fps) {
|
||||||
|
switch (mCurrentMode) {
|
||||||
|
case m640x480p60_4_3:
|
||||||
|
width = 640;
|
||||||
|
height = 480;
|
||||||
|
fps = 60;
|
||||||
|
break;
|
||||||
|
case m720x480p60_4_3:
|
||||||
|
case m720x480p60_16_9:
|
||||||
|
width = 720;
|
||||||
|
height = 480;
|
||||||
|
fps = 60;
|
||||||
|
break;
|
||||||
|
case m720x576p50_4_3:
|
||||||
|
case m720x576p50_16_9:
|
||||||
|
width = 720;
|
||||||
|
height = 576;
|
||||||
|
fps = 50;
|
||||||
|
break;
|
||||||
|
case m1280x720p50_16_9:
|
||||||
|
width = 1280;
|
||||||
|
height = 720;
|
||||||
|
fps = 50;
|
||||||
|
break;
|
||||||
|
case m1280x720p60_16_9:
|
||||||
|
width = 1280;
|
||||||
|
height = 720;
|
||||||
|
fps = 60;
|
||||||
|
break;
|
||||||
|
case m1920x1080p24_16_9:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
fps = 24;
|
||||||
|
break;
|
||||||
|
case m1920x1080p25_16_9:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
fps = 25;
|
||||||
|
break;
|
||||||
|
case m1920x1080p30_16_9:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
fps = 30;
|
||||||
|
break;
|
||||||
|
case m1920x1080p50_16_9:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
fps = 50;
|
||||||
|
break;
|
||||||
|
case m1920x1080p60_16_9:
|
||||||
|
width = 1920;
|
||||||
|
height = 1080;
|
||||||
|
fps = 60;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return -errno;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -30,27 +30,13 @@ namespace qhwc {
|
|||||||
|
|
||||||
class ExternalDisplay
|
class ExternalDisplay
|
||||||
{
|
{
|
||||||
//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:
|
public:
|
||||||
ExternalDisplay(hwc_context_t* ctx);
|
ExternalDisplay(hwc_context_t* ctx);
|
||||||
~ExternalDisplay();
|
~ExternalDisplay();
|
||||||
int getModeCount() const;
|
int getModeCount() const;
|
||||||
void getEDIDModes(int *out) const;
|
void getEDIDModes(int *out) const;
|
||||||
int getExternalDisplay() const;
|
|
||||||
void setExternalDisplay(int connected);
|
void setExternalDisplay(int connected);
|
||||||
bool commit();
|
bool post();
|
||||||
int enableHDMIVsync(int enable);
|
|
||||||
void setHPD(uint32_t startEnd);
|
void setHPD(uint32_t startEnd);
|
||||||
void setEDIDMode(int resMode);
|
void setEDIDMode(int resMode);
|
||||||
void setActionSafeDimension(int w, int h);
|
void setActionSafeDimension(int w, int h);
|
||||||
@@ -67,6 +53,8 @@ private:
|
|||||||
int getModeOrder(int mode);
|
int getModeOrder(int mode);
|
||||||
int getBestMode();
|
int getBestMode();
|
||||||
void resetInfo();
|
void resetInfo();
|
||||||
|
void setDpyAttr();
|
||||||
|
void getAttrForMode(int& width, int& height, int& fps);
|
||||||
|
|
||||||
mutable android::Mutex mExtDispLock;
|
mutable android::Mutex mExtDispLock;
|
||||||
int mFd;
|
int mFd;
|
||||||
|
|||||||
@@ -100,51 +100,22 @@ static int fb_setUpdateRect(struct framebuffer_device_t* dev,
|
|||||||
|
|
||||||
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
|
||||||
{
|
{
|
||||||
if (private_handle_t::validate(buffer) < 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
fb_context_t* ctx = (fb_context_t*) dev;
|
fb_context_t* ctx = (fb_context_t*) dev;
|
||||||
|
|
||||||
private_handle_t *hnd = static_cast<private_handle_t*>
|
private_handle_t *hnd = static_cast<private_handle_t*>
|
||||||
(const_cast<native_handle_t*>(buffer));
|
(const_cast<native_handle_t*>(buffer));
|
||||||
|
|
||||||
private_module_t* m =
|
private_module_t* m =
|
||||||
reinterpret_cast<private_module_t*>(dev->common.module);
|
reinterpret_cast<private_module_t*>(dev->common.module);
|
||||||
|
|
||||||
|
if (hnd && hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
||||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
|
m->info.activate = FB_ACTIVATE_VBL | FB_ACTIVATE_FORCE;
|
||||||
genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, GENLOCK_MAX_TIMEOUT);
|
m->info.yoffset = hnd->offset / m->finfo.line_length;
|
||||||
|
|
||||||
if (m->currentBuffer) {
|
|
||||||
genlock_unlock_buffer(m->currentBuffer);
|
|
||||||
m->currentBuffer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
|
||||||
ALOGE("FBIOPUT_VSCREENINFO failed");
|
ALOGE("%s: FBIOPUT_VSCREENINFO failed for external, err: %s", __FUNCTION__,
|
||||||
genlock_unlock_buffer(hnd);
|
strerror(errno));
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Signals the composition thread to unblock and loop over if necessary
|
|
||||||
pthread_mutex_lock(&m->fbPanLock);
|
|
||||||
m->fbPanDone = true;
|
|
||||||
pthread_cond_signal(&m->fbPanCond);
|
|
||||||
pthread_mutex_unlock(&m->fbPanLock);
|
|
||||||
|
|
||||||
CALC_FPS();
|
|
||||||
m->currentBuffer = hnd;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -387,7 +358,9 @@ static int fb_close(struct hw_device_t *dev)
|
|||||||
{
|
{
|
||||||
fb_context_t* ctx = (fb_context_t*)dev;
|
fb_context_t* ctx = (fb_context_t*)dev;
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
free(ctx);
|
//Hack until fbdev is removed. Framework could close this causing hwc a
|
||||||
|
//pain.
|
||||||
|
//free(ctx);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,10 +14,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
|||||||
LOCAL_SRC_FILES := hwc.cpp \
|
LOCAL_SRC_FILES := hwc.cpp \
|
||||||
hwc_video.cpp \
|
hwc_video.cpp \
|
||||||
hwc_utils.cpp \
|
hwc_utils.cpp \
|
||||||
hwc_uimirror.cpp \
|
|
||||||
hwc_uevents.cpp \
|
hwc_uevents.cpp \
|
||||||
hwc_copybit.cpp \
|
|
||||||
hwc_mdpcomp.cpp \
|
hwc_mdpcomp.cpp \
|
||||||
hwc_extonly.cpp
|
|
||||||
|
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
@@ -26,13 +26,9 @@
|
|||||||
#include <fb_priv.h>
|
#include <fb_priv.h>
|
||||||
#include <mdp_version.h>
|
#include <mdp_version.h>
|
||||||
#include "hwc_utils.h"
|
#include "hwc_utils.h"
|
||||||
#include "hwc_qbuf.h"
|
|
||||||
#include "hwc_video.h"
|
#include "hwc_video.h"
|
||||||
#include "hwc_uimirror.h"
|
|
||||||
#include "hwc_copybit.h"
|
|
||||||
#include "external.h"
|
#include "external.h"
|
||||||
#include "hwc_mdpcomp.h"
|
#include "hwc_mdpcomp.h"
|
||||||
#include "hwc_extonly.h"
|
|
||||||
|
|
||||||
using namespace qhwc;
|
using namespace qhwc;
|
||||||
|
|
||||||
@@ -76,56 +72,66 @@ static void hwc_registerProcs(struct hwc_composer_device_1* dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Helper
|
//Helper
|
||||||
static void reset() {
|
static void reset(hwc_context_t *ctx, int numDisplays) {
|
||||||
//reset for this draw round
|
memset(ctx->listStats, 0, sizeof(ctx->listStats));
|
||||||
VideoOverlay::reset();
|
for(int i = 0; i < numDisplays; i++){
|
||||||
ExtOnly::reset();
|
ctx->listStats[i].yuvIndex = -1;
|
||||||
UIMirrorOverlay::reset();
|
}
|
||||||
ExtOnly::reset();
|
}
|
||||||
//TODO MDPComp
|
|
||||||
|
static int hwc_prepare_primary(hwc_composer_device_1 *dev,
|
||||||
|
hwc_display_contents_1_t *list) {
|
||||||
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
|
if (LIKELY(list && list->numHwLayers)) {
|
||||||
|
setListStats(ctx, list, HWC_DISPLAY_PRIMARY);
|
||||||
|
if(VideoOverlay::prepare(ctx, list, HWC_DISPLAY_PRIMARY)) {
|
||||||
|
ctx->overlayInUse = true;
|
||||||
|
} else if(MDPComp::configure(ctx, list)) {
|
||||||
|
ctx->overlayInUse = true;
|
||||||
|
} else {
|
||||||
|
ctx->overlayInUse = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hwc_prepare_external(hwc_composer_device_1 *dev,
|
||||||
|
hwc_display_contents_1_t *list) {
|
||||||
|
|
||||||
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
|
if (LIKELY(list && list->numHwLayers)) {
|
||||||
|
setListStats(ctx, list, HWC_DISPLAY_EXTERNAL);
|
||||||
|
//Nothing to do for now
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
|
static int hwc_prepare(hwc_composer_device_1 *dev, size_t numDisplays,
|
||||||
hwc_display_contents_1_t** displays)
|
hwc_display_contents_1_t** displays)
|
||||||
{
|
{
|
||||||
|
int ret = 0;
|
||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
ctx->overlayInUse = false;
|
ctx->overlayInUse = false;
|
||||||
|
|
||||||
reset();
|
reset(ctx, numDisplays);
|
||||||
|
|
||||||
//If securing of h/w in progress skip comp using overlay.
|
//If securing of h/w in progress skip comp using overlay.
|
||||||
if(ctx->mSecuring == true) return 0;
|
if(ctx->mSecuring == true) return 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < numDisplays; i++) {
|
for (uint32_t i = 0; i < numDisplays; i++) {
|
||||||
hwc_display_contents_1_t *list = displays[i];
|
hwc_display_contents_1_t *list = displays[i];
|
||||||
//XXX: Actually handle the multiple displays
|
switch(i) {
|
||||||
if (LIKELY(list && list->numHwLayers)) {
|
case HWC_DISPLAY_PRIMARY:
|
||||||
ctx->dpys[i] = list->dpy;
|
ret = hwc_prepare_primary(dev, list);
|
||||||
|
break;
|
||||||
if(ctx->isPoweredDown)
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
ALOGW("SF called %s after a POWERDOWN", __FUNCTION__);
|
ret = hwc_prepare_external(dev, list);
|
||||||
|
break;
|
||||||
getLayerStats(ctx, list);
|
default:
|
||||||
if(VideoOverlay::prepare(ctx, list)) {
|
ret = -EINVAL;
|
||||||
ctx->overlayInUse = true;
|
|
||||||
//Nothing here
|
|
||||||
} else if(ExtOnly::prepare(ctx, list)) {
|
|
||||||
ctx->overlayInUse = true;
|
|
||||||
} else if(UIMirrorOverlay::prepare(ctx, list)) {
|
|
||||||
ctx->overlayInUse = true;
|
|
||||||
} else if(MDPComp::configure(dev, 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
|
static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
|
||||||
@@ -135,16 +141,15 @@ static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
|
|||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
ctx->mFbDev->common.module);
|
ctx->mFbDev->common.module);
|
||||||
//XXX: Handle dpy
|
|
||||||
switch(event) {
|
switch(event) {
|
||||||
case HWC_EVENT_VSYNC:
|
case HWC_EVENT_VSYNC:
|
||||||
if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &enabled) < 0)
|
if(ioctl(ctx->dpyAttr[dpy].fd, MSMFB_OVERLAY_VSYNC_CTRL,
|
||||||
|
&enabled) < 0) {
|
||||||
|
ALOGE("%s: vsync control failed. Dpy=%d, enabled=%d : %s",
|
||||||
|
__FUNCTION__, dpy, enabled, strerror(errno));
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
|
|
||||||
if(ctx->mExtDisplay->getExternalDisplay()) {
|
|
||||||
ret = ctx->mExtDisplay->enableHDMIVsync(enabled);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -153,23 +158,37 @@ static int hwc_eventControl(struct hwc_composer_device_1* dev, int dpy,
|
|||||||
|
|
||||||
static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
|
static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
|
||||||
{
|
{
|
||||||
//XXX: Handle based on dpy
|
|
||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
ctx->mFbDev->common.module);
|
ctx->mFbDev->common.module);
|
||||||
if(blank) {
|
int ret = 0;
|
||||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
|
||||||
ctx->qbuf->unlockAllPrevious();
|
switch(dpy) {
|
||||||
ALOGD("HWC Calling POWERDOWN ...");
|
case HWC_DISPLAY_PRIMARY:
|
||||||
ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
|
if(blank) {
|
||||||
ALOGD("HWC Done POWERDOWN ...");
|
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||||
ctx->isPoweredDown = true;
|
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
|
||||||
} else {
|
} else {
|
||||||
ALOGD("HWC Calling UNBLANK ...");
|
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
||||||
ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
}
|
||||||
ALOGD("HWC Done UNBLANK ...");
|
break;
|
||||||
ctx->isPoweredDown = false;
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
|
if(blank) {
|
||||||
|
//TODO actual
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(ret < 0) {
|
||||||
|
ALOGE("%s: failed. Dpy=%d, blank=%d : %s",
|
||||||
|
__FUNCTION__, dpy, blank, strerror(errno));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ALOGD("%s: Done Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
|
||||||
|
ctx->dpyAttr[dpy].isActive = !blank;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,16 +198,23 @@ static int hwc_query(struct hwc_composer_device_1* dev,
|
|||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
ctx->mFbDev->common.module);
|
ctx->mFbDev->common.module);
|
||||||
|
int supported = HWC_DISPLAY_PRIMARY_BIT;
|
||||||
|
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case HWC_BACKGROUND_LAYER_SUPPORTED:
|
case HWC_BACKGROUND_LAYER_SUPPORTED:
|
||||||
// Not supported for now
|
// Not supported for now
|
||||||
value[0] = 0;
|
value[0] = 0;
|
||||||
break;
|
break;
|
||||||
case HWC_VSYNC_PERIOD:
|
case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
|
||||||
value[0] = m->fps;
|
value[0] = m->fps;
|
||||||
ALOGI("fps: %d", value[0]);
|
ALOGI("fps: %d", value[0]);
|
||||||
break;
|
break;
|
||||||
|
case HWC_DISPLAY_TYPES_SUPPORTED:
|
||||||
|
//Enable later
|
||||||
|
//if(ctx->mMDP.hasOverlay)
|
||||||
|
//supported |= HWC_DISPLAY_EXTERNAL_BIT;
|
||||||
|
value[0] = supported;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -196,45 +222,122 @@ static int hwc_query(struct hwc_composer_device_1* dev,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
||||||
|
if (LIKELY(list && list->numHwLayers)) {
|
||||||
|
VideoOverlay::draw(ctx, list, HWC_DISPLAY_PRIMARY);
|
||||||
|
MDPComp::draw(ctx, list);
|
||||||
|
hwc_sync(ctx, list, HWC_DISPLAY_PRIMARY);
|
||||||
|
//TODO We dont check for SKIP flag on this layer because we need PAN
|
||||||
|
//always. Last layer is always FB
|
||||||
|
uint32_t last = list->numHwLayers - 1;
|
||||||
|
if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET) {
|
||||||
|
ctx->mFbDev->post(ctx->mFbDev, list->hwLayers[last].handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hwc_set_external(hwc_context_t *ctx,
|
||||||
|
hwc_display_contents_1_t* list) {
|
||||||
|
if (LIKELY(list && list->numHwLayers)) {
|
||||||
|
hwc_sync(ctx, list, HWC_DISPLAY_EXTERNAL);
|
||||||
|
uint32_t last = list->numHwLayers - 1;
|
||||||
|
if(list->hwLayers[last].compositionType == HWC_FRAMEBUFFER_TARGET &&
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive) {
|
||||||
|
//ctx->mExtDisplay->post(list->hwLayers[last].handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hwc_set(hwc_composer_device_1 *dev,
|
static int hwc_set(hwc_composer_device_1 *dev,
|
||||||
size_t numDisplays,
|
size_t numDisplays,
|
||||||
hwc_display_contents_1_t** displays)
|
hwc_display_contents_1_t** displays)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
for (uint32_t i = 0; i <numDisplays; i++) {
|
for (uint32_t i = 0; i < numDisplays; i++) {
|
||||||
hwc_display_contents_1_t* list = displays[i];
|
hwc_display_contents_1_t* list = displays[i];
|
||||||
//XXX: Actually handle the multiple displays
|
switch(i) {
|
||||||
if (LIKELY(list)) {
|
case HWC_DISPLAY_PRIMARY:
|
||||||
VideoOverlay::draw(ctx, list);
|
ret = hwc_set_primary(ctx, list);
|
||||||
ExtOnly::draw(ctx, list);
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
MDPComp::draw(ctx, list);
|
ret = hwc_set_external(ctx, list);
|
||||||
|
default:
|
||||||
//Sync TODO better error handling.
|
ret = -EINVAL;
|
||||||
hwc_sync(list);
|
|
||||||
|
|
||||||
EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
|
|
||||||
(EGLSurface)list->sur);
|
|
||||||
wait4fbPost(ctx);
|
|
||||||
//Can draw to HDMI only when fb_post is reached
|
|
||||||
UIMirrorOverlay::draw(ctx);
|
|
||||||
//HDMI commit and primary commit (PAN) happening in parallel
|
|
||||||
if(ctx->mExtDisplay->getExternalDisplay())
|
|
||||||
ctx->mExtDisplay->commit();
|
|
||||||
//Virtual barrier for threads to finish
|
|
||||||
wait4Pan(ctx);
|
|
||||||
} else {
|
|
||||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
|
||||||
ctx->qbuf->unlockAll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ctx->overlayInUse)
|
|
||||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
|
||||||
}
|
}
|
||||||
ctx->qbuf->unlockAllPrevious();
|
if(!ctx->overlayInUse)
|
||||||
|
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hwc_getDisplayConfigs(struct hwc_composer_device_1* dev, int disp,
|
||||||
|
uint32_t* configs, size_t* numConfigs) {
|
||||||
|
int ret = 0;
|
||||||
|
//in 1.1 there is no way to choose a config, report as config id # 0
|
||||||
|
//This config is passed to getDisplayAttributes. Ignore for now.
|
||||||
|
if(*numConfigs == 1)
|
||||||
|
*configs = 0;
|
||||||
|
switch(disp) {
|
||||||
|
case HWC_DISPLAY_PRIMARY:
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
|
//Hack until hotplug is supported.
|
||||||
|
//This makes framework ignore external display.
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hwc_getDisplayAttributes(struct hwc_composer_device_1* dev, int disp,
|
||||||
|
uint32_t config, const uint32_t* attributes, int32_t* values) {
|
||||||
|
|
||||||
|
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||||
|
//From HWComposer
|
||||||
|
static const uint32_t DISPLAY_ATTRIBUTES[] = {
|
||||||
|
HWC_DISPLAY_VSYNC_PERIOD,
|
||||||
|
HWC_DISPLAY_WIDTH,
|
||||||
|
HWC_DISPLAY_HEIGHT,
|
||||||
|
HWC_DISPLAY_DPI_X,
|
||||||
|
HWC_DISPLAY_DPI_Y,
|
||||||
|
HWC_DISPLAY_NO_ATTRIBUTE,
|
||||||
|
};
|
||||||
|
|
||||||
|
const int NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
|
||||||
|
sizeof(DISPLAY_ATTRIBUTES)[0]);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
|
||||||
|
switch (attributes[i]) {
|
||||||
|
case HWC_DISPLAY_VSYNC_PERIOD:
|
||||||
|
values[i] = ctx->dpyAttr[disp].vsync_period;
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_WIDTH:
|
||||||
|
values[i] = ctx->dpyAttr[disp].xres;
|
||||||
|
ALOGD("%s width = %d",__FUNCTION__, ctx->dpyAttr[disp].xres);
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_HEIGHT:
|
||||||
|
values[i] = ctx->dpyAttr[disp].yres;
|
||||||
|
ALOGD("%s height = %d",__FUNCTION__, ctx->dpyAttr[disp].yres);
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_DPI_X:
|
||||||
|
values[i] = ctx->dpyAttr[disp].xdpi;
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_DPI_Y:
|
||||||
|
values[i] = ctx->dpyAttr[disp].ydpi;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ALOGE("Unknown display attribute %d",
|
||||||
|
attributes[i]);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hwc_device_close(struct hw_device_t *dev)
|
static int hwc_device_close(struct hw_device_t *dev)
|
||||||
{
|
{
|
||||||
if(!dev) {
|
if(!dev) {
|
||||||
@@ -261,17 +364,20 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
|
|||||||
initContext(dev);
|
initContext(dev);
|
||||||
|
|
||||||
//Setup HWC methods
|
//Setup HWC methods
|
||||||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||||
dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
|
dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
|
||||||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||||||
dev->device.common.close = hwc_device_close;
|
dev->device.common.close = hwc_device_close;
|
||||||
dev->device.prepare = hwc_prepare;
|
dev->device.prepare = hwc_prepare;
|
||||||
dev->device.set = hwc_set;
|
dev->device.set = hwc_set;
|
||||||
dev->device.eventControl = hwc_eventControl;
|
dev->device.eventControl = hwc_eventControl;
|
||||||
dev->device.blank = hwc_blank;
|
dev->device.blank = hwc_blank;
|
||||||
dev->device.query = hwc_query;
|
dev->device.query = hwc_query;
|
||||||
dev->device.registerProcs = hwc_registerProcs;
|
dev->device.registerProcs = hwc_registerProcs;
|
||||||
*device = &dev->device.common;
|
dev->device.dump = NULL;
|
||||||
|
dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
|
||||||
|
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
|
||||||
|
*device = &dev->device.common;
|
||||||
status = 0;
|
status = 0;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
#include "hwc_extonly.h"
|
#include "hwc_extonly.h"
|
||||||
#include "external.h"
|
#include "external.h"
|
||||||
#include "hwc_qbuf.h"
|
|
||||||
|
|
||||||
namespace qhwc {
|
namespace qhwc {
|
||||||
|
|
||||||
@@ -130,8 +129,6 @@ bool ExtOnly::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list)
|
|||||||
private_handle_t *hnd = (private_handle_t *)
|
private_handle_t *hnd = (private_handle_t *)
|
||||||
list->hwLayers[sExtIndex].handle;
|
list->hwLayers[sExtIndex].handle;
|
||||||
|
|
||||||
// Lock this buffer for read.
|
|
||||||
ctx->qbuf->lockAndAdd(hnd);
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||||
ovutils::eOverlayState state = ov.getState();
|
ovutils::eOverlayState state = ov.getState();
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "hwc_mdpcomp.h"
|
#include "hwc_mdpcomp.h"
|
||||||
#include "hwc_qbuf.h"
|
|
||||||
#include "external.h"
|
#include "external.h"
|
||||||
|
|
||||||
#define SUPPORT_4LAYER 0
|
#define SUPPORT_4LAYER 0
|
||||||
@@ -332,23 +331,16 @@ int MDPComp::prepare(hwc_context_t *ctx, hwc_layer_1_t *layer,
|
|||||||
* 5. Overlay in use
|
* 5. Overlay in use
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
|
bool MDPComp::is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
||||||
hwc_display_contents_1_t* list) {
|
|
||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
|
||||||
|
|
||||||
if(!ctx) {
|
|
||||||
ALOGE("%s: hwc context is NULL", __FUNCTION__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Number of layers
|
//Number of layers
|
||||||
if(list->numHwLayers < 1 || list->numHwLayers > (uint32_t)sMaxLayers) {
|
int numAppLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
|
if(numAppLayers < 1 || numAppLayers > (uint32_t)sMaxLayers) {
|
||||||
ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
|
ALOGD_IF(isDebug(), "%s: Unsupported number of layers",__FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disable MDPComp when ext display connected
|
//Disable MDPComp when ext display connected
|
||||||
if(ctx->mExtDisplay->getExternalDisplay()) {
|
if(isExternalActive(ctx)) {
|
||||||
ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
|
ALOGD_IF(isDebug(), "%s: External display connected.", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -360,7 +352,7 @@ bool MDPComp::is_doable(hwc_composer_device_1_t *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//MDP composition is not efficient if rotation is needed.
|
//MDP composition is not efficient if rotation is needed.
|
||||||
for(unsigned int i = 0; i < list->numHwLayers; ++i) {
|
for(int i = 0; i < numAppLayers; ++i) {
|
||||||
if(list->hwLayers[i].transform) {
|
if(list->hwLayers[i].transform) {
|
||||||
ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
|
ALOGD_IF(isDebug(), "%s: orientation involved",__FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
@@ -410,10 +402,11 @@ void MDPComp::get_layer_info(hwc_layer_1_t* layer, int& flags) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int MDPComp::mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
|
int MDPComp::mark_layers(hwc_context_t *ctx,
|
||||||
frame_info& current_frame) {
|
hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
|
||||||
|
frame_info& current_frame) {
|
||||||
|
|
||||||
int layer_count = list->numHwLayers;
|
int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
|
|
||||||
if(layer_count > sMaxLayers) {
|
if(layer_count > sMaxLayers) {
|
||||||
if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
|
if(!sPipeMgr.req_for_pipe(PIPE_REQ_FB)) {
|
||||||
@@ -476,10 +469,11 @@ void MDPComp::reset_layer_mdp_info(layer_mdp_info* layer_info, int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
|
bool MDPComp::alloc_layer_pipes(hwc_context_t *ctx,
|
||||||
layer_mdp_info* layer_info, frame_info& current_frame) {
|
hwc_display_contents_1_t* list,
|
||||||
|
layer_mdp_info* layer_info, frame_info& current_frame) {
|
||||||
|
|
||||||
int layer_count = list->numHwLayers;
|
int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
int mdp_count = current_frame.count;
|
int mdp_count = current_frame.count;
|
||||||
int fallback_count = layer_count - mdp_count;
|
int fallback_count = layer_count - mdp_count;
|
||||||
int frame_pipe_count = 0;
|
int frame_pipe_count = 0;
|
||||||
@@ -518,10 +512,10 @@ bool MDPComp::alloc_layer_pipes(hwc_display_contents_1_t* list,
|
|||||||
}
|
}
|
||||||
|
|
||||||
//returns array of layers and their allocated pipes
|
//returns array of layers and their allocated pipes
|
||||||
bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
bool MDPComp::parse_and_allocate(hwc_context_t* ctx,
|
||||||
frame_info& current_frame ) {
|
hwc_display_contents_1_t* list, frame_info& current_frame ) {
|
||||||
|
|
||||||
int layer_count = list->numHwLayers;
|
int layer_count = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
|
|
||||||
/* clear pipe status */
|
/* clear pipe status */
|
||||||
sPipeMgr.reset();
|
sPipeMgr.reset();
|
||||||
@@ -532,7 +526,7 @@ bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* l
|
|||||||
reset_layer_mdp_info(bp_layer_info, layer_count);
|
reset_layer_mdp_info(bp_layer_info, layer_count);
|
||||||
|
|
||||||
/* iterate through layer list to mark candidate */
|
/* iterate through layer list to mark candidate */
|
||||||
if(mark_layers(list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
|
if(mark_layers(ctx, list, bp_layer_info, current_frame) == MDPCOMP_ABORT) {
|
||||||
free(bp_layer_info);
|
free(bp_layer_info);
|
||||||
current_frame.count = 0;
|
current_frame.count = 0;
|
||||||
ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
|
ALOGE_IF(isDebug(), "%s:mark_layers failed!!", __FUNCTION__);
|
||||||
@@ -542,7 +536,7 @@ bool MDPComp::parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* l
|
|||||||
malloc(sizeof(pipe_layer_pair) * current_frame.count);
|
malloc(sizeof(pipe_layer_pair) * current_frame.count);
|
||||||
|
|
||||||
/* allocate MDP pipes for marked layers */
|
/* allocate MDP pipes for marked layers */
|
||||||
alloc_layer_pipes( list, bp_layer_info, current_frame);
|
alloc_layer_pipes(ctx, list, bp_layer_info, current_frame);
|
||||||
|
|
||||||
free(bp_layer_info);
|
free(bp_layer_info);
|
||||||
return true;
|
return true;
|
||||||
@@ -586,7 +580,7 @@ int MDPComp::configure_var_pipe(hwc_context_t* ctx) {
|
|||||||
|
|
||||||
bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
|
bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
|
||||||
int nPipeIndex, vsync_wait, isFG;
|
int nPipeIndex, vsync_wait, isFG;
|
||||||
int numHwLayers = list->numHwLayers;
|
int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
|
|
||||||
frame_info ¤t_frame = sCurrentFrame;
|
frame_info ¤t_frame = sCurrentFrame;
|
||||||
current_frame.count = 0;
|
current_frame.count = 0;
|
||||||
@@ -649,9 +643,6 @@ bool MDPComp::setup(hwc_context_t* ctx, hwc_display_contents_1_t* list) {
|
|||||||
|
|
||||||
void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
|
void MDPComp::unsetMDPCompLayerFlags(hwc_context_t* ctx, hwc_display_contents_1_t* list)
|
||||||
{
|
{
|
||||||
if (!list)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int index = 0 ; index < sCurrentFrame.count; index++) {
|
for (int index = 0 ; index < sCurrentFrame.count; index++) {
|
||||||
int l_index = sCurrentFrame.pipe_layer[index].layer_index;
|
int l_index = sCurrentFrame.pipe_layer[index].layer_index;
|
||||||
if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
|
if(list->hwLayers[l_index].flags & HWC_MDPCOMP) {
|
||||||
@@ -678,7 +669,8 @@ int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
|
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||||
|
|
||||||
for(unsigned int i = 0; i < list->numHwLayers; i++ )
|
int numHwLayers = ctx->listStats[HWC_DISPLAY_PRIMARY].numAppLayers;
|
||||||
|
for(int i = 0; i < numHwLayers; i++ )
|
||||||
{
|
{
|
||||||
hwc_layer_1_t *layer = &list->hwLayers[i];
|
hwc_layer_1_t *layer = &list->hwLayers[i];
|
||||||
|
|
||||||
@@ -719,10 +711,6 @@ int MDPComp::draw(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//lock buffer before queue
|
|
||||||
//XXX: Handle lock failure
|
|
||||||
ctx->qbuf->lockAndAdd(hnd);
|
|
||||||
|
|
||||||
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
|
ALOGD_IF(isDebug(),"%s: MDP Comp: Drawing layer: %p hnd: %p \
|
||||||
using pipe: %d", __FUNCTION__, layer,
|
using pipe: %d", __FUNCTION__, layer,
|
||||||
hnd, index );
|
hnd, index );
|
||||||
@@ -793,17 +781,15 @@ bool MDPComp::init(hwc_context_t *dev) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MDPComp::configure(hwc_composer_device_1_t *dev, hwc_display_contents_1_t* list) {
|
bool MDPComp::configure(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
|
||||||
|
|
||||||
if(!isEnabled()) {
|
if(!isEnabled()) {
|
||||||
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
|
ALOGD_IF(isDebug(),"%s: MDP Comp. not enabled.", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
|
||||||
|
|
||||||
bool isMDPCompUsed = true;
|
bool isMDPCompUsed = true;
|
||||||
bool doable = is_doable(dev, list);
|
bool doable = is_doable(ctx, list);
|
||||||
|
|
||||||
if(doable) {
|
if(doable) {
|
||||||
if(setup(ctx, list)) {
|
if(setup(ctx, list)) {
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
static bool deinit();
|
static bool deinit();
|
||||||
|
|
||||||
/*sets up mdp comp for the current frame */
|
/*sets up mdp comp for the current frame */
|
||||||
static bool configure(hwc_composer_device_1_t *ctx, hwc_display_contents_1_t* list);
|
static bool configure(hwc_context_t *ctx, hwc_display_contents_1_t* list);
|
||||||
|
|
||||||
/* draw */
|
/* draw */
|
||||||
static int draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
static int draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
||||||
@@ -180,8 +180,7 @@ private:
|
|||||||
mdp_pipe_info& mdp_info);
|
mdp_pipe_info& mdp_info);
|
||||||
|
|
||||||
/* checks for conditions where mdpcomp is not possible */
|
/* checks for conditions where mdpcomp is not possible */
|
||||||
static bool is_doable(hwc_composer_device_1_t *dev,
|
static bool is_doable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
|
||||||
hwc_display_contents_1_t* list);
|
|
||||||
|
|
||||||
static bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
|
static bool setup(hwc_context_t* ctx, hwc_display_contents_1_t* list);
|
||||||
|
|
||||||
@@ -189,8 +188,9 @@ private:
|
|||||||
static void get_layer_info(hwc_layer_1_t* layer, int& flags);
|
static void get_layer_info(hwc_layer_1_t* layer, int& flags);
|
||||||
|
|
||||||
/* iterates through layer list to choose candidate to use overlay */
|
/* iterates through layer list to choose candidate to use overlay */
|
||||||
static int mark_layers(hwc_display_contents_1_t* list, layer_mdp_info* layer_info,
|
static int mark_layers(hwc_context_t *ctx, hwc_display_contents_1_t* list,
|
||||||
frame_info& current_frame);
|
layer_mdp_info* layer_info, frame_info& current_frame);
|
||||||
|
|
||||||
static bool parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
static bool parse_and_allocate(hwc_context_t* ctx, hwc_display_contents_1_t* list,
|
||||||
frame_info& current_frame );
|
frame_info& current_frame );
|
||||||
|
|
||||||
@@ -198,9 +198,10 @@ private:
|
|||||||
static void reset_layer_mdp_info(layer_mdp_info* layer_mdp_info,int count);
|
static void reset_layer_mdp_info(layer_mdp_info* layer_mdp_info,int count);
|
||||||
|
|
||||||
/* allocates pipes to selected candidates */
|
/* allocates pipes to selected candidates */
|
||||||
static bool alloc_layer_pipes(hwc_display_contents_1_t* list,
|
static bool alloc_layer_pipes(hwc_context_t *ctx,
|
||||||
layer_mdp_info* layer_info,
|
hwc_display_contents_1_t* list,
|
||||||
frame_info& current_frame);
|
layer_mdp_info* layer_info,
|
||||||
|
frame_info& current_frame);
|
||||||
/* updates variable pipe mode for the current frame */
|
/* updates variable pipe mode for the current frame */
|
||||||
static int configure_var_pipe(hwc_context_t* ctx);
|
static int configure_var_pipe(hwc_context_t* ctx);
|
||||||
|
|
||||||
|
|||||||
@@ -38,26 +38,30 @@ static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
|
|||||||
char* hdmi;
|
char* hdmi;
|
||||||
int64_t timestamp = 0;
|
int64_t timestamp = 0;
|
||||||
const char *str = udata;
|
const char *str = udata;
|
||||||
int hdmiconnected = ctx->mExtDisplay->getExternalDisplay();
|
int display = HWC_DISPLAY_PRIMARY;
|
||||||
|
|
||||||
if(!strcasestr(str, "@/devices/virtual/graphics/fb")) {
|
if(!strcasestr(str, "@/devices/virtual/graphics/fb")) {
|
||||||
ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
|
ALOGD_IF(UEVENT_DEBUG, "%s: Not Ext Disp Event ", __FUNCTION__);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hdmiconnected)
|
//Check if its primary vsync
|
||||||
|
vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
|
||||||
|
//If not primary vsync, see if its an external vsync
|
||||||
|
if(isExternalActive(ctx) && !vsync) {
|
||||||
vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1));
|
vsync = !strncmp(str, MSMFB_DEVICE_FB1, strlen(MSMFB_DEVICE_FB1));
|
||||||
else
|
display = HWC_DISPLAY_EXTERNAL;
|
||||||
vsync = !strncmp(str, MSMFB_DEVICE_FB0, strlen(MSMFB_DEVICE_FB0));
|
}
|
||||||
|
|
||||||
hdmi = strcasestr(str, MSMFB_HDMI_NODE);
|
hdmi = strcasestr(str, MSMFB_HDMI_NODE);
|
||||||
|
|
||||||
if(vsync) {
|
if(vsync) {
|
||||||
str += strlen(str) + 1;
|
str += strlen(str) + 1;
|
||||||
while(*str) {
|
while(*str) {
|
||||||
if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
|
if (!strncmp(str, "VSYNC=", strlen("VSYNC="))) {
|
||||||
timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
|
timestamp = strtoull(str + strlen("VSYNC="), NULL, 0);
|
||||||
//XXX: Handle vsync from multiple displays
|
//XXX: Handle vsync from multiple displays
|
||||||
ctx->proc->vsync(ctx->proc, (int)ctx->dpys[0], timestamp);
|
ctx->proc->vsync(ctx->proc, display, timestamp);
|
||||||
}
|
}
|
||||||
str += strlen(str) + 1;
|
str += strlen(str) + 1;
|
||||||
if(str - udata >= len)
|
if(str - udata >= len)
|
||||||
|
|||||||
@@ -60,25 +60,25 @@ void UIMirrorOverlay::reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Prepare the overlay for the UI mirroring
|
//Prepare the overlay for the UI mirroring
|
||||||
bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
|
bool UIMirrorOverlay::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
|
||||||
sState = ovutils::OV_CLOSED;
|
sState = ovutils::OV_CLOSED;
|
||||||
sIsUiMirroringOn = false;
|
sIsUiMirroringOn = false;
|
||||||
|
|
||||||
if(!ctx->mMDP.hasOverlay) {
|
if(!ctx->mMDP.hasOverlay) {
|
||||||
ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
|
ALOGD_IF(HWC_UI_MIRROR, "%s, this hw doesnt support mirroring",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// If external display is connected
|
// If external display is active
|
||||||
if(ctx->mExtDisplay->getExternalDisplay()) {
|
if(isExternalActive(ctx)) {
|
||||||
sState = ovutils::OV_UI_MIRROR;
|
sState = ovutils::OV_UI_MIRROR;
|
||||||
configure(ctx, list);
|
configure(ctx, fblayer);
|
||||||
}
|
}
|
||||||
return sIsUiMirroringOn;
|
return sIsUiMirroringOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure
|
// Configure
|
||||||
bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *list)
|
bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
|
||||||
{
|
{
|
||||||
if (LIKELY(ctx->mOverlay)) {
|
if (LIKELY(ctx->mOverlay)) {
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||||
@@ -86,14 +86,8 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *li
|
|||||||
ov.setState(sState);
|
ov.setState(sState);
|
||||||
framebuffer_device_t *fbDev = ctx->mFbDev;
|
framebuffer_device_t *fbDev = ctx->mFbDev;
|
||||||
if(fbDev) {
|
if(fbDev) {
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
fbDev->common.module);
|
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
||||||
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
|
// Determine the RGB pipe for UI depending on the state
|
||||||
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
ovutils::eDest dest = ovutils::OV_PIPE_ALL;
|
||||||
if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
if (sState == ovutils::OV_2D_TRUE_UI_MIRROR) {
|
||||||
@@ -118,21 +112,26 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *li
|
|||||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||||
ov.setSource(pargs, dest);
|
ov.setSource(pargs, dest);
|
||||||
|
|
||||||
|
hwc_rect_t sourceCrop = layer->sourceCrop;
|
||||||
// x,y,w,h
|
// x,y,w,h
|
||||||
ovutils::Dim dcrop(0, 0, m->info.xres, m->info.yres);
|
ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
|
||||||
|
sourceCrop.right - sourceCrop.left,
|
||||||
|
sourceCrop.bottom - sourceCrop.top);
|
||||||
ov.setCrop(dcrop, dest);
|
ov.setCrop(dcrop, dest);
|
||||||
|
|
||||||
//Get the current orientation on primary panel
|
//Get the current orientation on primary panel
|
||||||
int transform = getDeviceOrientation();
|
int transform = getDeviceOrientation();
|
||||||
ovutils::eTransform orient =
|
ovutils::eTransform orient =
|
||||||
static_cast<ovutils::eTransform>(transform);
|
static_cast<ovutils::eTransform>(transform);
|
||||||
ov.setTransform(orient, dest);
|
ov.setTransform(orient, dest);
|
||||||
|
|
||||||
ovutils::Dim dim;
|
hwc_rect_t displayFrame = layer->displayFrame;
|
||||||
dim.x = 0;
|
ovutils::Dim dpos(displayFrame.left,
|
||||||
dim.y = 0;
|
displayFrame.top,
|
||||||
dim.w = m->info.xres;
|
displayFrame.right - displayFrame.left,
|
||||||
dim.h = m->info.yres;
|
displayFrame.bottom - displayFrame.top);
|
||||||
ov.setPosition(dim, dest);
|
ov.setPosition(dpos, dest);
|
||||||
|
|
||||||
if (!ov.commit(dest)) {
|
if (!ov.commit(dest)) {
|
||||||
ALOGE("%s: commit fails", __FUNCTION__);
|
ALOGE("%s: commit fails", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
@@ -143,7 +142,7 @@ bool UIMirrorOverlay::configure(hwc_context_t *ctx, hwc_display_contents_1_t *li
|
|||||||
return sIsUiMirroringOn;
|
return sIsUiMirroringOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UIMirrorOverlay::draw(hwc_context_t *ctx)
|
bool UIMirrorOverlay::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
|
||||||
{
|
{
|
||||||
if(!sIsUiMirroringOn) {
|
if(!sIsUiMirroringOn) {
|
||||||
return true;
|
return true;
|
||||||
@@ -156,17 +155,21 @@ bool UIMirrorOverlay::draw(hwc_context_t *ctx)
|
|||||||
if(fbDev) {
|
if(fbDev) {
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
fbDev->common.module);
|
fbDev->common.module);
|
||||||
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case ovutils::OV_UI_MIRROR:
|
case ovutils::OV_UI_MIRROR:
|
||||||
if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
|
//TODO why is this primary fd
|
||||||
ovutils::OV_PIPE0)) {
|
if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
|
||||||
|
hnd->offset, //div by line_length like in PAN?
|
||||||
|
ovutils::OV_PIPE0)) {
|
||||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ovutils::OV_2D_TRUE_UI_MIRROR:
|
case ovutils::OV_2D_TRUE_UI_MIRROR:
|
||||||
if (!ov.queueBuffer(m->framebuffer->fd, m->currentOffset,
|
if (!ov.queueBuffer(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd,
|
||||||
ovutils::OV_PIPE2)) {
|
hnd->offset,
|
||||||
|
ovutils::OV_PIPE2)) {
|
||||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ namespace qhwc {
|
|||||||
class UIMirrorOverlay {
|
class UIMirrorOverlay {
|
||||||
public:
|
public:
|
||||||
// Sets up members and prepares overlay if conditions are met
|
// Sets up members and prepares overlay if conditions are met
|
||||||
static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
static bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
|
||||||
// Draws layer if this feature is on
|
// Draws layer if this feature is on
|
||||||
static bool draw(hwc_context_t *ctx);
|
static bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
|
||||||
//Reset values
|
//Reset values
|
||||||
static void reset();
|
static void reset();
|
||||||
private:
|
private:
|
||||||
//Configures overlay
|
//Configures overlay
|
||||||
static bool configure(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
static bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
|
||||||
//The chosen overlay state.
|
//The chosen overlay state.
|
||||||
static ovutils::eOverlayState sState;
|
static ovutils::eOverlayState sState;
|
||||||
//Flags if this feature is on.
|
//Flags if this feature is on.
|
||||||
|
|||||||
@@ -23,11 +23,8 @@
|
|||||||
#include "hwc_utils.h"
|
#include "hwc_utils.h"
|
||||||
#include "mdp_version.h"
|
#include "mdp_version.h"
|
||||||
#include "hwc_video.h"
|
#include "hwc_video.h"
|
||||||
#include "hwc_qbuf.h"
|
|
||||||
#include "hwc_copybit.h"
|
|
||||||
#include "external.h"
|
#include "external.h"
|
||||||
#include "hwc_mdpcomp.h"
|
#include "hwc_mdpcomp.h"
|
||||||
#include "hwc_extonly.h"
|
|
||||||
#include "QService.h"
|
#include "QService.h"
|
||||||
|
|
||||||
namespace qhwc {
|
namespace qhwc {
|
||||||
@@ -38,6 +35,16 @@ static void openFramebufferDevice(hwc_context_t *ctx)
|
|||||||
hw_module_t const *module;
|
hw_module_t const *module;
|
||||||
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
|
if (hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &module) == 0) {
|
||||||
framebuffer_open(module, &(ctx->mFbDev));
|
framebuffer_open(module, &(ctx->mFbDev));
|
||||||
|
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||||
|
ctx->mFbDev->common.module);
|
||||||
|
//xres, yres may not be 32 aligned
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres = m->info.xres;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].yres = m->info.yres;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xdpi = ctx->mFbDev->xdpi;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].ydpi = ctx->mFbDev->ydpi;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period =
|
||||||
|
1000000000l / ctx->mFbDev->fps;
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = openFb(HWC_DISPLAY_PRIMARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,12 +53,10 @@ void initContext(hwc_context_t *ctx)
|
|||||||
openFramebufferDevice(ctx);
|
openFramebufferDevice(ctx);
|
||||||
ctx->mOverlay = overlay::Overlay::getInstance();
|
ctx->mOverlay = overlay::Overlay::getInstance();
|
||||||
ctx->mQService = qService::QService::getInstance(ctx);
|
ctx->mQService = qService::QService::getInstance(ctx);
|
||||||
ctx->qbuf = new QueuedBufferStore();
|
|
||||||
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
|
ctx->mMDP.version = qdutils::MDPVersion::getInstance().getMDPVersion();
|
||||||
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
|
ctx->mMDP.hasOverlay = qdutils::MDPVersion::getInstance().hasOverlay();
|
||||||
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
|
ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
|
||||||
ctx->mExtDisplay = new ExternalDisplay(ctx);
|
ctx->mExtDisplay = new ExternalDisplay(ctx);
|
||||||
memset(ctx->dpys,(int)EGL_NO_DISPLAY, MAX_NUM_DISPLAYS);
|
|
||||||
MDPComp::init(ctx);
|
MDPComp::init(ctx);
|
||||||
|
|
||||||
ALOGI("Initializing Qualcomm Hardware Composer");
|
ALOGI("Initializing Qualcomm Hardware Composer");
|
||||||
@@ -65,19 +70,11 @@ void closeContext(hwc_context_t *ctx)
|
|||||||
ctx->mOverlay = NULL;
|
ctx->mOverlay = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx->mCopybitEngine) {
|
|
||||||
delete ctx->mCopybitEngine;
|
|
||||||
ctx->mCopybitEngine = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ctx->mFbDev) {
|
if(ctx->mFbDev) {
|
||||||
framebuffer_close(ctx->mFbDev);
|
framebuffer_close(ctx->mFbDev);
|
||||||
ctx->mFbDev = NULL;
|
ctx->mFbDev = NULL;
|
||||||
}
|
close(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd);
|
||||||
|
ctx->dpyAttr[HWC_DISPLAY_PRIMARY].fd = -1;
|
||||||
if(ctx->qbuf) {
|
|
||||||
delete ctx->qbuf;
|
|
||||||
ctx->qbuf = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ctx->mExtDisplay) {
|
if(ctx->mExtDisplay) {
|
||||||
@@ -101,56 +98,28 @@ void dumpLayer(hwc_layer_1_t const* l)
|
|||||||
l->displayFrame.bottom);
|
l->displayFrame.bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
void getLayerStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list)
|
void setListStats(hwc_context_t *ctx,
|
||||||
{
|
const hwc_display_contents_1_t *list, int dpy) {
|
||||||
//Video specific stats
|
|
||||||
int yuvCount = 0;
|
ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
|
||||||
int yuvLayerIndex = -1;
|
ctx->listStats[dpy].fbLayerIndex = list->numHwLayers - 1;
|
||||||
bool isYuvLayerSkip = false;
|
|
||||||
int skipCount = 0;
|
|
||||||
int ccLayerIndex = -1; //closed caption
|
|
||||||
int extLayerIndex = -1; //ext-only or block except closed caption
|
|
||||||
int extCount = 0; //ext-only except closed caption
|
|
||||||
bool isExtBlockPresent = false; //is BLOCK layer present
|
|
||||||
bool yuvSecure = false;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < list->numHwLayers; i++) {
|
for (size_t i = 0; i < list->numHwLayers; i++) {
|
||||||
private_handle_t *hnd =
|
private_handle_t *hnd =
|
||||||
(private_handle_t *)list->hwLayers[i].handle;
|
(private_handle_t *)list->hwLayers[i].handle;
|
||||||
|
|
||||||
if (UNLIKELY(isYuvBuffer(hnd))) {
|
if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
|
||||||
yuvCount++;
|
continue;
|
||||||
yuvLayerIndex = i;
|
//We disregard FB being skip for now! so the else if
|
||||||
yuvSecure = isSecureBuffer(hnd);
|
|
||||||
//Animating
|
|
||||||
//Do not mark as SKIP if it is secure buffer
|
|
||||||
if (isSkipLayer(&list->hwLayers[i]) && !yuvSecure) {
|
|
||||||
isYuvLayerSkip = true;
|
|
||||||
skipCount++;
|
|
||||||
}
|
|
||||||
} else if(UNLIKELY(isExtCC(hnd))) {
|
|
||||||
ccLayerIndex = i;
|
|
||||||
} else if(UNLIKELY(isExtBlock(hnd))) {
|
|
||||||
extCount++;
|
|
||||||
extLayerIndex = i;
|
|
||||||
isExtBlockPresent = true;
|
|
||||||
} else if(UNLIKELY(isExtOnly(hnd))) {
|
|
||||||
extCount++;
|
|
||||||
//If BLOCK layer present, dont cache index, display BLOCK only.
|
|
||||||
if(isExtBlockPresent == false) extLayerIndex = i;
|
|
||||||
} else if (isSkipLayer(&list->hwLayers[i])) {
|
} else if (isSkipLayer(&list->hwLayers[i])) {
|
||||||
skipCount++;
|
ctx->listStats[dpy].skipCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (UNLIKELY(isYuvBuffer(hnd))) {
|
||||||
|
ctx->listStats[dpy].yuvCount++;
|
||||||
|
ctx->listStats[dpy].yuvIndex = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip,
|
|
||||||
ccLayerIndex);
|
|
||||||
ExtOnly::setStats(extCount, extLayerIndex, isExtBlockPresent);
|
|
||||||
CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
|
|
||||||
MDPComp::setStats(skipCount);
|
|
||||||
|
|
||||||
ctx->numHwLayers = list->numHwLayers;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Crops source buffer against destination and FB boundaries
|
//Crops source buffer against destination and FB boundaries
|
||||||
@@ -209,41 +178,15 @@ void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait4fbPost(hwc_context_t* ctx) {
|
bool isExternalActive(hwc_context_t* ctx) {
|
||||||
framebuffer_device_t *fbDev = ctx->mFbDev;
|
return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
|
||||||
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));
|
|
||||||
}
|
|
||||||
m->fbPostDone = false;
|
|
||||||
pthread_mutex_unlock(&m->fbPostLock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait4Pan(hwc_context_t* ctx) {
|
int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
|
||||||
framebuffer_device_t *fbDev = ctx->mFbDev;
|
|
||||||
if(fbDev) {
|
|
||||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
|
||||||
fbDev->common.module);
|
|
||||||
//wait for the fb_post's PAN to finish
|
|
||||||
pthread_mutex_lock(&m->fbPanLock);
|
|
||||||
while(m->fbPanDone == false) {
|
|
||||||
pthread_cond_wait(&(m->fbPanCond), &(m->fbPanLock));
|
|
||||||
}
|
|
||||||
m->fbPanDone = false;
|
|
||||||
pthread_mutex_unlock(&m->fbPanLock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int hwc_sync(hwc_display_contents_1_t* list) {
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
#ifdef USE_FENCE_SYNC
|
#ifdef USE_FENCE_SYNC
|
||||||
struct mdp_buf_sync data;
|
struct mdp_buf_sync data;
|
||||||
int acquireFd[10];
|
int acquireFd[4];
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int releaseFd = -1;
|
int releaseFd = -1;
|
||||||
int fbFd = -1;
|
int fbFd = -1;
|
||||||
@@ -252,7 +195,8 @@ int hwc_sync(hwc_display_contents_1_t* list) {
|
|||||||
data.rel_fen_fd = &releaseFd;
|
data.rel_fen_fd = &releaseFd;
|
||||||
//Accumulate acquireFenceFds
|
//Accumulate acquireFenceFds
|
||||||
for(uint32_t i = 0; i < list->numHwLayers; i++) {
|
for(uint32_t i = 0; i < list->numHwLayers; i++) {
|
||||||
if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
|
if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
|
||||||
|
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
|
||||||
list->hwLayers[i].acquireFenceFd != -1) {
|
list->hwLayers[i].acquireFenceFd != -1) {
|
||||||
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
|
acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
|
||||||
}
|
}
|
||||||
@@ -260,13 +204,7 @@ int hwc_sync(hwc_display_contents_1_t* list) {
|
|||||||
|
|
||||||
if (count) {
|
if (count) {
|
||||||
data.acq_fen_fd_cnt = count;
|
data.acq_fen_fd_cnt = count;
|
||||||
|
fbFd = ctx->dpyAttr[dpy].fd;
|
||||||
//Open fb0 for ioctl
|
|
||||||
fbFd = open("/dev/graphics/fb0", O_RDWR);
|
|
||||||
if (fbFd < 0) {
|
|
||||||
ALOGE("%s: /dev/graphics/fb0 not available", __FUNCTION__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Waits for acquire fences, returns a release fence
|
//Waits for acquire fences, returns a release fence
|
||||||
ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
|
ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
|
||||||
@@ -274,22 +212,20 @@ int hwc_sync(hwc_display_contents_1_t* list) {
|
|||||||
ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
|
ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
}
|
}
|
||||||
close(fbFd);
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < list->numHwLayers; i++) {
|
for(uint32_t i = 0; i < list->numHwLayers; i++) {
|
||||||
if(list->hwLayers[i].compositionType == HWC_OVERLAY) {
|
if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
|
||||||
|
list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)) {
|
||||||
//Close the acquireFenceFds
|
//Close the acquireFenceFds
|
||||||
if(list->hwLayers[i].acquireFenceFd > 0) {
|
if(list->hwLayers[i].acquireFenceFd > 0) {
|
||||||
close(list->hwLayers[i].acquireFenceFd);
|
close(list->hwLayers[i].acquireFenceFd);
|
||||||
list->hwLayers[i].acquireFenceFd = -1;
|
list->hwLayers[i].acquireFenceFd = -1;
|
||||||
}
|
}
|
||||||
//Populate releaseFenceFds.
|
//Populate releaseFenceFds.
|
||||||
if (releaseFd != -1)
|
list->hwLayers[i].releaseFenceFd = dup(releaseFd);
|
||||||
list->hwLayers[i].releaseFenceFd = dup(releaseFd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (releaseFd != -1)
|
list->retireFenceFd = releaseFd;
|
||||||
close(releaseFd);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return ret;
|
return ret;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#define HWC_UTILS_H
|
#define HWC_UTILS_H
|
||||||
|
|
||||||
#define HWC_REMOVE_DEPRECATED_VERSIONS 1
|
#define HWC_REMOVE_DEPRECATED_VERSIONS 1
|
||||||
|
#include <fcntl.h>
|
||||||
#include <hardware/hwcomposer.h>
|
#include <hardware/hwcomposer.h>
|
||||||
#include <gralloc_priv.h>
|
#include <gralloc_priv.h>
|
||||||
|
|
||||||
@@ -44,7 +45,6 @@ namespace qhwc {
|
|||||||
//fwrd decl
|
//fwrd decl
|
||||||
class QueuedBufferStore;
|
class QueuedBufferStore;
|
||||||
class ExternalDisplay;
|
class ExternalDisplay;
|
||||||
class CopybitEngine;
|
|
||||||
|
|
||||||
struct MDPInfo {
|
struct MDPInfo {
|
||||||
int version;
|
int version;
|
||||||
@@ -52,16 +52,23 @@ struct MDPInfo {
|
|||||||
bool hasOverlay;
|
bool hasOverlay;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum external_display_type {
|
struct DisplayAttributes {
|
||||||
EXT_TYPE_NONE,
|
uint32_t vsync_period; //nanos
|
||||||
EXT_TYPE_HDMI,
|
uint32_t xres;
|
||||||
EXT_TYPE_WIFI
|
uint32_t yres;
|
||||||
|
uint32_t xdpi;
|
||||||
|
uint32_t ydpi;
|
||||||
|
int fd;
|
||||||
|
bool isActive;
|
||||||
};
|
};
|
||||||
enum HWCCompositionType {
|
|
||||||
HWC_USE_GPU = HWC_FRAMEBUFFER, // This layer is to be handled by
|
struct ListStats {
|
||||||
// Surfaceflinger
|
int numAppLayers; //Total - 1, excluding FB layer.
|
||||||
HWC_USE_OVERLAY = HWC_OVERLAY, // This layer is to be handled by the overlay
|
int skipCount;
|
||||||
HWC_USE_COPYBIT // This layer is to be handled by copybit
|
int fbLayerIndex; //Always last for now. = numAppLayers
|
||||||
|
//Video specific
|
||||||
|
int yuvCount;
|
||||||
|
int yuvIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -74,21 +81,18 @@ enum {
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Utility functions - implemented in hwc_utils.cpp
|
// Utility functions - implemented in hwc_utils.cpp
|
||||||
void dumpLayer(hwc_layer_1_t const* l);
|
void dumpLayer(hwc_layer_1_t const* l);
|
||||||
void getLayerStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list);
|
void setListStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list,
|
||||||
|
int dpy);
|
||||||
void initContext(hwc_context_t *ctx);
|
void initContext(hwc_context_t *ctx);
|
||||||
void closeContext(hwc_context_t *ctx);
|
void closeContext(hwc_context_t *ctx);
|
||||||
//Crops source buffer against destination and FB boundaries
|
//Crops source buffer against destination and FB boundaries
|
||||||
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
|
||||||
const int fbWidth, const int fbHeight);
|
const int fbWidth, const int fbHeight);
|
||||||
|
|
||||||
// Waits for the fb_post to be called
|
bool isExternalActive(hwc_context_t* ctx);
|
||||||
void wait4fbPost(hwc_context_t* ctx);
|
|
||||||
|
|
||||||
// Waits for the fb_post to finish PAN (primary commit)
|
|
||||||
void wait4Pan(hwc_context_t* ctx);
|
|
||||||
|
|
||||||
//Sync point impl.
|
//Sync point impl.
|
||||||
int hwc_sync(hwc_display_contents_1_t* list);
|
int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy);
|
||||||
|
|
||||||
// Inline utility functions
|
// Inline utility functions
|
||||||
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
|
static inline bool isSkipLayer(const hwc_layer_1_t* l) {
|
||||||
@@ -134,6 +138,16 @@ inline void getLayerResolution(const hwc_layer_1_t* layer,
|
|||||||
width = displayFrame.right - displayFrame.left;
|
width = displayFrame.right - displayFrame.left;
|
||||||
height = displayFrame.bottom - displayFrame.top;
|
height = displayFrame.bottom - displayFrame.top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int openFb(int dpy) {
|
||||||
|
int fd = -1;
|
||||||
|
const char *devtmpl = "/dev/graphics/fb%u";
|
||||||
|
char name[64] = {0};
|
||||||
|
snprintf(name, 64, devtmpl, dpy);
|
||||||
|
fd = open(name, O_RDWR);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
}; //qhwc namespace
|
}; //qhwc namespace
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -144,20 +158,13 @@ struct hwc_context_t {
|
|||||||
const hwc_procs_t* proc;
|
const hwc_procs_t* proc;
|
||||||
int numHwLayers;
|
int numHwLayers;
|
||||||
int overlayInUse;
|
int overlayInUse;
|
||||||
hwc_display_t dpys[MAX_NUM_DISPLAYS];
|
|
||||||
|
|
||||||
//Framebuffer device
|
//Framebuffer device
|
||||||
framebuffer_device_t *mFbDev;
|
framebuffer_device_t *mFbDev;
|
||||||
|
|
||||||
//Copybit Engine
|
|
||||||
qhwc::CopybitEngine* mCopybitEngine;
|
|
||||||
|
|
||||||
//Overlay object - NULL for non overlay devices
|
//Overlay object - NULL for non overlay devices
|
||||||
overlay::Overlay *mOverlay;
|
overlay::Overlay *mOverlay;
|
||||||
|
|
||||||
//QueuedBufferStore to hold buffers for overlay
|
|
||||||
qhwc::QueuedBufferStore *qbuf;
|
|
||||||
|
|
||||||
//QService object
|
//QService object
|
||||||
qService::QService *mQService;
|
qService::QService *mQService;
|
||||||
|
|
||||||
@@ -166,7 +173,9 @@ struct hwc_context_t {
|
|||||||
|
|
||||||
qhwc::MDPInfo mMDP;
|
qhwc::MDPInfo mMDP;
|
||||||
|
|
||||||
bool isPoweredDown;
|
qhwc::DisplayAttributes dpyAttr[HWC_NUM_DISPLAY_TYPES];
|
||||||
|
|
||||||
|
qhwc::ListStats listStats[HWC_NUM_DISPLAY_TYPES];
|
||||||
|
|
||||||
//Securing in progress indicator
|
//Securing in progress indicator
|
||||||
bool mSecuring;
|
bool mSecuring;
|
||||||
|
|||||||
@@ -17,9 +17,8 @@
|
|||||||
|
|
||||||
#define VIDEO_DEBUG 0
|
#define VIDEO_DEBUG 0
|
||||||
#include <overlay.h>
|
#include <overlay.h>
|
||||||
#include "hwc_qbuf.h"
|
|
||||||
#include "hwc_video.h"
|
#include "hwc_video.h"
|
||||||
#include "external.h"
|
#include "hwc_utils.h"
|
||||||
|
|
||||||
namespace qhwc {
|
namespace qhwc {
|
||||||
|
|
||||||
@@ -27,88 +26,81 @@ namespace qhwc {
|
|||||||
|
|
||||||
//Static Members
|
//Static Members
|
||||||
ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
|
ovutils::eOverlayState VideoOverlay::sState = ovutils::OV_CLOSED;
|
||||||
int VideoOverlay::sYuvCount = 0;
|
|
||||||
int VideoOverlay::sYuvLayerIndex = -1;
|
|
||||||
bool VideoOverlay::sIsYuvLayerSkip = false;
|
|
||||||
int VideoOverlay::sCCLayerIndex = -1;
|
|
||||||
bool VideoOverlay::sIsModeOn = false;
|
bool VideoOverlay::sIsModeOn = false;
|
||||||
|
|
||||||
//Cache stats, figure out the state, config overlay
|
//Cache stats, figure out the state, config overlay
|
||||||
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
|
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
|
||||||
sIsModeOn = false;
|
int dpy) {
|
||||||
|
int yuvIndex = ctx->listStats[dpy].yuvIndex;
|
||||||
|
|
||||||
if(!ctx->mMDP.hasOverlay) {
|
if(!ctx->mMDP.hasOverlay) {
|
||||||
ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
|
ALOGD_IF(VIDEO_DEBUG,"%s, this hw doesnt support overlay", __FUNCTION__);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(sYuvLayerIndex == -1) {
|
if(yuvIndex == -1) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
chooseState(ctx);
|
|
||||||
//if the state chosen above is CLOSED, skip this block.
|
|
||||||
if(sState != ovutils::OV_CLOSED) {
|
|
||||||
hwc_layer_1_t *yuvLayer = &list->hwLayers[sYuvLayerIndex];
|
|
||||||
hwc_layer_1_t *ccLayer = NULL;
|
|
||||||
if(sCCLayerIndex != -1)
|
|
||||||
ccLayer = &list->hwLayers[sCCLayerIndex];
|
|
||||||
|
|
||||||
if(configure(ctx, yuvLayer, ccLayer)) {
|
//index guaranteed to be not -1 at this point
|
||||||
markFlags(yuvLayer, ccLayer);
|
hwc_layer_1_t *yuvLayer = &list->hwLayers[yuvIndex];
|
||||||
sIsModeOn = true;
|
chooseState(ctx, dpy, yuvLayer);
|
||||||
}
|
if(configure(ctx, dpy, yuvLayer)) {
|
||||||
|
markFlags(yuvLayer);
|
||||||
|
sIsModeOn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
|
|
||||||
"IsYuvLayerSkip = %d, ccLayerIndex = %d, IsModeOn = %d",
|
|
||||||
__FUNCTION__, sYuvCount, sYuvLayerIndex,
|
|
||||||
sIsYuvLayerSkip, sCCLayerIndex, sIsModeOn);
|
|
||||||
|
|
||||||
return sIsModeOn;
|
return sIsModeOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOverlay::chooseState(hwc_context_t *ctx) {
|
void VideoOverlay::chooseState(hwc_context_t *ctx, int dpy,
|
||||||
|
hwc_layer_1_t *yuvLayer) {
|
||||||
ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
|
ALOGD_IF(VIDEO_DEBUG, "%s: old state = %s", __FUNCTION__,
|
||||||
ovutils::getStateString(sState));
|
ovutils::getStateString(sState));
|
||||||
|
|
||||||
ovutils::eOverlayState newState = ovutils::OV_CLOSED;
|
private_handle_t *hnd = NULL;
|
||||||
|
if(yuvLayer) {
|
||||||
//Support 1 video layer
|
hnd = (private_handle_t *)yuvLayer->handle;
|
||||||
if(sYuvCount == 1) {
|
|
||||||
//Skip on primary, display on ext.
|
|
||||||
if(sIsYuvLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
|
|
||||||
newState = ovutils::OV_2D_VIDEO_ON_TV;
|
|
||||||
} else if(sIsYuvLayerSkip) { //skip on primary, no ext
|
|
||||||
newState = ovutils::OV_CLOSED;
|
|
||||||
} else if(ctx->mExtDisplay->getExternalDisplay()) {
|
|
||||||
//display on both
|
|
||||||
newState = ovutils::OV_2D_VIDEO_ON_PANEL_TV;
|
|
||||||
} else { //display on primary only
|
|
||||||
newState = ovutils::OV_2D_VIDEO_ON_PANEL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
ovutils::eOverlayState newState = ovutils::OV_CLOSED;
|
||||||
|
switch(dpy) {
|
||||||
|
case HWC_DISPLAY_PRIMARY:
|
||||||
|
if(ctx->listStats[dpy].yuvCount == 1) {
|
||||||
|
newState = ovutils::OV_2D_VIDEO_ON_PANEL;
|
||||||
|
if(isSkipLayer(yuvLayer) && !isSecureBuffer(hnd)) {
|
||||||
|
newState = ovutils::OV_CLOSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
|
//TODO needs overlay state change for UI also
|
||||||
|
newState = sState; //Previously set by HWC_DISPLAY_PRIMARY
|
||||||
|
/*if(ctx->listStats[dpy].yuvCount == 1 && isExternalActive(ctx)) {
|
||||||
|
if(!isSkipLayer(yuvLayer) || isSecureBuffer(hnd)) {
|
||||||
|
switch(sState) { //set by primary chooseState
|
||||||
|
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
||||||
|
//upgrade
|
||||||
|
sState = ovutils::OV_2D_VIDEO_PANEL_TV;
|
||||||
|
break;
|
||||||
|
case ovutils::OV_CLOSED:
|
||||||
|
sState = ovutils::OV_2D_VIDEO_ON_TV;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
sState = newState;
|
sState = newState;
|
||||||
ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
|
ALOGD_IF(VIDEO_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
|
||||||
ovutils::getStateString(sState));
|
ovutils::getStateString(sState));
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer, hwc_layer_1_t *ccLayer) {
|
void VideoOverlay::markFlags(hwc_layer_1_t *yuvLayer) {
|
||||||
switch(sState) {
|
if(yuvLayer) {
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
yuvLayer->compositionType = HWC_OVERLAY;
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
yuvLayer->hints |= HWC_HINT_CLEAR_FB;
|
||||||
if(yuvLayer) {
|
|
||||||
yuvLayer->compositionType = HWC_OVERLAY;
|
|
||||||
yuvLayer->hints |= HWC_HINT_CLEAR_FB;
|
|
||||||
}
|
|
||||||
if(ccLayer) {
|
|
||||||
ccLayer->compositionType = HWC_OVERLAY;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ovutils::OV_2D_VIDEO_ON_TV:
|
|
||||||
if(ccLayer) {
|
|
||||||
ccLayer->compositionType = HWC_OVERLAY;
|
|
||||||
}
|
|
||||||
break; //dont update video layer flags.
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +111,7 @@ bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
|
|||||||
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
||||||
|
|
||||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
|
if (isSecureBuffer(hnd)) {
|
||||||
ovutils::setMdpFlags(mdpFlags,
|
ovutils::setMdpFlags(mdpFlags,
|
||||||
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||||
}
|
}
|
||||||
@@ -161,7 +153,7 @@ bool configPrimVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
|
|||||||
//Only for Primary
|
//Only for Primary
|
||||||
ov.setCrop(dcrop, ovutils::OV_PIPE0);
|
ov.setCrop(dcrop, ovutils::OV_PIPE0);
|
||||||
|
|
||||||
int transform = layer->transform & FINAL_TRANSFORM_MASK;
|
int transform = layer->transform;
|
||||||
ovutils::eTransform orient =
|
ovutils::eTransform orient =
|
||||||
static_cast<ovutils::eTransform>(transform);
|
static_cast<ovutils::eTransform>(transform);
|
||||||
ov.setTransform(orient, ovutils::OV_PIPE0);
|
ov.setTransform(orient, ovutils::OV_PIPE0);
|
||||||
@@ -186,7 +178,7 @@ bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
|
|||||||
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
||||||
|
|
||||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
||||||
if (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_BUFFER) {
|
if (isSecureBuffer(hnd)) {
|
||||||
ovutils::setMdpFlags(mdpFlags,
|
ovutils::setMdpFlags(mdpFlags,
|
||||||
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
|
||||||
}
|
}
|
||||||
@@ -233,144 +225,83 @@ bool configExtVid(hwc_context_t *ctx, hwc_layer_1_t *layer) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool configExtCC(hwc_context_t *ctx, hwc_layer_1_t *layer) {
|
bool VideoOverlay::configure(hwc_context_t *ctx, int dpy,
|
||||||
if(layer == NULL)
|
hwc_layer_1_t *yuvLayer) {
|
||||||
return true;
|
|
||||||
|
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
|
||||||
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
|
||||||
ovutils::Whf info(hnd->width, hnd->height, hnd->format, hnd->size);
|
|
||||||
ovutils::eIsFg isFgFlag = ovutils::IS_FG_OFF;
|
|
||||||
ovutils::eMdpFlags mdpFlags = ovutils::OV_MDP_FLAGS_NONE;
|
|
||||||
ovutils::PipeArgs parg(mdpFlags,
|
|
||||||
info,
|
|
||||||
ovutils::ZORDER_1,
|
|
||||||
isFgFlag,
|
|
||||||
ovutils::ROT_FLAG_DISABLED);
|
|
||||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
|
||||||
ov.setSource(pargs, ovutils::OV_PIPE2);
|
|
||||||
|
|
||||||
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_PIPE2);
|
|
||||||
|
|
||||||
// FIXME: Use source orientation for TV when source is portrait
|
|
||||||
//Only for External
|
|
||||||
ov.setTransform(0, ovutils::OV_PIPE2);
|
|
||||||
|
|
||||||
//Setting position same as crop
|
|
||||||
//FIXME stretch to full screen
|
|
||||||
ov.setPosition(dcrop, ovutils::OV_PIPE2);
|
|
||||||
|
|
||||||
if (!ov.commit(ovutils::OV_PIPE2)) {
|
|
||||||
ALOGE("%s: commit fails", __FUNCTION__);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_1_t *yuvLayer,
|
|
||||||
hwc_layer_1_t *ccLayer) {
|
|
||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
if (LIKELY(ctx->mOverlay)) {
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
switch(dpy) {
|
||||||
// Set overlay state
|
case HWC_DISPLAY_PRIMARY:
|
||||||
ov.setState(sState);
|
// Set overlay state
|
||||||
switch(sState) {
|
ov.setState(sState);
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
switch(sState) {
|
||||||
ret &= configPrimVid(ctx, yuvLayer);
|
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
||||||
break;
|
ret &= configPrimVid(ctx, yuvLayer);
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
break;
|
||||||
ret &= configExtVid(ctx, yuvLayer);
|
default:
|
||||||
ret &= configExtCC(ctx, ccLayer);
|
return false;
|
||||||
ret &= configPrimVid(ctx, yuvLayer);
|
}
|
||||||
break;
|
break;
|
||||||
case ovutils::OV_2D_VIDEO_ON_TV:
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
ret &= configExtVid(ctx, yuvLayer);
|
ov.setState(sState);
|
||||||
ret &= configExtCC(ctx, ccLayer);
|
switch(sState) {
|
||||||
break;
|
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||||
default:
|
case ovutils::OV_2D_VIDEO_ON_TV:
|
||||||
return false;
|
ret = configExtVid(ctx, yuvLayer);
|
||||||
}
|
break;
|
||||||
} else {
|
default:
|
||||||
//Ov null
|
return false;
|
||||||
return false;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list)
|
bool VideoOverlay::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
|
||||||
|
int dpy)
|
||||||
{
|
{
|
||||||
if(!sIsModeOn || sYuvLayerIndex == -1) {
|
int yuvIndex = ctx->listStats[dpy].yuvIndex;
|
||||||
|
if(!sIsModeOn || yuvIndex == -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private_handle_t *hnd = (private_handle_t *)
|
private_handle_t *hnd = (private_handle_t *)
|
||||||
list->hwLayers[sYuvLayerIndex].handle;
|
list->hwLayers[yuvIndex].handle;
|
||||||
|
|
||||||
private_handle_t *cchnd = NULL;
|
|
||||||
if(sCCLayerIndex != -1) {
|
|
||||||
cchnd = (private_handle_t *)list->hwLayers[sCCLayerIndex].handle;
|
|
||||||
ctx->qbuf->lockAndAdd(cchnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lock this buffer for read.
|
|
||||||
ctx->qbuf->lockAndAdd(hnd);
|
|
||||||
|
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||||
ovutils::eOverlayState state = ov.getState();
|
ovutils::eOverlayState state = ov.getState();
|
||||||
|
|
||||||
switch (state) {
|
switch(dpy) {
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
case HWC_DISPLAY_PRIMARY:
|
||||||
// Play external
|
switch (state) {
|
||||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
|
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
||||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
// Play primary
|
||||||
ret = false;
|
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
||||||
}
|
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
||||||
//Play CC on external
|
ret = false;
|
||||||
if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
|
}
|
||||||
ovutils::OV_PIPE2)) {
|
break;
|
||||||
ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
|
default:
|
||||||
ret = false;
|
ret = false;
|
||||||
}
|
break;
|
||||||
// Play primary
|
|
||||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
|
||||||
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
|
||||||
ret = false;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ovutils::OV_2D_VIDEO_ON_PANEL:
|
case HWC_DISPLAY_EXTERNAL:
|
||||||
// Play primary
|
switch(state) {
|
||||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||||
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
case ovutils::OV_2D_VIDEO_ON_TV:
|
||||||
ret = false;
|
// Play external
|
||||||
|
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
|
||||||
|
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ovutils::OV_2D_VIDEO_ON_TV:
|
|
||||||
// Play external
|
|
||||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE1)) {
|
|
||||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
//Play CC on external
|
|
||||||
if (cchnd && !ov.queueBuffer(cchnd->fd, cchnd->offset,
|
|
||||||
ovutils::OV_PIPE2)) {
|
|
||||||
ALOGE("%s: queueBuffer failed for cc external", __FUNCTION__);
|
|
||||||
ret = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ALOGE("%s Unused state %s", __FUNCTION__,
|
|
||||||
ovutils::getStateString(state));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,53 +26,29 @@ namespace qhwc {
|
|||||||
class VideoOverlay {
|
class VideoOverlay {
|
||||||
public:
|
public:
|
||||||
//Sets up members and prepares overlay if conditions are met
|
//Sets up members and prepares overlay if conditions are met
|
||||||
static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
|
||||||
|
int dpy);
|
||||||
//Draws layer if this feature is on
|
//Draws layer if this feature is on
|
||||||
static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list);
|
static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
|
||||||
//Receives data from hwc
|
int dpy);
|
||||||
static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip,
|
|
||||||
int ccLayerIndex);
|
|
||||||
//resets values
|
//resets values
|
||||||
static void reset();
|
static void reset();
|
||||||
private:
|
private:
|
||||||
//Choose an appropriate overlay state based on conditions
|
//Choose an appropriate overlay state based on conditions
|
||||||
static void chooseState(hwc_context_t *ctx);
|
static void chooseState(hwc_context_t *ctx, int dpy,
|
||||||
|
hwc_layer_1_t *yuvLayer);
|
||||||
//Configures overlay for video prim and ext
|
//Configures overlay for video prim and ext
|
||||||
static bool configure(hwc_context_t *ctx, hwc_layer_1_t *yuvlayer,
|
static bool configure(hwc_context_t *ctx, int dpy,
|
||||||
hwc_layer_1_t *ccLayer);
|
hwc_layer_1_t *yuvlayer);
|
||||||
//Marks layer flags if this feature is used
|
//Marks layer flags if this feature is used
|
||||||
static void markFlags(hwc_layer_1_t *yuvLayer, hwc_layer_1_t *ccLayer);
|
static void markFlags(hwc_layer_1_t *yuvLayer);
|
||||||
//returns yuv count
|
|
||||||
static int getYuvCount();
|
|
||||||
|
|
||||||
//The chosen overlay state.
|
//The chosen overlay state.
|
||||||
static ovutils::eOverlayState sState;
|
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 sIsYuvLayerSkip;
|
|
||||||
//Holds the closed caption layer index, -1 by default
|
|
||||||
static int sCCLayerIndex;
|
|
||||||
//Flags if this feature is on.
|
//Flags if this feature is on.
|
||||||
static bool sIsModeOn;
|
static bool sIsModeOn;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex,
|
|
||||||
bool isYuvLayerSkip, int ccLayerIndex) {
|
|
||||||
sYuvCount = yuvCount;
|
|
||||||
sYuvLayerIndex = yuvLayerIndex;
|
|
||||||
sIsYuvLayerSkip = isYuvLayerSkip;
|
|
||||||
sCCLayerIndex = ccLayerIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int VideoOverlay::getYuvCount() { return sYuvCount; }
|
|
||||||
inline void VideoOverlay::reset() {
|
inline void VideoOverlay::reset() {
|
||||||
sYuvCount = 0;
|
|
||||||
sYuvLayerIndex = -1;
|
|
||||||
sIsYuvLayerSkip = false;
|
|
||||||
sCCLayerIndex = -1;
|
|
||||||
sIsModeOn = false;
|
sIsModeOn = false;
|
||||||
sState = ovutils::OV_CLOSED;
|
sState = ovutils::OV_CLOSED;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user