summaryrefslogtreecommitdiff
path: root/libs/gui/Surface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/gui/Surface.cpp')
-rw-r--r--libs/gui/Surface.cpp259
1 files changed, 239 insertions, 20 deletions
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 87fd448f0c..66e7ddd915 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -21,6 +21,8 @@
#include <gui/Surface.h>
#include <condition_variable>
+#include <cstddef>
+#include <cstdint>
#include <deque>
#include <mutex>
#include <thread>
@@ -41,11 +43,9 @@
#include <ui/GraphicBuffer.h>
#include <ui/Region.h>
-#include <gui/AidlStatusUtil.h>
+#include <gui/AidlUtil.h>
#include <gui/BufferItem.h>
-#include <gui/IProducerListener.h>
-
#include <gui/ISurfaceComposer.h>
#include <gui/LayerState.h>
#include <private/gui/ComposerService.h>
@@ -77,9 +77,28 @@ bool isInterceptorRegistrationOp(int op) {
} // namespace
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+Surface::ProducerDeathListenerProxy::ProducerDeathListenerProxy(wp<SurfaceListener> surfaceListener)
+ : mSurfaceListener(surfaceListener) {}
+
+void Surface::ProducerDeathListenerProxy::binderDied(const wp<IBinder>&) {
+ sp<SurfaceListener> surfaceListener = mSurfaceListener.promote();
+ if (!surfaceListener) {
+ return;
+ }
+
+ if (surfaceListener->needsDeathNotify()) {
+ surfaceListener->onRemoteDied();
+ }
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
Surface::Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp,
const sp<IBinder>& surfaceControlHandle)
: mGraphicBufferProducer(bufferProducer),
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ mSurfaceDeathListener(nullptr),
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
mCrop(Rect::EMPTY_RECT),
mBufferAge(0),
mGenerationNumber(0),
@@ -134,6 +153,12 @@ Surface::~Surface() {
if (mConnectedToCpu) {
Surface::disconnect(NATIVE_WINDOW_API_CPU);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ if (mSurfaceDeathListener != nullptr) {
+ IInterface::asBinder(mGraphicBufferProducer)->unlinkToDeath(mSurfaceDeathListener);
+ mSurfaceDeathListener = nullptr;
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
}
sp<ISurfaceComposer> Surface::composerService() const {
@@ -163,6 +188,12 @@ void Surface::allocateBuffers() {
mReqFormat, mReqUsage);
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+status_t Surface::allowAllocation(bool allowAllocation) {
+ return mGraphicBufferProducer->allowAllocation(allowAllocation);
+}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
status_t Surface::setGenerationNumber(uint32_t generation) {
status_t result = mGraphicBufferProducer->setGenerationNumber(generation);
if (result == NO_ERROR) {
@@ -695,6 +726,51 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
return OK;
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+status_t Surface::dequeueBuffer(sp<GraphicBuffer>* buffer, sp<Fence>* outFence) {
+ if (buffer == nullptr || outFence == nullptr) {
+ return BAD_VALUE;
+ }
+
+ android_native_buffer_t* anb;
+ int fd = -1;
+ status_t res = dequeueBuffer(&anb, &fd);
+ *buffer = GraphicBuffer::from(anb);
+ *outFence = sp<Fence>::make(fd);
+ return res;
+}
+
+status_t Surface::queueBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& fd,
+ SurfaceQueueBufferOutput* output) {
+ if (buffer == nullptr) {
+ return BAD_VALUE;
+ }
+ return queueBuffer(buffer.get(), fd ? fd->get() : -1, output);
+}
+
+status_t Surface::detachBuffer(const sp<GraphicBuffer>& buffer) {
+ if (nullptr == buffer) {
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+
+ uint64_t bufferId = buffer->getId();
+ for (int slot = 0; slot < Surface::NUM_BUFFER_SLOTS; ++slot) {
+ auto& bufferSlot = mSlots[slot];
+ if (bufferSlot.buffer != nullptr && bufferSlot.buffer->getId() == bufferId) {
+ bufferSlot.buffer = nullptr;
+ bufferSlot.dirtyRegion = Region::INVALID_REGION;
+ return mGraphicBufferProducer->detachBuffer(slot);
+ }
+ }
+
+ return BAD_VALUE;
+}
+
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
int Surface::dequeueBuffers(std::vector<BatchBuffer>* buffers) {
using DequeueBufferInput = IGraphicBufferProducer::DequeueBufferInput;
using DequeueBufferOutput = IGraphicBufferProducer::DequeueBufferOutput;
@@ -1118,6 +1194,140 @@ void Surface::onBufferQueuedLocked(int slot, sp<Fence> fence,
}
}
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd,
+ SurfaceQueueBufferOutput* surfaceOutput) {
+ ATRACE_CALL();
+ ALOGV("Surface::queueBuffer");
+
+ IGraphicBufferProducer::QueueBufferOutput output;
+ IGraphicBufferProducer::QueueBufferInput input;
+ int slot;
+ sp<Fence> fence;
+ {
+ Mutex::Autolock lock(mMutex);
+
+ slot = getSlotFromBufferLocked(buffer);
+ if (slot < 0) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+ return slot;
+ }
+ if (mSharedBufferSlot == slot && mSharedBufferHasBeenQueued) {
+ if (fenceFd >= 0) {
+ close(fenceFd);
+ }
+ return OK;
+ }
+
+ getQueueBufferInputLocked(buffer, fenceFd, mTimestamp, &input);
+ applyGrallocMetadataLocked(buffer, input);
+ fence = input.fence;
+ }
+ nsecs_t now = systemTime();
+ // Drop the lock temporarily while we touch the underlying producer. In the case of a local
+ // BufferQueue, the following should be allowable:
+ //
+ // Surface::queueBuffer
+ // -> IConsumerListener::onFrameAvailable callback triggers automatically
+ // -> implementation calls IGraphicBufferConsumer::acquire/release immediately
+ // -> SurfaceListener::onBufferRelesed callback triggers automatically
+ // -> implementation calls Surface::dequeueBuffer
+ status_t err = mGraphicBufferProducer->queueBuffer(slot, input, &output);
+ {
+ Mutex::Autolock lock(mMutex);
+
+ mLastQueueDuration = systemTime() - now;
+ if (err != OK) {
+ ALOGE("queueBuffer: error queuing buffer, %d", err);
+ }
+
+ onBufferQueuedLocked(slot, fence, output);
+ }
+
+ if (surfaceOutput != nullptr) {
+ *surfaceOutput = {.bufferReplaced = output.bufferReplaced};
+ }
+
+ return err;
+}
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+int Surface::queueBuffers(const std::vector<BatchQueuedBuffer>& buffers,
+ std::vector<SurfaceQueueBufferOutput>* queueBufferOutputs)
+#else
+int Surface::queueBuffers(const std::vector<BatchQueuedBuffer>& buffers)
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+{
+ ATRACE_CALL();
+ ALOGV("Surface::queueBuffers");
+
+ size_t numBuffers = buffers.size();
+ std::vector<IGraphicBufferProducer::QueueBufferInput> igbpQueueBufferInputs(numBuffers);
+ std::vector<IGraphicBufferProducer::QueueBufferOutput> igbpQueueBufferOutputs;
+ std::vector<int> bufferSlots(numBuffers, -1);
+ std::vector<sp<Fence>> bufferFences(numBuffers);
+
+ int err;
+ {
+ Mutex::Autolock lock(mMutex);
+
+ if (mSharedBufferMode) {
+ ALOGE("%s: batched operation is not supported in shared buffer mode", __FUNCTION__);
+ return INVALID_OPERATION;
+ }
+
+ for (size_t batchIdx = 0; batchIdx < numBuffers; batchIdx++) {
+ int i = getSlotFromBufferLocked(buffers[batchIdx].buffer);
+ if (i < 0) {
+ if (buffers[batchIdx].fenceFd >= 0) {
+ close(buffers[batchIdx].fenceFd);
+ }
+ return i;
+ }
+ bufferSlots[batchIdx] = i;
+
+ IGraphicBufferProducer::QueueBufferInput input;
+ getQueueBufferInputLocked(buffers[batchIdx].buffer, buffers[batchIdx].fenceFd,
+ buffers[batchIdx].timestamp, &input);
+ input.slot = i;
+ bufferFences[batchIdx] = input.fence;
+ igbpQueueBufferInputs[batchIdx] = input;
+ }
+ }
+ nsecs_t now = systemTime();
+ err = mGraphicBufferProducer->queueBuffers(igbpQueueBufferInputs, &igbpQueueBufferOutputs);
+ {
+ Mutex::Autolock lock(mMutex);
+ mLastQueueDuration = systemTime() - now;
+ if (err != OK) {
+ ALOGE("%s: error queuing buffer, %d", __FUNCTION__, err);
+ }
+
+ for (size_t batchIdx = 0; batchIdx < numBuffers; batchIdx++) {
+ onBufferQueuedLocked(bufferSlots[batchIdx], bufferFences[batchIdx],
+ igbpQueueBufferOutputs[batchIdx]);
+ }
+ }
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ if (queueBufferOutputs != nullptr) {
+ queueBufferOutputs->clear();
+ queueBufferOutputs->resize(numBuffers);
+ for (size_t batchIdx = 0; batchIdx < numBuffers; batchIdx++) {
+ (*queueBufferOutputs)[batchIdx].bufferReplaced =
+ igbpQueueBufferOutputs[batchIdx].bufferReplaced;
+ }
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
+ return err;
+}
+
+#else
+
int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
ATRACE_CALL();
ALOGV("Surface::queueBuffer");
@@ -1205,6 +1415,8 @@ int Surface::queueBuffers(const std::vector<BatchQueuedBuffer>& buffers) {
return err;
}
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
void Surface::querySupportedTimestampsLocked() const {
// mMutex must be locked when calling this method.
@@ -1860,30 +2072,23 @@ bool Surface::transformToDisplayInverse() const {
}
int Surface::connect(int api) {
- static sp<IProducerListener> listener = new StubProducerListener();
+ static sp<SurfaceListener> listener = new StubSurfaceListener();
return connect(api, listener);
}
-int Surface::connect(int api, const sp<IProducerListener>& listener) {
- return connect(api, listener, false);
-}
-
-int Surface::connect(
- int api, bool reportBufferRemoval, const sp<SurfaceListener>& sListener) {
- if (sListener != nullptr) {
- mListenerProxy = new ProducerListenerProxy(this, sListener);
- }
- return connect(api, mListenerProxy, reportBufferRemoval);
-}
-
-int Surface::connect(
- int api, const sp<IProducerListener>& listener, bool reportBufferRemoval) {
+int Surface::connect(int api, const sp<SurfaceListener>& listener, bool reportBufferRemoval) {
ATRACE_CALL();
ALOGV("Surface::connect");
Mutex::Autolock lock(mMutex);
IGraphicBufferProducer::QueueBufferOutput output;
mReportRemovedBuffers = reportBufferRemoval;
- int err = mGraphicBufferProducer->connect(listener, api, mProducerControlledByApp, &output);
+
+ if (listener != nullptr) {
+ mListenerProxy = new ProducerListenerProxy(this, listener);
+ }
+
+ int err =
+ mGraphicBufferProducer->connect(mListenerProxy, api, mProducerControlledByApp, &output);
if (err == NO_ERROR) {
mDefaultWidth = output.width;
mDefaultHeight = output.height;
@@ -1898,6 +2103,13 @@ int Surface::connect(
}
mConsumerRunningBehind = (output.numPendingBuffers >= 2);
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ if (listener && listener->needsDeathNotify()) {
+ mSurfaceDeathListener = sp<ProducerDeathListenerProxy>::make(listener);
+ IInterface::asBinder(mGraphicBufferProducer)->linkToDeath(mSurfaceDeathListener);
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
}
if (!err && api == NATIVE_WINDOW_API_CPU) {
mConnectedToCpu = true;
@@ -1911,7 +2123,6 @@ int Surface::connect(
return err;
}
-
int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
ATRACE_CALL();
ALOGV("Surface::disconnect");
@@ -1939,6 +2150,14 @@ int Surface::disconnect(int api, IGraphicBufferProducer::DisconnectMode mode) {
mConnectedToCpu = false;
}
}
+
+#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+ if (mSurfaceDeathListener != nullptr) {
+ IInterface::asBinder(mGraphicBufferProducer)->unlinkToDeath(mSurfaceDeathListener);
+ mSurfaceDeathListener = nullptr;
+ }
+#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_PLATFORM_API_IMPROVEMENTS)
+
return err;
}