1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 //#define LOG_NDEBUG 0
17 #define LOG_TAG "Codec2-GraphicBufferAllocator"
18 
19 
20 #include <gui/IProducerListener.h>
21 #include <media/stagefright/foundation/ADebug.h>
22 
23 #include <codec2/aidl/GraphicBufferAllocator.h>
24 #include <codec2/aidl/GraphicsTracker.h>
25 
26 namespace aidl::android::hardware::media::c2::implementation {
27 
28 class OnBufferReleasedListener : public ::android::BnProducerListener {
29 private:
30     uint32_t mGeneration;
31     std::weak_ptr<GraphicBufferAllocator> mAllocator;
32 public:
OnBufferReleasedListener(uint32_t generation,const std::shared_ptr<GraphicBufferAllocator> & allocator)33     OnBufferReleasedListener(
34             uint32_t generation,
35             const std::shared_ptr<GraphicBufferAllocator> &allocator)
36             : mGeneration(generation), mAllocator(allocator) {}
37     virtual ~OnBufferReleasedListener() = default;
onBufferReleased()38     virtual void onBufferReleased() {
39         auto p = mAllocator.lock();
40         if (p) {
41             p->onBufferReleased(mGeneration);
42         }
43     }
needsReleaseNotify()44     virtual bool needsReleaseNotify() { return true; }
45 };
46 
allocate(const IGraphicBufferAllocator::Description & in_desc,IGraphicBufferAllocator::Allocation * _aidl_return)47 ::ndk::ScopedAStatus GraphicBufferAllocator::allocate(
48         const IGraphicBufferAllocator::Description& in_desc,
49         IGraphicBufferAllocator::Allocation* _aidl_return) {
50     AHardwareBuffer *buf;
51     ::android::sp<::android::Fence> fence;
52     c2_status_t ret = allocate(
53             in_desc.width, in_desc.height, in_desc.format, in_desc.usage,
54             &buf, &fence);
55     if (ret == C2_OK) {
56         _aidl_return->buffer.reset(buf);
57         _aidl_return->fence = ::ndk::ScopedFileDescriptor(fence->dup());
58         return ::ndk::ScopedAStatus::ok();
59     }
60     return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
61 }
62 
deallocate(int64_t in_id,bool * _aidl_return)63 ::ndk::ScopedAStatus GraphicBufferAllocator::deallocate(int64_t in_id, bool* _aidl_return) {
64     *_aidl_return = deallocate(in_id, ::android::Fence::NO_FENCE);
65     return ::ndk::ScopedAStatus::ok();
66 }
67 
getWaitableFd(::ndk::ScopedFileDescriptor * _aidl_return)68 ::ndk::ScopedAStatus GraphicBufferAllocator::getWaitableFd(
69         ::ndk::ScopedFileDescriptor* _aidl_return) {
70     int pipeFd;
71     c2_status_t ret = mGraphicsTracker->getWaitableFd(&pipeFd);
72     if (ret == C2_OK) {
73         _aidl_return->set(pipeFd);
74         return ::ndk::ScopedAStatus::ok();
75     }
76     return ::ndk::ScopedAStatus::fromServiceSpecificError(ret);
77 }
78 
configure(const::android::sp<IGraphicBufferProducer> & igbp,uint32_t generation,int maxDequeueBufferCount)79 bool GraphicBufferAllocator::configure(
80         const ::android::sp<IGraphicBufferProducer>& igbp,
81         uint32_t generation,
82         int maxDequeueBufferCount) {
83     c2_status_t ret = C2_OK;
84 
85     ret = mGraphicsTracker->configureGraphics(igbp, generation);
86     if (ret != C2_OK) {
87         ALOGE("configuring igbp failed gen #(%d), configuring max dequeue count didn't happen",
88               (unsigned int)generation);
89         return false;
90     }
91 
92     ret = mGraphicsTracker->configureMaxDequeueCount(maxDequeueBufferCount);
93     if (ret != C2_OK) {
94         ALOGE("configuring max dequeue count to %d failed", maxDequeueBufferCount);
95         return false;
96     }
97     return true;
98 }
99 
updateMaxDequeueBufferCount(int count)100 void GraphicBufferAllocator::updateMaxDequeueBufferCount(int count) {
101     c2_status_t ret = mGraphicsTracker->configureMaxDequeueCount(count);
102     if (ret != C2_OK) {
103         ALOGE("updating max dequeue buffer count failed %d", ret);
104     }
105 }
106 
reset()107 void GraphicBufferAllocator::reset() {
108     mGraphicsTracker->stop();
109 }
110 
createReleaseListener(uint32_t generation)111 const ::android::sp<::android::IProducerListener> GraphicBufferAllocator::createReleaseListener(
112       uint32_t generation) {
113     return new OnBufferReleasedListener(generation, ref<GraphicBufferAllocator>());
114 }
115 
onBufferReleased(uint32_t generation)116 void GraphicBufferAllocator::onBufferReleased(uint32_t generation) {
117     mGraphicsTracker->onReleased(generation);
118 }
119 
allocate(uint32_t width,uint32_t height,::android::PixelFormat format,uint64_t usage,AHardwareBuffer ** buf,::android::sp<::android::Fence> * fence)120 c2_status_t GraphicBufferAllocator::allocate(
121         uint32_t width, uint32_t height, ::android::PixelFormat format, uint64_t usage,
122         AHardwareBuffer **buf, ::android::sp<::android::Fence> *fence) {
123     return mGraphicsTracker->allocate(width, height, format, usage, buf, fence);
124 }
125 
deallocate(const uint64_t id,const::android::sp<::android::Fence> & fence)126 bool GraphicBufferAllocator::deallocate(const uint64_t id,
127                                         const ::android::sp<::android::Fence> &fence) {
128     c2_status_t ret = mGraphicsTracker->deallocate(id, fence);
129     if (ret != C2_OK) {
130         ALOGW("deallocate() %llu was not successful %d", (unsigned long long)id, ret);
131         return false;
132     }
133     return true;
134 }
135 
displayBuffer(const C2ConstGraphicBlock & block,const IGraphicBufferProducer::QueueBufferInput & input,IGraphicBufferProducer::QueueBufferOutput * output)136 c2_status_t GraphicBufferAllocator::displayBuffer(
137         const C2ConstGraphicBlock& block,
138         const IGraphicBufferProducer::QueueBufferInput& input,
139         IGraphicBufferProducer::QueueBufferOutput *output) {
140     return mGraphicsTracker->render(block, input, output);
141 }
142 
~GraphicBufferAllocator()143 GraphicBufferAllocator::~GraphicBufferAllocator() {}
144 
CreateGraphicBufferAllocator(int maxDequeueCount)145 std::shared_ptr<GraphicBufferAllocator> GraphicBufferAllocator::CreateGraphicBufferAllocator(
146         int maxDequeueCount) {
147     return ::ndk::SharedRefBase::make<GraphicBufferAllocator>(maxDequeueCount);
148 }
149 
GraphicBufferAllocator(int maxDequeueCount)150 GraphicBufferAllocator::GraphicBufferAllocator(int maxDequeueCount)
151         : mGraphicsTracker(GraphicsTracker::CreateGraphicsTracker(maxDequeueCount)) {}
152 
153 } // namespace aidl::android::hardware::media::c2::implementation
154