libhwcomposer: Add support for maintaining original resolution

When the layer flags are marked to maintain the original surface
resolution, draw the layer using the overlay.
Store the HDMI status in the overlay object instead of the HWC
context.
This commit is contained in:
Naomi Luis 2011-04-21 16:33:39 -07:00 committed by Govind Surti
parent f60705b3f4
commit 56a78ad233
3 changed files with 96 additions and 36 deletions

View File

@ -56,12 +56,21 @@ enum HWCCompositionType {
HWC_USE_COPYBIT // This layer is to be handled by copybit
};
enum HWCPrivateFlags {
HWC_USE_ORIGINAL_RESOLUTION = 0x10000000, // This layer is to be drawn using overlays
};
enum HWCLayerType{
HWC_SINGLE_VIDEO = 0x1,
HWC_ORIG_RESOLUTION = 0x2,
HWC_S3D_LAYER = 0x4,
HWC_STOP_UI_MIRRORING_MASK = 0xF
};
struct hwc_context_t {
hwc_composer_device_t device;
/* our private state goes below here */
overlay::Overlay* mOverlayLibObject;
bool hdmiConnected;
bool videoStarted;
};
static int hwc_device_open(const struct hw_module_t* module, const char* name,
@ -115,11 +124,45 @@ static void dump_layer(hwc_layer_t const* l) {
static void hwc_enableHDMIOutput(hwc_composer_device_t *dev, bool enable) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
if(ctx) {
ctx->hdmiConnected = enable;
if(ctx && ctx->mOverlayLibObject) {
overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
ovLibObject->setHDMIStatus(enable);
}
}
static int hwc_updateOverlayStatus(hwc_context_t* ctx, int layerType) {
private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
ctx->device.common.module);
overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
if(!hwcModule || !ovLibObject) {
LOGE("hwc_set_hdmi_status invalid params");
return -1;
}
framebuffer_device_t *fbDev = hwcModule->fbDevice;
if (!fbDev) {
LOGE("hwc_set_hdmi_status fbDev is NULL");
return -1;
}
if ((layerType & HWC_STOP_UI_MIRRORING_MASK) &&
(OVERLAY_CHANNEL_DOWN == ovLibObject->getChannelStatus())) {
// Inform the gralloc to stop UI mirroring
fbDev->videoOverlayStarted(fbDev, true);
}
if ((OVERLAY_CHANNEL_UP == ovLibObject->getChannelStatus()) &&
!(layerType & HWC_STOP_UI_MIRRORING_MASK)) {
// Video mirroring is going on, and we do not have any layers to
// mirror directly. Close the current video channel and inform the
// gralloc to start UI mirroring
ovLibObject->closeChannel();
fbDev->videoOverlayStarted(fbDev, false);
}
return 0;
}
static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
hwc_context_t* ctx = (hwc_context_t*)(dev);
@ -131,7 +174,6 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(
dev->common.module);
overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
if(!hwcModule) {
LOGE("hwc_prepare null module ");
@ -139,7 +181,7 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
}
int yuvBufferCount = 0;
int layerType = 0;
if (list && (list->flags & HWC_GEOMETRY_CHANGED)) {
for (size_t i=0 ; i<list->numHwLayers; i++) {
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
@ -155,9 +197,13 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
// If there is a single Fullscreen layer, we can bypass it - TBD
// If there is only one video/camera buffer, we can bypass itn
if(hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) {
if (hnd && (hnd->bufferType == BUFFER_TYPE_VIDEO) && (yuvBufferCount == 1)) {
list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
} else if (list->hwLayers[i].flags == HWC_USE_ORIGINAL_RESOLUTION) {
list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
list->hwLayers[i].hints |= HWC_HINT_CLEAR_FB;
layerType |= HWC_ORIG_RESOLUTION;
} else if (hnd && (hwcModule->compositionType & (COMPOSITION_TYPE_C2D|COMPOSITION_TYPE_MDP))) {
list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
} else {
@ -165,25 +211,9 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list) {
}
}
// Inform the gralloc to close the UI mirroring channel if HDMI is connected
// and we have a video buffer
framebuffer_device_t *fbDev = hwcModule->fbDevice;
if ((yuvBufferCount == 1) && !ctx->videoStarted) {
if (ctx->hdmiConnected && fbDev) {
fbDev->videoOverlayStarted(fbDev, true);
}
ctx->videoStarted = true;
}
if (ctx->videoStarted && yuvBufferCount != 1) {
if(ovLibObject)
ovLibObject->closeChannel();
if (ctx->hdmiConnected && fbDev) {
fbDev->videoOverlayStarted(fbDev, false);
}
ctx->videoStarted = false;
}
layerType |= (yuvBufferCount == 1) ? HWC_SINGLE_VIDEO: 0;
// Inform the gralloc of the current HDMI status
hwc_updateOverlayStatus(ctx, layerType);
}
return 0;
@ -303,10 +333,17 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
{
int ret = 0;
if (ctx && ctx->mOverlayLibObject) {
private_hwc_module_t* hwcModule = reinterpret_cast<private_hwc_module_t*>(ctx->device.common.module);
if (!hwcModule) {
LOGE("drawLayerUsingLayer null module ");
return -1;
}
private_handle_t *hnd = (private_handle_t *)layer->handle;
overlay::Overlay *ovLibObject = ctx->mOverlayLibObject;
ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform, ctx->hdmiConnected);
ret = ovLibObject->setSource(hnd->width, hnd->height, hnd->format, layer->transform,
(ovLibObject->getHDMIStatus()?true:false), false);
if (!ret) {
LOGE("drawLayerUsingOverlay setSource failed");
return -1;
@ -321,10 +358,16 @@ static int drawLayerUsingOverlay(hwc_context_t *ctx, hwc_layer_t *layer)
return -1;
}
hwc_rect_t displayFrame = layer->displayFrame;
ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top,
if (layer->flags == HWC_USE_ORIGINAL_RESOLUTION) {
framebuffer_device_t* fbDev = hwcModule->fbDevice;
ret = ovLibObject->setPosition(0, 0,
fbDev->width, fbDev->height);
} else {
hwc_rect_t displayFrame = layer->displayFrame;
ret = ovLibObject->setPosition(displayFrame.left, displayFrame.top,
(displayFrame.right - displayFrame.left),
(displayFrame.bottom-displayFrame.top));
}
if (!ret) {
LOGE("drawLayerUsingOverlay setPosition failed");
return -1;
@ -486,9 +529,6 @@ static int hwc_device_open(const struct hw_module_t* module, const char* name,
} else
dev->mOverlayLibObject = NULL;
dev->hdmiConnected = false;
dev->videoStarted = false;
/* initialize the procs */
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;

View File

@ -234,7 +234,6 @@ bool Overlay::closeChannel() {
}
mChannelUP = false;
mCloseChannel = false;
mHDMIConnected = false;
mS3DFormat = 0;
return true;
}
@ -299,8 +298,17 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation,
if (format3D != mS3DFormat)
s3dChanged = 0x10;
if (hdmiConnected != mHDMIConnected)
hdmiChanged = 0x1;
if (mHDMIConnected) {
// If HDMI is connected and both channels are not up, set the status
if (!objOvCtrlChannel[0].isChannelUP() || !objOvCtrlChannel[1].isChannelUP()) {
hdmiChanged = 0x1;
}
} else {
// HDMI is disconnected and both channels are up, set the status
if (objOvCtrlChannel[0].isChannelUP() && objOvCtrlChannel[1].isChannelUP()) {
hdmiChanged = 0x1;
}
}
stateChanged = s3dChanged|hdmiChanged;
if (stateChanged || !objOvCtrlChannel[0].setSource(w, h, colorFormat, orientation, ignoreFB)) {
@ -309,7 +317,6 @@ bool Overlay::setSource(uint32_t w, uint32_t h, int format, int orientation,
return false;
}
closeChannel();
mHDMIConnected = hdmiConnected;
mS3DFormat = format3D;
if (mHDMIConnected) {

View File

@ -50,6 +50,16 @@
#define NUM_CHANNELS 2
#define FRAMEBUFFER_0 0
#define FRAMEBUFFER_1 1
enum {
HDMI_OFF,
HDMI_ON
};
enum {
OVERLAY_CHANNEL_DOWN,
OVERLAY_CHANNEL_UP
};
/* ------------------------------- 3D defines ---------------------------------------*/
// The compound format passed to the overlay is
// ABCCC where A is the input 3D format,
@ -203,6 +213,9 @@ public:
int orientation, bool hdmiConnected,
bool ignoreFB = false, int numBuffers = 2);
bool setCrop(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
int getChannelStatus() const { return (mChannelUP ? OVERLAY_CHANNEL_UP: OVERLAY_CHANNEL_DOWN); }
void setHDMIStatus (bool isHDMIConnected) { mHDMIConnected = isHDMIConnected; }
int getHDMIStatus() const {return (mHDMIConnected ? HDMI_ON : HDMI_OFF); }
private:
bool startChannelHDMI(int w, int h, int format, bool norot);