summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Hall <jessehall@google.com>2014-03-13 20:28:16 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2014-03-13 20:28:17 +0000
commit73ed82f809a40560fd3a6d53d18e5c846362d764 (patch)
treecbf5d50d6c3b7cd49b69c1d95b4f294f64cae8a7
parenta3f519fe6ffb6ac358a3a8015beb94ef1b596ae5 (diff)
parent399184a4cd728ea1421fb0bc1722274a29e38f4a (diff)
downloadframeworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.zip
frameworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.tar.gz
frameworks_native-73ed82f809a40560fd3a6d53d18e5c846362d764.tar.bz2
Merge "Add sideband streams to BufferQueue and related classes"
-rw-r--r--include/gui/BufferQueue.h16
-rw-r--r--include/gui/BufferQueueConsumer.h3
-rw-r--r--include/gui/BufferQueueCore.h4
-rw-r--r--include/gui/BufferQueueProducer.h12
-rw-r--r--include/gui/ConsumerBase.h9
-rw-r--r--include/gui/IConsumerListener.h6
-rw-r--r--include/gui/IGraphicBufferConsumer.h8
-rw-r--r--include/gui/IGraphicBufferProducer.h13
-rw-r--r--include/gui/Surface.h13
-rw-r--r--libs/gui/BufferQueue.cpp15
-rw-r--r--libs/gui/BufferQueueConsumer.cpp4
-rw-r--r--libs/gui/BufferQueueProducer.cpp7
-rw-r--r--libs/gui/ConsumerBase.cpp3
-rw-r--r--libs/gui/IConsumerListener.cpp13
-rw-r--r--libs/gui/IGraphicBufferConsumer.cpp16
-rw-r--r--libs/gui/IGraphicBufferProducer.cpp30
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp11
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h4
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp4
-rw-r--r--services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h1
-rw-r--r--services/surfaceflinger/Layer.cpp28
-rw-r--r--services/surfaceflinger/Layer.h7
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.cpp27
-rw-r--r--services/surfaceflinger/SurfaceFlingerConsumer.h14
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.