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:
Saurabh Shah 2012-07-21 19:06:55 -07:00 committed by Naseer Ahmed
parent 446b936947
commit bf3c454efe
12 changed files with 409 additions and 31 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)

View File

@ -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);

View 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

View 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

View File

@ -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);

View File

@ -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);

View File

@ -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));

View File

@ -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

View File

@ -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;