blob: 01b0678087623a62c65de38f3fc0e0774f673db0 [file] [log] [blame]
Sungtak Leef075f712023-07-20 23:37:45 +00001/*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Sungtak Lee5bce4ca2023-10-12 03:13:04 +000016//#define LOG_NDEBUG 0
17#define LOG_TAG "GraphicsTracker"
Sungtak Leef6fe5f72023-09-17 23:53:50 +000018#include <fcntl.h>
19#include <unistd.h>
Sungtak Leef075f712023-07-20 23:37:45 +000020
21#include <media/stagefright/foundation/ADebug.h>
22#include <private/android/AHardwareBufferHelpers.h>
23#include <vndk/hardware_buffer.h>
24
Sungtak Lee72dfba62023-09-07 23:26:30 +000025#include <C2BlockInternal.h>
Sungtak Leef075f712023-07-20 23:37:45 +000026#include <codec2/aidl/GraphicsTracker.h>
27
28namespace aidl::android::hardware::media::c2::implementation {
29
30namespace {
31
Sungtak Leef6fe5f72023-09-17 23:53:50 +000032static constexpr int kMaxDequeueMin = 1;
33static constexpr int kMaxDequeueMax = ::android::BufferQueueDefs::NUM_BUFFER_SLOTS - 2;
34
Sungtak Leef075f712023-07-20 23:37:45 +000035c2_status_t retrieveAHardwareBufferId(const C2ConstGraphicBlock &blk, uint64_t *bid) {
Sungtak Lee72dfba62023-09-07 23:26:30 +000036 std::shared_ptr<const _C2BlockPoolData> bpData = _C2BlockFactory::GetGraphicBlockPoolData(blk);
37 if (bpData->getType() != _C2BlockPoolData::TYPE_AHWBUFFER) {
38 return C2_BAD_VALUE;
39 }
40 if (__builtin_available(android __ANDROID_API_T__, *)) {
41 AHardwareBuffer *pBuf;
42 if (!_C2BlockFactory::GetAHardwareBuffer(bpData, &pBuf)) {
43 return C2_CORRUPTED;
44 }
45 int ret = AHardwareBuffer_getId(pBuf, bid);
46 if (ret != ::android::OK) {
47 return C2_CORRUPTED;
48 }
49 return C2_OK;
50 } else {
51 return C2_OMITTED;
52 }
Sungtak Leef075f712023-07-20 23:37:45 +000053}
54
55} // anonymous namespace
56
57GraphicsTracker::BufferItem::BufferItem(
58 uint32_t generation, int slot, const sp<GraphicBuffer>& buf, const sp<Fence>& fence) :
59 mInit{false}, mGeneration{generation}, mSlot{slot} {
60 if (!buf) {
61 return;
62 }
Sungtak Lee72dfba62023-09-07 23:26:30 +000063 if (__builtin_available(android __ANDROID_API_T__, *)) {
64 AHardwareBuffer *pBuf = AHardwareBuffer_from_GraphicBuffer(buf.get());
65 int ret = AHardwareBuffer_getId(pBuf, &mId);
66 if (ret != ::android::OK) {
67 return;
68 }
69 mUsage = buf->getUsage();
70 AHardwareBuffer_acquire(pBuf);
71 mBuf = pBuf;
72 mFence = fence;
73 mInit = true;
Sungtak Leef075f712023-07-20 23:37:45 +000074 }
Sungtak Leef075f712023-07-20 23:37:45 +000075}
76
77GraphicsTracker::BufferItem::BufferItem(
Sungtak Lee5bce4ca2023-10-12 03:13:04 +000078 uint32_t generation, AHardwareBuffer *pBuf, uint64_t usage) :
Sungtak Leef075f712023-07-20 23:37:45 +000079 mInit{true}, mGeneration{generation}, mSlot{-1},
Sungtak Lee5bce4ca2023-10-12 03:13:04 +000080 mBuf{pBuf}, mUsage{usage},
Sungtak Leef075f712023-07-20 23:37:45 +000081 mFence{Fence::NO_FENCE} {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +000082 if (__builtin_available(android __ANDROID_API_T__, *)) {
83 int ret = AHardwareBuffer_getId(mBuf, &mId);
84 if (ret != ::android::OK) {
85 mInit = false;
86 mBuf = nullptr;
87 return;
88 }
89 }
90 AHardwareBuffer_acquire(mBuf);
Sungtak Leef075f712023-07-20 23:37:45 +000091}
92
93GraphicsTracker::BufferItem::~BufferItem() {
94 if (mInit) {
95 AHardwareBuffer_release(mBuf);
96 }
97}
98
Sungtak Lee5bce4ca2023-10-12 03:13:04 +000099
100std::shared_ptr<GraphicsTracker::BufferItem> GraphicsTracker::BufferItem::migrateBuffer(
Sungtak Leef075f712023-07-20 23:37:45 +0000101 uint64_t newUsage, uint32_t newGeneration) {
102 if (!mInit) {
103 return nullptr;
104 }
105 newUsage |= mUsage;
106 uint64_t ahbUsage = ::android::AHardwareBuffer_convertFromGrallocUsageBits(newUsage);
107 AHardwareBuffer_Desc desc;
108 AHardwareBuffer_describe(mBuf, &desc);
109 // TODO: we need well-established buffer migration features from graphics.
110 // (b/273776738)
111 desc.usage = ahbUsage;
112 const native_handle_t *handle = AHardwareBuffer_getNativeHandle(mBuf);
113 if (!handle) {
114 return nullptr;
115 }
116
117 AHardwareBuffer *newBuf;
118 int err = AHardwareBuffer_createFromHandle(&desc, handle,
119 AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
120 &newBuf);
121 if (err != ::android::NO_ERROR) {
122 return nullptr;
123 }
124
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000125 std::shared_ptr<BufferItem> newBuffer =
126 std::make_shared<BufferItem>(newGeneration, newBuf, newUsage);
127 AHardwareBuffer_release(newBuf);
128 return newBuffer;
129}
130
131sp<GraphicBuffer> GraphicsTracker::BufferItem::getGraphicBuffer() {
132 if (!mInit) {
Sungtak Leef075f712023-07-20 23:37:45 +0000133 return nullptr;
134 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000135 GraphicBuffer *gb = ::android::AHardwareBuffer_to_GraphicBuffer(mBuf);
136 if (!gb) {
137 return nullptr;
138 }
139 gb->setGenerationNumber(mGeneration);
Sungtak Leef075f712023-07-20 23:37:45 +0000140 return gb;
141}
142
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000143GraphicsTracker::BufferCache::~BufferCache() {
144 ALOGV("BufferCache destruction: generation(%d), igbp(%d)", mGeneration, (bool)mIgbp);
145}
146
Sungtak Leef075f712023-07-20 23:37:45 +0000147void GraphicsTracker::BufferCache::waitOnSlot(int slot) {
148 // TODO: log
149 CHECK(0 <= slot && slot < kNumSlots);
150 BlockedSlot *p = &mBlockedSlots[slot];
151 std::unique_lock<std::mutex> l(p->l);
152 while (p->blocked) {
153 p->cv.wait(l);
154 }
155}
156
157void GraphicsTracker::BufferCache::blockSlot(int slot) {
158 CHECK(0 <= slot && slot < kNumSlots);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000159 ALOGV("block slot %d", slot);
Sungtak Leef075f712023-07-20 23:37:45 +0000160 BlockedSlot *p = &mBlockedSlots[slot];
161 std::unique_lock<std::mutex> l(p->l);
162 p->blocked = true;
163}
164
165void GraphicsTracker::BufferCache::unblockSlot(int slot) {
166 CHECK(0 <= slot && slot < kNumSlots);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000167 ALOGV("unblock slot %d", slot);
Sungtak Leef075f712023-07-20 23:37:45 +0000168 BlockedSlot *p = &mBlockedSlots[slot];
169 std::unique_lock<std::mutex> l(p->l);
170 p->blocked = false;
171 l.unlock();
172 p->cv.notify_one();
173}
174
175GraphicsTracker::GraphicsTracker(int maxDequeueCount)
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000176 : mBufferCache(new BufferCache()), mMaxDequeue{maxDequeueCount},
Sungtak Leef075f712023-07-20 23:37:45 +0000177 mMaxDequeueCommitted{maxDequeueCount},
Sungtak Leef075f712023-07-20 23:37:45 +0000178 mDequeueable{maxDequeueCount},
179 mTotalDequeued{0}, mTotalCancelled{0}, mTotalDropped{0}, mTotalReleased{0},
180 mInConfig{false}, mStopped{false} {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000181 if (maxDequeueCount < kMaxDequeueMin) {
182 mMaxDequeue = kMaxDequeueMin;
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000183 mMaxDequeueCommitted = kMaxDequeueMin;
184 mDequeueable = kMaxDequeueMin;
185 } else if(maxDequeueCount > kMaxDequeueMax) {
186 mMaxDequeue = kMaxDequeueMax;
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000187 mMaxDequeueCommitted = kMaxDequeueMax;
188 mDequeueable = kMaxDequeueMax;
Sungtak Leef075f712023-07-20 23:37:45 +0000189 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000190 int pipefd[2] = { -1, -1};
191 int ret = ::pipe2(pipefd, O_CLOEXEC | O_NONBLOCK);
Sungtak Leef075f712023-07-20 23:37:45 +0000192
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000193 mReadPipeFd.reset(pipefd[0]);
194 mWritePipeFd.reset(pipefd[1]);
Sungtak Leef075f712023-07-20 23:37:45 +0000195
Sungtak Lee45246602023-11-27 07:17:24 +0000196 // ctor does not require lock to be held.
197 writeIncDequeueableLocked(mDequeueable);
Sungtak Leef075f712023-07-20 23:37:45 +0000198
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000199 CHECK(ret >= 0);
Sungtak Leef075f712023-07-20 23:37:45 +0000200}
201
202GraphicsTracker::~GraphicsTracker() {
203 stop();
Sungtak Leef075f712023-07-20 23:37:45 +0000204}
205
206bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {
207 // TODO: can't we adjust during config? not committing it may safe?
208 *updateDequeue = false;
Sungtak Leee625b932023-11-13 07:55:54 +0000209 if (!mInConfig && mMaxDequeueRequested.has_value() && mMaxDequeueRequested < mMaxDequeue) {
210 int delta = mMaxDequeue - mMaxDequeueRequested.value();
211 int drained = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000212 // Since we are supposed to increase mDequeuable by one already
213 int adjustable = mDequeueable + 1;
214 if (adjustable >= delta) {
Sungtak Leee625b932023-11-13 07:55:54 +0000215 mMaxDequeue = mMaxDequeueRequested.value();
Sungtak Leef075f712023-07-20 23:37:45 +0000216 mDequeueable -= (delta - 1);
Sungtak Leee625b932023-11-13 07:55:54 +0000217 drained = delta - 1;
Sungtak Leef075f712023-07-20 23:37:45 +0000218 } else {
219 mMaxDequeue -= adjustable;
Sungtak Leee625b932023-11-13 07:55:54 +0000220 drained = mDequeueable;
Sungtak Leef075f712023-07-20 23:37:45 +0000221 mDequeueable = 0;
222 }
Sungtak Leee625b932023-11-13 07:55:54 +0000223 if (drained > 0) {
224 drainDequeueableLocked(drained);
225 }
Sungtak Leef075f712023-07-20 23:37:45 +0000226 if (mMaxDequeueRequested == mMaxDequeue && mMaxDequeueRequested != mMaxDequeueCommitted) {
227 *updateDequeue = true;
228 }
229 return true;
230 }
231 return false;
232}
233
234c2_status_t GraphicsTracker::configureGraphics(
235 const sp<IGraphicBufferProducer>& igbp, uint32_t generation) {
Sungtak Lee45246602023-11-27 07:17:24 +0000236 // TODO: wait until operations to previous IGBP is completed.
Sungtak Leef075f712023-07-20 23:37:45 +0000237 std::shared_ptr<BufferCache> prevCache;
238 int prevDequeueCommitted;
239
240 std::unique_lock<std::mutex> cl(mConfigLock);
241 {
242 std::unique_lock<std::mutex> l(mLock);
243 mInConfig = true;
244 prevCache = mBufferCache;
245 prevDequeueCommitted = mMaxDequeueCommitted;
246 }
247 // NOTE: Switching to the same surface is blocked from MediaCodec.
248 // Switching to the same surface might not work if tried, since disconnect()
249 // to the old surface in MediaCodec and allocate from the new surface from
250 // GraphicsTracker cannot be synchronized properly.
251 uint64_t bqId{0ULL};
252 ::android::status_t ret = ::android::OK;
253 if (igbp) {
254 ret = igbp->getUniqueId(&bqId);
255 }
Sungtak Leee625b932023-11-13 07:55:54 +0000256 if (ret != ::android::OK ||
Sungtak Lee1e9513e2023-12-12 07:14:40 +0000257 prevCache->mGeneration == generation) {
Sungtak Leee625b932023-11-13 07:55:54 +0000258 ALOGE("new surface configure fail due to wrong or same bqId or same generation:"
259 "igbp(%d:%llu -> %llu), gen(%lu -> %lu)", (bool)igbp,
260 (unsigned long long)prevCache->mBqId, (unsigned long long)bqId,
261 (unsigned long)prevCache->mGeneration, (unsigned long)generation);
262 std::unique_lock<std::mutex> l(mLock);
263 mInConfig = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000264 return C2_BAD_VALUE;
265 }
Sungtak Leee625b932023-11-13 07:55:54 +0000266 if (igbp) {
267 ret = igbp->setMaxDequeuedBufferCount(prevDequeueCommitted);
268 if (ret != ::android::OK) {
269 ALOGE("new surface maxDequeueBufferCount configure fail");
270 // TODO: sort out the error from igbp and return an error accordingly.
271 std::unique_lock<std::mutex> l(mLock);
272 mInConfig = false;
273 return C2_CORRUPTED;
274 }
Sungtak Leef075f712023-07-20 23:37:45 +0000275 }
Sungtak Leee625b932023-11-13 07:55:54 +0000276 ALOGD("new surface configured with id:%llu gen:%lu maxDequeue:%d",
277 (unsigned long long)bqId, (unsigned long)generation, prevDequeueCommitted);
Sungtak Leef075f712023-07-20 23:37:45 +0000278 std::shared_ptr<BufferCache> newCache = std::make_shared<BufferCache>(bqId, generation, igbp);
279 {
280 std::unique_lock<std::mutex> l(mLock);
281 mInConfig = false;
282 mBufferCache = newCache;
283 }
284 return C2_OK;
285}
286
287c2_status_t GraphicsTracker::configureMaxDequeueCount(int maxDequeueCount) {
288 std::shared_ptr<BufferCache> cache;
289
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000290 if (maxDequeueCount < kMaxDequeueMin || maxDequeueCount > kMaxDequeueMax) {
291 ALOGE("max dequeue count %d is not valid", maxDequeueCount);
292 return C2_BAD_VALUE;
293 }
294
Sungtak Leef075f712023-07-20 23:37:45 +0000295 // max dequeue count which can be committed to IGBP.
296 // (Sometimes maxDequeueCount cannot be committed if the number of
297 // dequeued buffer count is bigger.)
298 int maxDequeueToCommit;
Sungtak Leef075f712023-07-20 23:37:45 +0000299 std::unique_lock<std::mutex> cl(mConfigLock);
300 {
301 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000302 if (mMaxDequeueRequested.has_value()) {
303 if (mMaxDequeueRequested == maxDequeueCount) {
304 ALOGD("maxDequeueCount requested with %d already", maxDequeueCount);
305 return C2_OK;
306 }
307 } else if (mMaxDequeue == maxDequeueCount) {
308 ALOGD("maxDequeueCount is already %d", maxDequeueCount);
Sungtak Leef075f712023-07-20 23:37:45 +0000309 return C2_OK;
310 }
311 mInConfig = true;
312 mMaxDequeueRequested = maxDequeueCount;
313 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000314 if (mMaxDequeue <= maxDequeueCount) {
315 maxDequeueToCommit = maxDequeueCount;
316 } else {
317 // Since mDequeuable is decreasing,
318 // a delievered ready to allocate event may not be fulfilled.
319 // Another waiting via a waitable object may be necessary in the case.
Sungtak Leee625b932023-11-13 07:55:54 +0000320 int delta = std::min(mMaxDequeue - maxDequeueCount, mDequeueable);
321 maxDequeueToCommit = mMaxDequeue - delta;
322 mDequeueable -= delta;
323 if (delta > 0) {
324 drainDequeueableLocked(delta);
Sungtak Leef075f712023-07-20 23:37:45 +0000325 }
326 }
327 }
328
329 bool committed = true;
Sungtak Leee625b932023-11-13 07:55:54 +0000330 if (cache->mIgbp && maxDequeueToCommit != mMaxDequeueCommitted) {
Sungtak Leef075f712023-07-20 23:37:45 +0000331 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(maxDequeueToCommit);
332 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000333 if (committed) {
334 ALOGD("maxDequeueCount committed to IGBP: %d", maxDequeueToCommit);
335 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000336 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000337 ALOGE("maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000338 }
339 }
340
Sungtak Leee625b932023-11-13 07:55:54 +0000341 int oldMaxDequeue = 0;
342 int requested = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000343 {
344 std::unique_lock<std::mutex> l(mLock);
345 mInConfig = false;
Sungtak Leee625b932023-11-13 07:55:54 +0000346 oldMaxDequeue = mMaxDequeue;
347 mMaxDequeue = maxDequeueToCommit; // we already drained dequeueable
Sungtak Leef075f712023-07-20 23:37:45 +0000348 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000349 clearCacheIfNecessaryLocked(cache, maxDequeueToCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000350 mMaxDequeueCommitted = maxDequeueToCommit;
Sungtak Leee625b932023-11-13 07:55:54 +0000351 if (mMaxDequeueRequested == mMaxDequeueCommitted &&
352 mMaxDequeueRequested == mMaxDequeue) {
353 mMaxDequeueRequested.reset();
354 }
355 if (mMaxDequeueRequested.has_value()) {
356 requested = mMaxDequeueRequested.value();
357 }
358 int delta = mMaxDequeueCommitted - oldMaxDequeue;
Sungtak Leef075f712023-07-20 23:37:45 +0000359 if (delta > 0) {
360 mDequeueable += delta;
Sungtak Lee45246602023-11-27 07:17:24 +0000361 writeIncDequeueableLocked(delta);
Sungtak Leef075f712023-07-20 23:37:45 +0000362 }
363 }
364 }
Sungtak Leee625b932023-11-13 07:55:54 +0000365 ALOGD("maxDqueueCount change %d -> %d: pending: %d",
366 oldMaxDequeue, maxDequeueToCommit, requested);
Sungtak Leef075f712023-07-20 23:37:45 +0000367
368 if (!committed) {
369 return C2_CORRUPTED;
370 }
371 return C2_OK;
372}
373
374void GraphicsTracker::updateDequeueConf() {
375 std::shared_ptr<BufferCache> cache;
376 int dequeueCommit;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000377 ALOGV("trying to update max dequeue count");
Sungtak Leef075f712023-07-20 23:37:45 +0000378 std::unique_lock<std::mutex> cl(mConfigLock);
379 {
380 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000381 if (!mMaxDequeueRequested.has_value() || mMaxDequeue != mMaxDequeueRequested) {
Sungtak Leef075f712023-07-20 23:37:45 +0000382 return;
383 }
Sungtak Leee625b932023-11-13 07:55:54 +0000384 if (mMaxDequeueCommitted == mMaxDequeueRequested) {
385 // already committed. may not happen.
386 mMaxDequeueRequested.reset();
387 return;
388 }
389 dequeueCommit = mMaxDequeue;
390 mInConfig = true;
391 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000392 }
393 bool committed = true;
394 if (cache->mIgbp) {
395 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(dequeueCommit);
396 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000397 if (committed) {
398 ALOGD("delayed maxDequeueCount update to IGBP: %d", dequeueCommit);
399 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000400 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000401 ALOGE("delayed maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000402 }
403 }
Sungtak Leef075f712023-07-20 23:37:45 +0000404 {
405 // cache == mCache here, since we locked config.
406 std::unique_lock<std::mutex> l(mLock);
407 mInConfig = false;
408 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000409 clearCacheIfNecessaryLocked(cache, dequeueCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000410 mMaxDequeueCommitted = dequeueCommit;
411 }
Sungtak Leee625b932023-11-13 07:55:54 +0000412 mMaxDequeueRequested.reset();
Sungtak Leef075f712023-07-20 23:37:45 +0000413 }
Sungtak Leee625b932023-11-13 07:55:54 +0000414}
Sungtak Leef075f712023-07-20 23:37:45 +0000415
Sungtak Leee625b932023-11-13 07:55:54 +0000416void GraphicsTracker::clearCacheIfNecessaryLocked(const std::shared_ptr<BufferCache> &cache,
417 int maxDequeueCommitted) {
418 int cleared = 0;
419 size_t origCacheSize = cache->mBuffers.size();
420 if (cache->mIgbp && maxDequeueCommitted < mMaxDequeueCommitted) {
421 // we are shrinking # of buffers in the case, so evict the previous
422 // cached buffers.
423 for (auto it = cache->mBuffers.begin(); it != cache->mBuffers.end();) {
424 uint64_t bid = it->second->mId;
425 if (mDequeued.count(bid) == 0 || mDeallocating.count(bid) > 0) {
426 ++cleared;
427 it = cache->mBuffers.erase(it);
428 } else {
429 ++it;
430 }
431 }
432 }
433 ALOGD("Cache size %zu -> %zu: maybe_cleared(%d), dequeued(%zu)",
434 origCacheSize, cache->mBuffers.size(), cleared, mDequeued.size());
Sungtak Leef075f712023-07-20 23:37:45 +0000435}
436
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000437int GraphicsTracker::getCurDequeueable() {
438 std::unique_lock<std::mutex> l(mLock);
439 return mDequeueable;
440}
441
Sungtak Leef075f712023-07-20 23:37:45 +0000442void GraphicsTracker::stop() {
Sungtak Lee45246602023-11-27 07:17:24 +0000443 // TODO: wait until all operation to current IGBP
444 // being completed.
445 std::unique_lock<std::mutex> l(mLock);
446 if (mStopped) {
447 return;
448 }
449 mStopped = true;
450 int writeFd = mWritePipeFd.release();
451 if (writeFd >= 0) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000452 ::close(writeFd);
Sungtak Leef075f712023-07-20 23:37:45 +0000453 }
454}
455
Sungtak Lee45246602023-11-27 07:17:24 +0000456void GraphicsTracker::writeIncDequeueableLocked(int inc) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000457 CHECK(inc > 0 && inc < kMaxDequeueMax);
458 thread_local char buf[kMaxDequeueMax];
Sungtak Lee45246602023-11-27 07:17:24 +0000459 if (mStopped) { // reading end closed;
460 return;
Sungtak Leef075f712023-07-20 23:37:45 +0000461 }
Sungtak Lee45246602023-11-27 07:17:24 +0000462 int writeFd = mWritePipeFd.get();
463 if (writeFd < 0) {
464 // initialization fail and not valid though.
465 return;
466 }
467 int ret = ::write(writeFd, buf, inc);
468 // Since this is non-blocking i/o, it never returns EINTR.
469 //
470 // ::write() to pipe guarantee to succeed atomically if it writes less than
471 // the given PIPE_BUF. And the buffer size in pipe/fifo is at least 4K and our total
472 // max pending buffer size is 64. So it never returns EAGAIN here either.
473 // See pipe(7) for further information.
474 //
475 // Other errors are serious errors and we cannot synchronize mDequeueable to
476 // length of pending buffer in pipe/fifo anymore. So better to abort here.
477 // TODO: do not abort here. (b/318717399)
478 CHECK(ret == inc);
Sungtak Leef075f712023-07-20 23:37:45 +0000479}
480
Sungtak Leee625b932023-11-13 07:55:54 +0000481void GraphicsTracker::drainDequeueableLocked(int dec) {
482 CHECK(dec > 0 && dec < kMaxDequeueMax);
483 thread_local char buf[kMaxDequeueMax];
484 if (mStopped) {
485 return;
486 }
Sungtak Lee45246602023-11-27 07:17:24 +0000487 int readFd = mReadPipeFd.get();
488 if (readFd < 0) {
489 // initializationf fail and not valid though.
490 return;
Sungtak Leee625b932023-11-13 07:55:54 +0000491 }
Sungtak Lee45246602023-11-27 07:17:24 +0000492 int ret = ::read(readFd, buf, dec);
493 // TODO: no dot abort here. (b/318717399)
494 CHECK(ret == dec);
Sungtak Leef075f712023-07-20 23:37:45 +0000495}
496
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000497c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
498 *pipeFd = ::dup(mReadPipeFd.get());
499 if (*pipeFd < 0) {
500 if (mReadPipeFd.get() < 0) {
501 return C2_BAD_STATE;
Sungtak Leef075f712023-07-20 23:37:45 +0000502 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000503 // dup error
504 ALOGE("dup() for the reading end failed %d", errno);
Sungtak Leef075f712023-07-20 23:37:45 +0000505 return C2_NO_MEMORY;
506 }
507 return C2_OK;
508}
509
510c2_status_t GraphicsTracker::requestAllocate(std::shared_ptr<BufferCache> *cache) {
511 std::lock_guard<std::mutex> l(mLock);
512 if (mDequeueable > 0) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000513 char buf[1];
514 int ret = ::read(mReadPipeFd.get(), buf, 1);
Sungtak Leef075f712023-07-20 23:37:45 +0000515 if (ret < 0) {
516 if (errno == EINTR) {
517 // Do we really need to care for cancel due to signal handling?
518 return C2_CANCELED;
519 }
520 if (errno == EAGAIN) {
521 // proper usage of waitable object should not return this.
522 // but there could be alloc requests from HAL ignoring the internal status.
523 return C2_BLOCKING;
524 }
525 CHECK(errno != 0);
526 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000527 if (ret == 0) {
528 // writing end is closed
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000529 ALOGE("writing end for the waitable object seems to be closed");
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000530 return C2_BAD_STATE;
531 }
Sungtak Leef075f712023-07-20 23:37:45 +0000532 mDequeueable--;
533 *cache = mBufferCache;
534 return C2_OK;
535 }
536 return C2_BLOCKING;
537}
538
539// If {@code cached} is {@code true}, {@code pBuffer} should be read from the
540// current cached status. Otherwise, {@code pBuffer} should be written to
541// current caches status.
542void GraphicsTracker::commitAllocate(c2_status_t res, const std::shared_ptr<BufferCache> &cache,
543 bool cached, int slot, const sp<Fence> &fence,
544 std::shared_ptr<BufferItem> *pBuffer, bool *updateDequeue) {
545 std::unique_lock<std::mutex> l(mLock);
546 if (res == C2_OK) {
547 if (cached) {
548 auto it = cache->mBuffers.find(slot);
549 CHECK(it != cache->mBuffers.end());
550 it->second->mFence = fence;
551 *pBuffer = it->second;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000552 ALOGV("an allocated buffer already cached, updated Fence");
Sungtak Leef075f712023-07-20 23:37:45 +0000553 } else if (cache.get() == mBufferCache.get() && mBufferCache->mIgbp) {
554 // Cache the buffer if it is allocated from the current IGBP
555 CHECK(slot >= 0);
556 auto ret = mBufferCache->mBuffers.emplace(slot, *pBuffer);
557 if (!ret.second) {
558 ret.first->second = *pBuffer;
559 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000560 ALOGV("an allocated buffer not cached from the current IGBP");
Sungtak Leef075f712023-07-20 23:37:45 +0000561 }
562 uint64_t bid = (*pBuffer)->mId;
563 auto mapRet = mDequeued.emplace(bid, *pBuffer);
564 CHECK(mapRet.second);
565 } else {
566 if (adjustDequeueConfLocked(updateDequeue)) {
567 return;
568 }
569 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000570 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000571 }
572}
573
574
575// if a buffer is newly allocated, {@code cached} is {@code false},
576// and the buffer is in the {@code buffer}
577// otherwise, {@code cached} is {@code false} and the buffer should be
578// retrieved by commitAllocate();
579c2_status_t GraphicsTracker::_allocate(const std::shared_ptr<BufferCache> &cache,
580 uint32_t width, uint32_t height, PixelFormat format,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000581 uint64_t usage,
Sungtak Leef075f712023-07-20 23:37:45 +0000582 bool *cached,
583 int *rSlotId,
584 sp<Fence> *rFence,
585 std::shared_ptr<BufferItem> *buffer) {
586 ::android::sp<IGraphicBufferProducer> igbp = cache->mIgbp;
587 uint32_t generation = cache->mGeneration;
588 if (!igbp) {
589 // allocate directly
590 AHardwareBuffer_Desc desc;
591 desc.width = width;
592 desc.height = height;
593 desc.layers = 1u;
594 desc.format = ::android::AHardwareBuffer_convertFromPixelFormat(format);
595 desc.usage = ::android::AHardwareBuffer_convertFromGrallocUsageBits(usage);
596 desc.rfu0 = 0;
597 desc.rfu1 = 0;
598
599 AHardwareBuffer *buf;
600 int ret = AHardwareBuffer_allocate(&desc, &buf);
601 if (ret != ::android::OK) {
602 ALOGE("direct allocation of AHB failed(%d)", ret);
603 return ret == ::android::NO_MEMORY ? C2_NO_MEMORY : C2_CORRUPTED;
604 }
605 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000606 *rSlotId = -1;
607 *rFence = Fence::NO_FENCE;
608 *buffer = std::make_shared<BufferItem>(generation, buf, usage);
609 AHardwareBuffer_release(buf); // remove an acquire count from
610 // AHwb_allocate().
Sungtak Leef075f712023-07-20 23:37:45 +0000611 if (!*buffer) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000612 ALOGE("direct allocation of AHB successful, but failed to create BufferItem");
Sungtak Leef075f712023-07-20 23:37:45 +0000613 return C2_NO_MEMORY;
614 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000615 if (!(*buffer)->mInit) {
616 ALOGE("direct allocation of AHB successful, but BufferItem init failed");
617 buffer->reset();
618 return C2_CORRUPTED;
619 }
620 ALOGV("allocate: direct allocate without igbp");
Sungtak Leef075f712023-07-20 23:37:45 +0000621 return C2_OK;
622 }
623
624 int slotId;
625 uint64_t outBufferAge;
626 ::android::FrameEventHistoryDelta outTimestamps;
627 sp<Fence> fence;
628
629 ::android::status_t status = igbp->dequeueBuffer(
630 &slotId, &fence, width, height, format, usage, &outBufferAge, &outTimestamps);
631 if (status < ::android::OK) {
632 ALOGE("dequeueBuffer() error %d", (int)status);
633 return C2_CORRUPTED;
634 }
635 cache->waitOnSlot(slotId);
636 bool exists = false;
637 {
638 std::unique_lock<std::mutex> l(mLock);
639 if (cache.get() == mBufferCache.get() &&
640 cache->mBuffers.find(slotId) != cache->mBuffers.end()) {
641 exists = true;
642 }
643 }
644 bool needsRealloc = status & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
645 if (needsRealloc || !exists) {
646 sp<GraphicBuffer> realloced;
647 status = igbp->requestBuffer(slotId, &realloced);
648 if (status != ::android::OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000649 ALOGE("allocate by dequeueBuffer() successful, but requestBuffer() failed %d",
650 status);
Sungtak Leef075f712023-07-20 23:37:45 +0000651 igbp->cancelBuffer(slotId, fence);
652 return C2_CORRUPTED;
653 }
654 *buffer = std::make_shared<BufferItem>(generation, slotId, realloced, fence);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000655 if (!*buffer) {
656 ALOGE("allocate by dequeueBuffer() successful, but creating BufferItem failed");
657 igbp->cancelBuffer(slotId, fence);
658 return C2_NO_MEMORY;
659 }
Sungtak Leef075f712023-07-20 23:37:45 +0000660 if (!(*buffer)->mInit) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000661 ALOGE("allocate by dequeueBuffer() successful, but BufferItem init failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000662 buffer->reset();
663 igbp->cancelBuffer(slotId, fence);
664 return C2_CORRUPTED;
665 }
666 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000667 } else {
668 *cached = true;
Sungtak Leef075f712023-07-20 23:37:45 +0000669 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000670 ALOGV("allocate: a new allocated buffer from igbp cached %d, slot: %d",
671 *cached, slotId);
Sungtak Leef075f712023-07-20 23:37:45 +0000672 *rSlotId = slotId;
673 *rFence = fence;
674 return C2_OK;
675}
676
677c2_status_t GraphicsTracker::allocate(
678 uint32_t width, uint32_t height, PixelFormat format, uint64_t usage,
679 AHardwareBuffer **buf, sp<Fence> *rFence) {
680 if (mStopped.load() == true) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000681 ALOGE("cannot allocate due to being stopped");
Sungtak Leef075f712023-07-20 23:37:45 +0000682 return C2_BAD_STATE;
683 }
684 std::shared_ptr<BufferCache> cache;
685 c2_status_t res = requestAllocate(&cache);
686 if (res != C2_OK) {
687 return res;
688 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000689 ALOGV("allocatable or dequeueable");
Sungtak Leef075f712023-07-20 23:37:45 +0000690
691 bool cached = false;
692 int slotId;
693 sp<Fence> fence;
694 std::shared_ptr<BufferItem> buffer;
695 bool updateDequeue;
696 res = _allocate(cache, width, height, format, usage, &cached, &slotId, &fence, &buffer);
697 commitAllocate(res, cache, cached, slotId, fence, &buffer, &updateDequeue);
698 if (res == C2_OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000699 ALOGV("allocated a buffer width:%u height:%u pixelformat:%d usage:%llu",
700 width, height, format, (unsigned long long)usage);
Sungtak Leef075f712023-07-20 23:37:45 +0000701 *buf = buffer->mBuf;
702 *rFence = buffer->mFence;
703 // *buf should be valid even if buffer is dtor-ed.
704 AHardwareBuffer_acquire(*buf);
705 }
706 if (updateDequeue) {
707 updateDequeueConf();
708 }
709 return res;
710}
711
712c2_status_t GraphicsTracker::requestDeallocate(uint64_t bid, const sp<Fence> &fence,
713 bool *completed, bool *updateDequeue,
714 std::shared_ptr<BufferCache> *cache, int *slotId,
715 sp<Fence> *rFence) {
716 std::unique_lock<std::mutex> l(mLock);
717 if (mDeallocating.find(bid) != mDeallocating.end()) {
718 ALOGE("Tries to deallocate a buffer which is already deallocating or rendering");
719 return C2_DUPLICATE;
720 }
721 auto it = mDequeued.find(bid);
722 if (it == mDequeued.end()) {
723 ALOGE("Tried to deallocate non dequeued buffer");
724 return C2_NOT_FOUND;
725 }
726
727 std::shared_ptr<BufferItem> buffer = it->second;
728 if (buffer->mGeneration == mBufferCache->mGeneration && mBufferCache->mIgbp) {
729 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
730 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
731 *cache = mBufferCache;
732 *slotId = buffer->mSlot;
733 *rFence = ( fence == Fence::NO_FENCE) ? buffer->mFence : fence;
734 // mark this deallocating
735 mDeallocating.emplace(bid);
736 mBufferCache->blockSlot(buffer->mSlot);
737 *completed = false;
738 } else { // buffer is not from the current underlying Graphics.
739 mDequeued.erase(bid);
740 *completed = true;
741 if (adjustDequeueConfLocked(updateDequeue)) {
742 return C2_OK;
743 }
744 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000745 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000746 }
747 return C2_OK;
748}
749
750void GraphicsTracker::commitDeallocate(
Sungtak Leee625b932023-11-13 07:55:54 +0000751 std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid, bool *updateDequeue) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000752 std::unique_lock<std::mutex> l(mLock);
Sungtak Leef075f712023-07-20 23:37:45 +0000753 size_t del1 = mDequeued.erase(bid);
754 size_t del2 = mDeallocating.erase(bid);
755 CHECK(del1 > 0 && del2 > 0);
Sungtak Leef075f712023-07-20 23:37:45 +0000756 if (cache) {
757 cache->unblockSlot(slotId);
758 }
Sungtak Leee625b932023-11-13 07:55:54 +0000759 if (adjustDequeueConfLocked(updateDequeue)) {
760 return;
761 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000762 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000763 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000764}
765
766
767c2_status_t GraphicsTracker::deallocate(uint64_t bid, const sp<Fence> &fence) {
768 bool completed;
769 bool updateDequeue;
770 std::shared_ptr<BufferCache> cache;
771 int slotId;
772 sp<Fence> rFence;
773 c2_status_t res = requestDeallocate(bid, fence, &completed, &updateDequeue,
774 &cache, &slotId, &rFence);
775 if (res != C2_OK) {
776 return res;
777 }
778 if (completed == true) {
779 if (updateDequeue) {
780 updateDequeueConf();
781 }
782 return C2_OK;
783 }
784
785 // ignore return value since IGBP could be already stale.
786 // cache->mIgbp is not null, if completed is false.
787 (void)cache->mIgbp->cancelBuffer(slotId, rFence);
788
Sungtak Leee625b932023-11-13 07:55:54 +0000789 commitDeallocate(cache, slotId, bid, &updateDequeue);
790 if (updateDequeue) {
791 updateDequeueConf();
792 }
Sungtak Leef075f712023-07-20 23:37:45 +0000793 return C2_OK;
794}
795
796c2_status_t GraphicsTracker::requestRender(uint64_t bid, std::shared_ptr<BufferCache> *cache,
797 std::shared_ptr<BufferItem> *pBuffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000798 bool *fromCache,
Sungtak Leef075f712023-07-20 23:37:45 +0000799 bool *updateDequeue) {
800 std::unique_lock<std::mutex> l(mLock);
801 if (mDeallocating.find(bid) != mDeallocating.end()) {
802 ALOGE("Tries to render a buffer which is already deallocating or rendering");
803 return C2_DUPLICATE;
804 }
805 auto it = mDequeued.find(bid);
806 if (it == mDequeued.end()) {
807 ALOGE("Tried to render non dequeued buffer");
808 return C2_NOT_FOUND;
809 }
810 if (!mBufferCache->mIgbp) {
811 // Render requested without surface.
812 // reclaim the buffer for dequeue.
813 // TODO: is this correct for API wise?
814 mDequeued.erase(it);
815 if (adjustDequeueConfLocked(updateDequeue)) {
816 return C2_BAD_STATE;
817 }
818 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000819 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000820 return C2_BAD_STATE;
821 }
822 std::shared_ptr<BufferItem> buffer = it->second;
823 *cache = mBufferCache;
824 if (buffer->mGeneration == mBufferCache->mGeneration) {
825 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
826 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
827 mBufferCache->blockSlot(buffer->mSlot);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000828 *fromCache = true;
829 } else {
830 *fromCache = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000831 }
832 *pBuffer = buffer;
833 mDeallocating.emplace(bid);
834 return C2_OK;
835}
836
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000837void GraphicsTracker::commitRender(const std::shared_ptr<BufferCache> &cache,
Sungtak Leef075f712023-07-20 23:37:45 +0000838 const std::shared_ptr<BufferItem> &buffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000839 const std::shared_ptr<BufferItem> &oldBuffer,
840 bool bufferReplaced,
Sungtak Leef075f712023-07-20 23:37:45 +0000841 bool *updateDequeue) {
842 std::unique_lock<std::mutex> l(mLock);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000843 uint64_t origBid = oldBuffer ? oldBuffer->mId : buffer->mId;
Sungtak Leef075f712023-07-20 23:37:45 +0000844
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000845 if (cache) {
846 cache->unblockSlot(buffer->mSlot);
847 if (oldBuffer) {
848 // migrated, register the new buffer to the cache.
849 cache->mBuffers.emplace(buffer->mSlot, buffer);
850 }
851 }
852 mDeallocating.erase(origBid);
853 mDequeued.erase(origBid);
854
855 if (cache.get() != mBufferCache.get() || bufferReplaced) {
Sungtak Leef075f712023-07-20 23:37:45 +0000856 // Surface changed, no need to wait for buffer being released.
Sungtak Leef075f712023-07-20 23:37:45 +0000857 if (adjustDequeueConfLocked(updateDequeue)) {
858 return;
859 }
860 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000861 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000862 return;
863 }
Sungtak Leef075f712023-07-20 23:37:45 +0000864}
865
866c2_status_t GraphicsTracker::render(const C2ConstGraphicBlock& blk,
867 const IGraphicBufferProducer::QueueBufferInput &input,
868 IGraphicBufferProducer::QueueBufferOutput *output) {
869 uint64_t bid;
870 c2_status_t res = retrieveAHardwareBufferId(blk, &bid);
871 if (res != C2_OK) {
872 ALOGE("retrieving AHB-ID for GraphicBlock failed");
873 return C2_CORRUPTED;
874 }
Sungtak Leee625b932023-11-13 07:55:54 +0000875 std::shared_ptr<_C2BlockPoolData> poolData =
876 _C2BlockFactory::GetGraphicBlockPoolData(blk);
877 _C2BlockFactory::DisownIgbaBlock(poolData);
Sungtak Leef075f712023-07-20 23:37:45 +0000878 std::shared_ptr<BufferCache> cache;
879 std::shared_ptr<BufferItem> buffer;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000880 std::shared_ptr<BufferItem> oldBuffer;
Sungtak Leef075f712023-07-20 23:37:45 +0000881 bool updateDequeue = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000882 bool fromCache = false;
883 res = requestRender(bid, &cache, &buffer, &fromCache, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000884 if (res != C2_OK) {
885 if (updateDequeue) {
886 updateDequeueConf();
887 }
888 return res;
889 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000890 int cacheSlotId = fromCache ? buffer->mSlot : -1;
891 ALOGV("render prepared: igbp(%d) slot(%d)", bool(cache->mIgbp), cacheSlotId);
892 if (!fromCache) {
893 // The buffer does not come from the current cache.
894 // The buffer is needed to be migrated(attached).
Sungtak Leef075f712023-07-20 23:37:45 +0000895 uint64_t newUsage = 0ULL;
Sungtak Leef075f712023-07-20 23:37:45 +0000896
897 (void) cache->mIgbp->getConsumerUsage(&newUsage);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000898 std::shared_ptr<BufferItem> newBuffer =
899 buffer->migrateBuffer(newUsage, cache->mGeneration);
900 sp<GraphicBuffer> gb = newBuffer ? newBuffer->getGraphicBuffer() : nullptr;
901
902 if (!gb) {
903 ALOGE("render: realloc-ing a new buffer for migration failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000904 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000905 commitDeallocate(nullCache, -1, bid, &updateDequeue);
906 if (updateDequeue) {
907 updateDequeueConf();
908 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000909 return C2_REFUSED;
Sungtak Leef075f712023-07-20 23:37:45 +0000910 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000911 if (cache->mIgbp->attachBuffer(&(newBuffer->mSlot), gb) != ::android::OK) {
912 ALOGE("render: attaching a new buffer to IGBP failed");
913 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000914 commitDeallocate(nullCache, -1, bid, &updateDequeue);
915 if (updateDequeue) {
916 updateDequeueConf();
917 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000918 return C2_REFUSED;
919 }
920 cache->waitOnSlot(newBuffer->mSlot);
921 cache->blockSlot(newBuffer->mSlot);
922 oldBuffer = buffer;
923 buffer = newBuffer;
924 }
925 ::android::status_t renderRes = cache->mIgbp->queueBuffer(buffer->mSlot, input, output);
926 ALOGV("render done: migration(%d), render(err = %d)", !fromCache, renderRes);
927 if (renderRes != ::android::OK) {
928 CHECK(renderRes != ::android::BAD_VALUE);
929 ALOGE("render: failed to queueBuffer() err = %d", renderRes);
930 (void) cache->mIgbp->cancelBuffer(buffer->mSlot, input.fence);
Sungtak Leee625b932023-11-13 07:55:54 +0000931 commitDeallocate(cache, buffer->mSlot, bid, &updateDequeue);
932 if (updateDequeue) {
933 updateDequeueConf();
934 }
Sungtak Leef075f712023-07-20 23:37:45 +0000935 return C2_REFUSED;
936 }
937
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000938 commitRender(cache, buffer, oldBuffer, output->bufferReplaced, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000939 if (updateDequeue) {
940 updateDequeueConf();
941 }
Sungtak Leef075f712023-07-20 23:37:45 +0000942 return C2_OK;
943}
944
945void GraphicsTracker::onReleased(uint32_t generation) {
946 bool updateDequeue = false;
947 {
948 std::unique_lock<std::mutex> l(mLock);
949 if (mBufferCache->mGeneration == generation) {
950 if (!adjustDequeueConfLocked(&updateDequeue)) {
951 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000952 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000953 }
954 }
955 }
956 if (updateDequeue) {
957 updateDequeueConf();
958 }
959}
960
961} // namespace aidl::android::hardware::media::c2::implementation