From 03414a1cfe6c1222fd7723949bd622f9cba145aa Mon Sep 17 00:00:00 2001 From: Riley Andrews Date: Tue, 1 Jul 2014 14:22:59 -0700 Subject: [PATCH] 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 --- include/gui/ISurfaceComposerClient.h | 1 + include/ui/GraphicBuffer.h | 4 +- .../DisplayHardware/HWComposer.cpp | 25 ++++++++++ .../DisplayHardware/HWComposer.h | 3 ++ services/surfaceflinger/Layer.cpp | 29 ++++++++++- services/surfaceflinger/Layer.h | 7 +++ services/surfaceflinger/SurfaceFlinger.cpp | 49 +++++++++++++++++++ services/surfaceflinger/SurfaceFlinger.h | 2 + 8 files changed, 117 insertions(+), 3 deletions(-) diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h index 58c1f6a55..bb79bd02b 100644 --- a/include/gui/ISurfaceComposerClient.h +++ b/include/gui/ISurfaceComposerClient.h @@ -47,6 +47,7 @@ public: eOpaque = 0x00000400, eProtectedByApp = 0x00000800, eProtectedByDRM = 0x00001000, + eCursorWindow = 0x00002000, eFXSurfaceNormal = 0x00000000, eFXSurfaceDim = 0x00020000, diff --git a/include/ui/GraphicBuffer.h b/include/ui/GraphicBuffer.h index ddc46359b..7630faa76 100644 --- a/include/ui/GraphicBuffer.h +++ b/include/ui/GraphicBuffer.h @@ -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(); diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 185dab227..a8fb5bdf9 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -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 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; diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index c62b924ca..9bd99eb78 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -141,6 +141,8 @@ public: // displays, writes to the output buffer are complete. sp 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 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; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 4861e3402..bbb5cfed5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -79,7 +79,8 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& 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& /* 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 = mSurfaceFlingerConsumer->getCurrentFence(); if (fence->isValid()) { fenceFd = fence->dup(); @@ -453,6 +455,26 @@ void Layer::setAcquireFence(const sp& /* hw */, layer.setAcquireFenceFd(fenceFd); } +Rect Layer::getPosition( + const sp& 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; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 2d8084df5..e21dd3623 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -201,6 +201,8 @@ public: void setAcquireFence(const sp& hw, HWComposer::HWCLayerInterface& layer); + Rect getPosition(const sp& 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 mClientRef; + + // This layer can be a cursor on some displays. + bool mPotentialCursor; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index aeba72053..53b0dc4d6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -990,6 +990,26 @@ void SurfaceFlinger::setUpHWComposer() { } } + // If possible, attempt to use the cursor overlay on each display. + for (size_t dpy=0 ; dpy hw(mDisplays[dpy]); + const int32_t id = hw->getHwcDisplayId(); + if (id >= 0) { + const Vector< sp >& 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& 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 hw(mDisplays[dpy]); + const int32_t id = hw->getHwcDisplayId(); + if (id < 0) { + continue; + } + const Vector< sp >& 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 && igetCompositionType() != HWC_CURSOR_OVERLAY) { + continue; + } + const sp& 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& 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) diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 996a795cf..476e549af 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -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. */