Turn on support for async cursor update in surfaceflinger.

If available, surfaceflinger will use the hwc setCursorPositionAsync()
api to change the position of supported cursor layers outside of
the usual prepare/set loop.

Change-Id: Ib3fc5c0c390b3489ddbba202379840a1d2748917
This commit is contained in:
Riley Andrews 2014-07-01 14:22:59 -07:00
parent d8e5e81343
commit 03414a1cfe
8 changed files with 117 additions and 3 deletions

View File

@ -47,6 +47,7 @@ public:
eOpaque = 0x00000400,
eProtectedByApp = 0x00000800,
eProtectedByDRM = 0x00001000,
eCursorWindow = 0x00002000,
eFXSurfaceNormal = 0x00000000,
eFXSurfaceDim = 0x00020000,

View File

@ -64,7 +64,9 @@ public:
USAGE_HW_2D = GRALLOC_USAGE_HW_2D,
USAGE_HW_COMPOSER = GRALLOC_USAGE_HW_COMPOSER,
USAGE_HW_VIDEO_ENCODER = GRALLOC_USAGE_HW_VIDEO_ENCODER,
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK
USAGE_HW_MASK = GRALLOC_USAGE_HW_MASK,
USAGE_CURSOR = GRALLOC_USAGE_CURSOR,
};
GraphicBuffer();

View File

@ -681,6 +681,9 @@ status_t HWComposer::prepare() {
if (l.compositionType == HWC_OVERLAY) {
disp.hasOvComp = true;
}
if (l.compositionType == HWC_CURSOR_OVERLAY) {
disp.hasOvComp = true;
}
}
if (disp.list->numHwLayers == (disp.framebufferTarget ? 1 : 0)) {
disp.hasFbComp = true;
@ -853,6 +856,16 @@ sp<Fence> HWComposer::getLastRetireFence(int32_t id) const {
return mDisplayData[id].lastRetireFence;
}
status_t HWComposer::setCursorPositionAsync(int32_t id, const Rect& pos)
{
if (mHwc->setCursorPositionAsync) {
return (status_t)mHwc->setCursorPositionAsync(mHwc, id, pos.left, pos.top);
}
else {
return NO_ERROR;
}
}
/*
* Helper template to implement a concrete HWCLayer
* This holds the pointer to the concrete hwc layer type
@ -935,6 +948,16 @@ public:
getLayer()->flags &= ~HWC_SKIP_LAYER;
}
}
virtual void setIsCursorLayerHint(bool isCursor) {
if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
if (isCursor) {
getLayer()->flags |= HWC_IS_CURSOR_LAYER;
}
else {
getLayer()->flags &= ~HWC_IS_CURSOR_LAYER;
}
}
}
virtual void setBlending(uint32_t blending) {
getLayer()->blending = blending;
}
@ -1122,6 +1145,8 @@ void HWComposer::dump(String8& result) const {
"HWC",
"BKGND",
"FB TARGET",
"SIDEBAND",
"HWC_CURSOR",
"UNKNOWN"};
if (type >= NELEM(compositionTypeName))
type = NELEM(compositionTypeName) - 1;

View File

@ -141,6 +141,8 @@ public:
// displays, writes to the output buffer are complete.
sp<Fence> getLastRetireFence(int32_t id) const;
status_t setCursorPositionAsync(int32_t id, const Rect &pos);
/*
* Interface to hardware composer's layers functionality.
* This abstracts the HAL interface to layers which can evolve in
@ -157,6 +159,7 @@ public:
virtual sp<Fence> getAndResetReleaseFence() = 0;
virtual void setDefaultState() = 0;
virtual void setSkip(bool skip) = 0;
virtual void setIsCursorLayerHint(bool isCursor = true) = 0;
virtual void setBlending(uint32_t blending) = 0;
virtual void setTransform(uint32_t transform) = 0;
virtual void setFrame(const Rect& frame) = 0;

View File

@ -79,7 +79,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mSecure(false),
mProtectedByApp(false),
mHasSurface(false),
mClientRef(client)
mClientRef(client),
mPotentialCursor(false)
{
mCurrentCrop.makeInvalid();
mFlinger->getRenderEngine().genTextures(1, &mTextureName);
@ -200,6 +201,7 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mFormat = format;
mPotentialCursor = (flags & ISurfaceComposerClient::eCursorWindow) ? true : false;
mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
mCurrentOpacity = getOpacityForFormat(format);
@ -441,7 +443,7 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
// TODO: there is a possible optimization here: we only need to set the
// acquire fence the first time a new buffer is acquired on EACH display.
if (layer.getCompositionType() == HWC_OVERLAY) {
if (layer.getCompositionType() == HWC_OVERLAY || layer.getCompositionType() == HWC_CURSOR_OVERLAY) {
sp<Fence> fence = mSurfaceFlingerConsumer->getCurrentFence();
if (fence->isValid()) {
fenceFd = fence->dup();
@ -453,6 +455,26 @@ void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */,
layer.setAcquireFenceFd(fenceFd);
}
Rect Layer::getPosition(
const sp<const DisplayDevice>& hw)
{
// this gives us only the "orientation" component of the transform
const State& s(getCurrentState());
// apply the layer's transform, followed by the display's global transform
// here we're guaranteed that the layer's transform preserves rects
Rect win(s.active.w, s.active.h);
if (!s.active.crop.isEmpty()) {
win.intersect(s.active.crop, &win);
}
// subtract the transparent region and snap to the bounds
Rect bounds = reduce(win, s.activeTransparentRegion);
Rect frame(s.transform.transform(bounds));
frame.intersect(hw->getViewport(), &frame);
const Transform& tr(hw->getTransform());
return Rect(tr.transform(frame));
}
// ---------------------------------------------------------------------------
// drawing...
// ---------------------------------------------------------------------------
@ -1187,6 +1209,9 @@ uint32_t Layer::getEffectiveUsage(uint32_t usage) const
// need a hardware-protected path to external video sink
usage |= GraphicBuffer::USAGE_PROTECTED;
}
if (mPotentialCursor) {
usage |= GraphicBuffer::USAGE_CURSOR;
}
usage |= GraphicBuffer::USAGE_HW_COMPOSER;
return usage;
}

View File

@ -201,6 +201,8 @@ public:
void setAcquireFence(const sp<const DisplayDevice>& hw,
HWComposer::HWCLayerInterface& layer);
Rect getPosition(const sp<const DisplayDevice>& hw);
/*
* called after page-flip
*/
@ -260,6 +262,8 @@ public:
*/
Region latchBuffer(bool& recomputeVisibleRegions);
bool isPotentialCursor() const { return mPotentialCursor;}
/*
* called with the state lock when the surface is removed from the
* current list
@ -391,6 +395,9 @@ private:
// Set to true once we've returned this surface's handle
mutable bool mHasSurface;
const wp<Client> mClientRef;
// This layer can be a cursor on some displays.
bool mPotentialCursor;
};
// ---------------------------------------------------------------------------

View File

@ -990,6 +990,26 @@ void SurfaceFlinger::setUpHWComposer() {
}
}
// If possible, attempt to use the cursor overlay on each display.
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id >= 0) {
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
const sp<Layer>& layer(currentLayers[i]);
if (layer->isPotentialCursor()) {
cur->setIsCursorLayerHint();
break;
}
}
}
}
status_t err = hwc.prepare();
ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
@ -1364,6 +1384,34 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags)
}
commitTransaction();
updateCursorAsync();
}
void SurfaceFlinger::updateCursorAsync()
{
HWComposer& hwc(getHwComposer());
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
sp<const DisplayDevice> hw(mDisplays[dpy]);
const int32_t id = hw->getHwcDisplayId();
if (id < 0) {
continue;
}
const Vector< sp<Layer> >& currentLayers(
hw->getVisibleLayersSortedByZ());
const size_t count = currentLayers.size();
HWComposer::LayerListIterator cur = hwc.begin(id);
const HWComposer::LayerListIterator end = hwc.end(id);
for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
if (cur->getCompositionType() != HWC_CURSOR_OVERLAY) {
continue;
}
const sp<Layer>& layer(currentLayers[i]);
Rect cursorPos = layer->getPosition(hw);
hwc.setCursorPositionAsync(id, cursorPos);
break;
}
}
}
void SurfaceFlinger::commitTransaction()
@ -1695,6 +1743,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
const Region clip(dirty.intersect(tr.transform(layer->visibleRegion)));
if (!clip.isEmpty()) {
switch (cur->getCompositionType()) {
case HWC_CURSOR_OVERLAY:
case HWC_OVERLAY: {
const Layer::State& state(layer->getDrawingState());
if ((cur->getHints() & HWC_HINT_CLEAR_FB)

View File

@ -249,6 +249,8 @@ private:
void handleTransaction(uint32_t transactionFlags);
void handleTransactionLocked(uint32_t transactionFlags);
void updateCursorAsync();
/* handlePageFilp: this is were we latch a new buffer
* if available and compute the dirty region.
*/