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