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