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. */