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:
parent
d8e5e81343
commit
03414a1cfe
@ -47,6 +47,7 @@ public:
|
||||
eOpaque = 0x00000400,
|
||||
eProtectedByApp = 0x00000800,
|
||||
eProtectedByDRM = 0x00001000,
|
||||
eCursorWindow = 0x00002000,
|
||||
|
||||
eFXSurfaceNormal = 0x00000000,
|
||||
eFXSurfaceDim = 0x00020000,
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user