Implement hardware.interface.media.c2@1.2 HAL
Implement block allocator using BufferQueue.
Bug: 157111613
Change-Id: I9d9e5b777f2253cd18960236dcbec73668ae215e
diff --git a/media/codec2/hidl/1.0/utils/Android.bp b/media/codec2/hidl/1.0/utils/Android.bp
index 008def8..122aacd 100644
--- a/media/codec2/hidl/1.0/utils/Android.bp
+++ b/media/codec2/hidl/1.0/utils/Android.bp
@@ -15,7 +15,6 @@
defaults: ["hidl_defaults"],
srcs: [
- "OutputBufferQueue.cpp",
"types.cpp",
],
diff --git a/media/codec2/hidl/1.1/utils/Android.bp b/media/codec2/hidl/1.1/utils/Android.bp
index 71a113d..0eeedb6 100644
--- a/media/codec2/hidl/1.1/utils/Android.bp
+++ b/media/codec2/hidl/1.1/utils/Android.bp
@@ -15,7 +15,6 @@
defaults: ["hidl_defaults"],
srcs: [
- "OutputBufferQueue.cpp",
"types.cpp",
],
diff --git a/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
deleted file mode 100644
index 65756e8..0000000
--- a/media/codec2/hidl/1.1/utils/OutputBufferQueue.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <codec2/hidl/1.1/OutputBufferQueue.h>
diff --git a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h b/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
deleted file mode 100644
index f77852d..0000000
--- a/media/codec2/hidl/1.1/utils/include/codec2/hidl/1.1/OutputBufferQueue.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
-#define CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
-
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
-#include <codec2/hidl/1.1/types.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_1 {
-namespace utils {
-
-using ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue;
-
-} // namespace utils
-} // namespace V1_1
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // CODEC2_HIDL_V1_1_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/1.2/utils/Android.bp b/media/codec2/hidl/1.2/utils/Android.bp
index 0a8d256..e4e4ad5 100644
--- a/media/codec2/hidl/1.2/utils/Android.bp
+++ b/media/codec2/hidl/1.2/utils/Android.bp
@@ -15,7 +15,6 @@
defaults: ["hidl_defaults"],
srcs: [
- "OutputBufferQueue.cpp",
"types.cpp",
],
diff --git a/media/codec2/hidl/1.2/utils/Component.cpp b/media/codec2/hidl/1.2/utils/Component.cpp
index 1de33b4..8924e6d 100644
--- a/media/codec2/hidl/1.2/utils/Component.cpp
+++ b/media/codec2/hidl/1.2/utils/Component.cpp
@@ -480,9 +480,31 @@
Return<Status> Component::setOutputSurfaceWithSyncObj(
uint64_t blockPoolId, const sp<HGraphicBufferProducer2>& surface,
const SurfaceSyncObj& syncObject) {
- (void) blockPoolId;
- (void) surface;
- (void) syncObject;
+ std::shared_ptr<C2BlockPool> pool;
+ GetCodec2BlockPool(blockPoolId, mComponent, &pool);
+ if (pool && pool->getAllocatorId() == C2PlatformAllocatorStore::BUFFERQUEUE) {
+ std::shared_ptr<C2BufferQueueBlockPool> bqPool =
+ std::static_pointer_cast<C2BufferQueueBlockPool>(pool);
+ C2BufferQueueBlockPool::OnRenderCallback cb =
+ [this](uint64_t producer, int32_t slot, int64_t nsecs) {
+ // TODO: batch this
+ hidl_vec<IComponentListener::RenderedFrame> rendered;
+ rendered.resize(1);
+ rendered[0] = { producer, slot, nsecs };
+ (void)mListener->onFramesRendered(rendered).isOk();
+ };
+ if (bqPool) {
+ const native_handle_t *h = syncObject.syncMemory;
+ native_handle_t *syncMemory = h ? native_handle_clone(h) : nullptr;
+ uint64_t bqId = syncObject.bqId;
+ uint32_t generationId = syncObject.generationId;
+ uint64_t consumerUsage = syncObject.consumerUsage;
+
+ bqPool->setRenderCallback(cb);
+ bqPool->configureProducer(surface, syncMemory, bqId,
+ generationId, consumerUsage);
+ }
+ }
return Status::OK;
}
diff --git a/media/codec2/hidl/1.2/utils/OutputBufferQueue.cpp b/media/codec2/hidl/1.2/utils/OutputBufferQueue.cpp
deleted file mode 100644
index 12b5f5b..0000000
--- a/media/codec2/hidl/1.2/utils/OutputBufferQueue.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <codec2/hidl/1.2/OutputBufferQueue.h>
diff --git a/media/codec2/hidl/1.2/utils/include/codec2/hidl/1.2/OutputBufferQueue.h b/media/codec2/hidl/1.2/utils/include/codec2/hidl/1.2/OutputBufferQueue.h
deleted file mode 100644
index 9fd5f07..0000000
--- a/media/codec2/hidl/1.2/utils/include/codec2/hidl/1.2/OutputBufferQueue.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CODEC2_HIDL_V1_2_UTILS_OUTPUT_BUFFER_QUEUE
-#define CODEC2_HIDL_V1_2_UTILS_OUTPUT_BUFFER_QUEUE
-
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
-#include <codec2/hidl/1.2/types.h>
-
-namespace android {
-namespace hardware {
-namespace media {
-namespace c2 {
-namespace V1_2 {
-namespace utils {
-
-using ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue;
-
-} // namespace utils
-} // namespace V1_2
-} // namespace c2
-} // namespace media
-} // namespace hardware
-} // namespace android
-
-#endif // CODEC2_HIDL_V1_2_UTILS_OUTPUT_BUFFER_QUEUE
diff --git a/media/codec2/hidl/client/Android.bp b/media/codec2/hidl/client/Android.bp
index b3ca5b1..0e52813 100644
--- a/media/codec2/hidl/client/Android.bp
+++ b/media/codec2/hidl/client/Android.bp
@@ -12,6 +12,11 @@
srcs: [
"client.cpp",
+ "output.cpp",
+ ],
+
+ header_libs: [
+ "libcodec2_internal", // private
],
shared_libs: [
diff --git a/media/codec2/hidl/client/client.cpp b/media/codec2/hidl/client/client.cpp
index 0a61fe2..0296004 100644
--- a/media/codec2/hidl/client/client.cpp
+++ b/media/codec2/hidl/client/client.cpp
@@ -33,17 +33,17 @@
#include <android-base/properties.h>
#include <bufferpool/ClientManager.h>
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
#include <codec2/hidl/1.0/types.h>
-#include <codec2/hidl/1.1/OutputBufferQueue.h>
#include <codec2/hidl/1.1/types.h>
#include <codec2/hidl/1.2/types.h>
+#include <codec2/hidl/output.h>
#include <cutils/native_handle.h>
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
#include <hidl/HidlSupport.h>
+
#include <deque>
#include <iterator>
#include <limits>
@@ -74,6 +74,7 @@
V2_0::utils::B2HGraphicBufferProducer;
using H2BGraphicBufferProducer2 = ::android::hardware::graphics::bufferqueue::
V2_0::utils::H2BGraphicBufferProducer;
+using ::android::hardware::media::c2::V1_2::SurfaceSyncObj;
namespace /* unnamed */ {
@@ -593,9 +594,9 @@
// Codec2Client::Component::OutputBufferQueue
struct Codec2Client::Component::OutputBufferQueue :
- hardware::media::c2::V1_1::utils::OutputBufferQueue {
+ hardware::media::c2::OutputBufferQueue {
OutputBufferQueue()
- : hardware::media::c2::V1_1::utils::OutputBufferQueue() {
+ : hardware::media::c2::OutputBufferQueue() {
}
};
@@ -1492,22 +1493,29 @@
igbp = new B2HGraphicBufferProducer2(surface);
}
+ std::shared_ptr<SurfaceSyncObj> syncObj;
+
if (!surface) {
- mOutputBufferQueue->configure(nullIgbp, generation, 0);
+ mOutputBufferQueue->configure(nullIgbp, generation, 0, nullptr);
} else if (surface->getUniqueId(&bqId) != OK) {
LOG(ERROR) << "setOutputSurface -- "
"cannot obtain bufferqueue id.";
bqId = 0;
- mOutputBufferQueue->configure(nullIgbp, generation, 0);
+ mOutputBufferQueue->configure(nullIgbp, generation, 0, nullptr);
} else {
- mOutputBufferQueue->configure(surface, generation, bqId);
+ mOutputBufferQueue->configure(surface, generation, bqId,
+ mBase1_2 ? &syncObj : nullptr);
}
- ALOGD("generation remote change %u", generation);
+ ALOGD("surface generation remote change %u HAL ver: %s",
+ generation, syncObj ? "1.2" : "1.0");
- (void)mBase1_2;
- Return<Status> transStatus = mBase1_0->setOutputSurface(
- static_cast<uint64_t>(blockPoolId),
- bqId == 0 ? nullHgbp : igbp);
+ Return<Status> transStatus = syncObj ?
+ mBase1_2->setOutputSurfaceWithSyncObj(
+ static_cast<uint64_t>(blockPoolId),
+ bqId == 0 ? nullHgbp : igbp, *syncObj) :
+ mBase1_0->setOutputSurface(
+ static_cast<uint64_t>(blockPoolId),
+ bqId == 0 ? nullHgbp : igbp);
if (!transStatus.isOk()) {
LOG(ERROR) << "setOutputSurface -- transaction failed.";
return C2_TRANSACTION_FAILED;
@@ -1517,6 +1525,7 @@
if (status != C2_OK) {
LOG(DEBUG) << "setOutputSurface -- call failed: " << status << ".";
}
+ ALOGD("Surface configure completed");
return status;
}
@@ -1527,6 +1536,11 @@
return mOutputBufferQueue->outputBuffer(block, input, output);
}
+void Codec2Client::Component::setOutputSurfaceMaxDequeueCount(
+ int maxDequeueCount) {
+ mOutputBufferQueue->updateMaxDequeueBufferCount(maxDequeueCount);
+}
+
c2_status_t Codec2Client::Component::connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
std::shared_ptr<InputSurfaceConnection>* connection) {
diff --git a/media/codec2/hidl/client/include/codec2/hidl/client.h b/media/codec2/hidl/client/include/codec2/hidl/client.h
index b574829..eca268e 100644
--- a/media/codec2/hidl/client/include/codec2/hidl/client.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/client.h
@@ -407,6 +407,9 @@
const QueueBufferInput& input,
QueueBufferOutput* output);
+ // Set max dequeue count for output surface.
+ void setOutputSurfaceMaxDequeueCount(int maxDequeueCount);
+
// Connect to a given InputSurface.
c2_status_t connectToInputSurface(
const std::shared_ptr<InputSurface>& inputSurface,
diff --git a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h b/media/codec2/hidl/client/include/codec2/hidl/output.h
similarity index 83%
rename from media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h
rename to media/codec2/hidl/client/include/codec2/hidl/output.h
index 80368f7..0f03b36 100644
--- a/media/codec2/hidl/1.0/utils/include/codec2/hidl/1.0/OutputBufferQueue.h
+++ b/media/codec2/hidl/client/include/codec2/hidl/output.h
@@ -19,16 +19,17 @@
#include <gui/IGraphicBufferProducer.h>
#include <codec2/hidl/1.0/types.h>
+#include <codec2/hidl/1.2/types.h>
#include <C2Work.h>
struct C2_HIDE _C2BlockPoolData;
+class C2SurfaceSyncMemory;
namespace android {
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
-namespace utils {
+
// BufferQueue-Based Block Operations
// ==================================
@@ -45,7 +46,8 @@
// Graphic blocks from older surface will be migrated to new surface.
bool configure(const sp<IGraphicBufferProducer>& igbp,
uint32_t generation,
- uint64_t bqId);
+ uint64_t bqId,
+ std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj);
// Render a graphic block to current surface.
status_t outputBuffer(
@@ -61,22 +63,27 @@
void holdBufferQueueBlocks(
const std::list<std::unique_ptr<C2Work>>& workList);
+ // Update # of max dequeue buffer from BQ. If # of max dequeued buffer is shared
+ // via shared memory between HAL and framework, Update # of max dequeued buffer
+ // and synchronize.
+ void updateMaxDequeueBufferCount(int maxDequeueBufferCount);
+
private:
std::mutex mMutex;
sp<IGraphicBufferProducer> mIgbp;
uint32_t mGeneration;
uint64_t mBqId;
+ int32_t mMaxDequeueBufferCount;
std::shared_ptr<int> mOwner;
// To migrate existing buffers
sp<GraphicBuffer> mBuffers[BufferQueueDefs::NUM_BUFFER_SLOTS]; // find a better way
std::weak_ptr<_C2BlockPoolData> mPoolDatas[BufferQueueDefs::NUM_BUFFER_SLOTS];
+ std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
bool registerBuffer(const C2ConstGraphicBlock& block);
};
-} // namespace utils
-} // namespace V1_0
} // namespace c2
} // namespace media
} // namespace hardware
diff --git a/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp b/media/codec2/hidl/client/output.cpp
similarity index 71%
rename from media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
rename to media/codec2/hidl/client/output.cpp
index 2b235f2..7df0da2 100644
--- a/media/codec2/hidl/1.0/utils/OutputBufferQueue.cpp
+++ b/media/codec2/hidl/client/output.cpp
@@ -19,13 +19,16 @@
#include <android-base/logging.h>
#include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
-#include <codec2/hidl/1.0/OutputBufferQueue.h>
+#include <codec2/hidl/output.h>
+#include <cutils/ashmem.h>
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
+#include <sys/mman.h>
#include <C2AllocatorGralloc.h>
#include <C2BlockInternal.h>
#include <C2Buffer.h>
#include <C2PlatformSupport.h>
+#include <C2SurfaceSyncObj.h>
#include <iomanip>
@@ -33,8 +36,6 @@
namespace hardware {
namespace media {
namespace c2 {
-namespace V1_0 {
-namespace utils {
using HGraphicBufferProducer = ::android::hardware::graphics::bufferqueue::
V2_0::IGraphicBufferProducer;
@@ -105,7 +106,8 @@
status_t attachToBufferQueue(const C2ConstGraphicBlock& block,
const sp<IGraphicBufferProducer>& igbp,
uint32_t generation,
- int32_t* bqSlot) {
+ int32_t* bqSlot,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
if (!igbp) {
LOG(WARNING) << "attachToBufferQueue -- null producer.";
return NO_INIT;
@@ -126,7 +128,25 @@
<< ", stride " << graphicBuffer->getStride()
<< ", generation " << graphicBuffer->getGenerationNumber();
- status_t result = igbp->attachBuffer(bqSlot, graphicBuffer);
+ C2SyncVariables *syncVar = syncMem ? syncMem->mem() : nullptr;
+ status_t result = OK;
+ if (syncVar) {
+ syncVar->lock();
+ if (!syncVar->isDequeueableLocked() ||
+ syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_SWITCHING) {
+ syncVar->unlock();
+ LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: "
+ "status = " << INVALID_OPERATION << ".";
+ return INVALID_OPERATION;
+ }
+ result = igbp->attachBuffer(bqSlot, graphicBuffer);
+ if (result == OK) {
+ syncVar->notifyDequeuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ result = igbp->attachBuffer(bqSlot, graphicBuffer);
+ }
if (result != OK) {
LOG(WARNING) << "attachToBufferQueue -- attachBuffer failed: "
"status = " << result << ".";
@@ -157,12 +177,40 @@
bool OutputBufferQueue::configure(const sp<IGraphicBufferProducer>& igbp,
uint32_t generation,
- uint64_t bqId) {
+ uint64_t bqId,
+ std::shared_ptr<V1_2::SurfaceSyncObj> *syncObj) {
uint64_t consumerUsage = 0;
if (igbp->getConsumerUsage(&consumerUsage) != OK) {
ALOGW("failed to get consumer usage");
}
+ // TODO : Abstract creation process into C2SurfaceSyncMemory class.
+ // use C2LinearBlock instead ashmem.
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem;
+ if (syncObj && igbp) {
+ bool mapped = false;
+ int memFd = ashmem_create_region("C2SurfaceMem", sizeof(C2SyncVariables));
+ size_t memSize = memFd < 0 ? 0 : ashmem_get_size_region(memFd);
+ if (memSize > 0) {
+ syncMem = C2SurfaceSyncMemory::Create(memFd, memSize);
+ if (syncMem) {
+ mapped = true;
+ *syncObj = std::make_shared<V1_2::SurfaceSyncObj>();
+ (*syncObj)->syncMemory = syncMem->handle();
+ (*syncObj)->bqId = bqId;
+ (*syncObj)->generationId = generation;
+ (*syncObj)->consumerUsage = consumerUsage;
+ ALOGD("C2SurfaceSyncMemory created %zu(%zu)", sizeof(C2SyncVariables), memSize);
+ }
+ }
+ if (!mapped) {
+ if (memFd >= 0) {
+ ::close(memFd);
+ }
+ ALOGW("SurfaceSyncObj creation failure");
+ }
+ }
+
size_t tryNum = 0;
size_t success = 0;
sp<GraphicBuffer> buffers[BufferQueueDefs::NUM_BUFFER_SLOTS];
@@ -173,6 +221,19 @@
if (generation == mGeneration) {
return false;
}
+ std::shared_ptr<C2SurfaceSyncMemory> oldMem = mSyncMem;
+ C2SyncVariables *oldSync = mSyncMem ? mSyncMem->mem() : nullptr;
+ if (oldSync) {
+ oldSync->lock();
+ oldSync->setSyncStatusLocked(C2SyncVariables::STATUS_SWITCHING);
+ oldSync->unlock();
+ }
+ mSyncMem.reset();
+ if (syncMem) {
+ mSyncMem = syncMem;
+ }
+ C2SyncVariables *newSync = mSyncMem ? mSyncMem->mem() : nullptr;
+
mIgbp = igbp;
mGeneration = generation;
mBqId = bqId;
@@ -212,7 +273,7 @@
}
bool attach =
_C2BlockFactory::EndAttachBlockToBufferQueue(
- data, mOwner, getHgbp(mIgbp),
+ data, mOwner, getHgbp(mIgbp), mSyncMem,
generation, bqId, bqSlot);
if (!attach) {
igbp->cancelBuffer(bqSlot, Fence::NO_FENCE);
@@ -226,8 +287,12 @@
mBuffers[i] = buffers[i];
mPoolDatas[i] = poolDatas[i];
}
+ if (newSync) {
+ newSync->setInitialDequeueCount(mMaxDequeueBufferCount, success);
+ }
}
- ALOGD("remote graphic buffer migration %zu/%zu", success, tryNum);
+ ALOGD("remote graphic buffer migration %zu/%zu",
+ success, tryNum);
return true;
}
@@ -258,7 +323,7 @@
<< ", bqSlot " << oldSlot
<< ", generation " << mGeneration
<< ".";
- _C2BlockFactory::HoldBlockFromBufferQueue(data, mOwner, getHgbp(mIgbp));
+ _C2BlockFactory::HoldBlockFromBufferQueue(data, mOwner, getHgbp(mIgbp), mSyncMem);
mPoolDatas[oldSlot] = data;
mBuffers[oldSlot] = createGraphicBuffer(block);
mBuffers[oldSlot]->setGenerationNumber(mGeneration);
@@ -278,25 +343,39 @@
uint32_t generation;
uint64_t bqId;
int32_t bqSlot;
- bool display = displayBufferQueueBlock(block);
+ bool display = V1_0::utils::displayBufferQueueBlock(block);
if (!getBufferQueueAssignment(block, &generation, &bqId, &bqSlot) ||
bqId == 0) {
// Block not from bufferqueue -- it must be attached before queuing.
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem;
mMutex.lock();
sp<IGraphicBufferProducer> outputIgbp = mIgbp;
uint32_t outputGeneration = mGeneration;
+ syncMem = mSyncMem;
mMutex.unlock();
status_t status = attachToBufferQueue(
- block, outputIgbp, outputGeneration, &bqSlot);
+ block, outputIgbp, outputGeneration, &bqSlot, syncMem);
+
if (status != OK) {
LOG(WARNING) << "outputBuffer -- attaching failed.";
return INVALID_OPERATION;
}
- status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
- input, output);
+ auto syncVar = syncMem ? syncMem->mem() : nullptr;
+ if(syncVar) {
+ syncVar->lock();
+ status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+ input, output);
+ if (status == OK) {
+ syncVar->notifyQueuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+ input, output);
+ }
if (status != OK) {
LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
"on non-bufferqueue-based block. "
@@ -306,10 +385,12 @@
return OK;
}
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem;
mMutex.lock();
sp<IGraphicBufferProducer> outputIgbp = mIgbp;
uint32_t outputGeneration = mGeneration;
uint64_t outputBqId = mBqId;
+ syncMem = mSyncMem;
mMutex.unlock();
if (!outputIgbp) {
@@ -330,8 +411,21 @@
return DEAD_OBJECT;
}
- status_t status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
- input, output);
+ auto syncVar = syncMem ? syncMem->mem() : nullptr;
+ status_t status = OK;
+ if (syncVar) {
+ syncVar->lock();
+ status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+ input, output);
+ if (status == OK) {
+ syncVar->notifyQueuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ status = outputIgbp->queueBuffer(static_cast<int>(bqSlot),
+ input, output);
+ }
+
if (status != OK) {
LOG(ERROR) << "outputBuffer -- queueBuffer() failed "
"on bufferqueue-based block. "
@@ -348,8 +442,18 @@
this, std::placeholders::_1));
}
-} // namespace utils
-} // namespace V1_0
+void OutputBufferQueue::updateMaxDequeueBufferCount(int maxDequeueBufferCount) {
+ mMutex.lock();
+ mMaxDequeueBufferCount = maxDequeueBufferCount;
+ auto syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ syncVar->updateMaxDequeueCountLocked(maxDequeueBufferCount);
+ syncVar->unlock();
+ }
+ mMutex.unlock();
+}
+
} // namespace c2
} // namespace media
} // namespace hardware
diff --git a/media/codec2/sfplugin/CCodecBufferChannel.cpp b/media/codec2/sfplugin/CCodecBufferChannel.cpp
index 3f717c9..c4f9d84 100644
--- a/media/codec2/sfplugin/CCodecBufferChannel.cpp
+++ b/media/codec2/sfplugin/CCodecBufferChannel.cpp
@@ -1177,9 +1177,10 @@
if (outputFormat != nullptr) {
sp<IGraphicBufferProducer> outputSurface;
uint32_t outputGeneration;
+ int maxDequeueCount = 0;
{
Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = numOutputSlots +
+ maxDequeueCount = output->maxDequeueBuffers = numOutputSlots +
reorderDepth.value + kRenderingDepth;
outputSurface = output->surface ?
output->surface->getIGraphicBufferProducer() : nullptr;
@@ -1188,6 +1189,9 @@
}
outputGeneration = output->generation;
}
+ if (maxDequeueCount > 0) {
+ mComponent->setOutputSurfaceMaxDequeueCount(maxDequeueCount);
+ }
bool graphic = (oStreamFormat.value == C2BufferData::GRAPHIC);
C2BlockPool::local_id_t outputPoolId_;
@@ -1766,15 +1770,22 @@
if (needMaxDequeueBufferCountUpdate) {
size_t numOutputSlots = 0;
uint32_t reorderDepth = 0;
+ int maxDequeueCount = 0;
{
Mutexed<Output>::Locked output(mOutput);
numOutputSlots = output->numSlots;
reorderDepth = output->buffers->getReorderDepth();
}
- Mutexed<OutputSurface>::Locked output(mOutputSurface);
- output->maxDequeueBuffers = numOutputSlots + reorderDepth + kRenderingDepth;
- if (output->surface) {
- output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
+ {
+ Mutexed<OutputSurface>::Locked output(mOutputSurface);
+ maxDequeueCount = output->maxDequeueBuffers =
+ numOutputSlots + reorderDepth + kRenderingDepth;
+ if (output->surface) {
+ output->surface->setMaxDequeuedBufferCount(output->maxDequeueBuffers);
+ }
+ }
+ if (maxDequeueCount > 0) {
+ mComponent->setOutputSurfaceMaxDequeueCount(maxDequeueCount);
}
}
diff --git a/media/codec2/vndk/include/C2BqBufferPriv.h b/media/codec2/vndk/include/C2BqBufferPriv.h
index 066f1e1..b2636e9 100644
--- a/media/codec2/vndk/include/C2BqBufferPriv.h
+++ b/media/codec2/vndk/include/C2BqBufferPriv.h
@@ -49,6 +49,14 @@
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override;
+ virtual c2_status_t fetchGraphicBlock(
+ uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
+ C2Fence *fence /* nonnull */) override;
+
typedef std::function<void(uint64_t producer, int32_t slot, int64_t nsecs)> OnRenderCallback;
/**
@@ -72,6 +80,27 @@
*/
virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer);
+ /**
+ * Configures an IGBP in order to create blocks. A newly created block is
+ * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
+ * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
+ * When IGBP is not configured, block will be created via allocator.
+ * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
+ * is configured as nullptr, unique id which is bundled in native_handle is zero.
+ *
+ * \param producer the IGBP, which will be used to fetch blocks
+ * \param syncMemory Shared memory for synchronization of allocation & deallocation.
+ * \param bqId Id of IGBP
+ * \param generationId Generation Id for rendering output
+ * \param consumerUsage consumerUsage flagof the IGBP
+ */
+ virtual void configureProducer(
+ const android::sp<HGraphicBufferProducer> &producer,
+ native_handle_t *syncMemory,
+ uint64_t bqId,
+ uint32_t generationId,
+ uint64_t consumerUsage);
+
private:
const std::shared_ptr<C2Allocator> mAllocator;
const local_id_t mLocalId;
@@ -82,6 +111,7 @@
friend struct C2BufferQueueBlockPoolData;
};
+class C2SurfaceSyncMemory;
struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
public:
@@ -97,7 +127,8 @@
// Create a local BlockPoolData.
C2BufferQueueBlockPoolData(
uint32_t generation, uint64_t bqId, int32_t bqSlot,
- const android::sp<HGraphicBufferProducer>& producer);
+ const android::sp<HGraphicBufferProducer>& producer,
+ std::shared_ptr<C2SurfaceSyncMemory>, int noUse);
virtual ~C2BufferQueueBlockPoolData() override;
@@ -105,7 +136,8 @@
int migrate(const android::sp<HGraphicBufferProducer>& producer,
uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
- android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration);
+ android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem);
private:
friend struct _C2BlockFactory;
@@ -113,12 +145,14 @@
// Methods delegated from _C2BlockFactory.
void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const;
bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner,
- const android::sp<HGraphicBufferProducer>& igbp);
+ const android::sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem);
bool beginTransferBlockToClient();
bool endTransferBlockToClient(bool transfer);
bool beginAttachBlockToBufferQueue();
bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner,
const android::sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem,
uint32_t generation, uint64_t bqId, int32_t bqSlot);
bool displayBlockToBufferQueue();
@@ -141,6 +175,7 @@
bool mDisplay; // display on remote;
std::weak_ptr<int> mOwner;
android::sp<HGraphicBufferProducer> mIgbp;
+ std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
mutable std::mutex mLock;
};
diff --git a/media/codec2/vndk/internal/C2BlockInternal.h b/media/codec2/vndk/internal/C2BlockInternal.h
index 4ae946a..c510fca 100644
--- a/media/codec2/vndk/internal/C2BlockInternal.h
+++ b/media/codec2/vndk/internal/C2BlockInternal.h
@@ -52,6 +52,8 @@
struct C2BufferQueueBlockPoolData;
+class C2SurfaceSyncMemory;
+
/**
* Internal only interface for creating blocks by block pool/buffer passing implementations.
*
@@ -279,6 +281,8 @@
* anymore.
* \param igbp \c IGraphicBufferProducer instance to be assigned to the
* block. This is not needed when the block is local.
+ * \param syncMem Memory block which will support synchronization
+ * between Framework and HAL.
*
* \return The previous held status.
*/
@@ -287,7 +291,8 @@
const std::shared_ptr<_C2BlockPoolData>& poolData,
const std::shared_ptr<int>& owner,
const ::android::sp<::android::hardware::graphics::bufferqueue::
- V2_0::IGraphicBufferProducer>& igbp = nullptr);
+ V2_0::IGraphicBufferProducer>& igbp = nullptr,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem = nullptr);
/**
* Prepare a block to be transferred to other process. This blocks
@@ -358,6 +363,7 @@
const std::shared_ptr<int>& owner,
const ::android::sp<::android::hardware::graphics::bufferqueue::
V2_0::IGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory>,
uint32_t generation,
uint64_t bqId,
int32_t bqSlot);
diff --git a/media/codec2/vndk/platform/C2BqBuffer.cpp b/media/codec2/vndk/platform/C2BqBuffer.cpp
index 3f6fa7d..8b53b24 100644
--- a/media/codec2/vndk/platform/C2BqBuffer.cpp
+++ b/media/codec2/vndk/platform/C2BqBuffer.cpp
@@ -29,6 +29,8 @@
#include <C2AllocatorGralloc.h>
#include <C2BqBufferPriv.h>
#include <C2BlockInternal.h>
+#include <C2FenceFactory.h>
+#include <C2SurfaceSyncObj.h>
#include <list>
#include <map>
@@ -69,10 +71,11 @@
bool _C2BlockFactory::HoldBlockFromBufferQueue(
const std::shared_ptr<_C2BlockPoolData>& data,
const std::shared_ptr<int>& owner,
- const sp<HGraphicBufferProducer>& igbp) {
+ const sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- return poolData->holdBlockFromBufferQueue(owner, igbp);
+ return poolData->holdBlockFromBufferQueue(owner, igbp, syncMem);
}
bool _C2BlockFactory::BeginTransferBlockToClient(
@@ -102,12 +105,13 @@
const std::shared_ptr<_C2BlockPoolData>& data,
const std::shared_ptr<int>& owner,
const sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem,
uint32_t generation,
uint64_t bqId,
int32_t bqSlot) {
const std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::static_pointer_cast<C2BufferQueueBlockPoolData>(data);
- return poolData->endAttachBlockToBufferQueue(owner, igbp, generation, bqId, bqSlot);
+ return poolData->endAttachBlockToBufferQueue(owner, igbp, syncMem, generation, bqId, bqSlot);
}
bool _C2BlockFactory::DisplayBlockToBufferQueue(
@@ -231,12 +235,58 @@
class C2BufferQueueBlockPool::Impl
: public std::enable_shared_from_this<C2BufferQueueBlockPool::Impl> {
private:
+ c2_status_t dequeueBuffer(
+ uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ C2AndroidMemoryUsage androidUsage,
+ int *slot, bool *needsRealloc, sp<Fence> *fence) {
+ status_t status{};
+ using Input = HGraphicBufferProducer::DequeueBufferInput;
+ using Output = HGraphicBufferProducer::DequeueBufferOutput;
+ Return<void> transResult = mProducer->dequeueBuffer(
+ Input{
+ width,
+ height,
+ format,
+ androidUsage.asGrallocUsage()},
+ [&status, slot, needsRealloc,
+ fence](HStatus hStatus,
+ int32_t hSlot,
+ Output const& hOutput) {
+ *slot = static_cast<int>(hSlot);
+ if (!h2b(hStatus, &status) ||
+ !h2b(hOutput.fence, fence)) {
+ status = ::android::BAD_VALUE;
+ } else {
+ *needsRealloc =
+ hOutput.bufferNeedsReallocation;
+ }
+ });
+ if (!transResult.isOk() || status != android::OK) {
+ if (transResult.isOk()) {
+ ++mDqFailure;
+ if (status == android::INVALID_OPERATION ||
+ status == android::TIMED_OUT ||
+ status == android::WOULD_BLOCK) {
+ // Dequeue buffer is blocked temporarily. Retrying is
+ // required.
+ return C2_BLOCKING;
+ }
+ }
+ ALOGD("cannot dequeue buffer %d", status);
+ return C2_BAD_VALUE;
+ }
+ return C2_OK;
+ }
+
c2_status_t fetchFromIgbp_l(
uint32_t width,
uint32_t height,
uint32_t format,
C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
+ C2Fence *c2Fence) {
// We have an IGBP now.
C2AndroidMemoryUsage androidUsage = usage;
status_t status{};
@@ -245,41 +295,39 @@
sp<Fence> fence = new Fence();
ALOGV("tries to dequeue buffer");
+ C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem(): nullptr;
{ // Call dequeueBuffer().
- using Input = HGraphicBufferProducer::DequeueBufferInput;
- using Output = HGraphicBufferProducer::DequeueBufferOutput;
- Return<void> transResult = mProducer->dequeueBuffer(
- Input{
- width,
- height,
- format,
- androidUsage.asGrallocUsage()},
- [&status, &slot, &bufferNeedsReallocation,
- &fence](HStatus hStatus,
- int32_t hSlot,
- Output const& hOutput) {
- slot = static_cast<int>(hSlot);
- if (!h2b(hStatus, &status) ||
- !h2b(hOutput.fence, &fence)) {
- status = ::android::BAD_VALUE;
- } else {
- bufferNeedsReallocation =
- hOutput.bufferNeedsReallocation;
- }
- });
- if (!transResult.isOk() || status != android::OK) {
- if (transResult.isOk()) {
- ++mDqFailure;
- if (status == android::INVALID_OPERATION ||
- status == android::TIMED_OUT ||
- status == android::WOULD_BLOCK) {
- // Dequeue buffer is blocked temporarily. Retrying is
- // required.
- return C2_BLOCKING;
+ c2_status_t c2Status;
+ if (syncVar) {
+ uint32_t waitId;
+ syncVar->lock();
+ if (!syncVar->isDequeueableLocked(&waitId)) {
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
}
+ return C2_BLOCKING;
}
- ALOGD("cannot dequeue buffer %d", status);
- return C2_BAD_VALUE;
+ if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_ACTIVE) {
+ waitId = syncVar->getWaitIdLocked();
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
+ }
+ return C2_BLOCKING;
+ }
+ c2Status = dequeueBuffer(width, height, format, androidUsage,
+ &slot, &bufferNeedsReallocation, &fence);
+ if (c2Status == C2_OK) {
+ syncVar->notifyDequeuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ c2Status = dequeueBuffer(width, height, format, usage,
+ &slot, &bufferNeedsReallocation, &fence);
+ }
+ if (c2Status != C2_OK) {
+ return c2Status;
}
mDqFailure = 0;
mLastDqTs = getTimestampNow();
@@ -290,18 +338,41 @@
return C2_BAD_VALUE;
}
ALOGV("dequeued a buffer successfully");
+ bool dequeueable = false;
+ uint32_t waitId;
if (fence) {
static constexpr int kFenceWaitTimeMs = 10;
status_t status = fence->wait(kFenceWaitTimeMs);
if (status == -ETIME) {
// fence is not signalled yet.
- (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ if (syncVar) {
+ syncVar->lock();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ dequeueable = syncVar->notifyQueuedLocked(&waitId);
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = dequeueable ? C2Fence() :
+ _C2FenceFactory::CreateSurfaceFence(mSyncMem, waitId);
+ }
+ } else {
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ }
return C2_BLOCKING;
}
if (status != android::NO_ERROR) {
ALOGD("buffer fence wait error %d", status);
- (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ if (syncVar) {
+ syncVar->lock();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ syncVar->notifyQueuedLocked();
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = C2Fence();
+ }
+ } else {
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ }
return C2_BAD_VALUE;
} else if (mRenderCallback) {
nsecs_t signalTime = fence->getSignalTime();
@@ -341,7 +412,17 @@
return C2_BAD_VALUE;
} else if (status != android::NO_ERROR) {
slotBuffer.clear();
- (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ if (syncVar) {
+ syncVar->lock();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ syncVar->notifyQueuedLocked();
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = C2Fence();
+ }
+ } else {
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ }
return C2_BAD_VALUE;
}
if (mGeneration == 0) {
@@ -372,14 +453,28 @@
std::make_shared<C2BufferQueueBlockPoolData>(
slotBuffer->getGenerationNumber(),
mProducerId, slot,
- mProducer);
+ mProducer, mSyncMem, 0);
mPoolDatas[slot] = poolData;
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
return C2_OK;
}
// Block was not created. call requestBuffer# again next time.
slotBuffer.clear();
- (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ if (syncVar) {
+ syncVar->lock();
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ syncVar->notifyQueuedLocked();
+ syncVar->unlock();
+ if (c2Fence) {
+ *c2Fence = C2Fence();
+ }
+ } else {
+ (void)mProducer->cancelBuffer(slot, hFenceWrapper.getHandle()).isOk();
+ }
+ return C2_BAD_VALUE;
+ }
+ if (c2Fence) {
+ *c2Fence = C2Fence();
}
return C2_BAD_VALUE;
}
@@ -409,7 +504,8 @@
uint32_t height,
uint32_t format,
C2MemoryUsage usage,
- std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
+ C2Fence *fence) {
block->reset();
if (mInit != C2_OK) {
return mInit;
@@ -440,17 +536,19 @@
}
std::shared_ptr<C2BufferQueueBlockPoolData> poolData =
std::make_shared<C2BufferQueueBlockPoolData>(
- 0, (uint64_t)0, ~0, nullptr);
+ 0, (uint64_t)0, ~0, nullptr, nullptr, 0);
*block = _C2BlockFactory::CreateGraphicBlock(alloc, poolData);
ALOGV("allocated a buffer successfully");
return C2_OK;
}
- c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block);
+ c2_status_t status = fetchFromIgbp_l(width, height, format, usage, block, fence);
if (status == C2_BLOCKING) {
lock.unlock();
- // in order not to drain cpu from component's spinning
- ::usleep(kMaxIgbpRetryDelayUs);
+ if (!fence) {
+ // in order not to drain cpu from component's spinning
+ ::usleep(kMaxIgbpRetryDelayUs);
+ }
}
return status;
}
@@ -460,11 +558,12 @@
mRenderCallback = renderCallback;
}
+ /* This is for Old HAL request for compatibility */
void configureProducer(const sp<HGraphicBufferProducer> &producer) {
uint64_t producerId = 0;
uint32_t generation = 0;
uint64_t usage = 0;
- bool haveGeneration = false;
+ bool bqInformation = false;
if (producer) {
Return<uint64_t> transResult = producer->getUniqueId();
if (!transResult.isOk()) {
@@ -472,14 +571,32 @@
return;
}
producerId = static_cast<uint64_t>(transResult);
- // TODO: provide gneration number from parameter.
- haveGeneration = getGenerationNumberAndUsage(producer, &generation, &usage);
- if (!haveGeneration) {
+ bqInformation = getGenerationNumberAndUsage(producer, &generation, &usage);
+ if (!bqInformation) {
ALOGW("get generationNumber failed %llu",
(unsigned long long)producerId);
}
}
+ configureProducer(producer, nullptr, producerId, generation, usage, bqInformation);
+ }
+
+ void configureProducer(const sp<HGraphicBufferProducer> &producer,
+ native_handle_t *syncHandle,
+ uint64_t producerId,
+ uint32_t generation,
+ uint64_t usage,
+ bool bqInformation) {
+ std::shared_ptr<C2SurfaceSyncMemory> c2SyncMem;
+ if (syncHandle) {
+ if (!producer) {
+ native_handle_close(syncHandle);
+ native_handle_delete(syncHandle);
+ } else {
+ c2SyncMem = C2SurfaceSyncMemory::Import(syncHandle);
+ }
+ }
int migrated = 0;
+ std::shared_ptr<C2SurfaceSyncMemory> oldMem;
// poolDatas dtor should not be called during lock is held.
std::shared_ptr<C2BufferQueueBlockPoolData>
poolDatas[NUM_BUFFER_SLOTS];
@@ -499,22 +616,30 @@
if (producer) {
mProducer = producer;
mProducerId = producerId;
- mGeneration = haveGeneration ? generation : 0;
+ mGeneration = bqInformation ? generation : 0;
} else {
mProducer = nullptr;
mProducerId = 0;
mGeneration = 0;
ALOGW("invalid producer producer(%d), generation(%d)",
- (bool)producer, haveGeneration);
+ (bool)producer, bqInformation);
}
- if (mProducer && haveGeneration) { // migrate buffers
+ oldMem = mSyncMem; // preven destruction while locked.
+ mSyncMem = c2SyncMem;
+ C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ syncVar->setSyncStatusLocked(C2SyncVariables::STATUS_ACTIVE);
+ syncVar->unlock();
+ }
+ if (mProducer && bqInformation) { // migrate buffers
for (int i = 0; i < NUM_BUFFER_SLOTS; ++i) {
std::shared_ptr<C2BufferQueueBlockPoolData> data =
mPoolDatas[i].lock();
if (data) {
int slot = data->migrate(
mProducer, generation, usage,
- producerId, mBuffers[i], oldGeneration);
+ producerId, mBuffers[i], oldGeneration, mSyncMem);
if (slot >= 0) {
buffers[slot] = mBuffers[i];
poolDatas[slot] = data;
@@ -528,7 +653,7 @@
mPoolDatas[i] = poolDatas[i];
}
}
- if (producer && haveGeneration) {
+ if (producer && bqInformation) {
ALOGD("local generation change %u , "
"bqId: %llu migrated buffers # %d",
generation, (unsigned long long)producerId, migrated);
@@ -555,6 +680,8 @@
sp<GraphicBuffer> mBuffers[NUM_BUFFER_SLOTS];
std::weak_ptr<C2BufferQueueBlockPoolData> mPoolDatas[NUM_BUFFER_SLOTS];
+
+ std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
};
C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
@@ -570,11 +697,14 @@
C2BufferQueueBlockPoolData::C2BufferQueueBlockPoolData(
uint32_t generation, uint64_t bqId, int32_t bqSlot,
- const android::sp<HGraphicBufferProducer>& producer) :
+ const android::sp<HGraphicBufferProducer>& producer,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem, int noUse) :
mLocal(true), mHeld(true),
mGeneration(generation), mBqId(bqId), mBqSlot(bqSlot),
mCurrentGeneration(generation), mCurrentBqId(bqId),
- mTransfer(false), mAttach(false), mDisplay(false), mIgbp(producer) {
+ mTransfer(false), mAttach(false), mDisplay(false),
+ mIgbp(producer), mSyncMem(syncMem) {
+ (void)noUse;
}
C2BufferQueueBlockPoolData::~C2BufferQueueBlockPoolData() {
@@ -584,10 +714,30 @@
if (mLocal) {
if (mGeneration == mCurrentGeneration && mBqId == mCurrentBqId) {
- mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ if (syncVar->getSyncStatusLocked() == C2SyncVariables::STATUS_ACTIVE) {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ syncVar->notifyQueuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ }
}
} else if (!mOwner.expired()) {
- mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ C2SyncVariables *syncVar = mSyncMem ? mSyncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ if (syncVar->getSyncStatusLocked() != C2SyncVariables::STATUS_SWITCHING) {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ syncVar->notifyQueuedLocked();
+ }
+ syncVar->unlock();
+ } else {
+ mIgbp->cancelBuffer(mBqSlot, hidl_handle{}).isOk();
+ }
}
}
@@ -598,7 +748,8 @@
int C2BufferQueueBlockPoolData::migrate(
const sp<HGraphicBufferProducer>& producer,
uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
- sp<GraphicBuffer>& graphicBuffer, uint32_t oldGeneration) {
+ sp<GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
std::scoped_lock<std::mutex> l(mLock);
mCurrentBqId = toBqId;
@@ -678,6 +829,14 @@
mGeneration = toGeneration;
mBqId = toBqId;
mBqSlot = slot;
+ mSyncMem = syncMem;
+
+ C2SyncVariables *syncVar = syncMem ? syncMem->mem() : nullptr;
+ if (syncVar) {
+ syncVar->lock();
+ syncVar->notifyDequeuedLocked();
+ syncVar->unlock();
+ }
return slot;
}
@@ -697,11 +856,13 @@
bool C2BufferQueueBlockPoolData::holdBlockFromBufferQueue(
const std::shared_ptr<int>& owner,
- const sp<HGraphicBufferProducer>& igbp) {
+ const sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem) {
std::scoped_lock<std::mutex> lock(mLock);
if (!mLocal) {
mOwner = owner;
mIgbp = igbp;
+ mSyncMem = syncMem;
}
if (mHeld) {
return false;
@@ -741,6 +902,7 @@
bool C2BufferQueueBlockPoolData::endAttachBlockToBufferQueue(
const std::shared_ptr<int>& owner,
const sp<HGraphicBufferProducer>& igbp,
+ std::shared_ptr<C2SurfaceSyncMemory> syncMem,
uint32_t generation,
uint64_t bqId,
int32_t bqSlot) {
@@ -757,6 +919,7 @@
mHeld = true;
mOwner = owner;
mIgbp = igbp;
+ mSyncMem = syncMem;
mGeneration = generation;
mBqId = bqId;
mBqSlot = bqSlot;
@@ -792,7 +955,20 @@
C2MemoryUsage usage,
std::shared_ptr<C2GraphicBlock> *block /* nonnull */) {
if (mImpl) {
- return mImpl->fetchGraphicBlock(width, height, format, usage, block);
+ return mImpl->fetchGraphicBlock(width, height, format, usage, block, nullptr);
+ }
+ return C2_CORRUPTED;
+}
+
+c2_status_t C2BufferQueueBlockPool::fetchGraphicBlock(
+ uint32_t width,
+ uint32_t height,
+ uint32_t format,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
+ C2Fence *fence /* nonnull */) {
+ if (mImpl) {
+ return mImpl->fetchGraphicBlock(width, height, format, usage, block, fence);
}
return C2_CORRUPTED;
}
@@ -803,6 +979,18 @@
}
}
+void C2BufferQueueBlockPool::configureProducer(
+ const sp<HGraphicBufferProducer> &producer,
+ native_handle_t *syncMemory,
+ uint64_t bqId,
+ uint32_t generationId,
+ uint64_t consumerUsage) {
+ if (mImpl) {
+ mImpl->configureProducer(
+ producer, syncMemory, bqId, generationId, consumerUsage, true);
+ }
+}
+
void C2BufferQueueBlockPool::setRenderCallback(const OnRenderCallback &renderCallback) {
if (mImpl) {
mImpl->setRenderCallback(renderCallback);