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:
parent
f60705b3f4
commit
56a78ad233
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user