| /* |
| * Copyright 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #ifndef ANDROID_GUI_BUFFERHUBPRODUCER_H_ |
| #define ANDROID_GUI_BUFFERHUBPRODUCER_H_ |
| |
| #include <gui/BufferSlot.h> |
| #include <gui/IGraphicBufferProducer.h> |
| #include <private/dvr/buffer_hub_queue_client.h> |
| #include <private/dvr/buffer_hub_queue_parcelable.h> |
| |
| namespace android { |
| |
| class BufferHubProducer : public IGraphicBufferProducer { |
| public: |
| static constexpr int kNoConnectedApi = -1; |
| |
| // TODO(b/36187402) The actual implementation of BufferHubQueue's consumer |
| // side logic doesn't limit the number of buffer it can acquire |
| // simultaneously. We need a way for consumer logic to configure and enforce |
| // that. |
| static constexpr int kDefaultUndequeuedBuffers = 1; |
| |
| // Creates a BufferHubProducer instance by importing an existing prodcuer |
| // queue. |
| static sp<BufferHubProducer> Create(const std::shared_ptr<dvr::ProducerQueue>& producer); |
| |
| // Creates a BufferHubProducer instance by importing an existing prodcuer |
| // parcelable. Note that this call takes the ownership of the parcelable |
| // object and is guaranteed to succeed if parcelable object is valid. |
| static sp<BufferHubProducer> Create(dvr::ProducerQueueParcelable parcelable); |
| |
| // See |IGraphicBufferProducer::requestBuffer| |
| status_t requestBuffer(int slot, sp<GraphicBuffer>* buf) override; |
| |
| // For the BufferHub based implementation. All buffers in the queue are |
| // allowed to be dequeued from the consumer side. It call always returns |
| // 0 for |NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS| query. Thus setting |
| // |max_dequeued_buffers| here can be considered the same as setting queue |
| // capacity. |
| // |
| // See |IGraphicBufferProducer::setMaxDequeuedBufferCount| for more info |
| status_t setMaxDequeuedBufferCount(int max_dequeued_buffers) override; |
| |
| // See |IGraphicBufferProducer::setAsyncMode| |
| status_t setAsyncMode(bool async) override; |
| |
| // See |IGraphicBufferProducer::dequeueBuffer| |
| status_t dequeueBuffer(int* out_slot, sp<Fence>* out_fence, uint32_t width, uint32_t height, |
| PixelFormat format, uint64_t usage, uint64_t* outBufferAge, |
| FrameEventHistoryDelta* outTimestamps) override; |
| |
| // See |IGraphicBufferProducer::detachBuffer| |
| status_t detachBuffer(int slot) override; |
| |
| // See |IGraphicBufferProducer::detachNextBuffer| |
| status_t detachNextBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence) override; |
| |
| // See |IGraphicBufferProducer::attachBuffer| |
| status_t attachBuffer(int* out_slot, const sp<GraphicBuffer>& buffer) override; |
| |
| // See |IGraphicBufferProducer::queueBuffer| |
| status_t queueBuffer(int slot, const QueueBufferInput& input, |
| QueueBufferOutput* output) override; |
| |
| // See |IGraphicBufferProducer::cancelBuffer| |
| status_t cancelBuffer(int slot, const sp<Fence>& fence) override; |
| |
| // See |IGraphicBufferProducer::query| |
| status_t query(int what, int* out_value) override; |
| |
| // See |IGraphicBufferProducer::connect| |
| status_t connect(const sp<IProducerListener>& listener, int api, |
| bool producer_controlled_by_app, QueueBufferOutput* output) override; |
| |
| // See |IGraphicBufferProducer::disconnect| |
| status_t disconnect(int api, DisconnectMode mode = DisconnectMode::Api) override; |
| |
| // See |IGraphicBufferProducer::setSidebandStream| |
| status_t setSidebandStream(const sp<NativeHandle>& stream) override; |
| |
| // See |IGraphicBufferProducer::allocateBuffers| |
| void allocateBuffers(uint32_t width, uint32_t height, PixelFormat format, |
| uint64_t usage) override; |
| |
| // See |IGraphicBufferProducer::allowAllocation| |
| status_t allowAllocation(bool allow) override; |
| |
| // See |IGraphicBufferProducer::setGenerationNumber| |
| status_t setGenerationNumber(uint32_t generation_number) override; |
| |
| // See |IGraphicBufferProducer::getConsumerName| |
| String8 getConsumerName() const override; |
| |
| // See |IGraphicBufferProducer::setSharedBufferMode| |
| status_t setSharedBufferMode(bool shared_buffer_mode) override; |
| |
| // See |IGraphicBufferProducer::setAutoRefresh| |
| status_t setAutoRefresh(bool auto_refresh) override; |
| |
| // See |IGraphicBufferProducer::setDequeueTimeout| |
| status_t setDequeueTimeout(nsecs_t timeout) override; |
| |
| // See |IGraphicBufferProducer::getLastQueuedBuffer| |
| status_t getLastQueuedBuffer(sp<GraphicBuffer>* out_buffer, sp<Fence>* out_fence, |
| float out_transform_matrix[16]) override; |
| |
| // See |IGraphicBufferProducer::getFrameTimestamps| |
| void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) override; |
| |
| // See |IGraphicBufferProducer::getUniqueId| |
| status_t getUniqueId(uint64_t* out_id) const override; |
| |
| // See |IGraphicBufferProducer::getConsumerUsage| |
| status_t getConsumerUsage(uint64_t* out_usage) const override; |
| |
| // Takes out the current producer as a binder parcelable object. Note that the |
| // producer must be disconnected to be exportable. After successful export, |
| // the producer queue can no longer be connected again. Returns NO_ERROR when |
| // takeout is successful and out_parcelable will hold the new parcelable |
| // object. Also note that out_parcelable cannot be NULL and must points to an |
| // invalid parcelable. |
| status_t TakeAsParcelable(dvr::ProducerQueueParcelable* out_parcelable); |
| |
| IBinder* onAsBinder() override; |
| |
| protected: |
| // See |IGraphicBufferProducer::exportToParcel| |
| status_t exportToParcel(Parcel* parcel) override; |
| |
| private: |
| using LocalHandle = pdx::LocalHandle; |
| |
| // Private constructor to force use of |Create|. |
| BufferHubProducer() {} |
| |
| static uint64_t genUniqueId() { |
| static std::atomic<uint32_t> counter{0}; |
| static uint64_t id = static_cast<uint64_t>(getpid()) << 32; |
| return id | counter++; |
| } |
| |
| // Allocate new buffer through BufferHub and add it into |queue_| for |
| // bookkeeping. |
| status_t AllocateBuffer(uint32_t width, uint32_t height, uint32_t layer_count, |
| PixelFormat format, uint64_t usage); |
| |
| // Remove a buffer via BufferHubRPC. |
| status_t RemoveBuffer(size_t slot); |
| |
| // Free all buffers which are owned by the prodcuer. Note that if graphic |
| // buffers are acquired by the consumer, we can't . |
| status_t FreeAllBuffers(); |
| |
| // Concreate implementation backed by BufferHubBuffer. |
| std::shared_ptr<dvr::ProducerQueue> queue_; |
| |
| // Mutex for thread safety. |
| std::mutex mutex_; |
| |
| // Connect client API, should be one of the NATIVE_WINDOW_API_* flags. |
| int connected_api_{kNoConnectedApi}; |
| |
| // |max_buffer_count_| sets the capacity of the underlying buffer queue. |
| int32_t max_buffer_count_{dvr::BufferHubQueue::kMaxQueueCapacity}; |
| |
| // |max_dequeued_buffer_count_| set the maximum number of buffers that can |
| // be dequeued at the same momment. |
| int32_t max_dequeued_buffer_count_{1}; |
| |
| // Sets how long dequeueBuffer or attachBuffer will block if a buffer or |
| // slot is not yet available. The timeout is stored in milliseconds. |
| int dequeue_timeout_ms_{dvr::BufferHubQueue::kNoTimeOut}; |
| |
| // |generation_number_| stores the current generation number of the attached |
| // producer. Any attempt to attach a buffer with a different generation |
| // number will fail. |
| // TOOD(b/38137191) Currently not used as we don't support |
| // IGraphicBufferProducer::detachBuffer. |
| uint32_t generation_number_{0}; |
| |
| // |buffers_| stores the buffers that have been dequeued from |
| // |dvr::BufferHubQueue|, It is initialized to invalid buffers, and gets |
| // filled in with the result of |Dequeue|. |
| // TODO(jwcai) The buffer allocated to a slot will also be replaced if the |
| // requested buffer usage or geometry differs from that of the buffer |
| // allocated to a slot. |
| struct BufferHubSlot : public BufferSlot { |
| BufferHubSlot() : mBufferProducer(nullptr), mIsReallocating(false) {} |
| // BufferSlot comes from android framework, using m prefix to comply with |
| // the name convention with the reset of data fields from BufferSlot. |
| std::shared_ptr<dvr::BufferProducer> mBufferProducer; |
| bool mIsReallocating; |
| }; |
| BufferHubSlot buffers_[dvr::BufferHubQueue::kMaxQueueCapacity]; |
| |
| // A uniqueId used by IGraphicBufferProducer interface. |
| const uint64_t unique_id_{genUniqueId()}; |
| |
| // A pending parcelable object which keeps the bufferhub channel alive. |
| dvr::ProducerQueueParcelable pending_producer_parcelable_; |
| }; |
| |
| } // namespace android |
| |
| #endif // ANDROID_GUI_BUFFERHUBPRODUCER_H_ |