hwc: Add support for external-only layers
Add support for different types of external-only layers EXTERNAL_ONLY: General purpose EXTERNAL_BLOCK: Blocks the display of other ext-only layers EXTERNAL_CC: Used for closed captions with videos. Change-Id: I7cb531a55a2f0015e3a51673faf08941bcea1923
This commit is contained in:
parent
446b936947
commit
bf3c454efe
@ -71,7 +71,7 @@ static bool canFallback(int usage, bool triedSystem)
|
||||
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PROTECTED |
|
||||
GRALLOC_USAGE_PRIVATE_CP_BUFFER))
|
||||
return false;
|
||||
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_EXTERNAL_ONLY))
|
||||
if(usage & (GRALLOC_HEAP_MASK | GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY))
|
||||
return false;
|
||||
//Return true by default
|
||||
return true;
|
||||
|
@ -146,11 +146,13 @@ int gpu_context_t::gralloc_alloc_buffer(size_t size, int usage,
|
||||
flags |= private_handle_t::PRIV_FLAGS_UNSYNCHRONIZED;
|
||||
}
|
||||
|
||||
if (usage & GRALLOC_USAGE_EXTERNAL_ONLY) {
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY;
|
||||
//The EXTERNAL_BLOCK flag is always an add-on
|
||||
if (usage & GRALLOC_USAGE_EXTERNAL_BLOCK) {
|
||||
if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK;
|
||||
}if (usage & GRALLOC_USAGE_PRIVATE_EXTERNAL_CC) {
|
||||
flags |= private_handle_t::PRIV_FLAGS_EXTERNAL_CC;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,18 +74,20 @@ enum {
|
||||
GRALLOC_USAGE_PRIVATE_DO_NOT_MAP = 0X00800000,
|
||||
|
||||
/* Buffer content should be displayed on an external display only */
|
||||
GRALLOC_USAGE_EXTERNAL_ONLY = 0x00010000,
|
||||
GRALLOC_USAGE_PRIVATE_EXTERNAL_ONLY = 0x00010000,
|
||||
|
||||
/* Only this buffer content should be displayed on external, even if
|
||||
* other EXTERNAL_ONLY buffers are available. Used during suspend.
|
||||
*/
|
||||
GRALLOC_USAGE_EXTERNAL_BLOCK = 0x00020000,
|
||||
GRALLOC_USAGE_PRIVATE_EXTERNAL_BLOCK = 0x00020000,
|
||||
|
||||
/* Close Caption displayed on an external display only */
|
||||
GRALLOC_USAGE_PRIVATE_EXTERNAL_CC = 0x00040000,
|
||||
|
||||
/* Use this flag to request content protected buffers. Please note
|
||||
* that this flag is different from the GRALLOC_USAGE_PROTECTED flag
|
||||
* which can be used for buffers that are not secured for DRM
|
||||
* but still need to be protected from screen captures
|
||||
* 0x00040000 is reserved and these values are subject to change.
|
||||
*/
|
||||
GRALLOC_USAGE_PRIVATE_CP_BUFFER = 0x00080000,
|
||||
};
|
||||
@ -165,6 +167,8 @@ struct private_handle_t : public native_handle {
|
||||
PRIV_FLAGS_EXTERNAL_ONLY = 0x00002000,
|
||||
// Display only this buffer on external
|
||||
PRIV_FLAGS_EXTERNAL_BLOCK = 0x00004000,
|
||||
// Display this buffer on external as close caption
|
||||
PRIV_FLAGS_EXTERNAL_CC = 0x00008000,
|
||||
};
|
||||
|
||||
// file-descriptors
|
||||
|
@ -9,8 +9,14 @@ LOCAL_SHARED_LIBRARIES := $(common_libs) libEGL liboverlay libgenlock \
|
||||
libqdutils libhardware_legacy libdl libmemalloc
|
||||
LOCAL_CFLAGS := $(common_flags) -DLOG_TAG=\"hwcomposer\"
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
|
||||
LOCAL_SRC_FILES := hwc.cpp hwc_video.cpp hwc_utils.cpp \
|
||||
hwc_uimirror.cpp hwc_external.cpp \
|
||||
hwc_uevents.cpp hwc_copybit.cpp \
|
||||
hwc_mdpcomp.cpp
|
||||
LOCAL_SRC_FILES := hwc.cpp \
|
||||
hwc_video.cpp \
|
||||
hwc_utils.cpp \
|
||||
hwc_uimirror.cpp \
|
||||
hwc_external.cpp \
|
||||
hwc_uevents.cpp \
|
||||
hwc_copybit.cpp \
|
||||
hwc_mdpcomp.cpp \
|
||||
hwc_extonly.cpp
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "hwc_copybit.h"
|
||||
#include "hwc_external.h"
|
||||
#include "hwc_mdpcomp.h"
|
||||
#include "hwc_extonly.h"
|
||||
|
||||
using namespace qhwc;
|
||||
|
||||
@ -80,10 +81,16 @@ static int hwc_prepare(hwc_composer_device_t *dev, hwc_layer_list_t* list)
|
||||
ctx->qbuf->unlockAllPrevious();
|
||||
|
||||
if (LIKELY(list)) {
|
||||
//reset for this draw round
|
||||
VideoOverlay::reset();
|
||||
ExtOnly::reset();
|
||||
|
||||
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)) {
|
||||
@ -155,6 +162,7 @@ static int hwc_set(hwc_composer_device_t *dev,
|
||||
hwc_context_t* ctx = (hwc_context_t*)(dev);
|
||||
if (LIKELY(list)) {
|
||||
VideoOverlay::draw(ctx, list);
|
||||
ExtOnly::draw(ctx, list);
|
||||
CopyBit::draw(ctx, list, (EGLDisplay)dpy, (EGLSurface)sur);
|
||||
MDPComp::draw(ctx, list);
|
||||
EGLBoolean sucess = eglSwapBuffers((EGLDisplay)dpy, (EGLSurface)sur);
|
||||
|
161
libhwcomposer/hwc_extonly.cpp
Normal file
161
libhwcomposer/hwc_extonly.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "hwc_extonly.h"
|
||||
#include "hwc_external.h"
|
||||
#include "hwc_qbuf.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
#define EXTONLY_DEBUG 0
|
||||
|
||||
//Static Members
|
||||
ovutils::eOverlayState ExtOnly::sState = ovutils::OV_CLOSED;
|
||||
int ExtOnly::sExtCount = 0;
|
||||
int ExtOnly::sExtIndex = -1;
|
||||
bool ExtOnly::sIsExtBlock = false;
|
||||
bool ExtOnly::sIsModeOn = false;
|
||||
|
||||
//Cache stats, figure out the state, config overlay
|
||||
bool ExtOnly::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
sIsModeOn = false;
|
||||
if(!ctx->mMDP.hasOverlay) {
|
||||
ALOGD_IF(EXTONLY_DEBUG,"%s, this hw doesnt support overlay",
|
||||
__FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
if(sExtIndex == -1) {
|
||||
return false;
|
||||
}
|
||||
chooseState(ctx);
|
||||
//if the state chosen above is CLOSED, skip this block.
|
||||
if(sState != ovutils::OV_CLOSED) {
|
||||
hwc_layer_t *extLayer = &list->hwLayers[sExtIndex];
|
||||
if(configure(ctx, extLayer)) {
|
||||
markFlags(extLayer);
|
||||
sIsModeOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
ALOGD_IF(EXTONLY_DEBUG, "%s: stats: extCount = %d, extIndex = %d,"
|
||||
"IsExtBlock = %d, IsModeOn = %d",
|
||||
__func__, sExtCount, sExtIndex,
|
||||
sIsExtBlock, sIsModeOn);
|
||||
|
||||
return sIsModeOn;
|
||||
}
|
||||
|
||||
void ExtOnly::chooseState(hwc_context_t *ctx) {
|
||||
ALOGD_IF(EXTONLY_DEBUG, "%s: old state = %s", __FUNCTION__,
|
||||
ovutils::getStateString(sState));
|
||||
|
||||
ovutils::eOverlayState newState = ovutils::OV_CLOSED;
|
||||
|
||||
if(sExtCount > 0 &&
|
||||
ctx->mExtDisplay->getExternalDisplay()) {
|
||||
newState = ovutils::OV_DUAL_DISP;
|
||||
}
|
||||
|
||||
sState = newState;
|
||||
ALOGD_IF(EXTONLY_DEBUG, "%s: new chosen state = %s", __FUNCTION__,
|
||||
ovutils::getStateString(sState));
|
||||
}
|
||||
|
||||
void ExtOnly::markFlags(hwc_layer_t *layer) {
|
||||
switch(sState) {
|
||||
case ovutils::OV_DUAL_DISP:
|
||||
layer->compositionType = HWC_OVERLAY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtOnly::configure(hwc_context_t *ctx, hwc_layer_t *layer) {
|
||||
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ov.setState(sState);
|
||||
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_0,
|
||||
isFgFlag,
|
||||
ovutils::ROT_FLAG_DISABLED);
|
||||
ovutils::PipeArgs pargs[ovutils::MAX_PIPES] = { parg, parg, parg };
|
||||
ov.setSource(pargs, ovutils::OV_PIPE0);
|
||||
|
||||
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);
|
||||
ov.setCrop(dcrop, ovutils::OV_PIPE0);
|
||||
|
||||
ov.setTransform(0, ovutils::OV_PIPE0);
|
||||
|
||||
//Setting position same as crop
|
||||
//FIXME stretch to full screen
|
||||
ov.setPosition(dcrop, ovutils::OV_PIPE0);
|
||||
|
||||
if (!ov.commit(ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: commit fails", __FUNCTION__);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExtOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
{
|
||||
if(!sIsModeOn || sExtIndex == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private_handle_t *hnd = (private_handle_t *)
|
||||
list->hwLayers[sExtIndex].handle;
|
||||
|
||||
// Lock this buffer for read.
|
||||
ctx->qbuf->lockAndAdd(hnd);
|
||||
bool ret = true;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
|
||||
switch (state) {
|
||||
case ovutils::OV_DUAL_DISP:
|
||||
// Play external
|
||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: queueBuffer failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
// Wait for external vsync to be done
|
||||
if (!ov.waitForVsync(ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s Unused state %s", __FUNCTION__,
|
||||
ovutils::getStateString(state));
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}; //namespace qhwc
|
82
libhwcomposer/hwc_extonly.h
Normal file
82
libhwcomposer/hwc_extonly.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2012, Code Aurora Forum. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef HWC_EXTONLY_H
|
||||
#define HWC_EXTONLY_H
|
||||
|
||||
#include <overlay.h>
|
||||
#include "hwc_utils.h"
|
||||
|
||||
#define LIKELY( exp ) (__builtin_expect( (exp) != 0, true ))
|
||||
#define UNLIKELY( exp ) (__builtin_expect( (exp) != 0, false ))
|
||||
|
||||
namespace qhwc {
|
||||
//Feature for using overlay to display external-only layers on HDTV
|
||||
class ExtOnly {
|
||||
public:
|
||||
//Sets up members and prepares overlay if conditions are met
|
||||
static bool prepare(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Draws layer if this feature is on
|
||||
static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Receives data from hwc
|
||||
static void setStats(int extCount, int extIndex, bool isExtBlock);
|
||||
//resets values
|
||||
static void reset();
|
||||
private:
|
||||
//Choose an appropriate overlay state based on conditions
|
||||
static void chooseState(hwc_context_t *ctx);
|
||||
//Configures overlay
|
||||
static bool configure(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
//Marks layer flags if this feature is used
|
||||
static void markFlags(hwc_layer_t *layer);
|
||||
//returns ext-only count
|
||||
static int getExtCount();
|
||||
|
||||
//The chosen overlay state.
|
||||
static ovutils::eOverlayState sState;
|
||||
//Number of ext-only layers in this drawing round. Used for stats/debugging.
|
||||
//This does not reflect the closed caption layer count even though its
|
||||
//ext-only.
|
||||
static int sExtCount;
|
||||
//Index of ext-only layer. If there are 2 such layers with 1 marked as BLOCK
|
||||
//then this will hold the index of BLOCK layer.
|
||||
static int sExtIndex;
|
||||
//Flags if ext-only layer is BLOCK, which means only this layer (sExtIndex)
|
||||
//is displayed even if other ext-only layers are present to block their
|
||||
//content. This is used for stats / debugging only.
|
||||
static bool sIsExtBlock;
|
||||
//Flags if this feature is on.
|
||||
static bool sIsModeOn;
|
||||
};
|
||||
|
||||
inline void ExtOnly::setStats(int extCount, int extIndex, bool isExtBlock) {
|
||||
sExtCount = extCount;
|
||||
sExtIndex = extIndex;
|
||||
sIsExtBlock = isExtBlock;
|
||||
}
|
||||
|
||||
inline int ExtOnly::getExtCount() { return sExtCount; }
|
||||
inline void ExtOnly::reset() {
|
||||
sExtCount = 0;
|
||||
sExtIndex = -1;
|
||||
sIsExtBlock = false;
|
||||
sIsModeOn = false;
|
||||
sState = ovutils::OV_CLOSED;
|
||||
}
|
||||
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_EXTONLY_H
|
@ -23,6 +23,7 @@
|
||||
#include "hwc_copybit.h"
|
||||
#include "hwc_external.h"
|
||||
#include "hwc_mdpcomp.h"
|
||||
#include "hwc_extonly.h"
|
||||
|
||||
namespace qhwc {
|
||||
|
||||
@ -107,18 +108,32 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list)
|
||||
int yuvLayerIndex = -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
|
||||
|
||||
for (size_t i = 0; i < list->numHwLayers; i++) {
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[i].handle;
|
||||
|
||||
if (isYuvBuffer(hnd)) {
|
||||
if (UNLIKELY(isYuvBuffer(hnd))) {
|
||||
yuvCount++;
|
||||
yuvLayerIndex = i;
|
||||
//Animating
|
||||
if (isSkipLayer(&list->hwLayers[i])) {
|
||||
isYuvLayerSkip = true;
|
||||
}
|
||||
} 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])) { //Popups
|
||||
//If video layer is below a skip layer
|
||||
if(yuvLayerIndex != -1 && yuvLayerIndex < (ssize_t)i) {
|
||||
@ -128,7 +143,9 @@ void getLayerStats(hwc_context_t *ctx, const hwc_layer_list_t *list)
|
||||
}
|
||||
}
|
||||
|
||||
VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
|
||||
VideoOverlay::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip,
|
||||
ccLayerIndex);
|
||||
ExtOnly::setStats(extCount, extLayerIndex, isExtBlockPresent);
|
||||
CopyBit::setStats(yuvCount, yuvLayerIndex, isYuvLayerSkip);
|
||||
MDPComp::setStats(skipCount);
|
||||
|
||||
|
@ -90,6 +90,21 @@ static inline bool isBufferLocked(const private_handle_t* hnd) {
|
||||
return (hnd && (private_handle_t::PRIV_FLAGS_HWC_LOCK & hnd->flags));
|
||||
}
|
||||
|
||||
//Return true if buffer is for external display only
|
||||
static inline bool isExtOnly(const private_handle_t* hnd) {
|
||||
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY));
|
||||
}
|
||||
|
||||
//Return true if buffer is for external display only with a BLOCK flag.
|
||||
static inline bool isExtBlock(const private_handle_t* hnd) {
|
||||
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK));
|
||||
}
|
||||
|
||||
//Return true if buffer is for external display only with a Close Caption flag.
|
||||
static inline bool isExtCC(const private_handle_t* hnd) {
|
||||
return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
|
||||
}
|
||||
|
||||
// Initialize uevent thread
|
||||
void init_uevent_thread(hwc_context_t* ctx);
|
||||
|
||||
|
@ -29,8 +29,9 @@ namespace qhwc {
|
||||
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::sIsLayerSkip = false;
|
||||
|
||||
//Cache stats, figure out the state, config overlay
|
||||
bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
@ -45,15 +46,21 @@ bool VideoOverlay::prepare(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
||||
chooseState(ctx);
|
||||
//if the state chosen above is CLOSED, skip this block.
|
||||
if(sState != ovutils::OV_CLOSED) {
|
||||
if(configure(ctx, &list->hwLayers[sYuvLayerIndex])) {
|
||||
hwc_layer_t *yuvLayer = &list->hwLayers[sYuvLayerIndex];
|
||||
hwc_layer_t *ccLayer = NULL;
|
||||
if(sCCLayerIndex != -1)
|
||||
ccLayer = &list->hwLayers[sCCLayerIndex];
|
||||
|
||||
if(configure(ctx, yuvLayer, ccLayer)) {
|
||||
markFlags(&list->hwLayers[sYuvLayerIndex]);
|
||||
sIsModeOn = true;
|
||||
}
|
||||
}
|
||||
|
||||
ALOGD_IF(VIDEO_DEBUG, "%s: stats: yuvCount = %d, yuvIndex = %d,"
|
||||
"IsModeOn = %d, IsSkipLayer = %d", __FUNCTION__, sYuvCount,
|
||||
sYuvLayerIndex, sIsModeOn, sIsLayerSkip);
|
||||
"IsYuvLayerSkip = %d, ccLayerIndex = %d, IsModeOn = %d",
|
||||
__FUNCTION__, sYuvCount, sYuvLayerIndex,
|
||||
sIsYuvLayerSkip, sCCLayerIndex, sIsModeOn);
|
||||
|
||||
return sIsModeOn;
|
||||
}
|
||||
@ -63,14 +70,13 @@ void VideoOverlay::chooseState(hwc_context_t *ctx) {
|
||||
ovutils::getStateString(sState));
|
||||
|
||||
ovutils::eOverlayState newState = ovutils::OV_CLOSED;
|
||||
//TODO check if device supports overlay and hdmi
|
||||
|
||||
//Support 1 video layer
|
||||
if(sYuvCount == 1) {
|
||||
//Skip on primary, display on ext.
|
||||
if(sIsLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
|
||||
if(sIsYuvLayerSkip && ctx->mExtDisplay->getExternalDisplay()) {
|
||||
newState = ovutils::OV_2D_VIDEO_ON_TV;
|
||||
} else if(sIsLayerSkip) { //skip on primary, no ext
|
||||
} else if(sIsYuvLayerSkip) { //skip on primary, no ext
|
||||
newState = ovutils::OV_CLOSED;
|
||||
} else if(ctx->mExtDisplay->getExternalDisplay()) {
|
||||
//display on both
|
||||
@ -228,8 +234,49 @@ bool configExtVid(hwc_context_t *ctx, hwc_layer_t *layer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer)
|
||||
{
|
||||
bool configExtCC(hwc_context_t *ctx, hwc_layer_t *layer) {
|
||||
if(layer == NULL)
|
||||
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_t *yuvLayer,
|
||||
hwc_layer_t *ccLayer) {
|
||||
|
||||
bool ret = true;
|
||||
if (LIKELY(ctx->mOverlay)) {
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
@ -241,10 +288,12 @@ bool VideoOverlay::configure(hwc_context_t *ctx, hwc_layer_t *yuvLayer)
|
||||
break;
|
||||
case ovutils::OV_2D_VIDEO_ON_PANEL_TV:
|
||||
ret &= configExtVid(ctx, yuvLayer);
|
||||
ret &= configExtCC(ctx, ccLayer);
|
||||
ret &= configPrimVid(ctx, yuvLayer);
|
||||
break;
|
||||
case ovutils::OV_2D_VIDEO_ON_TV:
|
||||
ret &= configExtVid(ctx, yuvLayer);
|
||||
ret &= configExtCC(ctx, ccLayer);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
@ -262,11 +311,18 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
return true;
|
||||
}
|
||||
|
||||
private_handle_t *hnd =
|
||||
(private_handle_t *)list->hwLayers[sYuvLayerIndex].handle;
|
||||
private_handle_t *hnd = (private_handle_t *)
|
||||
list->hwLayers[sYuvLayerIndex].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;
|
||||
overlay::Overlay& ov = *(ctx->mOverlay);
|
||||
ovutils::eOverlayState state = ov.getState();
|
||||
@ -278,6 +334,12 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
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;
|
||||
}
|
||||
// Play primary
|
||||
if (!ov.queueBuffer(hnd->fd, hnd->offset, ovutils::OV_PIPE0)) {
|
||||
ALOGE("%s: queueBuffer failed for primary", __FUNCTION__);
|
||||
@ -302,11 +364,18 @@ bool VideoOverlay::draw(hwc_context_t *ctx, hwc_layer_list_t *list)
|
||||
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;
|
||||
}
|
||||
// Wait for external vsync to be done
|
||||
if (!ov.waitForVsync(ovutils::OV_PIPE1)) {
|
||||
ALOGE("%s: waitForVsync failed for external", __FUNCTION__);
|
||||
ret = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ALOGE("%s Unused state %s", __FUNCTION__,
|
||||
ovutils::getStateString(state));
|
||||
|
@ -30,12 +30,16 @@ public:
|
||||
//Draws layer if this feature is on
|
||||
static bool draw(hwc_context_t *ctx, hwc_layer_list_t *list);
|
||||
//Receives data from hwc
|
||||
static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
|
||||
static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip,
|
||||
int ccLayerIndex);
|
||||
//resets values
|
||||
static void reset();
|
||||
private:
|
||||
//Choose an appropriate overlay state based on conditions
|
||||
static void chooseState(hwc_context_t *ctx);
|
||||
//Configures overlay
|
||||
static bool configure(hwc_context_t *ctx, hwc_layer_t *layer);
|
||||
//Configures overlay for video prim and ext
|
||||
static bool configure(hwc_context_t *ctx, hwc_layer_t *yuvlayer,
|
||||
hwc_layer_t *ccLayer);
|
||||
//Marks layer flags if this feature is used
|
||||
static void markFlags(hwc_layer_t *layer);
|
||||
//returns yuv count
|
||||
@ -48,20 +52,30 @@ private:
|
||||
//Index of YUV layer, relevant only if count is 1
|
||||
static int sYuvLayerIndex;
|
||||
//Flags if a yuv layer is animating or below something that is animating
|
||||
static bool sIsLayerSkip;
|
||||
static bool sIsYuvLayerSkip;
|
||||
//Holds the closed caption layer index, -1 by default
|
||||
static int sCCLayerIndex;
|
||||
//Flags if this feature is on.
|
||||
static bool sIsModeOn;
|
||||
};
|
||||
|
||||
inline void VideoOverlay::setStats(int yuvCount, int yuvLayerIndex,
|
||||
bool isYuvLayerSkip) {
|
||||
bool isYuvLayerSkip, int ccLayerIndex) {
|
||||
sYuvCount = yuvCount;
|
||||
sYuvLayerIndex = yuvLayerIndex;
|
||||
sIsLayerSkip = isYuvLayerSkip;
|
||||
sIsYuvLayerSkip = isYuvLayerSkip;
|
||||
sCCLayerIndex = ccLayerIndex;
|
||||
}
|
||||
|
||||
inline int VideoOverlay::getYuvCount() { return sYuvCount; }
|
||||
|
||||
inline void VideoOverlay::reset() {
|
||||
sYuvCount = 0;
|
||||
sYuvLayerIndex = -1;
|
||||
sIsYuvLayerSkip = false;
|
||||
sCCLayerIndex = -1;
|
||||
sIsModeOn = false;
|
||||
sState = ovutils::OV_CLOSED;
|
||||
}
|
||||
}; //namespace qhwc
|
||||
|
||||
#endif //HWC_VIDEO_H
|
||||
|
@ -265,7 +265,7 @@ template <> struct StateTraits<utils::OV_BYPASS_3_LAYER>
|
||||
template <> struct StateTraits<utils::OV_DUAL_DISP>
|
||||
{
|
||||
typedef overlay::GenericPipe<utils::EXTERNAL> pipe0;
|
||||
typedef overlay::GenericPipe<utils::EXTERNAL> pipe1;
|
||||
typedef overlay::NullPipe pipe1;
|
||||
typedef overlay::NullPipe pipe2;
|
||||
|
||||
typedef NullRotator rot0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user