206 lines
6.3 KiB
C++
206 lines
6.3 KiB
C++
// Copyright (C) 2020 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 <android/hardware/automotive/evs/1.1/IEvsEnumerator.h>
|
|
#include <android/hardware/automotive/evs/1.1/IEvsDisplay.h>
|
|
|
|
#include <android-base/logging.h>
|
|
#include "EvsDisplayManager.h"
|
|
|
|
#include "PixelFormatUtils.h"
|
|
#include "RenderDirectView.h"
|
|
|
|
namespace android {
|
|
namespace automotive {
|
|
namespace computepipe {
|
|
namespace runner {
|
|
namespace debug_display_manager {
|
|
namespace {
|
|
|
|
constexpr char kServiceName[] = "default";
|
|
|
|
using android::hardware::automotive::evs::V1_1::IEvsEnumerator;
|
|
using android::hardware::automotive::evs::V1_1::IEvsDisplay;
|
|
using android::hardware::automotive::evs::V1_0::EvsResult;
|
|
using android::hardware::automotive::evs::V1_0::DisplayState;
|
|
using android::hardware::automotive::evs::V1_0::BufferDesc;
|
|
|
|
using android::automotive::evs::support::RenderDirectView;
|
|
|
|
BufferDesc getBufferDesc(const std::shared_ptr<MemHandle>& frame) {
|
|
AHardwareBuffer_Desc hwDesc;
|
|
AHardwareBuffer_describe(frame->getHardwareBuffer(), &hwDesc);
|
|
|
|
BufferDesc buffer;
|
|
buffer.width = hwDesc.width;
|
|
buffer.height = hwDesc.height;
|
|
buffer.stride = hwDesc.stride;
|
|
buffer.pixelSize = numBytesPerPixel(static_cast<AHardwareBuffer_Format>(hwDesc.format));
|
|
buffer.format = hwDesc.format;
|
|
buffer.usage = hwDesc.usage;
|
|
buffer.memHandle = AHardwareBuffer_getNativeHandle(frame->getHardwareBuffer());
|
|
return buffer;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
EvsDisplayManager::~EvsDisplayManager() {
|
|
stopThread();
|
|
}
|
|
|
|
Status EvsDisplayManager::setArgs(std::string displayManagerArgs) {
|
|
auto pos = displayManagerArgs.find(kDisplayId);
|
|
if (pos == std::string::npos) {
|
|
return Status::SUCCESS;
|
|
}
|
|
mDisplayId = std::stoi(displayManagerArgs.substr(pos + strlen(kDisplayId)));
|
|
mOverrideDisplayId = true;
|
|
return Status::SUCCESS;
|
|
}
|
|
|
|
void EvsDisplayManager::stopThread() {
|
|
{
|
|
std::lock_guard<std::mutex> lk(mLock);
|
|
mStopThread = true;
|
|
mWait.notify_one();
|
|
}
|
|
if (mThread.joinable()) {
|
|
mThread.join();
|
|
}
|
|
}
|
|
|
|
void EvsDisplayManager::threadFn() {
|
|
sp<IEvsEnumerator> evsEnumerator = IEvsEnumerator::getService(std::string() + kServiceName);
|
|
|
|
if (!mOverrideDisplayId) {
|
|
evsEnumerator->getDisplayIdList([this] (auto ids) {
|
|
this->mDisplayId = ids[ids.size() - 1];
|
|
});
|
|
}
|
|
|
|
android::sp <IEvsDisplay> evsDisplay = evsEnumerator->openDisplay_1_1(mDisplayId);
|
|
|
|
if (evsDisplay != nullptr) {
|
|
LOG(INFO) << "Computepipe runner opened debug display.";
|
|
} else {
|
|
mStopThread = true;
|
|
LOG(ERROR) << "EVS Display unavailable. Exiting thread.";
|
|
return;
|
|
}
|
|
|
|
RenderDirectView evsRenderer;
|
|
EvsResult result = evsDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME);
|
|
if (result != EvsResult::OK) {
|
|
mStopThread = true;
|
|
LOG(ERROR) << "Set display state returned error - " << static_cast<int>(result);
|
|
evsEnumerator->closeDisplay(evsDisplay);
|
|
return;
|
|
}
|
|
|
|
if (!evsRenderer.activate()) {
|
|
mStopThread = true;
|
|
LOG(ERROR) << "Unable to activate evs renderer.";
|
|
evsEnumerator->closeDisplay(evsDisplay);
|
|
return;
|
|
}
|
|
|
|
std::unique_lock<std::mutex> lk(mLock);
|
|
while (true) {
|
|
mWait.wait(lk, [this]() { return mNextFrame != nullptr || mStopThread; });
|
|
|
|
if (mStopThread) {
|
|
// Free unused frame.
|
|
if (mFreePacketCallback && mNextFrame) {
|
|
mFreePacketCallback(mNextFrame->getBufferId());
|
|
}
|
|
break;
|
|
}
|
|
|
|
BufferDesc tgtBuffer = {};
|
|
evsDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) {
|
|
tgtBuffer = buff;
|
|
}
|
|
);
|
|
|
|
BufferDesc srcBuffer = getBufferDesc(mNextFrame);
|
|
if (!evsRenderer.drawFrame(tgtBuffer, srcBuffer)) {
|
|
LOG(ERROR) << "Error in rendering a frame.";
|
|
mStopThread = true;
|
|
}
|
|
|
|
evsDisplay->returnTargetBufferForDisplay(tgtBuffer);
|
|
if (mFreePacketCallback) {
|
|
mFreePacketCallback(mNextFrame->getBufferId());
|
|
}
|
|
mNextFrame = nullptr;
|
|
}
|
|
|
|
LOG(INFO) << "Computepipe runner closing debug display.";
|
|
evsRenderer.deactivate();
|
|
(void)evsDisplay->setDisplayState(DisplayState::NOT_VISIBLE);
|
|
evsEnumerator->closeDisplay(evsDisplay);
|
|
}
|
|
|
|
void EvsDisplayManager::setFreePacketCallback(
|
|
std::function<Status(int bufferId)> freePacketCallback) {
|
|
std::lock_guard<std::mutex> lk(mLock);
|
|
mFreePacketCallback = freePacketCallback;
|
|
}
|
|
|
|
Status EvsDisplayManager::displayFrame(const std::shared_ptr<MemHandle>& dataHandle) {
|
|
std::lock_guard<std::mutex> lk(mLock);
|
|
Status status = Status::SUCCESS;
|
|
if (mStopThread) {
|
|
return Status::ILLEGAL_STATE;
|
|
}
|
|
if (mNextFrame != nullptr && mFreePacketCallback) {
|
|
status = mFreePacketCallback(mNextFrame->getBufferId());
|
|
}
|
|
mNextFrame = dataHandle;
|
|
mWait.notify_one();
|
|
return status;
|
|
}
|
|
|
|
Status EvsDisplayManager::handleExecutionPhase(const RunnerEvent& e) {
|
|
if (e.isPhaseEntry()) {
|
|
std::lock_guard<std::mutex> lk(mLock);
|
|
mStopThread = false;
|
|
mThread = std::thread(&EvsDisplayManager::threadFn, this);
|
|
} else if (e.isAborted()) {
|
|
stopThread();
|
|
}
|
|
return Status::SUCCESS;
|
|
}
|
|
|
|
Status EvsDisplayManager::handleStopWithFlushPhase(const RunnerEvent& /* e */) {
|
|
stopThread();
|
|
return Status::SUCCESS;
|
|
}
|
|
|
|
Status EvsDisplayManager::handleStopImmediatePhase(const RunnerEvent& /* e */) {
|
|
stopThread();
|
|
return Status::SUCCESS;
|
|
}
|
|
|
|
Status EvsDisplayManager::handleResetPhase(const RunnerEvent& /* e */) {
|
|
stopThread();
|
|
return Status::SUCCESS;
|
|
}
|
|
|
|
} // namespace debug_display_manager
|
|
} // namespace runner
|
|
} // namespace computepipe
|
|
} // namespace automotive
|
|
} // namespace android
|