1 // Copyright (C) 2020 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include <android/hardware/automotive/evs/1.1/IEvsEnumerator.h> 16 #include <android/hardware/automotive/evs/1.1/IEvsDisplay.h> 17 18 #include <android-base/logging.h> 19 #include "EvsDisplayManager.h" 20 21 #include "PixelFormatUtils.h" 22 #include "RenderDirectView.h" 23 24 namespace android { 25 namespace automotive { 26 namespace computepipe { 27 namespace runner { 28 namespace debug_display_manager { 29 namespace { 30 31 constexpr char kServiceName[] = "default"; 32 33 using android::hardware::automotive::evs::V1_1::IEvsEnumerator; 34 using android::hardware::automotive::evs::V1_1::IEvsDisplay; 35 using android::hardware::automotive::evs::V1_0::EvsResult; 36 using android::hardware::automotive::evs::V1_0::DisplayState; 37 using android::hardware::automotive::evs::V1_0::BufferDesc; 38 39 using android::automotive::evs::support::RenderDirectView; 40 getBufferDesc(const std::shared_ptr<MemHandle> & frame)41BufferDesc getBufferDesc(const std::shared_ptr<MemHandle>& frame) { 42 AHardwareBuffer_Desc hwDesc; 43 AHardwareBuffer_describe(frame->getHardwareBuffer(), &hwDesc); 44 45 BufferDesc buffer; 46 buffer.width = hwDesc.width; 47 buffer.height = hwDesc.height; 48 buffer.stride = hwDesc.stride; 49 buffer.pixelSize = numBytesPerPixel(static_cast<AHardwareBuffer_Format>(hwDesc.format)); 50 buffer.format = hwDesc.format; 51 buffer.usage = hwDesc.usage; 52 buffer.memHandle = AHardwareBuffer_getNativeHandle(frame->getHardwareBuffer()); 53 return buffer; 54 } 55 56 } // namespace 57 ~EvsDisplayManager()58EvsDisplayManager::~EvsDisplayManager() { 59 stopThread(); 60 } 61 setArgs(std::string displayManagerArgs)62Status EvsDisplayManager::setArgs(std::string displayManagerArgs) { 63 auto pos = displayManagerArgs.find(kDisplayId); 64 if (pos == std::string::npos) { 65 return Status::SUCCESS; 66 } 67 mDisplayId = std::stoi(displayManagerArgs.substr(pos + strlen(kDisplayId))); 68 mOverrideDisplayId = true; 69 return Status::SUCCESS; 70 } 71 stopThread()72void EvsDisplayManager::stopThread() { 73 { 74 std::lock_guard<std::mutex> lk(mLock); 75 mStopThread = true; 76 mWait.notify_one(); 77 } 78 if (mThread.joinable()) { 79 mThread.join(); 80 } 81 } 82 threadFn()83void EvsDisplayManager::threadFn() { 84 sp<IEvsEnumerator> evsEnumerator = IEvsEnumerator::getService(std::string() + kServiceName); 85 86 if (!mOverrideDisplayId) { 87 evsEnumerator->getDisplayIdList([this] (auto ids) { 88 this->mDisplayId = ids[ids.size() - 1]; 89 }); 90 } 91 92 android::sp <IEvsDisplay> evsDisplay = evsEnumerator->openDisplay_1_1(mDisplayId); 93 94 if (evsDisplay != nullptr) { 95 LOG(INFO) << "Computepipe runner opened debug display."; 96 } else { 97 mStopThread = true; 98 LOG(ERROR) << "EVS Display unavailable. Exiting thread."; 99 return; 100 } 101 102 RenderDirectView evsRenderer; 103 EvsResult result = evsDisplay->setDisplayState(DisplayState::VISIBLE_ON_NEXT_FRAME); 104 if (result != EvsResult::OK) { 105 mStopThread = true; 106 LOG(ERROR) << "Set display state returned error - " << static_cast<int>(result); 107 evsEnumerator->closeDisplay(evsDisplay); 108 return; 109 } 110 111 if (!evsRenderer.activate()) { 112 mStopThread = true; 113 LOG(ERROR) << "Unable to activate evs renderer."; 114 evsEnumerator->closeDisplay(evsDisplay); 115 return; 116 } 117 118 std::unique_lock<std::mutex> lk(mLock); 119 while (true) { 120 mWait.wait(lk, [this]() { return mNextFrame != nullptr || mStopThread; }); 121 122 if (mStopThread) { 123 // Free unused frame. 124 if (mFreePacketCallback && mNextFrame) { 125 mFreePacketCallback(mNextFrame->getBufferId()); 126 } 127 break; 128 } 129 130 BufferDesc tgtBuffer = {}; 131 evsDisplay->getTargetBuffer([&tgtBuffer](const BufferDesc& buff) { 132 tgtBuffer = buff; 133 } 134 ); 135 136 BufferDesc srcBuffer = getBufferDesc(mNextFrame); 137 if (!evsRenderer.drawFrame(tgtBuffer, srcBuffer)) { 138 LOG(ERROR) << "Error in rendering a frame."; 139 mStopThread = true; 140 } 141 142 evsDisplay->returnTargetBufferForDisplay(tgtBuffer); 143 if (mFreePacketCallback) { 144 mFreePacketCallback(mNextFrame->getBufferId()); 145 } 146 mNextFrame = nullptr; 147 } 148 149 LOG(INFO) << "Computepipe runner closing debug display."; 150 evsRenderer.deactivate(); 151 (void)evsDisplay->setDisplayState(DisplayState::NOT_VISIBLE); 152 evsEnumerator->closeDisplay(evsDisplay); 153 } 154 setFreePacketCallback(std::function<Status (int bufferId)> freePacketCallback)155void EvsDisplayManager::setFreePacketCallback( 156 std::function<Status(int bufferId)> freePacketCallback) { 157 std::lock_guard<std::mutex> lk(mLock); 158 mFreePacketCallback = freePacketCallback; 159 } 160 displayFrame(const std::shared_ptr<MemHandle> & dataHandle)161Status EvsDisplayManager::displayFrame(const std::shared_ptr<MemHandle>& dataHandle) { 162 std::lock_guard<std::mutex> lk(mLock); 163 Status status = Status::SUCCESS; 164 if (mStopThread) { 165 return Status::ILLEGAL_STATE; 166 } 167 if (mNextFrame != nullptr && mFreePacketCallback) { 168 status = mFreePacketCallback(mNextFrame->getBufferId()); 169 } 170 mNextFrame = dataHandle; 171 mWait.notify_one(); 172 return status; 173 } 174 handleExecutionPhase(const RunnerEvent & e)175Status EvsDisplayManager::handleExecutionPhase(const RunnerEvent& e) { 176 if (e.isPhaseEntry()) { 177 std::lock_guard<std::mutex> lk(mLock); 178 mStopThread = false; 179 mThread = std::thread(&EvsDisplayManager::threadFn, this); 180 } else if (e.isAborted()) { 181 stopThread(); 182 } 183 return Status::SUCCESS; 184 } 185 handleStopWithFlushPhase(const RunnerEvent &)186Status EvsDisplayManager::handleStopWithFlushPhase(const RunnerEvent& /* e */) { 187 stopThread(); 188 return Status::SUCCESS; 189 } 190 handleStopImmediatePhase(const RunnerEvent &)191Status EvsDisplayManager::handleStopImmediatePhase(const RunnerEvent& /* e */) { 192 stopThread(); 193 return Status::SUCCESS; 194 } 195 handleResetPhase(const RunnerEvent &)196Status EvsDisplayManager::handleResetPhase(const RunnerEvent& /* e */) { 197 stopThread(); 198 return Status::SUCCESS; 199 } 200 201 } // namespace debug_display_manager 202 } // namespace runner 203 } // namespace computepipe 204 } // namespace automotive 205 } // namespace android 206