blob: c76d771262548a3a18b116252794ac1cb869a0d7 [file] [log] [blame]
/*
* 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} {
}
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 */
0 /* scalingMode = NATIVE_WINDOW_SCALING_MODE_FREEZE */,
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 {};
}
} // namespace utils
} // namespace V2_0
} // namespace bufferqueue
} // namespace graphics
} // namespace hardware
} // namespace android