blob: 1c9c04c89aed7b0582f9e96035c9e210f4ba36a7 [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 Leee625b932023-11-13 07:55:54 +0000195 mIncDequeueable = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000196
197 mEventQueueThread = std::thread([this](){processEvent();});
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000198 writeIncDequeueable(mDequeueable);
Sungtak Leef075f712023-07-20 23:37:45 +0000199
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000200 CHECK(ret >= 0);
Sungtak Leef075f712023-07-20 23:37:45 +0000201 CHECK(mEventQueueThread.joinable());
202}
203
204GraphicsTracker::~GraphicsTracker() {
205 stop();
206 if (mEventQueueThread.joinable()) {
Sungtak Leef075f712023-07-20 23:37:45 +0000207 mEventQueueThread.join();
208 }
209}
210
211bool GraphicsTracker::adjustDequeueConfLocked(bool *updateDequeue) {
212 // TODO: can't we adjust during config? not committing it may safe?
213 *updateDequeue = false;
Sungtak Leee625b932023-11-13 07:55:54 +0000214 if (!mInConfig && mMaxDequeueRequested.has_value() && mMaxDequeueRequested < mMaxDequeue) {
215 int delta = mMaxDequeue - mMaxDequeueRequested.value();
216 int drained = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000217 // Since we are supposed to increase mDequeuable by one already
218 int adjustable = mDequeueable + 1;
219 if (adjustable >= delta) {
Sungtak Leee625b932023-11-13 07:55:54 +0000220 mMaxDequeue = mMaxDequeueRequested.value();
Sungtak Leef075f712023-07-20 23:37:45 +0000221 mDequeueable -= (delta - 1);
Sungtak Leee625b932023-11-13 07:55:54 +0000222 drained = delta - 1;
Sungtak Leef075f712023-07-20 23:37:45 +0000223 } else {
224 mMaxDequeue -= adjustable;
Sungtak Leee625b932023-11-13 07:55:54 +0000225 drained = mDequeueable;
Sungtak Leef075f712023-07-20 23:37:45 +0000226 mDequeueable = 0;
227 }
Sungtak Leee625b932023-11-13 07:55:54 +0000228 if (drained > 0) {
229 drainDequeueableLocked(drained);
230 }
Sungtak Leef075f712023-07-20 23:37:45 +0000231 if (mMaxDequeueRequested == mMaxDequeue && mMaxDequeueRequested != mMaxDequeueCommitted) {
232 *updateDequeue = true;
233 }
234 return true;
235 }
236 return false;
237}
238
239c2_status_t GraphicsTracker::configureGraphics(
240 const sp<IGraphicBufferProducer>& igbp, uint32_t generation) {
241 std::shared_ptr<BufferCache> prevCache;
242 int prevDequeueCommitted;
243
244 std::unique_lock<std::mutex> cl(mConfigLock);
245 {
246 std::unique_lock<std::mutex> l(mLock);
247 mInConfig = true;
248 prevCache = mBufferCache;
249 prevDequeueCommitted = mMaxDequeueCommitted;
250 }
251 // NOTE: Switching to the same surface is blocked from MediaCodec.
252 // Switching to the same surface might not work if tried, since disconnect()
253 // to the old surface in MediaCodec and allocate from the new surface from
254 // GraphicsTracker cannot be synchronized properly.
255 uint64_t bqId{0ULL};
256 ::android::status_t ret = ::android::OK;
257 if (igbp) {
258 ret = igbp->getUniqueId(&bqId);
259 }
Sungtak Leee625b932023-11-13 07:55:54 +0000260 if (ret != ::android::OK ||
261 prevCache->mGeneration == generation ||
262 (bqId != 0 && prevCache->mBqId == bqId)) {
263 ALOGE("new surface configure fail due to wrong or same bqId or same generation:"
264 "igbp(%d:%llu -> %llu), gen(%lu -> %lu)", (bool)igbp,
265 (unsigned long long)prevCache->mBqId, (unsigned long long)bqId,
266 (unsigned long)prevCache->mGeneration, (unsigned long)generation);
267 std::unique_lock<std::mutex> l(mLock);
268 mInConfig = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000269 return C2_BAD_VALUE;
270 }
Sungtak Leee625b932023-11-13 07:55:54 +0000271 if (igbp) {
272 ret = igbp->setMaxDequeuedBufferCount(prevDequeueCommitted);
273 if (ret != ::android::OK) {
274 ALOGE("new surface maxDequeueBufferCount configure fail");
275 // TODO: sort out the error from igbp and return an error accordingly.
276 std::unique_lock<std::mutex> l(mLock);
277 mInConfig = false;
278 return C2_CORRUPTED;
279 }
Sungtak Leef075f712023-07-20 23:37:45 +0000280 }
Sungtak Leee625b932023-11-13 07:55:54 +0000281 ALOGD("new surface configured with id:%llu gen:%lu maxDequeue:%d",
282 (unsigned long long)bqId, (unsigned long)generation, prevDequeueCommitted);
Sungtak Leef075f712023-07-20 23:37:45 +0000283 std::shared_ptr<BufferCache> newCache = std::make_shared<BufferCache>(bqId, generation, igbp);
284 {
285 std::unique_lock<std::mutex> l(mLock);
286 mInConfig = false;
287 mBufferCache = newCache;
288 }
289 return C2_OK;
290}
291
292c2_status_t GraphicsTracker::configureMaxDequeueCount(int maxDequeueCount) {
293 std::shared_ptr<BufferCache> cache;
294
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000295 if (maxDequeueCount < kMaxDequeueMin || maxDequeueCount > kMaxDequeueMax) {
296 ALOGE("max dequeue count %d is not valid", maxDequeueCount);
297 return C2_BAD_VALUE;
298 }
299
Sungtak Leef075f712023-07-20 23:37:45 +0000300 // max dequeue count which can be committed to IGBP.
301 // (Sometimes maxDequeueCount cannot be committed if the number of
302 // dequeued buffer count is bigger.)
303 int maxDequeueToCommit;
Sungtak Leef075f712023-07-20 23:37:45 +0000304 std::unique_lock<std::mutex> cl(mConfigLock);
305 {
306 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000307 if (mMaxDequeueRequested.has_value()) {
308 if (mMaxDequeueRequested == maxDequeueCount) {
309 ALOGD("maxDequeueCount requested with %d already", maxDequeueCount);
310 return C2_OK;
311 }
312 } else if (mMaxDequeue == maxDequeueCount) {
313 ALOGD("maxDequeueCount is already %d", maxDequeueCount);
Sungtak Leef075f712023-07-20 23:37:45 +0000314 return C2_OK;
315 }
316 mInConfig = true;
317 mMaxDequeueRequested = maxDequeueCount;
318 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000319 if (mMaxDequeue <= maxDequeueCount) {
320 maxDequeueToCommit = maxDequeueCount;
321 } else {
322 // Since mDequeuable is decreasing,
323 // a delievered ready to allocate event may not be fulfilled.
324 // Another waiting via a waitable object may be necessary in the case.
Sungtak Leee625b932023-11-13 07:55:54 +0000325 int delta = std::min(mMaxDequeue - maxDequeueCount, mDequeueable);
326 maxDequeueToCommit = mMaxDequeue - delta;
327 mDequeueable -= delta;
328 if (delta > 0) {
329 drainDequeueableLocked(delta);
Sungtak Leef075f712023-07-20 23:37:45 +0000330 }
331 }
332 }
333
334 bool committed = true;
Sungtak Leee625b932023-11-13 07:55:54 +0000335 if (cache->mIgbp && maxDequeueToCommit != mMaxDequeueCommitted) {
Sungtak Leef075f712023-07-20 23:37:45 +0000336 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(maxDequeueToCommit);
337 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000338 if (committed) {
339 ALOGD("maxDequeueCount committed to IGBP: %d", maxDequeueToCommit);
340 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000341 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000342 ALOGE("maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000343 }
344 }
345
Sungtak Leee625b932023-11-13 07:55:54 +0000346 int oldMaxDequeue = 0;
347 int requested = 0;
Sungtak Leef075f712023-07-20 23:37:45 +0000348 {
349 std::unique_lock<std::mutex> l(mLock);
350 mInConfig = false;
Sungtak Leee625b932023-11-13 07:55:54 +0000351 oldMaxDequeue = mMaxDequeue;
352 mMaxDequeue = maxDequeueToCommit; // we already drained dequeueable
Sungtak Leef075f712023-07-20 23:37:45 +0000353 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000354 clearCacheIfNecessaryLocked(cache, maxDequeueToCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000355 mMaxDequeueCommitted = maxDequeueToCommit;
Sungtak Leee625b932023-11-13 07:55:54 +0000356 if (mMaxDequeueRequested == mMaxDequeueCommitted &&
357 mMaxDequeueRequested == mMaxDequeue) {
358 mMaxDequeueRequested.reset();
359 }
360 if (mMaxDequeueRequested.has_value()) {
361 requested = mMaxDequeueRequested.value();
362 }
363 int delta = mMaxDequeueCommitted - oldMaxDequeue;
Sungtak Leef075f712023-07-20 23:37:45 +0000364 if (delta > 0) {
365 mDequeueable += delta;
366 l.unlock();
367 writeIncDequeueable(delta);
368 }
369 }
370 }
Sungtak Leee625b932023-11-13 07:55:54 +0000371 ALOGD("maxDqueueCount change %d -> %d: pending: %d",
372 oldMaxDequeue, maxDequeueToCommit, requested);
Sungtak Leef075f712023-07-20 23:37:45 +0000373
374 if (!committed) {
375 return C2_CORRUPTED;
376 }
377 return C2_OK;
378}
379
380void GraphicsTracker::updateDequeueConf() {
381 std::shared_ptr<BufferCache> cache;
382 int dequeueCommit;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000383 ALOGV("trying to update max dequeue count");
Sungtak Leef075f712023-07-20 23:37:45 +0000384 std::unique_lock<std::mutex> cl(mConfigLock);
385 {
386 std::unique_lock<std::mutex> l(mLock);
Sungtak Leee625b932023-11-13 07:55:54 +0000387 if (!mMaxDequeueRequested.has_value() || mMaxDequeue != mMaxDequeueRequested) {
Sungtak Leef075f712023-07-20 23:37:45 +0000388 return;
389 }
Sungtak Leee625b932023-11-13 07:55:54 +0000390 if (mMaxDequeueCommitted == mMaxDequeueRequested) {
391 // already committed. may not happen.
392 mMaxDequeueRequested.reset();
393 return;
394 }
395 dequeueCommit = mMaxDequeue;
396 mInConfig = true;
397 cache = mBufferCache;
Sungtak Leef075f712023-07-20 23:37:45 +0000398 }
399 bool committed = true;
400 if (cache->mIgbp) {
401 ::android::status_t ret = cache->mIgbp->setMaxDequeuedBufferCount(dequeueCommit);
402 committed = (ret == ::android::OK);
Sungtak Leee625b932023-11-13 07:55:54 +0000403 if (committed) {
404 ALOGD("delayed maxDequeueCount update to IGBP: %d", dequeueCommit);
405 } else {
Sungtak Leef075f712023-07-20 23:37:45 +0000406 // This should not happen.
Sungtak Leee625b932023-11-13 07:55:54 +0000407 ALOGE("delayed maxdequeueCount update to IGBP failed with error(%d)", (int)ret);
Sungtak Leef075f712023-07-20 23:37:45 +0000408 }
409 }
Sungtak Leef075f712023-07-20 23:37:45 +0000410 {
411 // cache == mCache here, since we locked config.
412 std::unique_lock<std::mutex> l(mLock);
413 mInConfig = false;
414 if (committed) {
Sungtak Leee625b932023-11-13 07:55:54 +0000415 clearCacheIfNecessaryLocked(cache, dequeueCommit);
Sungtak Leef075f712023-07-20 23:37:45 +0000416 mMaxDequeueCommitted = dequeueCommit;
417 }
Sungtak Leee625b932023-11-13 07:55:54 +0000418 mMaxDequeueRequested.reset();
Sungtak Leef075f712023-07-20 23:37:45 +0000419 }
Sungtak Leee625b932023-11-13 07:55:54 +0000420}
Sungtak Leef075f712023-07-20 23:37:45 +0000421
Sungtak Leee625b932023-11-13 07:55:54 +0000422void GraphicsTracker::clearCacheIfNecessaryLocked(const std::shared_ptr<BufferCache> &cache,
423 int maxDequeueCommitted) {
424 int cleared = 0;
425 size_t origCacheSize = cache->mBuffers.size();
426 if (cache->mIgbp && maxDequeueCommitted < mMaxDequeueCommitted) {
427 // we are shrinking # of buffers in the case, so evict the previous
428 // cached buffers.
429 for (auto it = cache->mBuffers.begin(); it != cache->mBuffers.end();) {
430 uint64_t bid = it->second->mId;
431 if (mDequeued.count(bid) == 0 || mDeallocating.count(bid) > 0) {
432 ++cleared;
433 it = cache->mBuffers.erase(it);
434 } else {
435 ++it;
436 }
437 }
438 }
439 ALOGD("Cache size %zu -> %zu: maybe_cleared(%d), dequeued(%zu)",
440 origCacheSize, cache->mBuffers.size(), cleared, mDequeued.size());
Sungtak Leef075f712023-07-20 23:37:45 +0000441}
442
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000443int GraphicsTracker::getCurDequeueable() {
444 std::unique_lock<std::mutex> l(mLock);
445 return mDequeueable;
446}
447
Sungtak Leef075f712023-07-20 23:37:45 +0000448void GraphicsTracker::stop() {
449 bool expected = false;
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000450 std::unique_lock<std::mutex> l(mEventLock);
Sungtak Leef075f712023-07-20 23:37:45 +0000451 bool updated = mStopped.compare_exchange_strong(expected, true);
452 if (updated) {
Sungtak Leee625b932023-11-13 07:55:54 +0000453 // TODO: synchronize close and other i/o.
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000454 int writeFd = mWritePipeFd.release();
455 ::close(writeFd);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000456 int readFd = mReadPipeFd.release();
457 ::close(readFd);
458 mEventCv.notify_one();
Sungtak Leef075f712023-07-20 23:37:45 +0000459 }
460}
461
462void GraphicsTracker::writeIncDequeueable(int inc) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000463 CHECK(inc > 0 && inc < kMaxDequeueMax);
464 thread_local char buf[kMaxDequeueMax];
465 int diff = 0;
466 {
Sungtak Leef075f712023-07-20 23:37:45 +0000467 std::unique_lock<std::mutex> l(mEventLock);
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000468 if (mStopped) {
469 return;
470 }
471 CHECK(mWritePipeFd.get() >= 0);
472 int ret = ::write(mWritePipeFd.get(), buf, inc);
473 if (ret == inc) {
474 return;
475 }
476 diff = ret < 0 ? inc : inc - ret;
477
478 // Partial write or EINTR. This will not happen in a real scenario.
479 mIncDequeueable += diff;
480 if (mIncDequeueable > 0) {
481 l.unlock();
482 mEventCv.notify_one();
483 ALOGW("updating dequeueable to pipefd pending");
484 }
Sungtak Leef075f712023-07-20 23:37:45 +0000485 }
486}
487
Sungtak Leee625b932023-11-13 07:55:54 +0000488void GraphicsTracker::drainDequeueableLocked(int dec) {
489 CHECK(dec > 0 && dec < kMaxDequeueMax);
490 thread_local char buf[kMaxDequeueMax];
491 if (mStopped) {
492 return;
493 }
494 CHECK(mReadPipeFd.get() >= 0);
495 int ret = ::read(mReadPipeFd.get(), buf, dec);
496 if (ret < 0 && errno == EINTR) {
497 // signal cancel try again.
498 ret = ::read(mReadPipeFd.get(), buf, dec);
499 }
500 CHECK(mStopped || ret == dec);
501 // TODO: remove CHECK
502 // if ret < dec, drain the amount from EventThread.
503}
504
Sungtak Leef075f712023-07-20 23:37:45 +0000505void GraphicsTracker::processEvent() {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000506 // This is for partial/failed writes to the writing end.
507 // This may not happen in the real scenario.
508 thread_local char buf[kMaxDequeueMax];
Sungtak Leef075f712023-07-20 23:37:45 +0000509 while (true) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000510 std::unique_lock<std::mutex> l(mEventLock);
511 if (mStopped) {
512 break;
513 }
514 if (mIncDequeueable > 0) {
515 int inc = mIncDequeueable > kMaxDequeueMax ? kMaxDequeueMax : mIncDequeueable;
516 int ret = ::write(mWritePipeFd.get(), buf, inc);
517 int written = ret <= 0 ? 0 : ret;
518 mIncDequeueable -= written;
519 if (mIncDequeueable > 0) {
520 l.unlock();
521 if (ret < 0) {
522 ALOGE("write to writing end failed %d", errno);
523 } else {
524 ALOGW("partial write %d(%d)", inc, written);
Sungtak Leef075f712023-07-20 23:37:45 +0000525 }
Sungtak Leef075f712023-07-20 23:37:45 +0000526 continue;
527 }
528 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000529 mEventCv.wait(l);
Sungtak Leef075f712023-07-20 23:37:45 +0000530 }
531}
532
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000533c2_status_t GraphicsTracker::getWaitableFd(int *pipeFd) {
534 *pipeFd = ::dup(mReadPipeFd.get());
535 if (*pipeFd < 0) {
536 if (mReadPipeFd.get() < 0) {
537 return C2_BAD_STATE;
Sungtak Leef075f712023-07-20 23:37:45 +0000538 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000539 // dup error
540 ALOGE("dup() for the reading end failed %d", errno);
Sungtak Leef075f712023-07-20 23:37:45 +0000541 return C2_NO_MEMORY;
542 }
543 return C2_OK;
544}
545
546c2_status_t GraphicsTracker::requestAllocate(std::shared_ptr<BufferCache> *cache) {
547 std::lock_guard<std::mutex> l(mLock);
548 if (mDequeueable > 0) {
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000549 char buf[1];
550 int ret = ::read(mReadPipeFd.get(), buf, 1);
Sungtak Leef075f712023-07-20 23:37:45 +0000551 if (ret < 0) {
552 if (errno == EINTR) {
553 // Do we really need to care for cancel due to signal handling?
554 return C2_CANCELED;
555 }
556 if (errno == EAGAIN) {
557 // proper usage of waitable object should not return this.
558 // but there could be alloc requests from HAL ignoring the internal status.
559 return C2_BLOCKING;
560 }
561 CHECK(errno != 0);
562 }
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000563 if (ret == 0) {
564 // writing end is closed
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000565 ALOGE("writing end for the waitable object seems to be closed");
Sungtak Leef6fe5f72023-09-17 23:53:50 +0000566 return C2_BAD_STATE;
567 }
Sungtak Leef075f712023-07-20 23:37:45 +0000568 mDequeueable--;
569 *cache = mBufferCache;
570 return C2_OK;
571 }
572 return C2_BLOCKING;
573}
574
575// If {@code cached} is {@code true}, {@code pBuffer} should be read from the
576// current cached status. Otherwise, {@code pBuffer} should be written to
577// current caches status.
578void GraphicsTracker::commitAllocate(c2_status_t res, const std::shared_ptr<BufferCache> &cache,
579 bool cached, int slot, const sp<Fence> &fence,
580 std::shared_ptr<BufferItem> *pBuffer, bool *updateDequeue) {
581 std::unique_lock<std::mutex> l(mLock);
582 if (res == C2_OK) {
583 if (cached) {
584 auto it = cache->mBuffers.find(slot);
585 CHECK(it != cache->mBuffers.end());
586 it->second->mFence = fence;
587 *pBuffer = it->second;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000588 ALOGV("an allocated buffer already cached, updated Fence");
Sungtak Leef075f712023-07-20 23:37:45 +0000589 } else if (cache.get() == mBufferCache.get() && mBufferCache->mIgbp) {
590 // Cache the buffer if it is allocated from the current IGBP
591 CHECK(slot >= 0);
592 auto ret = mBufferCache->mBuffers.emplace(slot, *pBuffer);
593 if (!ret.second) {
594 ret.first->second = *pBuffer;
595 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000596 ALOGV("an allocated buffer not cached from the current IGBP");
Sungtak Leef075f712023-07-20 23:37:45 +0000597 }
598 uint64_t bid = (*pBuffer)->mId;
599 auto mapRet = mDequeued.emplace(bid, *pBuffer);
600 CHECK(mapRet.second);
601 } else {
602 if (adjustDequeueConfLocked(updateDequeue)) {
603 return;
604 }
605 mDequeueable++;
606 l.unlock();
607 writeIncDequeueable(1);
608 }
609}
610
611
612// if a buffer is newly allocated, {@code cached} is {@code false},
613// and the buffer is in the {@code buffer}
614// otherwise, {@code cached} is {@code false} and the buffer should be
615// retrieved by commitAllocate();
616c2_status_t GraphicsTracker::_allocate(const std::shared_ptr<BufferCache> &cache,
617 uint32_t width, uint32_t height, PixelFormat format,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000618 uint64_t usage,
Sungtak Leef075f712023-07-20 23:37:45 +0000619 bool *cached,
620 int *rSlotId,
621 sp<Fence> *rFence,
622 std::shared_ptr<BufferItem> *buffer) {
623 ::android::sp<IGraphicBufferProducer> igbp = cache->mIgbp;
624 uint32_t generation = cache->mGeneration;
625 if (!igbp) {
626 // allocate directly
627 AHardwareBuffer_Desc desc;
628 desc.width = width;
629 desc.height = height;
630 desc.layers = 1u;
631 desc.format = ::android::AHardwareBuffer_convertFromPixelFormat(format);
632 desc.usage = ::android::AHardwareBuffer_convertFromGrallocUsageBits(usage);
633 desc.rfu0 = 0;
634 desc.rfu1 = 0;
635
636 AHardwareBuffer *buf;
637 int ret = AHardwareBuffer_allocate(&desc, &buf);
638 if (ret != ::android::OK) {
639 ALOGE("direct allocation of AHB failed(%d)", ret);
640 return ret == ::android::NO_MEMORY ? C2_NO_MEMORY : C2_CORRUPTED;
641 }
642 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000643 *rSlotId = -1;
644 *rFence = Fence::NO_FENCE;
645 *buffer = std::make_shared<BufferItem>(generation, buf, usage);
646 AHardwareBuffer_release(buf); // remove an acquire count from
647 // AHwb_allocate().
Sungtak Leef075f712023-07-20 23:37:45 +0000648 if (!*buffer) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000649 ALOGE("direct allocation of AHB successful, but failed to create BufferItem");
Sungtak Leef075f712023-07-20 23:37:45 +0000650 return C2_NO_MEMORY;
651 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000652 if (!(*buffer)->mInit) {
653 ALOGE("direct allocation of AHB successful, but BufferItem init failed");
654 buffer->reset();
655 return C2_CORRUPTED;
656 }
657 ALOGV("allocate: direct allocate without igbp");
Sungtak Leef075f712023-07-20 23:37:45 +0000658 return C2_OK;
659 }
660
661 int slotId;
662 uint64_t outBufferAge;
663 ::android::FrameEventHistoryDelta outTimestamps;
664 sp<Fence> fence;
665
666 ::android::status_t status = igbp->dequeueBuffer(
667 &slotId, &fence, width, height, format, usage, &outBufferAge, &outTimestamps);
668 if (status < ::android::OK) {
669 ALOGE("dequeueBuffer() error %d", (int)status);
670 return C2_CORRUPTED;
671 }
672 cache->waitOnSlot(slotId);
673 bool exists = false;
674 {
675 std::unique_lock<std::mutex> l(mLock);
676 if (cache.get() == mBufferCache.get() &&
677 cache->mBuffers.find(slotId) != cache->mBuffers.end()) {
678 exists = true;
679 }
680 }
681 bool needsRealloc = status & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION;
682 if (needsRealloc || !exists) {
683 sp<GraphicBuffer> realloced;
684 status = igbp->requestBuffer(slotId, &realloced);
685 if (status != ::android::OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000686 ALOGE("allocate by dequeueBuffer() successful, but requestBuffer() failed %d",
687 status);
Sungtak Leef075f712023-07-20 23:37:45 +0000688 igbp->cancelBuffer(slotId, fence);
689 return C2_CORRUPTED;
690 }
691 *buffer = std::make_shared<BufferItem>(generation, slotId, realloced, fence);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000692 if (!*buffer) {
693 ALOGE("allocate by dequeueBuffer() successful, but creating BufferItem failed");
694 igbp->cancelBuffer(slotId, fence);
695 return C2_NO_MEMORY;
696 }
Sungtak Leef075f712023-07-20 23:37:45 +0000697 if (!(*buffer)->mInit) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000698 ALOGE("allocate by dequeueBuffer() successful, but BufferItem init failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000699 buffer->reset();
700 igbp->cancelBuffer(slotId, fence);
701 return C2_CORRUPTED;
702 }
703 *cached = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000704 } else {
705 *cached = true;
Sungtak Leef075f712023-07-20 23:37:45 +0000706 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000707 ALOGV("allocate: a new allocated buffer from igbp cached %d, slot: %d",
708 *cached, slotId);
Sungtak Leef075f712023-07-20 23:37:45 +0000709 *rSlotId = slotId;
710 *rFence = fence;
711 return C2_OK;
712}
713
714c2_status_t GraphicsTracker::allocate(
715 uint32_t width, uint32_t height, PixelFormat format, uint64_t usage,
716 AHardwareBuffer **buf, sp<Fence> *rFence) {
717 if (mStopped.load() == true) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000718 ALOGE("cannot allocate due to being stopped");
Sungtak Leef075f712023-07-20 23:37:45 +0000719 return C2_BAD_STATE;
720 }
721 std::shared_ptr<BufferCache> cache;
722 c2_status_t res = requestAllocate(&cache);
723 if (res != C2_OK) {
724 return res;
725 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000726 ALOGV("allocatable or dequeueable");
Sungtak Leef075f712023-07-20 23:37:45 +0000727
728 bool cached = false;
729 int slotId;
730 sp<Fence> fence;
731 std::shared_ptr<BufferItem> buffer;
732 bool updateDequeue;
733 res = _allocate(cache, width, height, format, usage, &cached, &slotId, &fence, &buffer);
734 commitAllocate(res, cache, cached, slotId, fence, &buffer, &updateDequeue);
735 if (res == C2_OK) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000736 ALOGV("allocated a buffer width:%u height:%u pixelformat:%d usage:%llu",
737 width, height, format, (unsigned long long)usage);
Sungtak Leef075f712023-07-20 23:37:45 +0000738 *buf = buffer->mBuf;
739 *rFence = buffer->mFence;
740 // *buf should be valid even if buffer is dtor-ed.
741 AHardwareBuffer_acquire(*buf);
742 }
743 if (updateDequeue) {
744 updateDequeueConf();
745 }
746 return res;
747}
748
749c2_status_t GraphicsTracker::requestDeallocate(uint64_t bid, const sp<Fence> &fence,
750 bool *completed, bool *updateDequeue,
751 std::shared_ptr<BufferCache> *cache, int *slotId,
752 sp<Fence> *rFence) {
753 std::unique_lock<std::mutex> l(mLock);
754 if (mDeallocating.find(bid) != mDeallocating.end()) {
755 ALOGE("Tries to deallocate a buffer which is already deallocating or rendering");
756 return C2_DUPLICATE;
757 }
758 auto it = mDequeued.find(bid);
759 if (it == mDequeued.end()) {
760 ALOGE("Tried to deallocate non dequeued buffer");
761 return C2_NOT_FOUND;
762 }
763
764 std::shared_ptr<BufferItem> buffer = it->second;
765 if (buffer->mGeneration == mBufferCache->mGeneration && mBufferCache->mIgbp) {
766 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
767 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
768 *cache = mBufferCache;
769 *slotId = buffer->mSlot;
770 *rFence = ( fence == Fence::NO_FENCE) ? buffer->mFence : fence;
771 // mark this deallocating
772 mDeallocating.emplace(bid);
773 mBufferCache->blockSlot(buffer->mSlot);
774 *completed = false;
775 } else { // buffer is not from the current underlying Graphics.
776 mDequeued.erase(bid);
777 *completed = true;
778 if (adjustDequeueConfLocked(updateDequeue)) {
779 return C2_OK;
780 }
781 mDequeueable++;
782 l.unlock();
783 writeIncDequeueable(1);
784 }
785 return C2_OK;
786}
787
788void GraphicsTracker::commitDeallocate(
Sungtak Leee625b932023-11-13 07:55:54 +0000789 std::shared_ptr<BufferCache> &cache, int slotId, uint64_t bid, bool *updateDequeue) {
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000790 std::unique_lock<std::mutex> l(mLock);
Sungtak Leef075f712023-07-20 23:37:45 +0000791 size_t del1 = mDequeued.erase(bid);
792 size_t del2 = mDeallocating.erase(bid);
793 CHECK(del1 > 0 && del2 > 0);
Sungtak Leef075f712023-07-20 23:37:45 +0000794 if (cache) {
795 cache->unblockSlot(slotId);
796 }
Sungtak Leee625b932023-11-13 07:55:54 +0000797 if (adjustDequeueConfLocked(updateDequeue)) {
798 return;
799 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000800 mDequeueable++;
801 l.unlock();
802 writeIncDequeueable(1);
Sungtak Leef075f712023-07-20 23:37:45 +0000803}
804
805
806c2_status_t GraphicsTracker::deallocate(uint64_t bid, const sp<Fence> &fence) {
807 bool completed;
808 bool updateDequeue;
809 std::shared_ptr<BufferCache> cache;
810 int slotId;
811 sp<Fence> rFence;
812 c2_status_t res = requestDeallocate(bid, fence, &completed, &updateDequeue,
813 &cache, &slotId, &rFence);
814 if (res != C2_OK) {
815 return res;
816 }
817 if (completed == true) {
818 if (updateDequeue) {
819 updateDequeueConf();
820 }
821 return C2_OK;
822 }
823
824 // ignore return value since IGBP could be already stale.
825 // cache->mIgbp is not null, if completed is false.
826 (void)cache->mIgbp->cancelBuffer(slotId, rFence);
827
Sungtak Leee625b932023-11-13 07:55:54 +0000828 commitDeallocate(cache, slotId, bid, &updateDequeue);
829 if (updateDequeue) {
830 updateDequeueConf();
831 }
Sungtak Leef075f712023-07-20 23:37:45 +0000832 return C2_OK;
833}
834
835c2_status_t GraphicsTracker::requestRender(uint64_t bid, std::shared_ptr<BufferCache> *cache,
836 std::shared_ptr<BufferItem> *pBuffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000837 bool *fromCache,
Sungtak Leef075f712023-07-20 23:37:45 +0000838 bool *updateDequeue) {
839 std::unique_lock<std::mutex> l(mLock);
840 if (mDeallocating.find(bid) != mDeallocating.end()) {
841 ALOGE("Tries to render a buffer which is already deallocating or rendering");
842 return C2_DUPLICATE;
843 }
844 auto it = mDequeued.find(bid);
845 if (it == mDequeued.end()) {
846 ALOGE("Tried to render non dequeued buffer");
847 return C2_NOT_FOUND;
848 }
849 if (!mBufferCache->mIgbp) {
850 // Render requested without surface.
851 // reclaim the buffer for dequeue.
852 // TODO: is this correct for API wise?
853 mDequeued.erase(it);
854 if (adjustDequeueConfLocked(updateDequeue)) {
855 return C2_BAD_STATE;
856 }
857 mDequeueable++;
858 l.unlock();
859 writeIncDequeueable(1);
860 return C2_BAD_STATE;
861 }
862 std::shared_ptr<BufferItem> buffer = it->second;
863 *cache = mBufferCache;
864 if (buffer->mGeneration == mBufferCache->mGeneration) {
865 auto it = mBufferCache->mBuffers.find(buffer->mSlot);
866 CHECK(it != mBufferCache->mBuffers.end() && it->second.get() == buffer.get());
867 mBufferCache->blockSlot(buffer->mSlot);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000868 *fromCache = true;
869 } else {
870 *fromCache = false;
Sungtak Leef075f712023-07-20 23:37:45 +0000871 }
872 *pBuffer = buffer;
873 mDeallocating.emplace(bid);
874 return C2_OK;
875}
876
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000877void GraphicsTracker::commitRender(const std::shared_ptr<BufferCache> &cache,
Sungtak Leef075f712023-07-20 23:37:45 +0000878 const std::shared_ptr<BufferItem> &buffer,
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000879 const std::shared_ptr<BufferItem> &oldBuffer,
880 bool bufferReplaced,
Sungtak Leef075f712023-07-20 23:37:45 +0000881 bool *updateDequeue) {
882 std::unique_lock<std::mutex> l(mLock);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000883 uint64_t origBid = oldBuffer ? oldBuffer->mId : buffer->mId;
Sungtak Leef075f712023-07-20 23:37:45 +0000884
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000885 if (cache) {
886 cache->unblockSlot(buffer->mSlot);
887 if (oldBuffer) {
888 // migrated, register the new buffer to the cache.
889 cache->mBuffers.emplace(buffer->mSlot, buffer);
890 }
891 }
892 mDeallocating.erase(origBid);
893 mDequeued.erase(origBid);
894
895 if (cache.get() != mBufferCache.get() || bufferReplaced) {
Sungtak Leef075f712023-07-20 23:37:45 +0000896 // Surface changed, no need to wait for buffer being released.
Sungtak Leef075f712023-07-20 23:37:45 +0000897 if (adjustDequeueConfLocked(updateDequeue)) {
898 return;
899 }
900 mDequeueable++;
901 l.unlock();
902 writeIncDequeueable(1);
903 return;
904 }
Sungtak Leef075f712023-07-20 23:37:45 +0000905}
906
907c2_status_t GraphicsTracker::render(const C2ConstGraphicBlock& blk,
908 const IGraphicBufferProducer::QueueBufferInput &input,
909 IGraphicBufferProducer::QueueBufferOutput *output) {
910 uint64_t bid;
911 c2_status_t res = retrieveAHardwareBufferId(blk, &bid);
912 if (res != C2_OK) {
913 ALOGE("retrieving AHB-ID for GraphicBlock failed");
914 return C2_CORRUPTED;
915 }
Sungtak Leee625b932023-11-13 07:55:54 +0000916 std::shared_ptr<_C2BlockPoolData> poolData =
917 _C2BlockFactory::GetGraphicBlockPoolData(blk);
918 _C2BlockFactory::DisownIgbaBlock(poolData);
Sungtak Leef075f712023-07-20 23:37:45 +0000919 std::shared_ptr<BufferCache> cache;
920 std::shared_ptr<BufferItem> buffer;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000921 std::shared_ptr<BufferItem> oldBuffer;
Sungtak Leef075f712023-07-20 23:37:45 +0000922 bool updateDequeue = false;
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000923 bool fromCache = false;
924 res = requestRender(bid, &cache, &buffer, &fromCache, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000925 if (res != C2_OK) {
926 if (updateDequeue) {
927 updateDequeueConf();
928 }
929 return res;
930 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000931 int cacheSlotId = fromCache ? buffer->mSlot : -1;
932 ALOGV("render prepared: igbp(%d) slot(%d)", bool(cache->mIgbp), cacheSlotId);
933 if (!fromCache) {
934 // The buffer does not come from the current cache.
935 // The buffer is needed to be migrated(attached).
Sungtak Leef075f712023-07-20 23:37:45 +0000936 uint64_t newUsage = 0ULL;
Sungtak Leef075f712023-07-20 23:37:45 +0000937
938 (void) cache->mIgbp->getConsumerUsage(&newUsage);
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000939 std::shared_ptr<BufferItem> newBuffer =
940 buffer->migrateBuffer(newUsage, cache->mGeneration);
941 sp<GraphicBuffer> gb = newBuffer ? newBuffer->getGraphicBuffer() : nullptr;
942
943 if (!gb) {
944 ALOGE("render: realloc-ing a new buffer for migration failed");
Sungtak Leef075f712023-07-20 23:37:45 +0000945 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000946 commitDeallocate(nullCache, -1, bid, &updateDequeue);
947 if (updateDequeue) {
948 updateDequeueConf();
949 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000950 return C2_REFUSED;
Sungtak Leef075f712023-07-20 23:37:45 +0000951 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000952 if (cache->mIgbp->attachBuffer(&(newBuffer->mSlot), gb) != ::android::OK) {
953 ALOGE("render: attaching a new buffer to IGBP failed");
954 std::shared_ptr<BufferCache> nullCache;
Sungtak Leee625b932023-11-13 07:55:54 +0000955 commitDeallocate(nullCache, -1, bid, &updateDequeue);
956 if (updateDequeue) {
957 updateDequeueConf();
958 }
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000959 return C2_REFUSED;
960 }
961 cache->waitOnSlot(newBuffer->mSlot);
962 cache->blockSlot(newBuffer->mSlot);
963 oldBuffer = buffer;
964 buffer = newBuffer;
965 }
966 ::android::status_t renderRes = cache->mIgbp->queueBuffer(buffer->mSlot, input, output);
967 ALOGV("render done: migration(%d), render(err = %d)", !fromCache, renderRes);
968 if (renderRes != ::android::OK) {
969 CHECK(renderRes != ::android::BAD_VALUE);
970 ALOGE("render: failed to queueBuffer() err = %d", renderRes);
971 (void) cache->mIgbp->cancelBuffer(buffer->mSlot, input.fence);
Sungtak Leee625b932023-11-13 07:55:54 +0000972 commitDeallocate(cache, buffer->mSlot, bid, &updateDequeue);
973 if (updateDequeue) {
974 updateDequeueConf();
975 }
Sungtak Leef075f712023-07-20 23:37:45 +0000976 return C2_REFUSED;
977 }
978
Sungtak Lee5bce4ca2023-10-12 03:13:04 +0000979 commitRender(cache, buffer, oldBuffer, output->bufferReplaced, &updateDequeue);
Sungtak Leef075f712023-07-20 23:37:45 +0000980 if (updateDequeue) {
981 updateDequeueConf();
982 }
Sungtak Leef075f712023-07-20 23:37:45 +0000983 return C2_OK;
984}
985
986void GraphicsTracker::onReleased(uint32_t generation) {
987 bool updateDequeue = false;
988 {
989 std::unique_lock<std::mutex> l(mLock);
990 if (mBufferCache->mGeneration == generation) {
991 if (!adjustDequeueConfLocked(&updateDequeue)) {
992 mDequeueable++;
993 l.unlock();
994 writeIncDequeueable(1);
995 }
996 }
997 }
998 if (updateDequeue) {
999 updateDequeueConf();
1000 }
1001}
1002
1003} // namespace aidl::android::hardware::media::c2::implementation