/* * Copyright (C) 2017 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 namespace android { namespace hardware { namespace graphics { namespace composer { namespace V2_1 { namespace vts { Composer::Composer(const sp& composer) : mComposer(composer) { // ASSERT_* can only be used in functions returning void. [this] { ASSERT_NE(nullptr, mComposer.get()) << "failed to get composer service"; std::vector capabilities = getCapabilities(); mCapabilities.insert(capabilities.begin(), capabilities.end()); }(); } sp Composer::getRaw() const { return mComposer; } bool Composer::hasCapability(IComposer::Capability capability) const { return mCapabilities.count(capability) > 0; } std::vector Composer::getCapabilities() { std::vector capabilities; mComposer->getCapabilities( [&](const auto& tmpCapabilities) { capabilities = tmpCapabilities; }); return capabilities; } std::string Composer::dumpDebugInfo() { std::string debugInfo; mComposer->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); }); return debugInfo; } std::unique_ptr Composer::createClient() { std::unique_ptr client; mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) { ASSERT_EQ(Error::NONE, tmpError) << "failed to create client"; client = std::make_unique(tmpClient); }); return client; } ComposerClient::ComposerClient(const sp& client) : mClient(client) {} ComposerClient::~ComposerClient() { for (const auto& it : mDisplayResources) { Display display = it.first; const DisplayResource& resource = it.second; for (auto layer : resource.layers) { EXPECT_EQ(Error::NONE, mClient->destroyLayer(display, layer)) << "failed to destroy layer " << layer; } if (resource.isVirtual) { EXPECT_EQ(Error::NONE, mClient->destroyVirtualDisplay(display)) << "failed to destroy virtual display " << display; } } mDisplayResources.clear(); } sp ComposerClient::getRaw() const { return mClient; } void ComposerClient::registerCallback(const sp& callback) { mClient->registerCallback(callback); } uint32_t ComposerClient::getMaxVirtualDisplayCount() { return mClient->getMaxVirtualDisplayCount(); } Display ComposerClient::createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount, PixelFormat* outFormat) { Display display = 0; mClient->createVirtualDisplay( width, height, formatHint, outputBufferSlotCount, [&](const auto& tmpError, const auto& tmpDisplay, const auto& tmpFormat) { ASSERT_EQ(Error::NONE, tmpError) << "failed to create virtual display"; display = tmpDisplay; *outFormat = tmpFormat; ASSERT_TRUE(mDisplayResources.insert({display, DisplayResource(true)}).second) << "duplicated virtual display id " << display; }); return display; } void ComposerClient::destroyVirtualDisplay(Display display) { Error error = mClient->destroyVirtualDisplay(display); ASSERT_EQ(Error::NONE, error) << "failed to destroy virtual display " << display; mDisplayResources.erase(display); } Layer ComposerClient::createLayer(Display display, uint32_t bufferSlotCount) { Layer layer = 0; mClient->createLayer(display, bufferSlotCount, [&](const auto& tmpError, const auto& tmpLayer) { ASSERT_EQ(Error::NONE, tmpError) << "failed to create layer"; layer = tmpLayer; auto resourceIt = mDisplayResources.find(display); if (resourceIt == mDisplayResources.end()) { resourceIt = mDisplayResources.insert({display, DisplayResource(false)}).first; } ASSERT_TRUE(resourceIt->second.layers.insert(layer).second) << "duplicated layer id " << layer; }); return layer; } void ComposerClient::destroyLayer(Display display, Layer layer) { Error error = mClient->destroyLayer(display, layer); ASSERT_EQ(Error::NONE, error) << "failed to destroy layer " << layer; auto resourceIt = mDisplayResources.find(display); ASSERT_NE(mDisplayResources.end(), resourceIt); resourceIt->second.layers.erase(layer); } Config ComposerClient::getActiveConfig(Display display) { Config config = 0; mClient->getActiveConfig(display, [&](const auto& tmpError, const auto& tmpConfig) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get active config"; config = tmpConfig; }); return config; } bool ComposerClient::getClientTargetSupport(Display display, uint32_t width, uint32_t height, PixelFormat format, Dataspace dataspace) { Error error = mClient->getClientTargetSupport(display, width, height, format, dataspace); return error == Error::NONE; } std::vector ComposerClient::getColorModes(Display display) { std::vector modes; mClient->getColorModes(display, [&](const auto& tmpError, const auto& tmpMode) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get color mode"; modes = tmpMode; }); return modes; } int32_t ComposerClient::getDisplayAttribute(Display display, Config config, IComposerClient::Attribute attribute) { int32_t value = 0; mClient->getDisplayAttribute( display, config, attribute, [&](const auto& tmpError, const auto& tmpValue) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get display attribute"; value = tmpValue; }); return value; } std::vector ComposerClient::getDisplayConfigs(Display display) { std::vector configs; mClient->getDisplayConfigs(display, [&](const auto& tmpError, const auto& tmpConfigs) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get display configs"; configs = tmpConfigs; }); return configs; } std::string ComposerClient::getDisplayName(Display display) { std::string name; mClient->getDisplayName(display, [&](const auto& tmpError, const auto& tmpName) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get display name"; name = tmpName.c_str(); }); return name; } IComposerClient::DisplayType ComposerClient::getDisplayType(Display display) { IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID; mClient->getDisplayType(display, [&](const auto& tmpError, const auto& tmpType) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get display type"; type = tmpType; }); return type; } bool ComposerClient::getDozeSupport(Display display) { bool support = false; mClient->getDozeSupport(display, [&](const auto& tmpError, const auto& tmpSupport) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get doze support"; support = tmpSupport; }); return support; } std::vector ComposerClient::getHdrCapabilities(Display display, float* outMaxLuminance, float* outMaxAverageLuminance, float* outMinLuminance) { std::vector types; mClient->getHdrCapabilities( display, [&](const auto& tmpError, const auto& tmpTypes, const auto& tmpMaxLuminance, const auto& tmpMaxAverageLuminance, const auto& tmpMinLuminance) { ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR capabilities"; types = tmpTypes; *outMaxLuminance = tmpMaxLuminance; *outMaxAverageLuminance = tmpMaxAverageLuminance; *outMinLuminance = tmpMinLuminance; }); return types; } void ComposerClient::setClientTargetSlotCount(Display display, uint32_t clientTargetSlotCount) { Error error = mClient->setClientTargetSlotCount(display, clientTargetSlotCount); ASSERT_EQ(Error::NONE, error) << "failed to set client target slot count"; } void ComposerClient::setActiveConfig(Display display, Config config) { Error error = mClient->setActiveConfig(display, config); ASSERT_EQ(Error::NONE, error) << "failed to set active config"; } void ComposerClient::setColorMode(Display display, ColorMode mode) { Error error = mClient->setColorMode(display, mode); ASSERT_EQ(Error::NONE, error) << "failed to set color mode"; } void ComposerClient::setPowerMode(Display display, IComposerClient::PowerMode mode) { Error error = mClient->setPowerMode(display, mode); ASSERT_EQ(Error::NONE, error) << "failed to set power mode"; } void ComposerClient::setVsyncEnabled(Display display, bool enabled) { IComposerClient::Vsync vsync = (enabled) ? IComposerClient::Vsync::ENABLE : IComposerClient::Vsync::DISABLE; Error error = mClient->setVsyncEnabled(display, vsync); ASSERT_EQ(Error::NONE, error) << "failed to set vsync mode"; // give the hwbinder thread some time to handle any pending vsync callback if (!enabled) { usleep(5 * 1000); } } void ComposerClient::execute(TestCommandReader* reader, CommandWriterBase* writer) { bool queueChanged = false; uint32_t commandLength = 0; hidl_vec commandHandles; ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles)); if (queueChanged) { auto ret = mClient->setInputCommandQueue(*writer->getMQDescriptor()); ASSERT_EQ(Error::NONE, static_cast(ret)); } mClient->executeCommands(commandLength, commandHandles, [&](const auto& tmpError, const auto& tmpOutQueueChanged, const auto& tmpOutLength, const auto& tmpOutHandles) { ASSERT_EQ(Error::NONE, tmpError); if (tmpOutQueueChanged) { mClient->getOutputCommandQueue( [&](const auto& tmpError, const auto& tmpDescriptor) { ASSERT_EQ(Error::NONE, tmpError); reader->setMQDescriptor(tmpDescriptor); }); } ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles)); reader->parse(); }); reader->reset(); writer->reset(); } NativeHandleWrapper::~NativeHandleWrapper() { if (mHandle) { mGralloc.freeBuffer(mHandle); } } Gralloc::Gralloc() { [this] { ASSERT_NO_FATAL_FAILURE(mGralloc4 = std::make_shared("default", "default", /*errOnFailure=*/false)); if (mGralloc4->getAllocator() == nullptr || mGralloc4->getMapper() == nullptr) { mGralloc4 = nullptr; ASSERT_NO_FATAL_FAILURE(mGralloc3 = std::make_shared("default", "default", /*errOnFailure=*/false)); if (mGralloc3->getAllocator() == nullptr || mGralloc3->getMapper() == nullptr) { mGralloc3 = nullptr; ASSERT_NO_FATAL_FAILURE(mGralloc2 = std::make_shared()); } } }(); } const NativeHandleWrapper Gralloc::allocate(uint32_t width, uint32_t height, uint32_t layerCount, PixelFormat format, uint64_t usage, bool import, uint32_t* outStride) { const native_handle_t* handle; if (mGralloc4) { IMapper4::BufferDescriptorInfo info{}; info.width = width; info.height = height; info.layerCount = layerCount; info.format = static_cast(format); info.usage = usage; handle = mGralloc4->allocate(info, import, outStride); } else if (mGralloc3) { IMapper3::BufferDescriptorInfo info{}; info.width = width; info.height = height; info.layerCount = layerCount; info.format = static_cast(format); info.usage = usage; handle = mGralloc3->allocate(info, import, outStride); } else { IMapper2::BufferDescriptorInfo info{}; info.width = width; info.height = height; info.layerCount = layerCount; info.format = format; info.usage = usage; handle = mGralloc2->allocate(info, import, outStride); } return NativeHandleWrapper(*this, handle); } void* Gralloc::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage, const AccessRegion& accessRegionRect, int acquireFence) { if (mGralloc4) { IMapper4::Rect accessRegion; accessRegion.left = accessRegionRect.left; accessRegion.top = accessRegionRect.top; accessRegion.width = accessRegionRect.width; accessRegion.height = accessRegionRect.height; return mGralloc4->lock(bufferHandle, cpuUsage, accessRegion, acquireFence); } else if (mGralloc3) { IMapper3::Rect accessRegion; accessRegion.left = accessRegionRect.left; accessRegion.top = accessRegionRect.top; accessRegion.width = accessRegionRect.width; accessRegion.height = accessRegionRect.height; int32_t bytesPerPixel; int32_t bytesPerStride; return mGralloc3->lock(bufferHandle, cpuUsage, accessRegion, acquireFence, &bytesPerPixel, &bytesPerStride); } else { IMapper2::Rect accessRegion; accessRegion.left = accessRegionRect.left; accessRegion.top = accessRegionRect.top; accessRegion.width = accessRegionRect.width; accessRegion.height = accessRegionRect.height; return mGralloc2->lock(bufferHandle, cpuUsage, accessRegion, acquireFence); } } int Gralloc::unlock(const native_handle_t* bufferHandle) { if (mGralloc4) { return mGralloc4->unlock(bufferHandle); } else if (mGralloc3) { return mGralloc3->unlock(bufferHandle); } else { return mGralloc2->unlock(bufferHandle); } } void Gralloc::freeBuffer(const native_handle_t* bufferHandle) { if (mGralloc4) { mGralloc4->freeBuffer(bufferHandle); } else if (mGralloc3) { mGralloc3->freeBuffer(bufferHandle); } else { mGralloc2->freeBuffer(bufferHandle); } } } // namespace vts } // namespace V2_1 } // namespace composer } // namespace graphics } // namespace hardware } // namespace android