diff options
author | Jesse Hall <jessehall@google.com> | 2014-03-13 20:28:16 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-03-13 20:28:17 +0000 |
commit | 73ed82f809a40560fd3a6d53d18e5c846362d764 (patch) | |
tree | cbf5d50d6c3b7cd49b69c1d95b4f294f64cae8a7 | |
parent | a3f519fe6ffb6ac358a3a8015beb94ef1b596ae5 (diff) | |
parent | 399184a4cd728ea1421fb0bc1722274a29e38f4a (diff) | |
download | frameworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.zip frameworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.tar.gz frameworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.tar.bz2 |
Merge "Add sideband streams to BufferQueue and related classes"
24 files changed, 252 insertions, 16 deletions
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h index b0180a6..f74dc26 100644 --- a/include/gui/BufferQueue.h +++ b/include/gui/BufferQueue.h @@ -100,6 +100,7 @@ public: virtual ~ProxyConsumerListener(); virtual void onFrameAvailable(); virtual void onBuffersReleased(); + virtual void onSidebandStreamChanged(); private: // mConsumerListener is a weak reference to the IConsumerListener. This is // the raison d'etre of ProxyConsumerListener. @@ -253,6 +254,18 @@ public: // connected to the specified producer API. virtual status_t disconnect(int api); + // Attaches a sideband buffer stream to the BufferQueue. + // + // A sideband stream is a device-specific mechanism for passing buffers + // from the producer to the consumer without using dequeueBuffer/ + // queueBuffer. If a sideband stream is present, the consumer can choose + // whether to acquire buffers from the sideband stream or from the queued + // buffers. + // + // Passing NULL or a different stream handle will detach the previous + // handle if any. + virtual status_t setSidebandStream(const sp<NativeHandle>& stream); + /* * IGraphicBufferConsumer interface */ @@ -362,6 +375,9 @@ public: // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). virtual status_t setTransformHint(uint32_t hint); + // Retrieve the BufferQueue's sideband stream, if any. + virtual sp<NativeHandle> getSidebandStream() const; + // dump our state in a String virtual void dump(String8& result, const char* prefix) const; diff --git a/include/gui/BufferQueueConsumer.h b/include/gui/BufferQueueConsumer.h index 71105df..7f24c83 100644 --- a/include/gui/BufferQueueConsumer.h +++ b/include/gui/BufferQueueConsumer.h @@ -139,6 +139,9 @@ public: // NATIVE_WINDOW_TRANSFORM_ROT_90. The default is 0 (no transform). virtual status_t setTransformHint(uint32_t hint); + // Retrieve the sideband buffer stream, if any. + virtual sp<NativeHandle> getSidebandStream() const; + // dump our state in a String virtual void dump(String8& result, const char* prefix) const; diff --git a/include/gui/BufferQueueCore.h b/include/gui/BufferQueueCore.h index f4341f8..89f2779 100644 --- a/include/gui/BufferQueueCore.h +++ b/include/gui/BufferQueueCore.h @@ -22,6 +22,7 @@ #include <utils/Condition.h> #include <utils/Mutex.h> +#include <utils/NativeHandle.h> #include <utils/RefBase.h> #include <utils/String8.h> #include <utils/StrongPointer.h> @@ -230,6 +231,9 @@ private: // mTransformHint is used to optimize for screen rotations. uint32_t mTransformHint; + // mSidebandStream is a handle to the sideband buffer stream, if any + sp<NativeHandle> mSidebandStream; + }; // class BufferQueueCore } // namespace android diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h index 2eeb979..0013b0a 100644 --- a/include/gui/BufferQueueProducer.h +++ b/include/gui/BufferQueueProducer.h @@ -153,6 +153,18 @@ public: // connected to the specified producer API. virtual status_t disconnect(int api); + // Attaches a sideband buffer stream to the IGraphicBufferProducer. + // + // A sideband stream is a device-specific mechanism for passing buffers + // from the producer to the consumer without using dequeueBuffer/ + // queueBuffer. If a sideband stream is present, the consumer can choose + // whether to acquire buffers from the sideband stream or from the queued + // buffers. + // + // Passing NULL or a different stream handle will detach the previous + // handle if any. + virtual status_t setSidebandStream(const sp<NativeHandle>& stream); + private: // This is required by the IBinder::DeathRecipient interface virtual void binderDied(const wp<IBinder>& who); diff --git a/include/gui/ConsumerBase.h b/include/gui/ConsumerBase.h index fb21185..100bb26 100644 --- a/include/gui/ConsumerBase.h +++ b/include/gui/ConsumerBase.h @@ -101,11 +101,14 @@ protected: // Implementation of the IConsumerListener interface. These // calls are used to notify the ConsumerBase of asynchronous events in the - // BufferQueue. These methods should not need to be overridden by derived - // classes, but if they are overridden the ConsumerBase implementation - // must be called from the derived class. + // BufferQueue. The onFrameAvailable and onBuffersReleased methods should + // not need to be overridden by derived classes, but if they are overridden + // the ConsumerBase implementation must be called from the derived class. + // The ConsumerBase version of onSidebandStreamChanged does nothing and can + // be overriden by derived classes if they want the notification. virtual void onFrameAvailable(); virtual void onBuffersReleased(); + virtual void onSidebandStreamChanged(); // freeBufferLocked frees up the given buffer slot. If the slot has been // initialized this will release the reference to the GraphicBuffer in that diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h index ac2f9bb..260099e 100644 --- a/include/gui/IConsumerListener.h +++ b/include/gui/IConsumerListener.h @@ -57,6 +57,12 @@ public: // This is called without any lock held and can be called concurrently // by multiple threads. virtual void onBuffersReleased() = 0; /* Asynchronous */ + + // onSidebandStreamChanged is called to notify the buffer consumer that the + // BufferQueue's sideband buffer stream has changed. This is called when a + // stream is first attached and when it is either detached or replaced by a + // different stream. + virtual void onSidebandStreamChanged() = 0; /* Asynchronous */ }; diff --git a/include/gui/IGraphicBufferConsumer.h b/include/gui/IGraphicBufferConsumer.h index 5e97854..b0d4c76 100644 --- a/include/gui/IGraphicBufferConsumer.h +++ b/include/gui/IGraphicBufferConsumer.h @@ -30,9 +30,10 @@ namespace android { // ---------------------------------------------------------------------------- -class IConsumerListener; -class GraphicBuffer; class Fence; +class GraphicBuffer; +class IConsumerListener; +class NativeHandle; class IGraphicBufferConsumer : public IInterface { @@ -296,6 +297,9 @@ public: // Return of a value other than NO_ERROR means an unknown error has occurred. virtual status_t setTransformHint(uint32_t hint) = 0; + // Retrieve the sideband buffer stream, if any. + virtual sp<NativeHandle> getSidebandStream() const = 0; + // dump state into a string virtual void dump(String8& result, const char* prefix) const = 0; diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h index 25a86a5..0874f03 100644 --- a/include/gui/IGraphicBufferProducer.h +++ b/include/gui/IGraphicBufferProducer.h @@ -32,6 +32,7 @@ namespace android { // ---------------------------------------------------------------------------- +class NativeHandle; class Surface; /* @@ -392,6 +393,18 @@ public: // * api was out of range (see above). // * DEAD_OBJECT - the token is hosted by an already-dead process virtual status_t disconnect(int api) = 0; + + // Attaches a sideband buffer stream to the IGraphicBufferProducer. + // + // A sideband stream is a device-specific mechanism for passing buffers + // from the producer to the consumer without using dequeueBuffer/ + // queueBuffer. If a sideband stream is present, the consumer can choose + // whether to acquire buffers from the sideband stream or from the queued + // buffers. + // + // Passing NULL or a different stream handle will detach the previous + // handle if any. + virtual status_t setSidebandStream(const sp<NativeHandle>& stream) = 0; }; // ---------------------------------------------------------------------------- diff --git a/include/gui/Surface.h b/include/gui/Surface.h index 6f8a97c..d8e9756 100644 --- a/include/gui/Surface.h +++ b/include/gui/Surface.h @@ -78,6 +78,19 @@ public: return surface != NULL && surface->getIGraphicBufferProducer() != NULL; } + /* Attaches a sideband buffer stream to the Surface's IGraphicBufferProducer. + * + * A sideband stream is a device-specific mechanism for passing buffers + * from the producer to the consumer without using dequeueBuffer/ + * queueBuffer. If a sideband stream is present, the consumer can choose + * whether to acquire buffers from the sideband stream or from the queued + * buffers. + * + * Passing NULL or a different stream handle will detach the previous + * handle if any. + */ + void setSidebandStream(const sp<NativeHandle>& stream); + protected: virtual ~Surface(); diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 5000444..c306f9d 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -128,6 +128,10 @@ status_t BufferQueue::disconnect(int api) { return mProducer->disconnect(api); } +status_t BufferQueue::setSidebandStream(const sp<NativeHandle>& stream) { + return mProducer->setSidebandStream(stream); +} + status_t BufferQueue::acquireBuffer(BufferItem* buffer, nsecs_t presentWhen) { return mConsumer->acquireBuffer(buffer, presentWhen); } @@ -192,8 +196,19 @@ status_t BufferQueue::setTransformHint(uint32_t hint) { return mConsumer->setTransformHint(hint); } +sp<NativeHandle> BufferQueue::getSidebandStream() const { + return mConsumer->getSidebandStream(); +} + void BufferQueue::dump(String8& result, const char* prefix) const { mConsumer->dump(result, prefix); } +void BufferQueue::ProxyConsumerListener::onSidebandStreamChanged() { + sp<ConsumerListener> listener(mConsumerListener.promote()); + if (listener != NULL) { + listener->onSidebandStreamChanged(); + } +} + }; // namespace android diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 66fdab3..756cd61 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -478,6 +478,10 @@ status_t BufferQueueConsumer::setTransformHint(uint32_t hint) { return NO_ERROR; } +sp<NativeHandle> BufferQueueConsumer::getSidebandStream() const { + return mCore->mSidebandStream; +} + void BufferQueueConsumer::dump(String8& result, const char* prefix) const { mCore->dump(result, prefix); } diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 58e19f0..7db344a 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -767,6 +767,7 @@ status_t BufferQueueProducer::disconnect(int api) { } mCore->mConnectedProducerToken = NULL; mCore->mConnectedApi = BufferQueueCore::NO_CONNECTED_API; + mCore->mSidebandStream.clear(); mCore->mDequeueCondition.broadcast(); listener = mCore->mConsumerListener; } else { @@ -790,6 +791,12 @@ status_t BufferQueueProducer::disconnect(int api) { return status; } +status_t BufferQueueProducer::setSidebandStream(const sp<NativeHandle>& stream) { + Mutex::Autolock _l(mCore->mMutex); + mCore->mSidebandStream = stream; + return NO_ERROR; +} + void BufferQueueProducer::binderDied(const wp<android::IBinder>& /* who */) { // If we're here, it means that a producer we were connected to died. // We're guaranteed that we are still connected to it because we remove diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index c5900aa..b6adc54 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -130,6 +130,9 @@ void ConsumerBase::onBuffersReleased() { } } +void ConsumerBase::onSidebandStreamChanged() { +} + void ConsumerBase::abandon() { CB_LOGV("abandon"); Mutex::Autolock lock(mMutex); diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index 5304462..4ccf0ac 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -28,7 +28,8 @@ namespace android { enum { ON_FRAME_AVAILABLE = IBinder::FIRST_CALL_TRANSACTION, - ON_BUFFER_RELEASED + ON_BUFFER_RELEASED, + ON_SIDEBAND_STREAM_CHANGED, }; class BpConsumerListener : public BpInterface<IConsumerListener> @@ -49,6 +50,12 @@ public: data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); remote()->transact(ON_BUFFER_RELEASED, data, &reply, IBinder::FLAG_ONEWAY); } + + virtual void onSidebandStreamChanged() { + Parcel data, reply; + data.writeInterfaceToken(IConsumerListener::getInterfaceDescriptor()); + remote()->transact(ON_SIDEBAND_STREAM_CHANGED, data, &reply, IBinder::FLAG_ONEWAY); + } }; IMPLEMENT_META_INTERFACE(ConsumerListener, "android.gui.IConsumerListener"); @@ -67,6 +74,10 @@ status_t BnConsumerListener::onTransact( CHECK_INTERFACE(IConsumerListener, data, reply); onBuffersReleased(); return NO_ERROR; + case ON_SIDEBAND_STREAM_CHANGED: + CHECK_INTERFACE(IConsumerListener, data, reply); + onSidebandStreamChanged(); + return NO_ERROR; } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp index 8d64380..3598a86 100644 --- a/libs/gui/IGraphicBufferConsumer.cpp +++ b/libs/gui/IGraphicBufferConsumer.cpp @@ -24,6 +24,7 @@ #include <sys/types.h> #include <utils/Errors.h> +#include <utils/NativeHandle.h> #include <binder/Parcel.h> #include <binder/IInterface.h> @@ -197,6 +198,7 @@ enum { SET_DEFAULT_BUFFER_FORMAT, SET_CONSUMER_USAGE_BITS, SET_TRANSFORM_HINT, + GET_SIDEBAND_STREAM, DUMP, }; @@ -381,6 +383,20 @@ public: return reply.readInt32(); } + virtual sp<NativeHandle> getSidebandStream() const { + Parcel data, reply; + status_t err; + data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); + if ((err = remote()->transact(GET_SIDEBAND_STREAM, data, &reply)) != NO_ERROR) { + return NULL; + } + sp<NativeHandle> stream; + if (reply.readInt32()) { + stream = NativeHandle::create(reply.readNativeHandle()); + } + return stream; + } + virtual void dump(String8& result, const char* prefix) const { Parcel data, reply; data.writeInterfaceToken(IGraphicBufferConsumer::getInterfaceDescriptor()); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 16d8c05..1d4ec1c 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -18,9 +18,10 @@ #include <sys/types.h> #include <utils/Errors.h> +#include <utils/NativeHandle.h> #include <utils/RefBase.h> -#include <utils/Vector.h> #include <utils/Timers.h> +#include <utils/Vector.h> #include <binder/Parcel.h> #include <binder/IInterface.h> @@ -41,6 +42,7 @@ enum { QUERY, CONNECT, DISCONNECT, + SET_SIDEBAND_STREAM, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -196,6 +198,22 @@ public: result = reply.readInt32(); return result; } + + virtual status_t setSidebandStream(const sp<NativeHandle>& stream) { + Parcel data, reply; + status_t result; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + if (stream.get()) { + data.writeInt32(true); + data.writeNativeHandle(stream->handle()); + } else { + data.writeInt32(false); + } + if ((result = remote()->transact(SET_SIDEBAND_STREAM, data, &reply)) == NO_ERROR) { + result = reply.readInt32(); + } + return result; + } }; IMPLEMENT_META_INTERFACE(GraphicBufferProducer, "android.gui.IGraphicBufferProducer"); @@ -307,6 +325,16 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(res); return NO_ERROR; } break; + case SET_SIDEBAND_STREAM: { + CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + sp<NativeHandle> stream; + if (data.readInt32()) { + stream = NativeHandle::create(data.readNativeHandle()); + } + status_t result = setSidebandStream(stream); + reply->writeInt32(result); + return NO_ERROR; + } break; } return BBinder::onTransact(code, data, reply, flags); } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 474f633..0ca93c8 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -25,6 +25,7 @@ #include <utils/Errors.h> #include <utils/misc.h> +#include <utils/NativeHandle.h> #include <utils/String8.h> #include <utils/Thread.h> #include <utils/Trace.h> @@ -942,12 +943,22 @@ public: SharedBuffer const* sb = reg.getSharedBuffer(&visibleRegion.numRects); visibleRegion.rects = reinterpret_cast<hwc_rect_t const *>(sb->data()); } + virtual void setSidebandStream(const sp<NativeHandle>& stream) { + ALOG_ASSERT(stream->handle() != NULL); + getLayer()->compositionType = HWC_SIDEBAND; + getLayer()->sidebandStream = stream->handle(); + } virtual void setBuffer(const sp<GraphicBuffer>& buffer) { if (buffer == 0 || buffer->handle == 0) { getLayer()->compositionType = HWC_FRAMEBUFFER; getLayer()->flags |= HWC_SKIP_LAYER; getLayer()->handle = 0; } else { + if (getLayer()->compositionType == HWC_SIDEBAND) { + // If this was a sideband layer but the stream was removed, reset + // it to FRAMEBUFFER. The HWC can change it to OVERLAY in prepare. + getLayer()->compositionType = HWC_FRAMEBUFFER; + } getLayer()->handle = buffer->handle; } } diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index 9f96113..9218bf6 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -45,9 +45,10 @@ struct framebuffer_device_t; namespace android { // --------------------------------------------------------------------------- -class GraphicBuffer; class Fence; class FloatRect; +class GraphicBuffer; +class NativeHandle; class Region; class String8; class SurfaceFlinger; @@ -164,6 +165,7 @@ public: virtual void setFrame(const Rect& frame) = 0; virtual void setCrop(const FloatRect& crop) = 0; virtual void setVisibleRegionScreen(const Region& reg) = 0; + virtual void setSidebandStream(const sp<NativeHandle>& stream) = 0; virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0; virtual void setAcquireFenceFd(int fenceFd) = 0; virtual void setPlaneAlpha(uint8_t alpha) = 0; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 91be439..11c42e0 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -469,6 +469,10 @@ status_t VirtualDisplaySurface::disconnect(int api) { return mSource[SOURCE_SINK]->disconnect(api); } +status_t VirtualDisplaySurface::setSidebandStream(const sp<NativeHandle>& /*stream*/) { + return INVALID_OPERATION; +} + void VirtualDisplaySurface::updateQueueBufferOutput( const QueueBufferOutput& qbo) { uint32_t w, h, transformHint, numPendingBuffers; diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h index cd9a5b0..0d30a1b 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h @@ -107,6 +107,7 @@ private: virtual status_t connect(const sp<IBinder>& token, int api, bool producerControlledByApp, QueueBufferOutput* output); virtual status_t disconnect(int api); + virtual status_t setSidebandStream(const sp<NativeHandle>& stream); // // Utility methods diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 465d376..019d892 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,6 +27,7 @@ #include <utils/Errors.h> #include <utils/Log.h> +#include <utils/NativeHandle.h> #include <utils/StopWatch.h> #include <utils/Trace.h> @@ -66,6 +67,7 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client, mFormat(PIXEL_FORMAT_NONE), mTransactionFlags(0), mQueuedFrames(0), + mSidebandStreamChanged(false), mCurrentTransform(0), mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE), mCurrentOpacity(true), @@ -118,7 +120,7 @@ void Layer::onFirstRef() { mBufferQueue = new SurfaceTextureLayer(mFlinger); mSurfaceFlingerConsumer = new SurfaceFlingerConsumer(mBufferQueue, mTextureName); mSurfaceFlingerConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mSurfaceFlingerConsumer->setFrameAvailableListener(this); + mSurfaceFlingerConsumer->setContentsChangedListener(this); mSurfaceFlingerConsumer->setName(mName); #ifdef TARGET_DISABLE_TRIPLE_BUFFERING @@ -158,6 +160,13 @@ void Layer::onFrameAvailable() { mFlinger->signalLayerUpdate(); } +void Layer::onSidebandStreamChanged() { + if (android_atomic_release_cas(false, true, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was false + mFlinger->signalLayerUpdate(); + } +} + // called with SurfaceFlinger::mStateLock from the drawing thread after // the layer has been remove from the current state list (and just before // it's removed from the drawing state list) @@ -413,9 +422,13 @@ void Layer::setPerFrameData(const sp<const DisplayDevice>& hw, Region visible = tr.transform(visibleRegion.intersect(hw->getViewport())); layer.setVisibleRegionScreen(visible); - // NOTE: buffer can be NULL if the client never drew into this - // layer yet, or if we ran out of memory - layer.setBuffer(mActiveBuffer); + if (mSidebandStream.get()) { + layer.setSidebandStream(mSidebandStream); + } else { + // NOTE: buffer can be NULL if the client never drew into this + // layer yet, or if we ran out of memory + layer.setBuffer(mActiveBuffer); + } } void Layer::setAcquireFence(const sp<const DisplayDevice>& /* hw */, @@ -907,7 +920,7 @@ bool Layer::setLayerStack(uint32_t layerStack) { bool Layer::onPreComposition() { mRefreshPending = false; - return mQueuedFrames > 0; + return mQueuedFrames > 0 || mSidebandStreamChanged; } void Layer::onPostComposition() { @@ -950,6 +963,11 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) { ATRACE_CALL(); + if (android_atomic_acquire_cas(true, false, &mSidebandStreamChanged) == 0) { + // mSidebandStreamChanged was true + mSidebandStream = mSurfaceFlingerConsumer->getSidebandStream(); + } + Region outDirtyRegion; if (mQueuedFrames > 0) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9283eaa..43de999 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -66,7 +66,7 @@ class SurfaceFlinger; * This also implements onFrameAvailable(), which notifies SurfaceFlinger * that new data has arrived. */ -class Layer : public SurfaceFlingerConsumer::FrameAvailableListener { +class Layer : public SurfaceFlingerConsumer::ContentsChangedListener { static int32_t sSequence; public: @@ -313,8 +313,9 @@ protected: private: - // Interface implementation for SurfaceFlingerConsumer::FrameAvailableListener + // Interface implementation for SurfaceFlingerConsumer::ContentsChangedListener virtual void onFrameAvailable(); + virtual void onSidebandStreamChanged(); void commitTransaction(); @@ -351,10 +352,12 @@ private: // thread-safe volatile int32_t mQueuedFrames; + volatile int32_t mSidebandStreamChanged; // used like an atomic boolean FrameTracker mFrameTracker; // main thread sp<GraphicBuffer> mActiveBuffer; + sp<NativeHandle> mSidebandStream; Rect mCurrentCrop; uint32_t mCurrentTransform; uint32_t mCurrentScalingMode; diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp index 6dc093e..a412543 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp +++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp @@ -21,8 +21,9 @@ #include <private/gui/SyncFeatures.h> -#include <utils/Trace.h> #include <utils/Errors.h> +#include <utils/NativeHandle.h> +#include <utils/Trace.h> namespace android { @@ -112,6 +113,10 @@ bool SurfaceFlingerConsumer::getTransformToDisplayInverse() const { return mTransformToDisplayInverse; } +sp<NativeHandle> SurfaceFlingerConsumer::getSidebandStream() const { + return mConsumer->getSidebandStream(); +} + // We need to determine the time when a buffer acquired now will be // displayed. This can be calculated: // time when previous buffer's actual-present fence was signaled @@ -154,6 +159,26 @@ nsecs_t SurfaceFlingerConsumer::computeExpectedPresent() return prevVsync + hwcLatency * vsyncPeriod + extraPadding; } +void SurfaceFlingerConsumer::setContentsChangedListener( + const wp<ContentsChangedListener>& listener) { + setFrameAvailableListener(listener); + Mutex::Autolock lock(mMutex); + mContentsChangedListener = listener; +} + +void SurfaceFlingerConsumer::onSidebandStreamChanged() { + sp<ContentsChangedListener> listener; + { // scope for the lock + Mutex::Autolock lock(mMutex); + ALOG_ASSERT(mFrameAvailableListener.unsafe_get() == mContentsChangedListener.unsafe_get()); + listener = mContentsChangedListener.promote(); + } + + if (listener != NULL) { + listener->onSidebandStreamChanged(); + } +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h index 688ad32..becd5d3 100644 --- a/services/surfaceflinger/SurfaceFlingerConsumer.h +++ b/services/surfaceflinger/SurfaceFlingerConsumer.h @@ -27,6 +27,10 @@ namespace android { */ class SurfaceFlingerConsumer : public GLConsumer { public: + struct ContentsChangedListener: public FrameAvailableListener { + virtual void onSidebandStreamChanged() = 0; + }; + SurfaceFlingerConsumer(const sp<BufferQueue>& bq, uint32_t tex) : GLConsumer(bq, tex, GLConsumer::TEXTURE_EXTERNAL, false) {} @@ -54,9 +58,19 @@ public: // must be called from SF main thread bool getTransformToDisplayInverse() const; + // Sets the contents changed listener. This should be used instead of + // ConsumerBase::setFrameAvailableListener(). + void setContentsChangedListener(const wp<ContentsChangedListener>& listener); + + sp<NativeHandle> getSidebandStream() const; + private: nsecs_t computeExpectedPresent(); + virtual void onSidebandStreamChanged(); + + wp<ContentsChangedListener> mContentsChangedListener; + // Indicates this buffer must be transformed by the inverse transform of the screen // it is displayed onto. This is applied after GLConsumer::mCurrentTransform. // This must be set/read from SurfaceFlinger's main thread. |