blob: ca2f6e68bdd9227d59dcfaf3b16a780ae2931522 [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 ||
257 prevCache->mGeneration == generation ||
258 (bqId != 0 && prevCache->mBqId == bqId)) {
259 ALOGE("new surface configure fail due to wrong or same bqId or same generation:"
260 "igbp(%d:%llu -> %llu), gen(%lu -> %lu)", (bool)igbp,
261 (unsigned long long)prevCache->mBqId, (unsigned long long)bqId,
262 (unsigned long)prevCache->mGeneration, (unsigned long)generation);
263 std::unique_lock<std::mutex> l(mLock);
264 mInConfig = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000265 return C2_BAD_VALUE;
266 }
Sungtak Leee625b932023-11-13 07:55:54 +0000267 if (igbp) {
268 ret = igbp->setMaxDequeuedBufferCount(prevDequeueCommitted);
269 if (ret != ::android::OK) {
270 ALOGE("new surface maxDequeueBufferCount configure fail");
271 // TODO: sort out the error from igbp and return an error accordingly.
272 std::unique_lock<std::mutex> l(mLock);
273 mInConfig = false;
274 return C2_CORRUPTED;
275 }
Sungtak Leef075f712023-07-20 23:37:45 +0000276 }
Sungtak Leee625b932023-11-13 07:55:54 +0000277 ALOGD("new surface configured with id:%llu gen:%lu maxDequeue:%d",
278 (unsigned long long)bqId, (unsigned long)generation, prevDequeueCommitted);
Sungtak Leef075f712023-07-20 23:37:45 +0000279 std::shared_ptr<BufferCache> newCache = std::make_shared<BufferCache>(bqId, generation, igbp);
280 {
281 std::unique_lock<std::mutex> l(mLock);
282 mInConfig = false;
283 mBufferCache = newCache;
284 }
285 return C2_OK;
286}
287
288c2_status_t GraphicsTracker::configureMaxDequeueCount(int maxDequeueCount) {
289 std::shared_ptr<BufferCache> cache;
290
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000291 if (maxDequeueCount < kMaxDequeueMin || maxDequeueCount > kMaxDequeueMax) {
292 ALOGE("max dequeue count %d is not valid", maxDequeueCount);
293 return C2_BAD_VALUE;
294 }
295
Sungtak Leef075f712023-07-20 23:37:45 +0000296 // max dequeue count which can be committed to IGBP.
297 // (Sometimes maxDequeueCount cannot be committed if the number of
298 // dequeued buffer count is bigger.)
299 int maxDequeueToCommit;
Sungtak Leef075f712023-07-20 23:37:45 +0000300 std::unique_lock<std::mutex> cl(mConfigLock);
301 {
302 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000303 if (mMaxDequeueRequested.has_value()) {
304 if (mMaxDequeueRequested == maxDequeueCount) {
305 ALOGD("maxDequeueCount requested with %d already", maxDequeueCount);
306 return C2_OK;
307 }
308 } else if (mMaxDequeue == maxDequeueCount) {
309 ALOGD("maxDequeueCount is already %d", maxDequeueCount);
Sungtak Leef075f712023-07-20 23:37:45 +0000310 return C2_OK;
311 }
312 mInConfig = true;
313 mMaxDequeueRequested = maxDequeueCount;
314 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000315 if (mMaxDequeue <= maxDequeueCount) {
316 maxDequeueToCommit = maxDequeueCount;
317 } else {
318 // Since mDequeuable is decreasing,
319 // a delievered ready to allocate event may not be fulfilled.
320 // Another waiting via a waitable object may be necessary in the case.
Sungtak Leee625b932023-11-13 07:55:54 +0000321 int delta = std::min(mMaxDequeue - maxDequeueCount, mDequeueable);
322 maxDequeueToCommit = mMaxDequeue - delta;
323 mDequeueable -= delta;
324 if (delta > 0) {
325 drainDequeueableLocked(delta);
Sungtak Leef075f712023-07-20 23:37:45 +0000326 }
327 }
328 }
329
330 bool committed = true;
Sungtak Leee625b932023-11-13 07:55:54 +0000331 if (cache->mIgbp && maxDequeueToCommit != mMaxDequeueCommitted) {
Sungtak Leef075f712023-07-20 23:37:45 +0000332 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(maxDequeueToCommit);
333 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000334 if (committed) {
335 ALOGD("maxDequeueCount committed to IGBP: %d", maxDequeueToCommit);
336 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000337 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000338 ALOGE("maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000339 }
340 }
341
Sungtak Leee625b932023-11-13 07:55:54 +0000342 int oldMaxDequeue = 0;
343 int requested = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000344 {
345 std::unique_lock<std::mutex> l(mLock);
346 mInConfig = false;
Sungtak Leee625b932023-11-13 07:55:54 +0000347 oldMaxDequeue = mMaxDequeue;
348 mMaxDequeue = maxDequeueToCommit; // we already drained dequeueable
Sungtak Leef075f712023-07-20 23:37:45 +0000349 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000350 clearCacheIfNecessaryLocked(cache, maxDequeueToCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000351 mMaxDequeueCommitted = maxDequeueToCommit;
Sungtak Leee625b932023-11-13 07:55:54 +0000352 if (mMaxDequeueRequested == mMaxDequeueCommitted &&
353 mMaxDequeueRequested == mMaxDequeue) {
354 mMaxDequeueRequested.reset();
355 }
356 if (mMaxDequeueRequested.has_value()) {
357 requested = mMaxDequeueRequested.value();
358 }
359 int delta = mMaxDequeueCommitted - oldMaxDequeue;
Sungtak Leef075f712023-07-20 23:37:45 +0000360 if (delta > 0) {
361 mDequeueable += delta;
Sungtak Lee45246602023-11-27 07:17:24 +0000362 writeIncDequeueableLocked(delta);
Sungtak Leef075f712023-07-20 23:37:45 +0000363 }
364 }
365 }
Sungtak Leee625b932023-11-13 07:55:54 +0000366 ALOGD("maxDqueueCount change %d -> %d: pending: %d",
367 oldMaxDequeue, maxDequeueToCommit, requested);
Sungtak Leef075f712023-07-20 23:37:45 +0000368
369 if (!committed) {
370 return C2_CORRUPTED;
371 }
372 return C2_OK;
373}
374
375void GraphicsTracker::updateDequeueConf() {
376 std::shared_ptr<BufferCache> cache;
377 int dequeueCommit;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000378 ALOGV("trying to update max dequeue count");
Sungtak Leef075f712023-07-20 23:37:45 +0000379 std::unique_lock<std::mutex> cl(mConfigLock);
380 {
381 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000382 if (!mMaxDequeueRequested.has_value() || mMaxDequeue != mMaxDequeueRequested) {
Sungtak Leef075f712023-07-20 23:37:45 +0000383 return;
384 }
Sungtak Leee625b932023-11-13 07:55:54 +0000385 if (mMaxDequeueCommitted == mMaxDequeueRequested) {
386 // already committed. may not happen.
387 mMaxDequeueRequested.reset();
388 return;
389 }
390 dequeueCommit = mMaxDequeue;
391 mInConfig = true;
392 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000393 }
394 bool committed = true;
395 if (cache->mIgbp) {
396 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(dequeueCommit);
397 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000398 if (committed) {
399 ALOGD("delayed maxDequeueCount update to IGBP: %d", dequeueCommit);
400 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000401 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000402 ALOGE("delayed maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000403 }
404 }
Sungtak Leef075f712023-07-20 23:37:45 +0000405 {
406 // cache == mCache here, since we locked config.
407 std::unique_lock<std::mutex> l(mLock);
408 mInConfig = false;
409 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000410 clearCacheIfNecessaryLocked(cache, dequeueCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000411 mMaxDequeueCommitted = dequeueCommit;
412 }
Sungtak Leee625b932023-11-13 07:55:54 +0000413 mMaxDequeueRequested.reset();
Sungtak Leef075f712023-07-20 23:37:45 +0000414 }
Sungtak Leee625b932023-11-13 07:55:54 +0000415}
Sungtak Leef075f712023-07-20 23:37:45 +0000416
Sungtak Leee625b932023-11-13 07:55:54 +0000417void GraphicsTracker::clearCacheIfNecessaryLocked(const std::shared_ptr<BufferCache> &cache,
418 int maxDequeueCommitted) {
419 int cleared = 0;
420 size_t origCacheSize = cache->mBuffers.size();
421 if (cache->mIgbp && maxDequeueCommitted < mMaxDequeueCommitted) {
422 // we are shrinking # of buffers in the case, so evict the previous
423 // cached buffers.
424 for (auto it = cache->mBuffers.begin(); it != cache->mBuffers.end();) {
425 uint64_t bid = it->second->mId;
426 if (mDequeued.count(bid) == 0 || mDeallocating.count(bid) > 0) {
427 ++cleared;
428 it = cache->mBuffers.erase(it);
429 } else {
430 ++it;
431 }
432 }
433 }
434 ALOGD("Cache size %zu -> %zu: maybe_cleared(%d), dequeued(%zu)",
435 origCacheSize, cache->mBuffers.size(), cleared, mDequeued.size());
Sungtak Leef075f712023-07-20 23:37:45 +0000436}
437
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000438int GraphicsTracker::getCurDequeueable() {
439 std::unique_lock<std::mutex> l(mLock);
440 return mDequeueable;
441}
442
Sungtak Leef075f712023-07-20 23:37:45 +0000443void GraphicsTracker::stop() {
Sungtak Lee45246602023-11-27 07:17:24 +0000444 // TODO: wait until all operation to current IGBP
445 // being completed.
446 std::unique_lock<std::mutex> l(mLock);
447 if (mStopped) {
448 return;
449 }
450 mStopped = true;
451 int writeFd = mWritePipeFd.release();
452 if (writeFd >= 0) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000453 ::close(writeFd);
Sungtak Leef075f712023-07-20 23:37:45 +0000454 }
455}
456
Sungtak Lee45246602023-11-27 07:17:24 +0000457void GraphicsTracker::writeIncDequeueableLocked(int inc) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000458 CHECK(inc > 0 && inc < kMaxDequeueMax);
459 thread_local char buf[kMaxDequeueMax];
Sungtak Lee45246602023-11-27 07:17:24 +0000460 if (mStopped) { // reading end closed;
461 return;
Sungtak Leef075f712023-07-20 23:37:45 +0000462 }
Sungtak Lee45246602023-11-27 07:17:24 +0000463 int writeFd = mWritePipeFd.get();
464 if (writeFd < 0) {
465 // initialization fail and not valid though.
466 return;
467 }
468 int ret = ::write(writeFd, buf, inc);
469 // Since this is non-blocking i/o, it never returns EINTR.
470 //
471 // ::write() to pipe guarantee to succeed atomically if it writes less than
472 // the given PIPE_BUF. And the buffer size in pipe/fifo is at least 4K and our total
473 // max pending buffer size is 64. So it never returns EAGAIN here either.
474 // See pipe(7) for further information.
475 //
476 // Other errors are serious errors and we cannot synchronize mDequeueable to
477 // length of pending buffer in pipe/fifo anymore. So better to abort here.
478 // TODO: do not abort here. (b/318717399)
479 CHECK(ret == inc);
Sungtak Leef075f712023-07-20 23:37:45 +0000480}
481
Sungtak Leee625b932023-11-13 07:55:54 +0000482void GraphicsTracker::drainDequeueableLocked(int dec) {
483 CHECK(dec > 0 && dec < kMaxDequeueMax);
484 thread_local char buf[kMaxDequeueMax];
485 if (mStopped) {
486 return;
487 }
Sungtak Lee45246602023-11-27 07:17:24 +0000488 int readFd = mReadPipeFd.get();
489 if (readFd < 0) {
490 // initializationf fail and not valid though.
491 return;
Sungtak Leee625b932023-11-13 07:55:54 +0000492 }
Sungtak Lee45246602023-11-27 07:17:24 +0000493 int ret = ::read(readFd, buf, dec);
494 // TODO: no dot abort here. (b/318717399)
495 CHECK(ret == dec);
Sungtak Leef075f712023-07-20 23:37:45 +0000496}
497
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000498c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
499 *pipeFd = ::dup(mReadPipeFd.get());
500 if (*pipeFd < 0) {
501 if (mReadPipeFd.get() < 0) {
502 return C2_BAD_STATE;
Sungtak Leef075f712023-07-20 23:37:45 +0000503 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000504 // dup error
505 ALOGE("dup() for the reading end failed %d", errno);
Sungtak Leef075f712023-07-20 23:37:45 +0000506 return C2_NO_MEMORY;
507 }
508 return C2_OK;
509}
510
511c2_status_t GraphicsTracker::requestAllocate(std::shared_ptr<BufferCache> *cache) {
512 std::lock_guard<std::mutex> l(mLock);
513 if (mDequeueable > 0) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000514 char buf[1];
515 int ret = ::read(mReadPipeFd.get(), buf, 1);
Sungtak Leef075f712023-07-20 23:37:45 +0000516 if (ret < 0) {
517 if (errno == EINTR) {
518 // Do we really need to care for cancel due to signal handling?
519 return C2_CANCELED;
520 }
521 if (errno == EAGAIN) {
522 // proper usage of waitable object should not return this.
523 // but there could be alloc requests from HAL ignoring the internal status.
524 return C2_BLOCKING;
525 }
526 CHECK(errno != 0);
527 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000528 if (ret == 0) {
529 // writing end is closed
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000530 ALOGE("writing end for the waitable object seems to be closed");
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000531 return C2_BAD_STATE;
532 }
Sungtak Leef075f712023-07-20 23:37:45 +0000533 mDequeueable--;
534 *cache = mBufferCache;
535 return C2_OK;
536 }
537 return C2_BLOCKING;
538}
539
540// If {@code cached} is {@code true}, {@code pBuffer} should be read from the
541// current cached status. Otherwise, {@code pBuffer} should be written to
542// current caches status.
543void GraphicsTracker::commitAllocate(c2_status_t res, const std::shared_ptr<BufferCache> &cache,
544 bool cached, int slot, const sp<Fence> &fence,
545 std::shared_ptr<BufferItem> *pBuffer, bool *updateDequeue) {
546 std::unique_lock<std::mutex> l(mLock);
547 if (res == C2_OK) {
548 if (cached) {
549 auto it = cache->mBuffers.find(slot);
550 CHECK(it != cache->mBuffers.end());
551 it->second->mFence = fence;
552 *pBuffer = it->second;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000553 ALOGV("an allocated buffer already cached, updated Fence");
Sungtak Leef075f712023-07-20 23:37:45 +0000554 } else if (cache.get() == mBufferCache.get() && mBufferCache->mIgbp) {
555 // Cache the buffer if it is allocated from the current IGBP
556 CHECK(slot >= 0);
557 auto ret = mBufferCache->mBuffers.emplace(slot, *pBuffer);
558 if (!ret.second) {
559 ret.first->second = *pBuffer;
560 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000561 ALOGV("an allocated buffer not cached from the current IGBP");
Sungtak Leef075f712023-07-20 23:37:45 +0000562 }
563 uint64_t bid = (*pBuffer)->mId;
564 auto mapRet = mDequeued.emplace(bid, *pBuffer);
565 CHECK(mapRet.second);
566 } else {
567 if (adjustDequeueConfLocked(updateDequeue)) {
568 return;
569 }
570 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000571 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000572 }
573}
574
575
576// if a buffer is newly allocated, {@code cached} is {@code false},
577// and the buffer is in the {@code buffer}
578// otherwise, {@code cached} is {@code false} and the buffer should be
579// retrieved by commitAllocate();
580c2_status_t GraphicsTracker::_allocate(const std::shared_ptr<BufferCache> &cache,
581 uint32_t width, uint32_t height, PixelFormat format,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000582 uint64_t usage,
Sungtak Leef075f712023-07-20 23:37:45 +0000583 bool *cached,
584 int *rSlotId,
585 sp<Fence> *rFence,
586 std::shared_ptr<BufferItem> *buffer) {
587 ::android::sp<IGraphicBufferProducer> igbp = cache->mIgbp;
588 uint32_t generation = cache->mGeneration;
589 if (!igbp) {
590 // allocate directly
591 AHardwareBuffer_Desc desc;
592 desc.width = width;
593 desc.height = height;
594 desc.layers = 1u;
595 desc.format = ::android::AHardwareBuffer_convertFromPixelFormat(format);
596 desc.usage = ::android::AHardwareBuffer_convertFromGrallocUsageBits(usage);
597 desc.rfu0 = 0;
598 desc.rfu1 = 0;
599
600 AHardwareBuffer *buf;
601 int ret = AHardwareBuffer_allocate(&desc, &buf);
602 if (ret != ::android::OK) {
603 ALOGE("direct allocation of AHB failed(%d)", ret);
604 return ret == ::android::NO_MEMORY ? C2_NO_MEMORY : C2_CORRUPTED;
605 }
606 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000607 *rSlotId = -1;
608 *rFence = Fence::NO_FENCE;
609 *buffer = std::make_shared<BufferItem>(generation, buf, usage);
610 AHardwareBuffer_release(buf); // remove an acquire count from
611 // AHwb_allocate().
Sungtak Leef075f712023-07-20 23:37:45 +0000612 if (!*buffer) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000613 ALOGE("direct allocation of AHB successful, but failed to create BufferItem");
Sungtak Leef075f712023-07-20 23:37:45 +0000614 return C2_NO_MEMORY;
615 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000616 if (!(*buffer)->mInit) {
617 ALOGE("direct allocation of AHB successful, but BufferItem init failed");
618 buffer->reset();
619 return C2_CORRUPTED;
620 }
621 ALOGV("allocate: direct allocate without igbp");
Sungtak Leef075f712023-07-20 23:37:45 +0000622 return C2_OK;
623 }
624
625 int slotId;
626 uint64_t outBufferAge;
627 ::android::FrameEventHistoryDelta outTimestamps;
628 sp<Fence> fence;
629
630 ::android::status_t status = igbp->dequeueBuffer(
631 &slotId, &fence, width, height, format, usage, &outBufferAge, &outTimestamps);
632 if (status < ::android::OK) {
633 ALOGE("dequeueBuffer() error %d", (int)status);
634 return C2_CORRUPTED;
635 }
636 cache->waitOnSlot(slotId);
637 bool exists = false;
638 {
639 std::unique_lock<std::mutex> l(mLock);
640 if (cache.get() == mBufferCache.get() &&
641 cache->mBuffers.find(slotId) != cache->mBuffers.end()) {
642 exists = true;
643 }
644 }
645 bool needsRealloc = status & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
646 if (needsRealloc || !exists) {
647 sp<GraphicBuffer> realloced;
648 status = igbp->requestBuffer(slotId, &realloced);
649 if (status != ::android::OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000650 ALOGE("allocate by dequeueBuffer() successful, but requestBuffer() failed %d",
651 status);
Sungtak Leef075f712023-07-20 23:37:45 +0000652 igbp->cancelBuffer(slotId, fence);
653 return C2_CORRUPTED;
654 }
655 *buffer = std::make_shared<BufferItem>(generation, slotId, realloced, fence);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000656 if (!*buffer) {
657 ALOGE("allocate by dequeueBuffer() successful, but creating BufferItem failed");
658 igbp->cancelBuffer(slotId, fence);
659 return C2_NO_MEMORY;
660 }
Sungtak Leef075f712023-07-20 23:37:45 +0000661 if (!(*buffer)->mInit) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000662 ALOGE("allocate by dequeueBuffer() successful, but BufferItem init failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000663 buffer->reset();
664 igbp->cancelBuffer(slotId, fence);
665 return C2_CORRUPTED;
666 }
667 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000668 } else {
669 *cached = true;
Sungtak Leef075f712023-07-20 23:37:45 +0000670 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000671 ALOGV("allocate: a new allocated buffer from igbp cached %d, slot: %d",
672 *cached, slotId);
Sungtak Leef075f712023-07-20 23:37:45 +0000673 *rSlotId = slotId;
674 *rFence = fence;
675 return C2_OK;
676}
677
678c2_status_t GraphicsTracker::allocate(
679 uint32_t width, uint32_t height, PixelFormat format, uint64_t usage,
680 AHardwareBuffer **buf, sp<Fence> *rFence) {
681 if (mStopped.load() == true) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000682 ALOGE("cannot allocate due to being stopped");
Sungtak Leef075f712023-07-20 23:37:45 +0000683 return C2_BAD_STATE;
684 }
685 std::shared_ptr<BufferCache> cache;
686 c2_status_t res = requestAllocate(&cache);
687 if (res != C2_OK) {
688 return res;
689 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000690 ALOGV("allocatable or dequeueable");
Sungtak Leef075f712023-07-20 23:37:45 +0000691
692 bool cached = false;
693 int slotId;
694 sp<Fence> fence;
695 std::shared_ptr<BufferItem> buffer;
696 bool updateDequeue;
697 res = _allocate(cache, width, height, format, usage, &cached, &slotId, &fence, &buffer);
698 commitAllocate(res, cache, cached, slotId, fence, &buffer, &updateDequeue);
699 if (res == C2_OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000700 ALOGV("allocated a buffer width:%u height:%u pixelformat:%d usage:%llu",
701 width, height, format, (unsigned long long)usage);
Sungtak Leef075f712023-07-20 23:37:45 +0000702 *buf = buffer->mBuf;
703 *rFence = buffer->mFence;
704 // *buf should be valid even if buffer is dtor-ed.
705 AHardwareBuffer_acquire(*buf);
706 }
707 if (updateDequeue) {
708 updateDequeueConf();
709 }
710 return res;
711}
712
713c2_status_t GraphicsTracker::requestDeallocate(uint64_t bid, const sp<Fence> &fence,
714 bool *completed, bool *updateDequeue,
715 std::shared_ptr<BufferCache> *cache, int *slotId,
716 sp<Fence> *rFence) {
717 std::unique_lock<std::mutex> l(mLock);
718 if (mDeallocating.find(bid) != mDeallocating.end()) {
719 ALOGE("Tries to deallocate a buffer which is already deallocating or rendering");
720 return C2_DUPLICATE;
721 }
722 auto it = mDequeued.find(bid);
723 if (it == mDequeued.end()) {
724 ALOGE("Tried to deallocate non dequeued buffer");
725 return C2_NOT_FOUND;
726 }
727
728 std::shared_ptr<BufferItem> buffer = it->second;
729 if (buffer->mGeneration == mBufferCache->mGeneration && mBufferCache->mIgbp) {
730 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
731 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
732 *cache = mBufferCache;
733 *slotId = buffer->mSlot;
734 *rFence = ( fence == Fence::NO_FENCE) ? buffer->mFence : fence;
735 // mark this deallocating
736 mDeallocating.emplace(bid);
737 mBufferCache->blockSlot(buffer->mSlot);
738 *completed = false;
739 } else { // buffer is not from the current underlying Graphics.
740 mDequeued.erase(bid);
741 *completed = true;
742 if (adjustDequeueConfLocked(updateDequeue)) {
743 return C2_OK;
744 }
745 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000746 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000747 }
748 return C2_OK;
749}
750
751void GraphicsTracker::commitDeallocate(
Sungtak Leee625b932023-11-13 07:55:54 +0000752 std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid, bool *updateDequeue) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000753 std::unique_lock<std::mutex> l(mLock);
Sungtak Leef075f712023-07-20 23:37:45 +0000754 size_t del1 = mDequeued.erase(bid);
755 size_t del2 = mDeallocating.erase(bid);
756 CHECK(del1 > 0 && del2 > 0);
Sungtak Leef075f712023-07-20 23:37:45 +0000757 if (cache) {
758 cache->unblockSlot(slotId);
759 }
Sungtak Leee625b932023-11-13 07:55:54 +0000760 if (adjustDequeueConfLocked(updateDequeue)) {
761 return;
762 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000763 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000764 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000765}
766
767
768c2_status_t GraphicsTracker::deallocate(uint64_t bid, const sp<Fence> &fence) {
769 bool completed;
770 bool updateDequeue;
771 std::shared_ptr<BufferCache> cache;
772 int slotId;
773 sp<Fence> rFence;
774 c2_status_t res = requestDeallocate(bid, fence, &completed, &updateDequeue,
775 &cache, &slotId, &rFence);
776 if (res != C2_OK) {
777 return res;
778 }
779 if (completed == true) {
780 if (updateDequeue) {
781 updateDequeueConf();
782 }
783 return C2_OK;
784 }
785
786 // ignore return value since IGBP could be already stale.
787 // cache->mIgbp is not null, if completed is false.
788 (void)cache->mIgbp->cancelBuffer(slotId, rFence);
789
Sungtak Leee625b932023-11-13 07:55:54 +0000790 commitDeallocate(cache, slotId, bid, &updateDequeue);
791 if (updateDequeue) {
792 updateDequeueConf();
793 }
Sungtak Leef075f712023-07-20 23:37:45 +0000794 return C2_OK;
795}
796
797c2_status_t GraphicsTracker::requestRender(uint64_t bid, std::shared_ptr<BufferCache> *cache,
798 std::shared_ptr<BufferItem> *pBuffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000799 bool *fromCache,
Sungtak Leef075f712023-07-20 23:37:45 +0000800 bool *updateDequeue) {
801 std::unique_lock<std::mutex> l(mLock);
802 if (mDeallocating.find(bid) != mDeallocating.end()) {
803 ALOGE("Tries to render a buffer which is already deallocating or rendering");
804 return C2_DUPLICATE;
805 }
806 auto it = mDequeued.find(bid);
807 if (it == mDequeued.end()) {
808 ALOGE("Tried to render non dequeued buffer");
809 return C2_NOT_FOUND;
810 }
811 if (!mBufferCache->mIgbp) {
812 // Render requested without surface.
813 // reclaim the buffer for dequeue.
814 // TODO: is this correct for API wise?
815 mDequeued.erase(it);
816 if (adjustDequeueConfLocked(updateDequeue)) {
817 return C2_BAD_STATE;
818 }
819 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000820 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000821 return C2_BAD_STATE;
822 }
823 std::shared_ptr<BufferItem> buffer = it->second;
824 *cache = mBufferCache;
825 if (buffer->mGeneration == mBufferCache->mGeneration) {
826 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
827 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
828 mBufferCache->blockSlot(buffer->mSlot);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000829 *fromCache = true;
830 } else {
831 *fromCache = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000832 }
833 *pBuffer = buffer;
834 mDeallocating.emplace(bid);
835 return C2_OK;
836}
837
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000838void GraphicsTracker::commitRender(const std::shared_ptr<BufferCache> &cache,
Sungtak Leef075f712023-07-20 23:37:45 +0000839 const std::shared_ptr<BufferItem> &buffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000840 const std::shared_ptr<BufferItem> &oldBuffer,
841 bool bufferReplaced,
Sungtak Leef075f712023-07-20 23:37:45 +0000842 bool *updateDequeue) {
843 std::unique_lock<std::mutex> l(mLock);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000844 uint64_t origBid = oldBuffer ? oldBuffer->mId : buffer->mId;
Sungtak Leef075f712023-07-20 23:37:45 +0000845
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000846 if (cache) {
847 cache->unblockSlot(buffer->mSlot);
848 if (oldBuffer) {
849 // migrated, register the new buffer to the cache.
850 cache->mBuffers.emplace(buffer->mSlot, buffer);
851 }
852 }
853 mDeallocating.erase(origBid);
854 mDequeued.erase(origBid);
855
856 if (cache.get() != mBufferCache.get() || bufferReplaced) {
Sungtak Leef075f712023-07-20 23:37:45 +0000857 // Surface changed, no need to wait for buffer being released.
Sungtak Leef075f712023-07-20 23:37:45 +0000858 if (adjustDequeueConfLocked(updateDequeue)) {
859 return;
860 }
861 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000862 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000863 return;
864 }
Sungtak Leef075f712023-07-20 23:37:45 +0000865}
866
867c2_status_t GraphicsTracker::render(const C2ConstGraphicBlock& blk,
868 const IGraphicBufferProducer::QueueBufferInput &input,
869 IGraphicBufferProducer::QueueBufferOutput *output) {
870 uint64_t bid;
871 c2_status_t res = retrieveAHardwareBufferId(blk, &bid);
872 if (res != C2_OK) {
873 ALOGE("retrieving AHB-ID for GraphicBlock failed");
874 return C2_CORRUPTED;
875 }
Sungtak Leee625b932023-11-13 07:55:54 +0000876 std::shared_ptr<_C2BlockPoolData> poolData =
877 _C2BlockFactory::GetGraphicBlockPoolData(blk);
878 _C2BlockFactory::DisownIgbaBlock(poolData);
Sungtak Leef075f712023-07-20 23:37:45 +0000879 std::shared_ptr<BufferCache> cache;
880 std::shared_ptr<BufferItem> buffer;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000881 std::shared_ptr<BufferItem> oldBuffer;
Sungtak Leef075f712023-07-20 23:37:45 +0000882 bool updateDequeue = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000883 bool fromCache = false;
884 res = requestRender(bid, &cache, &buffer, &fromCache, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000885 if (res != C2_OK) {
886 if (updateDequeue) {
887 updateDequeueConf();
888 }
889 return res;
890 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000891 int cacheSlotId = fromCache ? buffer->mSlot : -1;
892 ALOGV("render prepared: igbp(%d) slot(%d)", bool(cache->mIgbp), cacheSlotId);
893 if (!fromCache) {
894 // The buffer does not come from the current cache.
895 // The buffer is needed to be migrated(attached).
Sungtak Leef075f712023-07-20 23:37:45 +0000896 uint64_t newUsage = 0ULL;
Sungtak Leef075f712023-07-20 23:37:45 +0000897
898 (void) cache->mIgbp->getConsumerUsage(&newUsage);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000899 std::shared_ptr<BufferItem> newBuffer =
900 buffer->migrateBuffer(newUsage, cache->mGeneration);
901 sp<GraphicBuffer> gb = newBuffer ? newBuffer->getGraphicBuffer() : nullptr;
902
903 if (!gb) {
904 ALOGE("render: realloc-ing a new buffer for migration failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000905 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000906 commitDeallocate(nullCache, -1, bid, &updateDequeue);
907 if (updateDequeue) {
908 updateDequeueConf();
909 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000910 return C2_REFUSED;
Sungtak Leef075f712023-07-20 23:37:45 +0000911 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000912 if (cache->mIgbp->attachBuffer(&(newBuffer->mSlot), gb) != ::android::OK) {
913 ALOGE("render: attaching a new buffer to IGBP failed");
914 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000915 commitDeallocate(nullCache, -1, bid, &updateDequeue);
916 if (updateDequeue) {
917 updateDequeueConf();
918 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000919 return C2_REFUSED;
920 }
921 cache->waitOnSlot(newBuffer->mSlot);
922 cache->blockSlot(newBuffer->mSlot);
923 oldBuffer = buffer;
924 buffer = newBuffer;
925 }
926 ::android::status_t renderRes = cache->mIgbp->queueBuffer(buffer->mSlot, input, output);
927 ALOGV("render done: migration(%d), render(err = %d)", !fromCache, renderRes);
928 if (renderRes != ::android::OK) {
929 CHECK(renderRes != ::android::BAD_VALUE);
930 ALOGE("render: failed to queueBuffer() err = %d", renderRes);
931 (void) cache->mIgbp->cancelBuffer(buffer->mSlot, input.fence);
Sungtak Leee625b932023-11-13 07:55:54 +0000932 commitDeallocate(cache, buffer->mSlot, bid, &updateDequeue);
933 if (updateDequeue) {
934 updateDequeueConf();
935 }
Sungtak Leef075f712023-07-20 23:37:45 +0000936 return C2_REFUSED;
937 }
938
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000939 commitRender(cache, buffer, oldBuffer, output->bufferReplaced, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000940 if (updateDequeue) {
941 updateDequeueConf();
942 }
Sungtak Leef075f712023-07-20 23:37:45 +0000943 return C2_OK;
944}
945
946void GraphicsTracker::onReleased(uint32_t generation) {
947 bool updateDequeue = false;
948 {
949 std::unique_lock<std::mutex> l(mLock);
950 if (mBufferCache->mGeneration == generation) {
951 if (!adjustDequeueConfLocked(&updateDequeue)) {
952 mDequeueable++;
Sungtak Lee45246602023-11-27 07:17:24 +0000953 writeIncDequeueableLocked(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000954 }
955 }
956 }
957 if (updateDequeue) {
958 updateDequeueConf();
959 }
960}
961
962} // namespace aidl::android::hardware::media::c2::implementation