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
@@ -26,13 +26,9 @@
|
||||
#include <fb_priv.h>
|
||||
#include <mdp_version.h>
|
||||
#include "hwc_utils.h"
|
||||
#include "hwc_qbuf.h"
|
||||
#include "hwc_video.h"
|
||||
#include "hwc_uimirror.h"
|
||||
#include "hwc_copybit.h"
|
||||
#include "external.h"
|
||||
#include "hwc_mdpcomp.h"
|
||||
#include "hwc_extonly.h"
|
||||
|
||||
using namespace qhwc;
|
||||
|
||||
@@ -76,56 +72,66 @@ static void hwc_registerProcs(struct hwc_composer_device_1* dev,
|
||||
}
|
||||
|
||||
//Helper
|
||||
static void reset() {
|
||||
//reset for this draw round
|
||||
VideoOverlay::reset();
|
||||
ExtOnly::reset();
|
||||
UIMirrorOverlay::reset();
|
||||
ExtOnly::reset();
|
||||
//TODO MDPComp
|
||||
static void reset(hwc_context_t *ctx, int numDisplays) {
|
||||
memset(ctx->listStats, 0, sizeof(ctx->listStats));
|
||||
for(int i = 0; i < numDisplays; i++){
|
||||
ctx->listStats[i].yuvIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
hwc_display_contents_1_t** displays)
|
||||
{
|
||||
int ret = 0;
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
ctx->overlayInUse = false;
|
||||
|
||||
reset();
|
||||
reset(ctx, numDisplays);
|
||||
|
||||
//If securing of h/w in progress skip comp using overlay.
|
||||
if(ctx->mSecuring == true) return 0;
|
||||
|
||||
for (uint32_t i = 0; i < numDisplays; i++) {
|
||||
hwc_display_contents_1_t *list = displays[i];
|
||||
//XXX: Actually handle the multiple displays
|
||||
if (LIKELY(list && list->numHwLayers)) {
|
||||
ctx->dpys[i] = list->dpy;
|
||||
|
||||
if(ctx->isPoweredDown)
|
||||
ALOGW("SF called %s after a POWERDOWN", __FUNCTION__);
|
||||
|
||||
getLayerStats(ctx, list);
|
||||
if(VideoOverlay::prepare(ctx, list)) {
|
||||
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;
|
||||
}
|
||||
switch(i) {
|
||||
case HWC_DISPLAY_PRIMARY:
|
||||
ret = hwc_prepare_primary(dev, list);
|
||||
break;
|
||||
case HWC_DISPLAY_EXTERNAL:
|
||||
ret = hwc_prepare_external(dev, list);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ctx->mFbDev->common.module);
|
||||
//XXX: Handle dpy
|
||||
switch(event) {
|
||||
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;
|
||||
|
||||
if(ctx->mExtDisplay->getExternalDisplay()) {
|
||||
ret = ctx->mExtDisplay->enableHDMIVsync(enabled);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
//XXX: Handle based on dpy
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ctx->mFbDev->common.module);
|
||||
if(blank) {
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
ALOGD("HWC Calling POWERDOWN ...");
|
||||
ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
|
||||
ALOGD("HWC Done POWERDOWN ...");
|
||||
ctx->isPoweredDown = true;
|
||||
} else {
|
||||
ALOGD("HWC Calling UNBLANK ...");
|
||||
ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
||||
ALOGD("HWC Done UNBLANK ...");
|
||||
ctx->isPoweredDown = false;
|
||||
int ret = 0;
|
||||
ALOGD("%s: Doing Dpy=%d, blank=%d", __FUNCTION__, dpy, blank);
|
||||
switch(dpy) {
|
||||
case HWC_DISPLAY_PRIMARY:
|
||||
if(blank) {
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_POWERDOWN);
|
||||
} else {
|
||||
ret = ioctl(m->framebuffer->fd, FBIOBLANK, FB_BLANK_UNBLANK);
|
||||
}
|
||||
break;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -179,16 +198,23 @@ static int hwc_query(struct hwc_composer_device_1* dev,
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
private_module_t* m = reinterpret_cast<private_module_t*>(
|
||||
ctx->mFbDev->common.module);
|
||||
int supported = HWC_DISPLAY_PRIMARY_BIT;
|
||||
|
||||
switch (param) {
|
||||
case HWC_BACKGROUND_LAYER_SUPPORTED:
|
||||
// Not supported for now
|
||||
value[0] = 0;
|
||||
break;
|
||||
case HWC_VSYNC_PERIOD:
|
||||
case HWC_VSYNC_PERIOD: //Not used for hwc > 1.1
|
||||
value[0] = m->fps;
|
||||
ALOGI("fps: %d", value[0]);
|
||||
break;
|
||||
case HWC_DISPLAY_TYPES_SUPPORTED:
|
||||
//Enable later
|
||||
//if(ctx->mMDP.hasOverlay)
|
||||
//supported |= HWC_DISPLAY_EXTERNAL_BIT;
|
||||
value[0] = supported;
|
||||
break;
|
||||
default:
|
||||
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,
|
||||
size_t numDisplays,
|
||||
hwc_display_contents_1_t** displays)
|
||||
{
|
||||
int ret = 0;
|
||||
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];
|
||||
//XXX: Actually handle the multiple displays
|
||||
if (LIKELY(list)) {
|
||||
VideoOverlay::draw(ctx, list);
|
||||
ExtOnly::draw(ctx, list);
|
||||
MDPComp::draw(ctx, list);
|
||||
|
||||
//Sync TODO better error handling.
|
||||
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();
|
||||
switch(i) {
|
||||
case HWC_DISPLAY_PRIMARY:
|
||||
ret = hwc_set_primary(ctx, list);
|
||||
case HWC_DISPLAY_EXTERNAL:
|
||||
ret = hwc_set_external(ctx, list);
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if(!ctx->overlayInUse)
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
}
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
if(!ctx->overlayInUse)
|
||||
ctx->mOverlay->setState(ovutils::OV_CLOSED);
|
||||
|
||||
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)
|
||||
{
|
||||
if(!dev) {
|
||||
@@ -261,17 +364,20 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
|
||||
initContext(dev);
|
||||
|
||||
//Setup HWC methods
|
||||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||
dev->device.common.version = HWC_DEVICE_API_VERSION_1_0;
|
||||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||||
dev->device.common.close = hwc_device_close;
|
||||
dev->device.prepare = hwc_prepare;
|
||||
dev->device.set = hwc_set;
|
||||
dev->device.eventControl = hwc_eventControl;
|
||||
dev->device.blank = hwc_blank;
|
||||
dev->device.query = hwc_query;
|
||||
dev->device.registerProcs = hwc_registerProcs;
|
||||
*device = &dev->device.common;
|
||||
dev->device.common.tag = HARDWARE_DEVICE_TAG;
|
||||
dev->device.common.version = HWC_DEVICE_API_VERSION_1_1;
|
||||
dev->device.common.module = const_cast<hw_module_t*>(module);
|
||||
dev->device.common.close = hwc_device_close;
|
||||
dev->device.prepare = hwc_prepare;
|
||||
dev->device.set = hwc_set;
|
||||
dev->device.eventControl = hwc_eventControl;
|
||||
dev->device.blank = hwc_blank;
|
||||
dev->device.query = hwc_query;
|
||||
dev->device.registerProcs = hwc_registerProcs;
|
||||
dev->device.dump = NULL;
|
||||
dev->device.getDisplayConfigs = hwc_getDisplayConfigs;
|
||||
dev->device.getDisplayAttributes = hwc_getDisplayAttributes;
|
||||
*device = &dev->device.common;
|
||||
status = 0;
|
||||
}
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user