1 /*
2  * Copyright (C) 2018 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 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "C2BqBuffer"
19 #define ATRACE_TAG  ATRACE_TAG_VIDEO
20 #include <android/hardware_buffer.h>
21 #include <utils/Log.h>
22 #include <utils/Trace.h>
23 
24 #include <ui/BufferQueueDefs.h>
25 #include <ui/GraphicBuffer.h>
26 #include <ui/Fence.h>
27 
28 #include <types.h>
29 
30 #include <hidl/HidlSupport.h>
31 
32 #include <C2AllocatorGralloc.h>
33 #include <C2BqBufferPriv.h>
34 #include <C2BlockInternal.h>
35 #include <C2FenceFactory.h>
36 #include <C2SurfaceSyncObj.h>
37 
38 #include <atomic>
39 #include <list>
40 #include <map>
41 #include <mutex>
42 
43 using ::android::ScopedTrace;
44 using ::android::BufferQueueDefs::NUM_BUFFER_SLOTS;
45 using ::android::C2AllocatorGralloc;
46 using ::android::C2AndroidMemoryUsage;
47 using ::android::Fence;
48 using ::android::GraphicBuffer;
49 using ::android::sp;
50 using ::android::status_t;
51 using ::android::wp;
52 using ::android::hardware::hidl_handle;
53 using ::android::hardware::Return;
54 
55 using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
56 using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
57 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
58 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
59 using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
60 
61 using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::V2_0
62         ::IGraphicBufferProducer;
63 
GetBufferQueueData(const std::shared_ptr<const _C2BlockPoolData> & data,uint32_t * generation,uint64_t * bqId,int32_t * bqSlot)64 bool _C2BlockFactory::GetBufferQueueData(
65         const std::shared_ptr<const _C2BlockPoolData>& data,
66         uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) {
67     if (data && data->getType() == _C2BlockPoolData::TYPE_BUFFERQUEUE) {
68         const std::shared_ptr<const C2BufferQueueBlockPoolData> poolData =
69                 std::static_pointer_cast<const C2BufferQueueBlockPoolData>(data);
70         poolData->getBufferQueueData(generation, bqId, bqSlot);
71         return true;
72     }
73     return false;
74 }
75 
HoldBlockFromBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem)76 bool _C2BlockFactory::HoldBlockFromBufferQueue(
77         const std::shared_ptr<_C2BlockPoolData>& data,
78         const std::shared_ptr<int>& owner,
79         const sp<HGraphicBufferProducer>& igbp,
80         std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
81     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
82             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
83     return poolData->holdBlockFromBufferQueue(owner, igbp, syncMem);
84 }
85 
BeginTransferBlockToClient(const std::shared_ptr<_C2BlockPoolData> & data)86 bool _C2BlockFactory::BeginTransferBlockToClient(
87         const std::shared_ptr<_C2BlockPoolData>& data) {
88     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
89             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
90     return poolData->beginTransferBlockToClient();
91 }
92 
EndTransferBlockToClient(const std::shared_ptr<_C2BlockPoolData> & data,bool transfer)93 bool _C2BlockFactory::EndTransferBlockToClient(
94         const std::shared_ptr<_C2BlockPoolData>& data,
95         bool transfer) {
96     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
97             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
98     return poolData->endTransferBlockToClient(transfer);
99 }
100 
BeginAttachBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data)101 bool _C2BlockFactory::BeginAttachBlockToBufferQueue(
102         const std::shared_ptr<_C2BlockPoolData>& data) {
103     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
104             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
105     return poolData->beginAttachBlockToBufferQueue();
106 }
107 
108 // if display was tried during attach, buffer should be retired ASAP.
EndAttachBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t generation,uint64_t bqId,int32_t bqSlot)109 bool _C2BlockFactory::EndAttachBlockToBufferQueue(
110         const std::shared_ptr<_C2BlockPoolData>& data,
111         const std::shared_ptr<int>& owner,
112         const sp<HGraphicBufferProducer>& igbp,
113         std::shared_ptr<C2SurfaceSyncMemory> syncMem,
114         uint32_t generation,
115         uint64_t bqId,
116         int32_t bqSlot) {
117     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
118             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
119     return poolData->endAttachBlockToBufferQueue(owner, igbp, syncMem, generation, bqId, bqSlot);
120 }
121 
DisplayBlockToBufferQueue(const std::shared_ptr<_C2BlockPoolData> & data)122 bool _C2BlockFactory::DisplayBlockToBufferQueue(
123         const std::shared_ptr<_C2BlockPoolData>& data) {
124     const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
125             std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
126     return poolData->displayBlockToBufferQueue();
127 }
128 
CreateGraphicBlock(const C2Handle * handle)129 std::shared_ptr<C2GraphicBlock> _C2BlockFactory::CreateGraphicBlock(
130         const C2Handle *handle) {
131     // TODO: get proper allocator? and mutex?
132     static std::unique_ptr<C2AllocatorGralloc> sAllocator = std::make_unique<C2AllocatorGralloc>(0);
133 
134     std::shared_ptr<C2GraphicAllocation> alloc;
135     if (C2AllocatorGralloc::CheckHandle(handle)) {
136         uint32_t width;
137         uint32_t height;
138         uint32_t format;
139         uint64_t usage;
140         uint32_t stride;
141         uint32_t generation;
142         uint64_t bqId;
143         uint32_t bqSlot;
144         android::_UnwrapNativeCodec2GrallocMetadata(
145                 handle, &width, &height, &format, &usage, &stride, &generation, &bqId, &bqSlot);
146         c2_status_t err = sAllocator->priorGraphicAllocation(handle, &alloc);
147         if (err == C2_OK) {
148             std::shared_ptr<C2GraphicBlock> block;
149             if (bqId || bqSlot) {
150                 // BQBBP
151                 std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
152                         std::make_shared<C2BufferQueueBlockPoolData>(generation,
153                                                                      bqId,
154                                                                      (int32_t)bqSlot,
155                                                                      nullptr,
156                                                                      nullptr);
157                 block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
158             } else {
159                 block = _C2BlockFactory::CreateGraphicBlock(alloc);
160             }
161             return block;
162         }
163     }
164     return nullptr;
165 }
166 
167 namespace {
168 
getTimestampNow()169 int64_t getTimestampNow() {
170     int64_t stamp;
171     struct timespec ts;
172     // TODO: CLOCK_MONOTONIC_COARSE?
173     clock_gettime(CLOCK_MONOTONIC, &ts);
174     stamp = ts.tv_nsec / 1000;
175     stamp += (ts.tv_sec * 1000000LL);
176     return stamp;
177 }
178 
179 // Do not rely on AHardwareBuffer module for GraphicBuffer handling since AHardwareBuffer
180 // module is linked to framework which could have a different implementation of GraphicBuffer
181 // than mainline/vndk implementation.(See b/203347494.)
182 //
183 // b2h/h2b between HardwareBuffer and GraphicBuffer cannot be used. (b2h/h2b depend on
184 // AHardwareBuffer module for the conversion between HardwareBuffer and GraphicBuffer.)
185 // hgbp_ prefixed methods are added to be used instead of b2h/h2b.
186 //
187 // TODO: Remove dependency with existing AHwB module. Also clean up conversions.(conversions here
188 // and h2b/b2h coversions)
hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer * buffer)189 const GraphicBuffer* hgbp_AHBuffer_to_GraphicBuffer(const AHardwareBuffer* buffer) {
190     return GraphicBuffer::fromAHardwareBuffer(buffer);
191 }
192 
hgbp_createFromHandle(const AHardwareBuffer_Desc * desc,const native_handle_t * handle,sp<GraphicBuffer> * outBuffer)193 int hgbp_createFromHandle(const AHardwareBuffer_Desc* desc,
194                                      const native_handle_t* handle,
195                                      sp<GraphicBuffer> *outBuffer) {
196 
197     if (!desc || !handle || !outBuffer) return ::android::BAD_VALUE;
198     if (desc->rfu0 != 0 || desc->rfu1 != 0) return ::android::BAD_VALUE;
199     if (desc->format == AHARDWAREBUFFER_FORMAT_BLOB && desc->height != 1)
200         return ::android::BAD_VALUE;
201 
202     const int format = uint32_t(desc->format);
203     const uint64_t usage = uint64_t(desc->usage);
204     sp<GraphicBuffer> gbuffer(new GraphicBuffer(handle,
205                                                 GraphicBuffer::HandleWrapMethod::CLONE_HANDLE,
206                                                 desc->width, desc->height,
207                                                 format, desc->layers, usage, desc->stride));
208     status_t err = gbuffer->initCheck();
209     if (err != 0 || gbuffer->handle == 0) return err;
210 
211     *outBuffer = gbuffer;
212 
213     return ::android::NO_ERROR;
214 }
215 
hgbp_describe(const AHardwareBuffer * buffer,AHardwareBuffer_Desc * outDesc)216 void hgbp_describe(const AHardwareBuffer* buffer,
217         AHardwareBuffer_Desc* outDesc) {
218     if (!buffer || !outDesc) return;
219 
220     const GraphicBuffer* gbuffer = hgbp_AHBuffer_to_GraphicBuffer(buffer);
221 
222     outDesc->width = gbuffer->getWidth();
223     outDesc->height = gbuffer->getHeight();
224     outDesc->layers = gbuffer->getLayerCount();
225     outDesc->format = uint32_t(gbuffer->getPixelFormat());
226     outDesc->usage = uint64_t(gbuffer->getUsage());
227     outDesc->stride = gbuffer->getStride();
228     outDesc->rfu0 = 0;
229     outDesc->rfu1 = 0;
230 }
231 
232 
hgbp_h2b(HBuffer const & from,sp<GraphicBuffer> * to)233 bool hgbp_h2b(HBuffer const& from, sp<GraphicBuffer>* to) {
234     AHardwareBuffer_Desc const* desc =
235             reinterpret_cast<AHardwareBuffer_Desc const*>(
236             from.description.data());
237     native_handle_t const* handle = from.nativeHandle;
238     if (hgbp_createFromHandle(desc, handle, to) != ::android::OK) {
239         return false;
240     }
241     return true;
242 }
243 
hgbp_b2h(sp<GraphicBuffer> const & from,HBuffer * to,uint32_t * toGenerationNumber)244 bool hgbp_b2h(sp<GraphicBuffer> const& from, HBuffer* to,
245          uint32_t* toGenerationNumber) {
246     if (!from) {
247         return false;
248     }
249     AHardwareBuffer* hwBuffer = from->toAHardwareBuffer();
250     to->nativeHandle.setTo(
251           const_cast<native_handle_t*>(from->handle),
252           false);
253     hgbp_describe(
254             hwBuffer,
255             reinterpret_cast<AHardwareBuffer_Desc*>(to->description.data()));
256     if (toGenerationNumber) {
257         *toGenerationNumber = from->getGenerationNumber();
258     }
259     return true;
260 }
261 
262 // End of hgbp methods for GraphicBuffer creation.
263 
getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> & producer,uint32_t * generation,uint64_t * usage)264 bool getGenerationNumberAndUsage(const sp<HGraphicBufferProducer> &producer,
265                                  uint32_t *generation, uint64_t *usage) {
266     status_t status{};
267     int slot{};
268     bool bufferNeedsReallocation{};
269     sp<Fence> fence = new Fence();
270 
271     using Input = HGraphicBufferProducer::DequeueBufferInput;
272     using Output = HGraphicBufferProducer::DequeueBufferOutput;
273     Return<void> transResult = producer->dequeueBuffer(
274             Input{640, 480, HAL_PIXEL_FORMAT_YCBCR_420_888, 0},
275             [&status, &slot, &bufferNeedsReallocation, &fence]
276             (HStatus hStatus, int32_t hSlot, Output const& hOutput) {
277                 slot = static_cast<int>(hSlot);
278                 if (!h2b(hStatus, &status) || !h2b(hOutput.fence, &fence)) {
279                     status = ::android::BAD_VALUE;
280                 } else {
281                     bufferNeedsReallocation =
282                             hOutput.bufferNeedsReallocation;
283                 }
284             });
285     if (!transResult.isOk() || status != android::OK) {
286         return false;
287     }
288     HFenceWrapper hFenceWrapper{};
289     if (!b2h(fence, &hFenceWrapper)) {
290         (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
291         ALOGE("Invalid fence received from dequeueBuffer.");
292         return false;
293     }
294     sp<GraphicBuffer> slotBuffer = new GraphicBuffer();
295     // N.B. This assumes requestBuffer# returns an existing allocation
296     // instead of a new allocation.
297     transResult = producer->requestBuffer(
298             slot,
299             [&status, &slotBuffer, &generation, &usage](
300                     HStatus hStatus,
301                     HBuffer const& hBuffer,
302                     uint32_t generationNumber){
303                 if (h2b(hStatus, &status) &&
304                         hgbp_h2b(hBuffer, &slotBuffer) &&
305                         slotBuffer) {
306                     *generation = generationNumber;
307                     *usage = slotBuffer->getUsage();
308                     slotBuffer->setGenerationNumber(generationNumber);
309                 } else {
310                     status = android::BAD_VALUE;
311                 }
312             });
313     if (!transResult.isOk()) {
314         return false;
315     } else if (status != android::NO_ERROR) {
316         (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
317         return false;
318     }
319     (void)producer->detachBuffer(static_cast<int32_t>(slot)).isOk();
320     return true;
321 }
322 
323 };
324 
325 class C2BufferQueueBlockPool::Impl
326         : public std::enable_shared_from_this<C2BufferQueueBlockPool::Impl> {
327 private:
dequeueBuffer(uint32_t width,uint32_t height,uint32_t format,C2AndroidMemoryUsage androidUsage,int * slot,bool * needsRealloc,sp<Fence> * fence)328     c2_status_t dequeueBuffer(
329             uint32_t width,
330             uint32_t height,
331             uint32_t format,
332             C2AndroidMemoryUsage androidUsage,
333             int *slot, bool *needsRealloc, sp<Fence> *fence) {
334         status_t status{};
335         using Input = HGraphicBufferProducer::DequeueBufferInput;
336         using Output = HGraphicBufferProducer::DequeueBufferOutput;
337         Return<void> transResult = mProducer->dequeueBuffer(
338                 Input{
339                     width,
340                     height,
341                     format,
342                     androidUsage.asGrallocUsage()},
343                 [&status, slot, needsRealloc,
344                  fence](HStatus hStatus,
345                          int32_t hSlot,
346                          Output const& hOutput) {
347                     *slot = static_cast<int>(hSlot);
348                     if (!h2b(hStatus, &status) ||
349                             !h2b(hOutput.fence, fence)) {
350                         status = ::android::BAD_VALUE;
351                     } else {
352                         *needsRealloc =
353                                 hOutput.bufferNeedsReallocation;
354                     }
355                 });
356         if (!transResult.isOk() || status != android::OK) {
357             if (transResult.isOk()) {
358                 ++mDqFailure;
359                 if (status == android::INVALID_OPERATION ||
360                     status == android::TIMED_OUT ||
361                     status == android::WOULD_BLOCK) {
362                     // Dequeue buffer is blocked temporarily. Retrying is
363                     // required.
364                     return C2_BLOCKING;
365                 }
366             }
367             ALOGD("cannot dequeue buffer %d", status);
368             return C2_BAD_VALUE;
369         }
370         return C2_OK;
371     }
372 
fetchFromIgbp_l(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * c2Fence)373     c2_status_t fetchFromIgbp_l(
374             uint32_t width,
375             uint32_t height,
376             uint32_t format,
377             C2MemoryUsage usage,
378             std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
379             C2Fence *c2Fence) {
380         // We have an IGBP now.
381         C2AndroidMemoryUsage androidUsage = usage;
382         status_t status{};
383         int slot{};
384         bool bufferNeedsReallocation{};
385         sp<Fence> fence = new Fence();
386         ALOGV("tries to dequeue buffer");
387 
388         C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem(): nullptr;
389         { // Call dequeueBuffer().
390             c2_status_t c2Status;
391             if (syncVar) {
392                 uint32_t waitId;
393                 syncVar->lock();
394                 if (!syncVar->isDequeueableLocked(&waitId)) {
395                     syncVar->unlock();
396                     if (c2Fence) {
397                         *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
398                     }
399                     if (mInvalidated) {
400                         if (c2Fence) {
401                             *c2Fence = C2Fence();
402                         }
403                         return C2_BAD_STATE;
404                     }
405                     return C2_BLOCKING;
406                 }
407                 if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_ACTIVE) {
408                     waitId = syncVar->getWaitIdLocked();
409                     syncVar->unlock();
410                     if (c2Fence) {
411                         *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
412                     }
413                     if (mInvalidated) {
414                         if (c2Fence) {
415                             *c2Fence = C2Fence();
416                         }
417                         return C2_BAD_STATE;
418                     }
419                     return C2_BLOCKING;
420                 }
421                 syncVar->notifyDequeuedLocked();
422                 syncVar->unlock();
423                 c2Status = dequeueBuffer(width, height, format, androidUsage,
424                               &slot, &bufferNeedsReallocation, &fence);
425                 if (c2Status != C2_OK) {
426                     syncVar->lock();
427                     syncVar->notifyQueuedLocked();
428                     syncVar->unlock();
429                 }
430             } else {
431                 c2Status = dequeueBuffer(width, height, format, usage,
432                               &slot, &bufferNeedsReallocation, &fence);
433             }
434             if (c2Status != C2_OK) {
435                 return c2Status;
436             }
437             mDqFailure = 0;
438             mLastDqTs = getTimestampNow();
439         }
440         HFenceWrapper hFenceWrapper{};
441         if (!b2h(fence, &hFenceWrapper)) {
442             ALOGE("Invalid fence received from dequeueBuffer.");
443             return C2_BAD_VALUE;
444         }
445         ALOGV("dequeued a buffer successfully");
446         bool dequeueable = false;
447         uint32_t waitId;
448         if (fence) {
449             static constexpr int kFenceWaitTimeMs = 10;
450 
451             if (bufferNeedsReallocation) {
452                 mBuffers[slot].clear();
453             }
454 
455             status_t status = fence->wait(kFenceWaitTimeMs);
456             if (status == -ETIME) {
457                 // fence is not signalled yet.
458                 if (syncVar) {
459                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
460                     syncVar->lock();
461                     dequeueable = syncVar->notifyQueuedLocked(&waitId);
462                     syncVar->unlock();
463                     if (c2Fence) {
464                         *c2Fence = dequeueable ? C2Fence() :
465                                 _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
466                     }
467                 } else {
468                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
469                 }
470                 return C2_BLOCKING;
471             }
472             if (status != android::NO_ERROR) {
473                 ALOGD("buffer fence wait error %d", status);
474                 if (syncVar) {
475                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
476                     syncVar->lock();
477                     syncVar->notifyQueuedLocked();
478                     syncVar->unlock();
479                     if (c2Fence) {
480                         *c2Fence = C2Fence();
481                     }
482                 } else {
483                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
484                 }
485                 return C2_BAD_VALUE;
486             } else if (mRenderCallback) {
487                 nsecs_t signalTime = fence->getSignalTime();
488                 if (signalTime >= 0 && signalTime < INT64_MAX) {
489                     mRenderCallback(mProducerId, slot, signalTime);
490                 } else {
491                     ALOGV("got fence signal time of %lld", (long long)signalTime);
492                 }
493             }
494         }
495 
496         sp<GraphicBuffer> &slotBuffer = mBuffers[slot];
497         uint32_t outGeneration;
498         if (bufferNeedsReallocation || !slotBuffer) {
499             if (!slotBuffer) {
500                 slotBuffer = new GraphicBuffer();
501             }
502             // N.B. This assumes requestBuffer# returns an existing allocation
503             // instead of a new allocation.
504             Return<void> transResult = mProducer->requestBuffer(
505                     slot,
506                     [&status, &slotBuffer, &outGeneration](
507                             HStatus hStatus,
508                             HBuffer const& hBuffer,
509                             uint32_t generationNumber){
510                         if (h2b(hStatus, &status) &&
511                                 hgbp_h2b(hBuffer, &slotBuffer) &&
512                                 slotBuffer) {
513                             slotBuffer->setGenerationNumber(generationNumber);
514                             outGeneration = generationNumber;
515                         } else {
516                             status = android::BAD_VALUE;
517                         }
518                     });
519             if (!transResult.isOk()) {
520                 slotBuffer.clear();
521                 return C2_BAD_VALUE;
522             } else if (status != android::NO_ERROR) {
523                 slotBuffer.clear();
524                 if (syncVar) {
525                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
526                     syncVar->lock();
527                     syncVar->notifyQueuedLocked();
528                     syncVar->unlock();
529                     if (c2Fence) {
530                         *c2Fence = C2Fence();
531                     }
532                 } else {
533                     (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
534                 }
535                 return C2_BAD_VALUE;
536             }
537             if (mGeneration == 0) {
538                 // getting generation # lazily due to dequeue failure.
539                 mGeneration = outGeneration;
540             }
541         }
542         if (slotBuffer) {
543             ALOGV("buffer wraps %llu %d", (unsigned long long)mProducerId, slot);
544             C2Handle *c2Handle = android::WrapNativeCodec2GrallocHandle(
545                     slotBuffer->handle,
546                     slotBuffer->width,
547                     slotBuffer->height,
548                     slotBuffer->format,
549                     slotBuffer->usage,
550                     slotBuffer->stride,
551                     slotBuffer->getGenerationNumber(),
552                     mProducerId, slot);
553             if (c2Handle) {
554                 std::shared_ptr<C2GraphicAllocation> alloc;
555                 c2_status_t err = mAllocator->priorGraphicAllocation(c2Handle, &alloc);
556                 if (err != C2_OK) {
557                     native_handle_close(c2Handle);
558                     native_handle_delete(c2Handle);
559                     return err;
560                 }
561                 std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
562                         std::make_shared<C2BufferQueueBlockPoolData>(
563                                 slotBuffer->getGenerationNumber(),
564                                 mProducerId, slot,
565                                 mIgbpValidityToken, mProducer, mSyncMem);
566                 mPoolDatas[slot] = poolData;
567                 *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
568                 return C2_OK;
569             }
570             // Block was not created. call requestBuffer# again next time.
571             slotBuffer.clear();
572             if (syncVar) {
573                 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
574                 syncVar->lock();
575                 syncVar->notifyQueuedLocked();
576                 syncVar->unlock();
577                 if (c2Fence) {
578                     *c2Fence = C2Fence();
579                 }
580             } else {
581                 (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
582             }
583             return C2_BAD_VALUE;
584         }
585         if (c2Fence) {
586             *c2Fence = C2Fence();
587         }
588         return C2_BAD_VALUE;
589     }
590 
clearDeferredBlocks_l()591     void clearDeferredBlocks_l() {
592         if (mHavingDeallocationDeferred) {
593             mHavingDeallocationDeferred = false;
594             for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
595                 mBuffersWithDeallocationDeferred[i].clear();
596             }
597         }
598     }
599 
600 public:
Impl(const std::shared_ptr<C2Allocator> & allocator)601     Impl(const std::shared_ptr<C2Allocator> &allocator)
602         : mInit(C2_OK), mProducerId(0), mGeneration(0),
603           mConsumerUsage(0), mDqFailure(0), mLastDqTs(0),
604           mLastDqLogTs(0), mAllocator(allocator),
605           mDeferDeallocationAfterStop(false),
606           mHavingDeallocationDeferred(false), mIgbpValidityToken(std::make_shared<int>(0)) {
607     }
608 
~Impl()609     ~Impl() {
610         mIgbpValidityToken.reset();
611         for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
612             mBuffers[i].clear();
613         }
614     }
615 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * fence)616     c2_status_t fetchGraphicBlock(
617             uint32_t width,
618             uint32_t height,
619             uint32_t format,
620             C2MemoryUsage usage,
621             std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
622             C2Fence *fence) {
623         block->reset();
624         if (mInit != C2_OK) {
625             return mInit;
626         }
627 
628         static int kMaxIgbpRetryDelayUs = 10000;
629 
630         std::unique_lock<std::mutex> lock(mMutex);
631         if (mInvalidated) {
632             return C2_BAD_STATE;
633         }
634         if (mLastDqLogTs == 0) {
635             mLastDqLogTs = getTimestampNow();
636         } else {
637             int64_t now = getTimestampNow();
638             if (now >= mLastDqLogTs + 5000000) {
639                 if (now >= mLastDqTs + 1000000 || mDqFailure > 5) {
640                     ALOGW("last successful dequeue was %lld us ago, "
641                           "%zu consecutive failures",
642                           (long long)(now - mLastDqTs), mDqFailure);
643                 }
644                 mLastDqLogTs = now;
645             }
646         }
647         if (mProducerId == 0) {
648             clearDeferredBlocks_l();
649             std::shared_ptr<C2GraphicAllocation> alloc;
650             c2_status_t err = mAllocator->newGraphicAllocation(
651                     width, height, format, usage, &alloc);
652             if (err != C2_OK) {
653                 return err;
654             }
655             std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
656                     std::make_shared<C2BufferQueueBlockPoolData>(
657                             0, (uint64_t)0, ~0, nullptr, nullptr, nullptr);
658             *block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
659             ALOGV("allocated a buffer successfully");
660 
661             return C2_OK;
662         }
663         c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block, fence);
664         if (status == C2_BLOCKING) {
665             lock.unlock();
666             if (!fence) {
667                 // in order not to drain cpu from component's spinning
668                 ::usleep(kMaxIgbpRetryDelayUs);
669             }
670         }
671         return status;
672     }
673 
setRenderCallback(const OnRenderCallback & renderCallback)674     void setRenderCallback(const OnRenderCallback &renderCallback) {
675         std::scoped_lock<std::mutex> lock(mMutex);
676         mRenderCallback = renderCallback;
677     }
678 
679     /* This is for Old HAL request for compatibility */
configureProducer(const sp<HGraphicBufferProducer> & producer)680     void configureProducer(const sp<HGraphicBufferProducer> &producer) {
681         uint64_t producerId = 0;
682         uint32_t generation = 0;
683         uint64_t usage = 0;
684         bool bqInformation = false;
685         if (producer) {
686             Return<uint64_t> transResult = producer->getUniqueId();
687             if (!transResult.isOk()) {
688                 ALOGD("configureProducer -- failed to connect to the producer");
689                 return;
690             }
691             producerId = static_cast<uint64_t>(transResult);
692             bqInformation = getGenerationNumberAndUsage(producer, &generation, &usage);
693             if (!bqInformation) {
694                 ALOGW("get generationNumber failed %llu",
695                       (unsigned long long)producerId);
696             }
697         }
698         configureProducer(producer, nullptr, producerId, generation, usage, bqInformation);
699     }
700 
configureProducer(const sp<HGraphicBufferProducer> & producer,native_handle_t * syncHandle,uint64_t producerId,uint32_t generation,uint64_t usage,bool bqInformation)701     void configureProducer(const sp<HGraphicBufferProducer> &producer,
702                            native_handle_t *syncHandle,
703                            uint64_t producerId,
704                            uint32_t generation,
705                            uint64_t usage,
706                            bool bqInformation) {
707         bool toNullSurface = false;
708         std::shared_ptr<C2SurfaceSyncMemory> c2SyncMem;
709         if (syncHandle) {
710             if (!producer) {
711                 native_handle_close(syncHandle);
712                 native_handle_delete(syncHandle);
713             } else {
714                 c2SyncMem = C2SurfaceSyncMemory::Import(syncHandle);
715             }
716         }
717         int migrated = 0;
718         // poolDatas dtor should not be called during lock is held.
719         std::shared_ptr<C2BufferQueueBlockPoolData>
720                 poolDatas[NUM_BUFFER_SLOTS];
721         {
722             sp<GraphicBuffer> buffers[NUM_BUFFER_SLOTS];
723             std::scoped_lock<std::mutex> lock(mMutex);
724             int32_t oldGeneration = mGeneration;
725             if (producer) {
726                 mProducer = producer;
727                 mProducerId = producerId;
728                 mGeneration = bqInformation ? generation : 0;
729             } else {
730                 if (mProducer) {
731                     toNullSurface = true;
732                 }
733                 mProducer = nullptr;
734                 mProducerId = 0;
735                 mGeneration = 0;
736                 ALOGD("configuring null producer: igbp_information(%d)", bqInformation);
737             }
738             if (mInvalidated) {
739                 return;
740             }
741             {
742                 std::unique_lock<std::mutex> memLock(mSyncMemMutex);
743                 mOldMem = mSyncMem; // prevent destruction while locked.
744                                     // The waiters from the old memory will be
745                                     // woken up by the client after this
746                                     // configuration from HAL being finished.
747                                     // But we will keep this in case of the
748                                     // client being dead in between.
749                                     // In the case the death listener will wake
750                                     // up the wiators for the old memory using
751                                     // mOldMem here.
752                 mSyncMem = c2SyncMem;
753             }
754             C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
755             if (syncVar) {
756                 syncVar->lock();
757                 syncVar->setSyncStatusLocked(C2SyncVariables::STATUS_ACTIVE);
758                 syncVar->unlock();
759             }
760             if (mProducer && bqInformation) { // migrate buffers
761                 for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
762                     std::shared_ptr<C2BufferQueueBlockPoolData> data =
763                             mPoolDatas[i].lock();
764                     if (data) {
765                         int slot = data->migrate(
766                                 mProducer, generation, usage,
767                                 producerId, mBuffers[i], oldGeneration, mSyncMem);
768                         if (slot >= 0) {
769                             buffers[slot] = mBuffers[i];
770                             poolDatas[slot] = data;
771                             ++migrated;
772                         }
773                     }
774                 }
775             } else {
776                 // old buffers should not be cancelled since the associated IGBP
777                 // is no longer valid.
778                 mIgbpValidityToken = std::make_shared<int>(0);
779                 if (mDeferDeallocationAfterStop) {
780                     if (toNullSurface) {
781                         mHavingDeallocationDeferred = true;
782                         for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
783                             mBuffersWithDeallocationDeferred[i] = mBuffers[i];
784                         }
785                     }
786                 }
787             }
788             if (!toNullSurface) {
789                 clearDeferredBlocks_l();
790             }
791             if (mInvalidated) {
792                 mIgbpValidityToken = std::make_shared<int>(0);
793             }
794             for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
795                 mBuffers[i] = buffers[i];
796                 mPoolDatas[i] = poolDatas[i];
797             }
798         }
799         if (producer && bqInformation) {
800             ALOGD("local generation change %u , "
801                   "bqId: %llu migrated buffers # %d",
802                   generation, (unsigned long long)producerId, migrated);
803         }
804         mConsumerUsage = usage;
805     }
806 
getConsumerUsage(uint64_t * consumeUsage)807     void getConsumerUsage(uint64_t *consumeUsage) {
808         *consumeUsage = mConsumerUsage;
809     }
810 
invalidate()811     void invalidate() {
812         std::shared_ptr<C2SurfaceSyncMemory> syncMem;
813         std::shared_ptr<C2SurfaceSyncMemory> oldMem;
814         {
815             std::unique_lock<std::mutex> l(mSyncMemMutex);
816             bool old = mInvalidated.exchange(true);
817             if (old) {
818                 return;
819             }
820             syncMem = mSyncMem;
821             oldMem = mOldMem;
822         }
823         mIgbpValidityToken.reset();
824         C2SyncVariables *syncVar = syncMem ? syncMem->mem(): nullptr;
825         if (syncVar) {
826             syncVar->invalidate();
827         }
828         C2SyncVariables *oldVar = oldMem ? oldMem->mem(): nullptr;
829         if (oldVar) {
830             oldVar->invalidate();
831         }
832         // invalidate pending lock from a dead process if any
833         if (syncVar) {
834             syncVar->clearLockIfNecessary();
835         }
836         if (oldVar) {
837             oldVar->clearLockIfNecessary();
838         }
839     }
840 
setDeferDeallocationAfterStop()841     void setDeferDeallocationAfterStop() {
842         std::scoped_lock<std::mutex> lock(mMutex);
843         mDeferDeallocationAfterStop = true;
844     }
845 
clearDeferredBlocks()846     void clearDeferredBlocks() {
847         std::scoped_lock<std::mutex> lock(mMutex);
848         clearDeferredBlocks_l();
849     }
850 
851 private:
852     friend struct C2BufferQueueBlockPoolData;
853 
854     c2_status_t mInit;
855     uint64_t mProducerId;
856     uint32_t mGeneration;
857     uint64_t mConsumerUsage;
858     OnRenderCallback mRenderCallback;
859 
860     size_t mDqFailure;
861     int64_t mLastDqTs;
862     int64_t mLastDqLogTs;
863 
864     const std::shared_ptr<C2Allocator> mAllocator;
865 
866     std::mutex mMutex;
867     sp<HGraphicBufferProducer> mProducer;
868     sp<HGraphicBufferProducer> mSavedProducer;
869 
870     sp<GraphicBuffer> mBuffers[NUM_BUFFER_SLOTS];
871     std::weak_ptr<C2BufferQueueBlockPoolData> mPoolDatas[NUM_BUFFER_SLOTS];
872 
873     // In order to workaround b/322731059,
874     // deallocating buffers due to stop using the current surface
875     // could be deferred until the component calling stop or a
876     // new allocation being requested.
877     bool mDeferDeallocationAfterStop;
878     bool mHavingDeallocationDeferred;
879     sp<GraphicBuffer> mBuffersWithDeallocationDeferred[NUM_BUFFER_SLOTS];
880 
881     std::mutex mSyncMemMutex;
882     std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
883     std::shared_ptr<C2SurfaceSyncMemory> mOldMem;
884 
885     // IGBP invalidation notification token.
886     // The buffers(C2BufferQueueBlockPoolData) has the reference to the IGBP where
887     // they belong in order to call IGBP::cancelBuffer() when they are of no use.
888     //
889     // In certain cases, IGBP is no longer used by this class(actually MediaCodec)
890     // any more and the situation needs to be addressed quickly. In order to
891     // achieve those, std::shared_ptr<> is used as a token for quick IGBP invalidation
892     // notification from the buffers.
893     //
894     // The buffer side will have the reference of the token as std::weak_ptr<>.
895     // if the token has been expired, the buffers will not call IGBP::cancelBuffer()
896     // when they are no longer used.
897     std::shared_ptr<int> mIgbpValidityToken;
898     std::atomic<bool> mInvalidated{false};
899 };
900 
C2BufferQueueBlockPoolData(uint32_t generation,uint64_t bqId,int32_t bqSlot,const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & producer)901 C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
902         uint32_t generation, uint64_t bqId, int32_t bqSlot,
903         const std::shared_ptr<int>& owner,
904         const sp<HGraphicBufferProducer>& producer) :
905         mLocal(false), mHeld(producer && bqId != 0),
906         mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
907         mCurrentGeneration(generation), mCurrentBqId(bqId),
908         mTransfer(false), mAttach(false), mDisplay(false),
909         mOwner(owner), mIgbp(producer) {
910 }
911 
C2BufferQueueBlockPoolData(uint32_t generation,uint64_t bqId,int32_t bqSlot,const std::shared_ptr<int> & owner,const android::sp<HGraphicBufferProducer> & producer,std::shared_ptr<C2SurfaceSyncMemory> syncMem)912 C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
913         uint32_t generation, uint64_t bqId, int32_t bqSlot,
914         const std::shared_ptr<int>& owner,
915         const android::sp<HGraphicBufferProducer>& producer,
916         std::shared_ptr<C2SurfaceSyncMemory> syncMem) :
917         mLocal(true), mHeld(true),
918         mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
919         mCurrentGeneration(generation), mCurrentBqId(bqId),
920         mTransfer(false), mAttach(false), mDisplay(false),
921         mOwner(owner), mIgbp(producer), mSyncMem(syncMem) {
922 }
923 
~C2BufferQueueBlockPoolData()924 C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
925     if (!mHeld || mBqId == 0 || !mIgbp) {
926         return;
927     }
928 
929     if (mLocal) {
930         if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId && !mOwner.expired()) {
931             C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
932             if (syncVar) {
933                 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
934                 syncVar->lock();
935                 syncVar->notifyQueuedLocked(nullptr,
936                         syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE);
937                 syncVar->unlock();
938             } else {
939                 mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
940             }
941         }
942     } else if (!mOwner.expired()) {
943         C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
944         if (syncVar) {
945             mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
946             syncVar->lock();
947             syncVar->notifyQueuedLocked(nullptr,
948                     syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING);
949             syncVar->unlock();
950         } else {
951             mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
952         }
953     }
954 }
955 
getType() const956 C2BufferQueueBlockPoolData::type_t C2BufferQueueBlockPoolData::getType() const {
957     return TYPE_BUFFERQUEUE;
958 }
959 
migrate(const sp<HGraphicBufferProducer> & producer,uint32_t toGeneration,uint64_t toUsage,uint64_t toBqId,sp<GraphicBuffer> & graphicBuffer,uint32_t oldGeneration,std::shared_ptr<C2SurfaceSyncMemory> syncMem)960 int C2BufferQueueBlockPoolData::migrate(
961         const sp<HGraphicBufferProducer>& producer,
962         uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
963         sp<GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
964         std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
965     std::scoped_lock<std::mutex> l(mLock);
966 
967     mCurrentBqId = toBqId;
968     mCurrentGeneration = toGeneration;
969 
970     if (!mHeld || mBqId == 0) {
971         ALOGV("buffer is not owned");
972         return -1;
973     }
974     if (!mLocal) {
975         ALOGV("pool is not local");
976         return -1;
977     }
978     if (mBqSlot < 0 || mBqSlot >= NUM_BUFFER_SLOTS) {
979         ALOGV("slot is not in effect");
980         return -1;
981     }
982     if (!graphicBuffer) {
983         ALOGV("buffer is null");
984         return -1;
985     }
986     if (toGeneration == mGeneration && mBqId == toBqId) {
987         ALOGV("cannot migrate to same bufferqueue");
988         return -1;
989     }
990     if (oldGeneration != mGeneration) {
991         ALOGV("cannot migrate stale buffer");
992         return -1;
993     }
994     if (mTransfer) {
995         // either transferred or detached.
996         ALOGV("buffer is in transfer");
997         return -1;
998     }
999 
1000     if (toUsage != graphicBuffer->getUsage()) {
1001         sp<GraphicBuffer> newBuffer = new GraphicBuffer(
1002             graphicBuffer->handle, GraphicBuffer::CLONE_HANDLE,
1003             graphicBuffer->width, graphicBuffer->height, graphicBuffer->format,
1004             graphicBuffer->layerCount, toUsage | graphicBuffer->getUsage(), graphicBuffer->stride);
1005         if (newBuffer->initCheck() == android::NO_ERROR) {
1006             graphicBuffer = std::move(newBuffer);
1007         } else {
1008             ALOGW("%s() failed to update usage, original usage=%" PRIx64 ", toUsage=%" PRIx64,
1009                   __func__, graphicBuffer->getUsage(), toUsage);
1010         }
1011     }
1012     graphicBuffer->setGenerationNumber(toGeneration);
1013 
1014     HBuffer hBuffer{};
1015     uint32_t hGenerationNumber{};
1016     if (!hgbp_b2h(graphicBuffer, &hBuffer, &hGenerationNumber)) {
1017         ALOGD("I to O conversion failed");
1018         return -1;
1019     }
1020 
1021     bool converted{};
1022     status_t bStatus{};
1023     int slot;
1024     int *outSlot = &slot;
1025     Return<void> transResult =
1026             producer->attachBuffer(hBuffer, hGenerationNumber,
1027                     [&converted, &bStatus, outSlot](
1028                             HStatus hStatus, int32_t hSlot, bool releaseAll) {
1029                         converted = h2b(hStatus, &bStatus);
1030                         *outSlot = static_cast<int>(hSlot);
1031                         if (converted && releaseAll && bStatus == android::OK) {
1032                             bStatus = android::INVALID_OPERATION;
1033                         }
1034                     });
1035     if (!transResult.isOk() || !converted || bStatus != android::OK) {
1036         ALOGD("attach failed %d", static_cast<int>(bStatus));
1037         return -1;
1038     }
1039     ALOGV("local migration from gen %u : %u slot %d : %d",
1040           mGeneration, toGeneration, mBqSlot, slot);
1041     mIgbp = producer;
1042     mGeneration = toGeneration;
1043     mBqId = toBqId;
1044     mBqSlot = slot;
1045     mSyncMem = syncMem;
1046 
1047     C2SyncVariables *syncVar = syncMem ? syncMem->mem() : nullptr;
1048     if (syncVar) {
1049         syncVar->lock();
1050         syncVar->notifyDequeuedLocked();
1051         syncVar->unlock();
1052     }
1053     return slot;
1054 }
1055 
getBufferQueueData(uint32_t * generation,uint64_t * bqId,int32_t * bqSlot) const1056 void C2BufferQueueBlockPoolData::getBufferQueueData(
1057         uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const {
1058     if (generation) {
1059         std::scoped_lock<std::mutex> lock(mLock);
1060         *generation = mGeneration;
1061         if (bqId) {
1062             *bqId = mBqId;
1063         }
1064         if (bqSlot) {
1065             *bqSlot = mBqSlot;
1066         }
1067     }
1068 }
1069 
holdBlockFromBufferQueue(const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem)1070 bool C2BufferQueueBlockPoolData::holdBlockFromBufferQueue(
1071         const std::shared_ptr<int>& owner,
1072         const sp<HGraphicBufferProducer>& igbp,
1073         std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
1074     std::scoped_lock<std::mutex> lock(mLock);
1075     if (!mLocal) {
1076         mOwner = owner;
1077         mIgbp = igbp;
1078         mSyncMem = syncMem;
1079     }
1080     if (mHeld) {
1081         return false;
1082     }
1083     mHeld = true;
1084     return true;
1085 }
1086 
beginTransferBlockToClient()1087 bool C2BufferQueueBlockPoolData::beginTransferBlockToClient() {
1088     std::scoped_lock<std::mutex> lock(mLock);
1089     mTransfer = true;
1090     return true;
1091 }
1092 
endTransferBlockToClient(bool transfer)1093 bool C2BufferQueueBlockPoolData::endTransferBlockToClient(bool transfer) {
1094     std::scoped_lock<std::mutex> lock(mLock);
1095     mTransfer = false;
1096     if (transfer) {
1097         mHeld = false;
1098     }
1099     return true;
1100 }
1101 
beginAttachBlockToBufferQueue()1102 bool C2BufferQueueBlockPoolData::beginAttachBlockToBufferQueue() {
1103     std::scoped_lock<std::mutex> lock(mLock);
1104     if (mLocal || mDisplay ||
1105         mAttach || !mHeld) {
1106         return false;
1107     }
1108     if (mBqId == 0) {
1109         return false;
1110     }
1111     mAttach = true;
1112     return true;
1113 }
1114 
endAttachBlockToBufferQueue(const std::shared_ptr<int> & owner,const sp<HGraphicBufferProducer> & igbp,std::shared_ptr<C2SurfaceSyncMemory> syncMem,uint32_t generation,uint64_t bqId,int32_t bqSlot)1115 bool C2BufferQueueBlockPoolData::endAttachBlockToBufferQueue(
1116         const std::shared_ptr<int>& owner,
1117         const sp<HGraphicBufferProducer>& igbp,
1118         std::shared_ptr<C2SurfaceSyncMemory> syncMem,
1119         uint32_t generation,
1120         uint64_t bqId,
1121         int32_t bqSlot) {
1122     std::scoped_lock<std::mutex> lock(mLock);
1123     if (mLocal || !mAttach) {
1124         return false;
1125     }
1126     if (mDisplay) {
1127         mAttach = false;
1128         mHeld = false;
1129         return false;
1130     }
1131     mAttach = false;
1132     mHeld = true;
1133     mOwner = owner;
1134     mIgbp = igbp;
1135     mSyncMem = syncMem;
1136     mGeneration = generation;
1137     mBqId = bqId;
1138     mBqSlot = bqSlot;
1139     return true;
1140 }
1141 
displayBlockToBufferQueue()1142 bool C2BufferQueueBlockPoolData::displayBlockToBufferQueue() {
1143     std::scoped_lock<std::mutex> lock(mLock);
1144     if (mLocal || mDisplay || !mHeld) {
1145         return false;
1146     }
1147     if (mBqId == 0) {
1148         return false;
1149     }
1150     mDisplay = true;
1151     if (mAttach) {
1152         return false;
1153     }
1154     mHeld = false;
1155     return true;
1156 }
1157 
C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> & allocator,const local_id_t localId)1158 C2BufferQueueBlockPool::C2BufferQueueBlockPool(
1159         const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
1160         : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
1161 
~C2BufferQueueBlockPool()1162 C2BufferQueueBlockPool::~C2BufferQueueBlockPool() {}
1163 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block)1164 c2_status_t C2BufferQueueBlockPool::fetchGraphicBlock(
1165         uint32_t width,
1166         uint32_t height,
1167         uint32_t format,
1168         C2MemoryUsage usage,
1169         std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
1170     ScopedTrace trace(ATRACE_TAG,"C2BufferQueueBlockPool::fetchGraphicBlock");
1171     if (mImpl) {
1172         return mImpl->fetchGraphicBlock(width, height, format, usage, block, nullptr);
1173     }
1174     return C2_CORRUPTED;
1175 }
1176 
fetchGraphicBlock(uint32_t width,uint32_t height,uint32_t format,C2MemoryUsage usage,std::shared_ptr<C2GraphicBlock> * block,C2Fence * fence)1177 c2_status_t C2BufferQueueBlockPool::fetchGraphicBlock(
1178         uint32_t width,
1179         uint32_t height,
1180         uint32_t format,
1181         C2MemoryUsage usage,
1182         std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
1183         C2Fence *fence /* nonnull */) {
1184     if (mImpl) {
1185         return mImpl->fetchGraphicBlock(width, height, format, usage, block, fence);
1186     }
1187     return C2_CORRUPTED;
1188 }
1189 
configureProducer(const sp<HGraphicBufferProducer> & producer)1190 void C2BufferQueueBlockPool::configureProducer(const sp<HGraphicBufferProducer> &producer) {
1191     if (mImpl) {
1192         mImpl->configureProducer(producer);
1193     }
1194 }
1195 
configureProducer(const sp<HGraphicBufferProducer> & producer,native_handle_t * syncMemory,uint64_t bqId,uint32_t generationId,uint64_t consumerUsage)1196 void C2BufferQueueBlockPool::configureProducer(
1197         const sp<HGraphicBufferProducer> &producer,
1198         native_handle_t *syncMemory,
1199         uint64_t bqId,
1200         uint32_t generationId,
1201         uint64_t consumerUsage) {
1202     if (mImpl) {
1203         mImpl->configureProducer(
1204                producer, syncMemory, bqId, generationId, consumerUsage, true);
1205     }
1206 }
1207 
setRenderCallback(const OnRenderCallback & renderCallback)1208 void C2BufferQueueBlockPool::setRenderCallback(const OnRenderCallback &renderCallback) {
1209     if (mImpl) {
1210         mImpl->setRenderCallback(renderCallback);
1211     }
1212 }
1213 
getConsumerUsage(uint64_t * consumeUsage)1214 void C2BufferQueueBlockPool::getConsumerUsage(uint64_t *consumeUsage) {
1215     if (mImpl) {
1216         mImpl->getConsumerUsage(consumeUsage);
1217     }
1218 }
1219 
invalidate()1220 void C2BufferQueueBlockPool::invalidate() {
1221     if (mImpl) {
1222         mImpl->invalidate();
1223     }
1224 }
1225 
setDeferDeallocationAfterStop()1226 void C2BufferQueueBlockPool::setDeferDeallocationAfterStop() {
1227     if (mImpl) {
1228         mImpl->setDeferDeallocationAfterStop();
1229     }
1230 }
1231 
clearDeferredBlocks()1232 void C2BufferQueueBlockPool::clearDeferredBlocks() {
1233     if (mImpl) {
1234         mImpl->clearDeferredBlocks();
1235     }
1236 }
1237 
1238