diff options
-rw-r--r-- | libs/gui/BufferQueueProducer.cpp | 20 | ||||
-rw-r--r-- | libs/gui/IGraphicBufferProducer.cpp | 95 | ||||
-rw-r--r-- | libs/gui/Surface.cpp | 36 | ||||
-rw-r--r-- | libs/gui/include/gui/BufferQueueProducer.h | 4 | ||||
-rw-r--r-- | libs/gui/include/gui/IGraphicBufferProducer.h | 16 | ||||
-rw-r--r-- | libs/gui/include/gui/Surface.h | 1 | ||||
-rw-r--r-- | libs/nativewindow/include/system/window.h | 26 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/MonitoredProducer.h | 2 |
9 files changed, 205 insertions, 0 deletions
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index a7cf39add9..df308d897b 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1621,6 +1621,26 @@ status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, return NO_ERROR; } +status_t BufferQueueProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, + Rect* outRect, uint32_t* outTransform) { + ATRACE_CALL(); + BQ_LOGV("getLastQueuedBuffer"); + + std::lock_guard<std::mutex> lock(mCore->mMutex); + if (mCore->mLastQueuedSlot == BufferItem::INVALID_BUFFER_SLOT) { + *outBuffer = nullptr; + *outFence = Fence::NO_FENCE; + return NO_ERROR; + } + + *outBuffer = mSlots[mCore->mLastQueuedSlot].mGraphicBuffer; + *outFence = mLastQueueBufferFence; + *outRect = mLastQueuedCrop; + *outTransform = mLastQueuedTransform; + + return NO_ERROR; +} + void BufferQueueProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) { addAndGetFrameTimestamps(nullptr, outDelta); } diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index ad00939976..6c485341e5 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -74,6 +74,7 @@ enum { GET_CONSUMER_USAGE, SET_LEGACY_BUFFER_DROP, SET_AUTO_PREROTATION, + GET_LAST_QUEUED_BUFFER2, }; class BpGraphicBufferProducer : public BpInterface<IGraphicBufferProducer> @@ -491,6 +492,56 @@ public: return result; } + virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, + Rect* outRect, uint32_t* outTransform) override { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + status_t result = remote()->transact(GET_LAST_QUEUED_BUFFER2, data, &reply); + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to transact: %d", result); + return result; + } + status_t remoteError = NO_ERROR; + result = reply.readInt32(&remoteError); + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to read status: %d", result); + return result; + } + if (remoteError != NO_ERROR) { + return remoteError; + } + bool hasBuffer = false; + result = reply.readBool(&hasBuffer); + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to read buffer: %d", result); + return result; + } + sp<GraphicBuffer> buffer; + if (hasBuffer) { + buffer = new GraphicBuffer(); + result = reply.read(*buffer); + if (result == NO_ERROR) { + result = reply.read(*outRect); + } + if (result == NO_ERROR) { + result = reply.readUint32(outTransform); + } + } + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to read buffer: %d", result); + return result; + } + sp<Fence> fence(new Fence); + result = reply.read(*fence); + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to read fence: %d", result); + return result; + } + *outBuffer = buffer; + *outFence = fence; + return result; + } + virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) { Parcel data, reply; status_t result = data.writeInterfaceToken( @@ -676,6 +727,11 @@ public: outBuffer, outFence, outTransformMatrix); } + status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, Rect* outRect, + uint32_t* outTransform) override { + return mBase->getLastQueuedBuffer(outBuffer, outFence, outRect, outTransform); + } + void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override { return mBase->getFrameTimestamps(outDelta); } @@ -1025,6 +1081,45 @@ status_t BnGraphicBufferProducer::onTransact( } return NO_ERROR; } + case GET_LAST_QUEUED_BUFFER2: { + CHECK_INTERFACE(IGraphicBufferProducer, data, reply); + sp<GraphicBuffer> buffer(nullptr); + sp<Fence> fence(Fence::NO_FENCE); + Rect crop; + uint32_t transform; + status_t result = getLastQueuedBuffer(&buffer, &fence, &crop, &transform); + reply->writeInt32(result); + if (result != NO_ERROR) { + return result; + } + if (!buffer.get()) { + reply->writeBool(false); + } else { + reply->writeBool(true); + result = reply->write(*buffer); + if (result == NO_ERROR) { + result = reply->write(crop); + } + if (result == NO_ERROR) { + result = reply->writeUint32(transform); + } + } + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to write buffer: %d", result); + return result; + } + if (fence == nullptr) { + ALOGE("getLastQueuedBuffer returned a NULL fence, setting to Fence::NO_FENCE"); + fence = Fence::NO_FENCE; + } + result = reply->write(*fence); + if (result != NO_ERROR) { + ALOGE("getLastQueuedBuffer failed to write fence: %d", result); + return result; + } + return NO_ERROR; + } + case GET_FRAME_TIMESTAMPS: { CHECK_INTERFACE(IGraphicBufferProducer, data, reply); FrameEventHistoryDelta frameTimestamps; diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index d6f9e635f3..8a64a4f0f7 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1207,6 +1207,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER: res = dispatchGetLastQueuedBuffer(args); break; + case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2: + res = dispatchGetLastQueuedBuffer2(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1513,6 +1516,39 @@ int Surface::dispatchGetLastQueuedBuffer(va_list args) { return result; } +int Surface::dispatchGetLastQueuedBuffer2(va_list args) { + AHardwareBuffer** buffer = va_arg(args, AHardwareBuffer**); + int* fence = va_arg(args, int*); + ARect* crop = va_arg(args, ARect*); + uint32_t* transform = va_arg(args, uint32_t*); + sp<GraphicBuffer> graphicBuffer; + sp<Fence> spFence; + + Rect r; + int result = + mGraphicBufferProducer->getLastQueuedBuffer(&graphicBuffer, &spFence, &r, transform); + + if (graphicBuffer != nullptr) { + *buffer = graphicBuffer->toAHardwareBuffer(); + AHardwareBuffer_acquire(*buffer); + + // Avoid setting crop* unless buffer is valid (matches IGBP behavior) + crop->left = r.left; + crop->top = r.top; + crop->right = r.right; + crop->bottom = r.bottom; + } else { + *buffer = nullptr; + } + + if (spFence != nullptr) { + *fence = spFence->dup(); + } else { + *fence = -1; + } + return result; +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h index a7f7d1defa..0ad3075a4d 100644 --- a/libs/gui/include/gui/BufferQueueProducer.h +++ b/libs/gui/include/gui/BufferQueueProducer.h @@ -186,6 +186,10 @@ public: virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, float outTransformMatrix[16]) override; + // See IGraphicBufferProducer::getLastQueuedBuffer + virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, + Rect* outRect, uint32_t* outTransform) override; + // See IGraphicBufferProducer::getFrameTimestamps virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override; diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 45e0a134ba..4905b748d8 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -619,6 +619,22 @@ public: virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, float outTransformMatrix[16]) = 0; + // Returns the last queued buffer along with a fence which must signal + // before the contents of the buffer are read. If there are no buffers in + // the queue, outBuffer will be populated with nullptr and outFence will be + // populated with Fence::NO_FENCE + // + // outRect & outTransform are not modified if outBuffer is null. + // + // Returns NO_ERROR or the status of the Binder transaction + virtual status_t getLastQueuedBuffer([[maybe_unused]] sp<GraphicBuffer>* outBuffer, + [[maybe_unused]] sp<Fence>* outFence, + [[maybe_unused]] Rect* outRect, + [[maybe_unused]] uint32_t* outTransform) { + // Too many things implement IGraphicBufferProducer... + return UNKNOWN_TRANSACTION; + } + // Gets the frame events that haven't already been retrieved. virtual void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {} diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index 55b4101908..10f4df906e 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -265,6 +265,7 @@ private: int dispatchAddQueueInterceptor(va_list args); int dispatchAddQueryInterceptor(va_list args); int dispatchGetLastQueuedBuffer(va_list args); + int dispatchGetLastQueuedBuffer2(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index b78fc5dbbc..73b46b202e 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -255,6 +255,7 @@ enum { NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */ NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */ NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */ + NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2 = 50, /* private */ // clang-format on }; @@ -1053,6 +1054,31 @@ static inline int ANativeWindow_getLastQueuedBuffer(ANativeWindow* window, } /** + * Retrieves the last queued buffer for this window, along with the fence that + * fires when the buffer is ready to be read. The cropRect & transform should be applied to the + * buffer's content. + * + * If there was no buffer previously queued, then outBuffer will be NULL and + * the value of outFence will be -1. + * + * Note that if outBuffer is not NULL, then the caller will hold a reference + * onto the buffer. Accordingly, the caller must call AHardwareBuffer_release + * when the buffer is no longer needed so that the system may reclaim the + * buffer. + * + * \return NO_ERROR on success. + * \return NO_MEMORY if there was insufficient memory. + * \return STATUS_UNKNOWN_TRANSACTION if this ANativeWindow doesn't support this method, callers + * should fall back to ANativeWindow_getLastQueuedBuffer instead. + */ +static inline int ANativeWindow_getLastQueuedBuffer2(ANativeWindow* window, + AHardwareBuffer** outBuffer, int* outFence, + ARect* outCropRect, uint32_t* outTransform) { + return window->perform(window, NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER2, outBuffer, outFence, + outCropRect, outTransform); +} + +/** * Retrieves an identifier for the next frame to be queued by this window. * * \return the next frame id. diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 18a28918fd..6b2d745998 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -140,6 +140,11 @@ status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, outTransformMatrix); } +status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, + Rect* outRect, uint32_t* outTransform) { + return mProducer->getLastQueuedBuffer(outBuffer, outFence, outRect, outTransform); +} + void MonitoredProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) { mProducer->getFrameTimestamps(outDelta); } diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 788919b3da..3778277fd3 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -64,6 +64,8 @@ public: virtual status_t setLegacyBufferDrop(bool drop) override; virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, float outTransformMatrix[16]) override; + virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence, + Rect* outRect, uint32_t* outTransform) override; virtual IBinder* onAsBinder(); virtual status_t setSharedBufferMode(bool sharedBufferMode) override; virtual status_t setAutoRefresh(bool autoRefresh) override; |