You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
390 lines
12 KiB
390 lines
12 KiB
/*
|
|
* 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.
|
|
*/
|
|
|
|
//#define LOG_NDEBUG 0
|
|
#define LOG_TAG "B2HGraphicBufferProducer@2.0"
|
|
|
|
#include <android-base/logging.h>
|
|
|
|
#include <android/hardware/graphics/bufferqueue/2.0/types.h>
|
|
#include <android/hardware/graphics/common/1.2/types.h>
|
|
#include <gui/bufferqueue/2.0/H2BProducerListener.h>
|
|
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
|
|
#include <gui/bufferqueue/2.0/types.h>
|
|
#include <ui/GraphicBuffer.h>
|
|
#include <ui/Rect.h>
|
|
#include <ui/Region.h>
|
|
#include <vndk/hardware_buffer.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace graphics {
|
|
namespace bufferqueue {
|
|
namespace V2_0 {
|
|
namespace utils {
|
|
|
|
namespace /* unnamed */ {
|
|
|
|
using BQueueBufferInput = ::android::
|
|
IGraphicBufferProducer::QueueBufferInput;
|
|
using HQueueBufferInput = ::android::hardware::graphics::bufferqueue::V2_0::
|
|
IGraphicBufferProducer::QueueBufferInput;
|
|
using BQueueBufferOutput = ::android::
|
|
IGraphicBufferProducer::QueueBufferOutput;
|
|
using HQueueBufferOutput = ::android::hardware::graphics::bufferqueue::V2_0::
|
|
IGraphicBufferProducer::QueueBufferOutput;
|
|
|
|
using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
|
|
using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
|
|
|
|
bool b2h(BQueueBufferOutput const& from, HQueueBufferOutput* to) {
|
|
to->width = from.width;
|
|
to->height = from.height;
|
|
to->transformHint = static_cast<int32_t>(from.transformHint);
|
|
to->numPendingBuffers = from.numPendingBuffers;
|
|
to->nextFrameNumber = from.nextFrameNumber;
|
|
to->bufferReplaced = from.bufferReplaced;
|
|
return true;
|
|
}
|
|
|
|
} // unnamed namespace
|
|
|
|
// B2HGraphicBufferProducer
|
|
// ========================
|
|
|
|
B2HGraphicBufferProducer::B2HGraphicBufferProducer(
|
|
sp<BGraphicBufferProducer> const& base)
|
|
: mBase{base},
|
|
// HUANGLONG begin
|
|
// Support set scaling mode when queuebuffer at the vendor side
|
|
// such as nxplayer output buffer to fb
|
|
scalingMode(0) /* NATIVE_WINDOW_SCALING_MODE_FREEZE */
|
|
// HUANGLONG end
|
|
{
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::setMaxDequeuedBufferCount(
|
|
int32_t maxDequeuedBuffers) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(
|
|
mBase->setMaxDequeuedBufferCount(
|
|
static_cast<int>(maxDequeuedBuffers)),
|
|
&hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::requestBuffer(
|
|
int32_t slot,
|
|
requestBuffer_cb _hidl_cb) {
|
|
sp<GraphicBuffer> bBuffer;
|
|
HStatus hStatus{};
|
|
HardwareBuffer hBuffer{};
|
|
uint32_t hGenerationNumber{};
|
|
bool converted =
|
|
b2h(mBase->requestBuffer(
|
|
static_cast<int>(slot), &bBuffer),
|
|
&hStatus) &&
|
|
b2h(bBuffer, &hBuffer, &hGenerationNumber);
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
|
|
hBuffer, hGenerationNumber);
|
|
return {};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::setAsyncMode(bool async) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(mBase->setAsyncMode(async), &hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::dequeueBuffer(
|
|
DequeueBufferInput const& input,
|
|
dequeueBuffer_cb _hidl_cb) {
|
|
int bSlot{};
|
|
sp<BFence> bFence;
|
|
HStatus hStatus{};
|
|
DequeueBufferOutput hOutput{};
|
|
HFenceWrapper hFenceWrapper;
|
|
bool converted =
|
|
b2h(mBase->dequeueBuffer(
|
|
&bSlot,
|
|
&bFence,
|
|
input.width,
|
|
input.height,
|
|
static_cast<PixelFormat>(input.format),
|
|
input.usage,
|
|
&hOutput.bufferAge,
|
|
nullptr /* outTimestamps */),
|
|
&hStatus,
|
|
&hOutput.bufferNeedsReallocation,
|
|
&hOutput.releaseAllBuffers) &&
|
|
b2h(bFence, &hFenceWrapper);
|
|
hOutput.fence = hFenceWrapper.getHandle();
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
|
|
static_cast<int32_t>(bSlot),
|
|
hOutput);
|
|
return {};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::detachBuffer(int32_t slot) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(
|
|
mBase->detachBuffer(static_cast<int>(slot)), &hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::detachNextBuffer(
|
|
detachNextBuffer_cb _hidl_cb) {
|
|
sp<GraphicBuffer> bBuffer;
|
|
sp<BFence> bFence;
|
|
HStatus hStatus{};
|
|
HardwareBuffer hBuffer{};
|
|
HFenceWrapper hFenceWrapper;
|
|
bool converted =
|
|
b2h(mBase->detachNextBuffer(&bBuffer, &bFence), &hStatus) &&
|
|
b2h(bBuffer, &hBuffer) &&
|
|
b2h(bFence, &hFenceWrapper);
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
|
|
hBuffer,
|
|
hFenceWrapper.getHandle());
|
|
return {};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::attachBuffer(
|
|
HardwareBuffer const& hBuffer,
|
|
uint32_t generationNumber,
|
|
attachBuffer_cb _hidl_cb) {
|
|
sp<GraphicBuffer> bBuffer;
|
|
if (!h2b(hBuffer, &bBuffer) || !bBuffer) {
|
|
_hidl_cb(HStatus::UNKNOWN_ERROR,
|
|
static_cast<int32_t>(SlotIndex::INVALID),
|
|
false);
|
|
return {};
|
|
}
|
|
bBuffer->setGenerationNumber(generationNumber);
|
|
|
|
int bSlot{};
|
|
HStatus hStatus{};
|
|
bool releaseAllBuffers{};
|
|
bool converted = b2h(
|
|
mBase->attachBuffer(&bSlot, bBuffer), &hStatus,
|
|
nullptr /* bufferNeedsReallocation */,
|
|
&releaseAllBuffers);
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR,
|
|
static_cast<int32_t>(bSlot),
|
|
releaseAllBuffers);
|
|
return {};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::queueBuffer(
|
|
int32_t slot,
|
|
QueueBufferInput const& hInput,
|
|
queueBuffer_cb _hidl_cb) {
|
|
BQueueBufferInput bInput{
|
|
hInput.timestamp,
|
|
hInput.isAutoTimestamp,
|
|
static_cast<android_dataspace>(hInput.dataSpace),
|
|
{}, /* crop */
|
|
// HUANGLONG begin
|
|
// Support set scaling mode when queuebuffer at the vendor side
|
|
// such as nxplayer output buffer to fb
|
|
scalingMode,
|
|
// HUANGLONG end
|
|
static_cast<uint32_t>(hInput.transform),
|
|
{}, /* fence */
|
|
static_cast<uint32_t>(hInput.stickyTransform),
|
|
false /* getFrameTimestamps */};
|
|
|
|
// Convert crop.
|
|
if (!h2b(hInput.crop, &bInput.crop)) {
|
|
_hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
|
|
return {};
|
|
}
|
|
|
|
// Convert surfaceDamage.
|
|
if (!h2b(hInput.surfaceDamage, &bInput.surfaceDamage)) {
|
|
_hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
|
|
return {};
|
|
}
|
|
|
|
// Convert fence.
|
|
if (!h2b(hInput.fence, &bInput.fence)) {
|
|
_hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
|
|
return {};
|
|
}
|
|
|
|
BQueueBufferOutput bOutput{};
|
|
HStatus hStatus{};
|
|
QueueBufferOutput hOutput{};
|
|
bool converted =
|
|
b2h(
|
|
mBase->queueBuffer(static_cast<int>(slot), bInput, &bOutput),
|
|
&hStatus) &&
|
|
b2h(bOutput, &hOutput);
|
|
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
|
|
return {};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::cancelBuffer(
|
|
int32_t slot,
|
|
hidl_handle const& fence) {
|
|
sp<BFence> bFence;
|
|
if (!h2b(fence.getNativeHandle(), &bFence)) {
|
|
return {HStatus::UNKNOWN_ERROR};
|
|
}
|
|
HStatus hStatus{};
|
|
bool converted = b2h(
|
|
mBase->cancelBuffer(static_cast<int>(slot), bFence),
|
|
&hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::query(int32_t what, query_cb _hidl_cb) {
|
|
int value{};
|
|
int result = mBase->query(static_cast<int>(what), &value);
|
|
_hidl_cb(static_cast<int32_t>(result), static_cast<int32_t>(value));
|
|
return {};
|
|
}
|
|
|
|
struct Obituary : public hardware::hidl_death_recipient {
|
|
wp<B2HGraphicBufferProducer> producer;
|
|
sp<HProducerListener> listener;
|
|
HConnectionType apiType;
|
|
Obituary(const wp<B2HGraphicBufferProducer>& p,
|
|
const sp<HProducerListener>& l,
|
|
HConnectionType t)
|
|
: producer(p), listener(l), apiType(t) {}
|
|
|
|
void serviceDied(uint64_t /* cookie */,
|
|
const wp<::android::hidl::base::V1_0::IBase>& /* who */) override {
|
|
sp<B2HGraphicBufferProducer> dr = producer.promote();
|
|
if (dr != nullptr) {
|
|
(void)dr->disconnect(apiType);
|
|
}
|
|
}
|
|
};
|
|
|
|
Return<void> B2HGraphicBufferProducer::connect(
|
|
sp<HProducerListener> const& hListener,
|
|
HConnectionType hConnectionType,
|
|
bool producerControlledByApp,
|
|
connect_cb _hidl_cb) {
|
|
sp<BProducerListener> bListener = new H2BProducerListener(hListener);
|
|
int bConnectionType{};
|
|
if (!bListener || !h2b(hConnectionType, &bConnectionType)) {
|
|
_hidl_cb(HStatus::UNKNOWN_ERROR, QueueBufferOutput{});
|
|
return {};
|
|
}
|
|
BQueueBufferOutput bOutput{};
|
|
HStatus hStatus{};
|
|
QueueBufferOutput hOutput{};
|
|
bool converted =
|
|
b2h(mBase->connect(bListener,
|
|
bConnectionType,
|
|
producerControlledByApp,
|
|
&bOutput),
|
|
&hStatus) &&
|
|
b2h(bOutput, &hOutput);
|
|
#ifdef NO_BINDER
|
|
if (converted && hListener != nullptr) {
|
|
mObituary = new Obituary(this, hListener, hConnectionType);
|
|
hListener->linkToDeath(mObituary, 0);
|
|
}
|
|
#endif // NO_BINDER
|
|
_hidl_cb(converted ? hStatus : HStatus::UNKNOWN_ERROR, hOutput);
|
|
return {};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::disconnect(
|
|
HConnectionType hConnectionType) {
|
|
int bConnectionType;
|
|
if (!h2b(hConnectionType, &bConnectionType)) {
|
|
return {HStatus::UNKNOWN_ERROR};
|
|
}
|
|
HStatus hStatus{};
|
|
bool converted = b2h(mBase->disconnect(bConnectionType), &hStatus);
|
|
#ifdef NO_BINDER
|
|
if (mObituary != nullptr) {
|
|
mObituary->listener->unlinkToDeath(mObituary);
|
|
mObituary.clear();
|
|
}
|
|
#endif // NO_BINDER
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::allocateBuffers(
|
|
uint32_t width, uint32_t height,
|
|
uint32_t format, uint64_t usage) {
|
|
mBase->allocateBuffers(
|
|
width, height, static_cast<PixelFormat>(format), usage);
|
|
return {HStatus::OK};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::allowAllocation(bool allow) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(mBase->allowAllocation(allow), &hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::setGenerationNumber(
|
|
uint32_t generationNumber) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(
|
|
mBase->setGenerationNumber(generationNumber),
|
|
&hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<HStatus> B2HGraphicBufferProducer::setDequeueTimeout(
|
|
int64_t timeoutNs) {
|
|
HStatus hStatus{};
|
|
bool converted = b2h(
|
|
mBase->setDequeueTimeout(static_cast<nsecs_t>(timeoutNs)),
|
|
&hStatus);
|
|
return {converted ? hStatus : HStatus::UNKNOWN_ERROR};
|
|
}
|
|
|
|
Return<uint64_t> B2HGraphicBufferProducer::getUniqueId() {
|
|
uint64_t outId{};
|
|
HStatus hStatus{};
|
|
bool converted = b2h(mBase->getUniqueId(&outId), &hStatus);
|
|
return {converted ? outId : 0};
|
|
}
|
|
|
|
Return<void> B2HGraphicBufferProducer::getConsumerName(
|
|
getConsumerName_cb _hidl_cb) {
|
|
_hidl_cb(hidl_string{mBase->getConsumerName().c_str()});
|
|
return {};
|
|
}
|
|
|
|
// HUANGLONG begin
|
|
// Support set scaling mode when queuebuffer at the vendor side
|
|
// such as nxplayer output buffer to fb
|
|
Return<void> B2HGraphicBufferProducer::setScalingMode(int mode)
|
|
{
|
|
scalingMode = mode;
|
|
return {};
|
|
}
|
|
// HUANGLONG end
|
|
|
|
} // namespace utils
|
|
} // namespace V2_0
|
|
} // namespace bufferqueue
|
|
} // namespace graphics
|
|
} // namespace hardware
|
|
} // namespace android
|
|
|