graphics: move ComposerClient to HAL support library
libhwcomposer-client is empty and can be removed. Note that ComposerClient::initialize is renamed and can fail now. Test: boots and VTS Change-Id: Iacd3f995bc094c7dd6b7f91ae64aad0522b3f3d3
This commit is contained in:
parent
78211cf7d0
commit
da5fdd4494
6 changed files with 389 additions and 543 deletions
|
@ -1,35 +1,9 @@
|
|||
cc_library_static {
|
||||
name: "libhwcomposer-client",
|
||||
vendor_available: true,
|
||||
defaults: ["hidl_defaults"],
|
||||
export_include_dirs: ["."],
|
||||
srcs: ["ComposerClient.cpp"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"libhardware",
|
||||
"libhidlbase",
|
||||
"libhidltransport",
|
||||
"liblog",
|
||||
"libsync",
|
||||
"libutils",
|
||||
],
|
||||
header_libs: [
|
||||
"android.hardware.graphics.composer@2.1-command-buffer",
|
||||
"android.hardware.graphics.composer@2.1-hal",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "android.hardware.graphics.composer@2.1-impl",
|
||||
defaults: ["hidl_defaults"],
|
||||
proprietary: true,
|
||||
relative_install_path: "hw",
|
||||
srcs: ["Hwc.cpp"],
|
||||
static_libs: ["libhwcomposer-client"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"android.hardware.graphics.mapper@2.0",
|
||||
|
@ -58,7 +32,6 @@ cc_binary {
|
|||
relative_install_path: "hw",
|
||||
srcs: ["service.cpp"],
|
||||
init_rc: ["android.hardware.graphics.composer@2.1-service.rc"],
|
||||
static_libs: ["libhwcomposer-client"],
|
||||
shared_libs: [
|
||||
"android.hardware.graphics.composer@2.1",
|
||||
"libbase",
|
||||
|
|
|
@ -1,392 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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_TAG "HwcPassthrough"
|
||||
|
||||
#include <android/hardware/graphics/mapper/2.0/IMapper.h>
|
||||
#include <log/log.h>
|
||||
|
||||
#include "ComposerClient.h"
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
ComposerClient::ComposerClient(ComposerHal& hal)
|
||||
: mHal(hal)
|
||||
{
|
||||
}
|
||||
|
||||
ComposerClient::~ComposerClient()
|
||||
{
|
||||
ALOGD("destroying composer client");
|
||||
|
||||
mHal.enableCallback(false);
|
||||
destroyResources();
|
||||
mHal.removeClient();
|
||||
|
||||
ALOGD("removed composer client");
|
||||
}
|
||||
|
||||
void ComposerClient::destroyResources()
|
||||
{
|
||||
// We want to call hwc2_close here (and move hwc2_open to the
|
||||
// constructor), with the assumption that hwc2_close would
|
||||
//
|
||||
// - clean up all resources owned by the client
|
||||
// - make sure all displays are blank (since there is no layer)
|
||||
//
|
||||
// But since SF used to crash at this point, different hwcomposer2
|
||||
// implementations behave differently on hwc2_close. Our only portable
|
||||
// choice really is to abort(). But that is not an option anymore
|
||||
// because we might also have VTS or VR as clients that can come and go.
|
||||
//
|
||||
// Below we manually clean all resources (layers and virtual
|
||||
// displays), and perform a presentDisplay afterwards.
|
||||
mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
|
||||
ALOGW("destroying client resources for display %" PRIu64, display);
|
||||
|
||||
for (auto layer : layers) {
|
||||
mHal.destroyLayer(display, layer);
|
||||
}
|
||||
|
||||
if (isVirtual) {
|
||||
mHal.destroyVirtualDisplay(display);
|
||||
} else {
|
||||
ALOGW("performing a final presentDisplay");
|
||||
|
||||
std::vector<Layer> changedLayers;
|
||||
std::vector<IComposerClient::Composition> compositionTypes;
|
||||
uint32_t displayRequestMask = 0;
|
||||
std::vector<Layer> requestedLayers;
|
||||
std::vector<uint32_t> requestMasks;
|
||||
mHal.validateDisplay(display, &changedLayers, &compositionTypes, &displayRequestMask,
|
||||
&requestedLayers, &requestMasks);
|
||||
|
||||
mHal.acceptDisplayChanges(display);
|
||||
|
||||
int32_t presentFence = -1;
|
||||
std::vector<Layer> releasedLayers;
|
||||
std::vector<int32_t> releaseFences;
|
||||
mHal.presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
|
||||
if (presentFence >= 0) {
|
||||
close(presentFence);
|
||||
}
|
||||
for (auto fence : releaseFences) {
|
||||
if (fence >= 0) {
|
||||
close(fence);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mResources.reset();
|
||||
}
|
||||
|
||||
void ComposerClient::initialize()
|
||||
{
|
||||
mResources = createResources();
|
||||
if (!mResources) {
|
||||
LOG_ALWAYS_FATAL("failed to create resources");
|
||||
}
|
||||
|
||||
mCommandEngine = createCommandEngine();
|
||||
}
|
||||
|
||||
void ComposerClient::onHotplug(Display display,
|
||||
IComposerCallback::Connection connected)
|
||||
{
|
||||
if (connected == IComposerCallback::Connection::CONNECTED) {
|
||||
mResources->addPhysicalDisplay(display);
|
||||
} else if (connected == IComposerCallback::Connection::DISCONNECTED) {
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
auto ret = mCallback->onHotplug(display, connected);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s",
|
||||
ret.description().c_str());
|
||||
}
|
||||
|
||||
void ComposerClient::onRefresh(Display display)
|
||||
{
|
||||
auto ret = mCallback->onRefresh(display);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s",
|
||||
ret.description().c_str());
|
||||
}
|
||||
|
||||
void ComposerClient::onVsync(Display display, int64_t timestamp)
|
||||
{
|
||||
auto ret = mCallback->onVsync(display, timestamp);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s",
|
||||
ret.description().c_str());
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::registerCallback(
|
||||
const sp<IComposerCallback>& callback)
|
||||
{
|
||||
// no locking as we require this function to be called only once
|
||||
mCallback = callback;
|
||||
mHal.enableCallback(callback != nullptr);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<uint32_t> ComposerClient::getMaxVirtualDisplayCount()
|
||||
{
|
||||
return mHal.getMaxVirtualDisplayCount();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::createVirtualDisplay(uint32_t width,
|
||||
uint32_t height, PixelFormat formatHint, uint32_t outputBufferSlotCount,
|
||||
createVirtualDisplay_cb hidl_cb)
|
||||
{
|
||||
Display display = 0;
|
||||
Error err = mHal.createVirtualDisplay(width, height,
|
||||
&formatHint, &display);
|
||||
if (err == Error::NONE) {
|
||||
mResources->addVirtualDisplay(display, outputBufferSlotCount);
|
||||
}
|
||||
|
||||
hidl_cb(err, display, formatHint);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::destroyVirtualDisplay(Display display)
|
||||
{
|
||||
Error err = mHal.destroyVirtualDisplay(display);
|
||||
if (err == Error::NONE) {
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::createLayer(Display display,
|
||||
uint32_t bufferSlotCount, createLayer_cb hidl_cb)
|
||||
{
|
||||
Layer layer = 0;
|
||||
Error err = mHal.createLayer(display, &layer);
|
||||
if (err == Error::NONE) {
|
||||
err = mResources->addLayer(display, layer, bufferSlotCount);
|
||||
if (err != Error::NONE) {
|
||||
// The display entry may have already been removed by onHotplug.
|
||||
// Note: We do not destroy the layer on this error as the hotplug
|
||||
// disconnect invalidates the display id. The implementation should
|
||||
// ensure all layers for the display are destroyed.
|
||||
}
|
||||
}
|
||||
|
||||
hidl_cb(err, layer);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::destroyLayer(Display display, Layer layer)
|
||||
{
|
||||
Error err = mHal.destroyLayer(display, layer);
|
||||
if (err == Error::NONE) {
|
||||
mResources->removeLayer(display, layer);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getActiveConfig(Display display,
|
||||
getActiveConfig_cb hidl_cb)
|
||||
{
|
||||
Config config = 0;
|
||||
Error err = mHal.getActiveConfig(display, &config);
|
||||
|
||||
hidl_cb(err, config);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace)
|
||||
{
|
||||
Error err = mHal.getClientTargetSupport(display,
|
||||
width, height, format, dataspace);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getColorModes(Display display,
|
||||
getColorModes_cb hidl_cb)
|
||||
{
|
||||
hidl_vec<ColorMode> modes;
|
||||
Error err = mHal.getColorModes(display, &modes);
|
||||
|
||||
hidl_cb(err, modes);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getDisplayAttribute(Display display,
|
||||
Config config, Attribute attribute,
|
||||
getDisplayAttribute_cb hidl_cb)
|
||||
{
|
||||
int32_t value = 0;
|
||||
Error err = mHal.getDisplayAttribute(display, config, attribute, &value);
|
||||
|
||||
hidl_cb(err, value);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getDisplayConfigs(Display display,
|
||||
getDisplayConfigs_cb hidl_cb)
|
||||
{
|
||||
hidl_vec<Config> configs;
|
||||
Error err = mHal.getDisplayConfigs(display, &configs);
|
||||
|
||||
hidl_cb(err, configs);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getDisplayName(Display display,
|
||||
getDisplayName_cb hidl_cb)
|
||||
{
|
||||
hidl_string name;
|
||||
Error err = mHal.getDisplayName(display, &name);
|
||||
|
||||
hidl_cb(err, name);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getDisplayType(Display display,
|
||||
getDisplayType_cb hidl_cb)
|
||||
{
|
||||
DisplayType type = DisplayType::INVALID;
|
||||
Error err = mHal.getDisplayType(display, &type);
|
||||
|
||||
hidl_cb(err, type);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getDozeSupport(Display display,
|
||||
getDozeSupport_cb hidl_cb)
|
||||
{
|
||||
bool support = false;
|
||||
Error err = mHal.getDozeSupport(display, &support);
|
||||
|
||||
hidl_cb(err, support);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getHdrCapabilities(Display display,
|
||||
getHdrCapabilities_cb hidl_cb)
|
||||
{
|
||||
hidl_vec<Hdr> types;
|
||||
float max_lumi = 0.0f;
|
||||
float max_avg_lumi = 0.0f;
|
||||
float min_lumi = 0.0f;
|
||||
Error err = mHal.getHdrCapabilities(display, &types,
|
||||
&max_lumi, &max_avg_lumi, &min_lumi);
|
||||
|
||||
hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount)
|
||||
{
|
||||
return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setActiveConfig(Display display, Config config)
|
||||
{
|
||||
Error err = mHal.setActiveConfig(display, config);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setColorMode(Display display, ColorMode mode)
|
||||
{
|
||||
Error err = mHal.setColorMode(display, mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setPowerMode(Display display, PowerMode mode)
|
||||
{
|
||||
Error err = mHal.setPowerMode(display, mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setVsyncEnabled(Display display, Vsync enabled)
|
||||
{
|
||||
Error err = mHal.setVsyncEnabled(display, enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> ComposerClient::setInputCommandQueue(
|
||||
const MQDescriptorSync<uint32_t>& descriptor)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mCommandEngineMutex);
|
||||
return mCommandEngine->setInputMQDescriptor(descriptor) ?
|
||||
Error::NONE : Error::NO_RESOURCES;
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::getOutputCommandQueue(
|
||||
getOutputCommandQueue_cb hidl_cb)
|
||||
{
|
||||
// no locking as we require this function to be called inside
|
||||
// executeCommands_cb
|
||||
|
||||
auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
|
||||
if (outDescriptor) {
|
||||
hidl_cb(Error::NONE, *outDescriptor);
|
||||
} else {
|
||||
hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> ComposerClient::executeCommands(uint32_t inLength,
|
||||
const hidl_vec<hidl_handle>& inHandles,
|
||||
executeCommands_cb hidl_cb)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mCommandEngineMutex);
|
||||
|
||||
bool outChanged = false;
|
||||
uint32_t outLength = 0;
|
||||
hidl_vec<hidl_handle> outHandles;
|
||||
Error error = mCommandEngine->execute(inLength, inHandles,
|
||||
&outChanged, &outLength, &outHandles);
|
||||
|
||||
hidl_cb(error, outChanged, outLength, outHandles);
|
||||
|
||||
mCommandEngine->reset();
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
std::unique_ptr<ComposerResources> ComposerClient::createResources()
|
||||
{
|
||||
return ComposerResources::create();
|
||||
}
|
||||
|
||||
std::unique_ptr<ComposerCommandEngine>
|
||||
ComposerClient::createCommandEngine()
|
||||
{
|
||||
return std::make_unique<ComposerCommandEngine>(&mHal, mResources.get());
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
#ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
|
||||
#define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
|
||||
#include <composer-hal/2.1/ComposerCommandEngine.h>
|
||||
#include <composer-hal/2.1/ComposerHal.h>
|
||||
#include <composer-hal/2.1/ComposerResources.h>
|
||||
#include <hardware/hwcomposer2.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace implementation {
|
||||
|
||||
using namespace hal;
|
||||
|
||||
class ComposerClient : public IComposerClient {
|
||||
public:
|
||||
ComposerClient(ComposerHal& hal);
|
||||
virtual ~ComposerClient();
|
||||
|
||||
void initialize();
|
||||
|
||||
void onHotplug(Display display, IComposerCallback::Connection connected);
|
||||
void onRefresh(Display display);
|
||||
void onVsync(Display display, int64_t timestamp);
|
||||
|
||||
// IComposerClient interface
|
||||
Return<void> registerCallback(
|
||||
const sp<IComposerCallback>& callback) override;
|
||||
Return<uint32_t> getMaxVirtualDisplayCount() override;
|
||||
Return<void> createVirtualDisplay(uint32_t width, uint32_t height,
|
||||
PixelFormat formatHint, uint32_t outputBufferSlotCount,
|
||||
createVirtualDisplay_cb hidl_cb) override;
|
||||
Return<Error> destroyVirtualDisplay(Display display) override;
|
||||
Return<void> createLayer(Display display, uint32_t bufferSlotCount,
|
||||
createLayer_cb hidl_cb) override;
|
||||
Return<Error> destroyLayer(Display display, Layer layer) override;
|
||||
Return<void> getActiveConfig(Display display,
|
||||
getActiveConfig_cb hidl_cb) override;
|
||||
Return<Error> getClientTargetSupport(Display display,
|
||||
uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace) override;
|
||||
Return<void> getColorModes(Display display,
|
||||
getColorModes_cb hidl_cb) override;
|
||||
Return<void> getDisplayAttribute(Display display,
|
||||
Config config, Attribute attribute,
|
||||
getDisplayAttribute_cb hidl_cb) override;
|
||||
Return<void> getDisplayConfigs(Display display,
|
||||
getDisplayConfigs_cb hidl_cb) override;
|
||||
Return<void> getDisplayName(Display display,
|
||||
getDisplayName_cb hidl_cb) override;
|
||||
Return<void> getDisplayType(Display display,
|
||||
getDisplayType_cb hidl_cb) override;
|
||||
Return<void> getDozeSupport(Display display,
|
||||
getDozeSupport_cb hidl_cb) override;
|
||||
Return<void> getHdrCapabilities(Display display,
|
||||
getHdrCapabilities_cb hidl_cb) override;
|
||||
Return<Error> setActiveConfig(Display display, Config config) override;
|
||||
Return<Error> setColorMode(Display display, ColorMode mode) override;
|
||||
Return<Error> setPowerMode(Display display, PowerMode mode) override;
|
||||
Return<Error> setVsyncEnabled(Display display, Vsync enabled) override;
|
||||
Return<Error> setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount) override;
|
||||
Return<Error> setInputCommandQueue(
|
||||
const MQDescriptorSync<uint32_t>& descriptor) override;
|
||||
Return<void> getOutputCommandQueue(
|
||||
getOutputCommandQueue_cb hidl_cb) override;
|
||||
Return<void> executeCommands(uint32_t inLength,
|
||||
const hidl_vec<hidl_handle>& inHandles,
|
||||
executeCommands_cb hidl_cb) override;
|
||||
|
||||
protected:
|
||||
virtual std::unique_ptr<ComposerResources> createResources();
|
||||
virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine();
|
||||
|
||||
void destroyResources();
|
||||
|
||||
ComposerHal& mHal;
|
||||
|
||||
std::unique_ptr<ComposerResources> mResources;
|
||||
|
||||
std::mutex mCommandEngineMutex;
|
||||
std::unique_ptr<ComposerCommandEngine> mCommandEngine;
|
||||
|
||||
sp<IComposerCallback> mCallback;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_COMPOSER_CLIENT_H
|
|
@ -22,7 +22,6 @@
|
|||
#include <type_traits>
|
||||
#include <log/log.h>
|
||||
|
||||
#include "ComposerClient.h"
|
||||
#include "hardware/fb.h"
|
||||
#include "hardware/hwcomposer.h"
|
||||
#include "hwc2on1adapter/HWC2On1Adapter.h"
|
||||
|
@ -281,9 +280,14 @@ Return<void> HwcHal::createClient(createClient_cb hidl_cb)
|
|||
|
||||
// only one client is allowed
|
||||
if (mClient == nullptr) {
|
||||
client = new ComposerClient(*this);
|
||||
client->initialize();
|
||||
mClient = client;
|
||||
// We assume Composer outlives ComposerClient here. It is true
|
||||
// only because Composer is binderized.
|
||||
client = ComposerClient::create(this).release();
|
||||
if (client) {
|
||||
mClient = client;
|
||||
} else {
|
||||
err = Error::NO_RESOURCES;
|
||||
}
|
||||
} else {
|
||||
err = Error::NO_RESOURCES;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <hardware/hwcomposer2.h>
|
||||
#undef HWC2_INCLUDE_STRINGIFICATION
|
||||
#undef HWC2_USE_CPP11
|
||||
#include <composer-hal/2.1/ComposerClient.h>
|
||||
#include <composer-hal/2.1/ComposerHal.h>
|
||||
|
||||
namespace android {
|
||||
|
@ -53,8 +54,6 @@ using android::hardware::graphics::common::V1_0::ColorMode;
|
|||
using android::hardware::graphics::common::V1_0::ColorTransform;
|
||||
using android::hardware::graphics::common::V1_0::Hdr;
|
||||
|
||||
class ComposerClient;
|
||||
|
||||
class HwcHal : public IComposer, public ComposerHal {
|
||||
public:
|
||||
HwcHal(const hw_module_t* module);
|
||||
|
|
|
@ -0,0 +1,380 @@
|
|||
/*
|
||||
* Copyright 2018 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef LOG_TAG
|
||||
#warning "ComposerClient.h included without LOG_TAG"
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
#include <android/hardware/graphics/composer/2.1/IComposerClient.h>
|
||||
#include <composer-hal/2.1/ComposerCommandEngine.h>
|
||||
#include <composer-hal/2.1/ComposerHal.h>
|
||||
#include <composer-hal/2.1/ComposerResources.h>
|
||||
#include <log/log.h>
|
||||
|
||||
namespace android {
|
||||
namespace hardware {
|
||||
namespace graphics {
|
||||
namespace composer {
|
||||
namespace V2_1 {
|
||||
namespace hal {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// ComposerClientImpl implements V2_*::IComposerClient on top of V2_*::ComposerHal
|
||||
template <typename Interface, typename Hal>
|
||||
class ComposerClientImpl : public Interface {
|
||||
public:
|
||||
static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
|
||||
auto client = std::make_unique<ComposerClientImpl>(hal);
|
||||
return client->init() ? std::move(client) : nullptr;
|
||||
}
|
||||
|
||||
ComposerClientImpl(Hal* hal) : mHal(hal) {}
|
||||
|
||||
virtual ~ComposerClientImpl() {
|
||||
// not initialized
|
||||
if (!mCommandEngine) {
|
||||
return;
|
||||
}
|
||||
|
||||
ALOGD("destroying composer client");
|
||||
|
||||
mHal->enableCallback(false);
|
||||
destroyResources();
|
||||
mHal->removeClient();
|
||||
|
||||
ALOGD("removed composer client");
|
||||
}
|
||||
|
||||
bool init() {
|
||||
mResources = createResources();
|
||||
if (!mResources) {
|
||||
ALOGE("failed to create composer resources");
|
||||
return false;
|
||||
}
|
||||
|
||||
mCommandEngine = createCommandEngine();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void onHotplug(Display display, IComposerCallback::Connection connected) {
|
||||
if (connected == IComposerCallback::Connection::CONNECTED) {
|
||||
mResources->addPhysicalDisplay(display);
|
||||
} else if (connected == IComposerCallback::Connection::DISCONNECTED) {
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
auto ret = mCallback->onHotplug(display, connected);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onHotplug: %s", ret.description().c_str());
|
||||
}
|
||||
|
||||
void onRefresh(Display display) {
|
||||
auto ret = mCallback->onRefresh(display);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
|
||||
}
|
||||
|
||||
void onVsync(Display display, int64_t timestamp) {
|
||||
auto ret = mCallback->onVsync(display, timestamp);
|
||||
ALOGE_IF(!ret.isOk(), "failed to send onVsync: %s", ret.description().c_str());
|
||||
}
|
||||
|
||||
// IComposerClient 2.1 interface
|
||||
|
||||
Return<void> registerCallback(const sp<IComposerCallback>& callback) override {
|
||||
// no locking as we require this function to be called only once
|
||||
mCallback = callback;
|
||||
mHal->enableCallback(callback != nullptr);
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<uint32_t> getMaxVirtualDisplayCount() override {
|
||||
return mHal->getMaxVirtualDisplayCount();
|
||||
}
|
||||
|
||||
Return<void> createVirtualDisplay(uint32_t width, uint32_t height, PixelFormat formatHint,
|
||||
uint32_t outputBufferSlotCount,
|
||||
IComposerClient::createVirtualDisplay_cb hidl_cb) override {
|
||||
Display display = 0;
|
||||
Error err = mHal->createVirtualDisplay(width, height, &formatHint, &display);
|
||||
if (err == Error::NONE) {
|
||||
mResources->addVirtualDisplay(display, outputBufferSlotCount);
|
||||
}
|
||||
|
||||
hidl_cb(err, display, formatHint);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> destroyVirtualDisplay(Display display) override {
|
||||
Error err = mHal->destroyVirtualDisplay(display);
|
||||
if (err == Error::NONE) {
|
||||
mResources->removeDisplay(display);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> createLayer(Display display, uint32_t bufferSlotCount,
|
||||
IComposerClient::createLayer_cb hidl_cb) override {
|
||||
Layer layer = 0;
|
||||
Error err = mHal->createLayer(display, &layer);
|
||||
if (err == Error::NONE) {
|
||||
err = mResources->addLayer(display, layer, bufferSlotCount);
|
||||
if (err != Error::NONE) {
|
||||
// The display entry may have already been removed by onHotplug.
|
||||
// Note: We do not destroy the layer on this error as the hotplug
|
||||
// disconnect invalidates the display id. The implementation should
|
||||
// ensure all layers for the display are destroyed.
|
||||
layer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
hidl_cb(err, layer);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> destroyLayer(Display display, Layer layer) override {
|
||||
Error err = mHal->destroyLayer(display, layer);
|
||||
if (err == Error::NONE) {
|
||||
mResources->removeLayer(display, layer);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> getActiveConfig(Display display,
|
||||
IComposerClient::getActiveConfig_cb hidl_cb) override {
|
||||
Config config = 0;
|
||||
Error err = mHal->getActiveConfig(display, &config);
|
||||
hidl_cb(err, config);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> getClientTargetSupport(Display display, uint32_t width, uint32_t height,
|
||||
PixelFormat format, Dataspace dataspace) override {
|
||||
Error err = mHal->getClientTargetSupport(display, width, height, format, dataspace);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<void> getColorModes(Display display,
|
||||
IComposerClient::getColorModes_cb hidl_cb) override {
|
||||
hidl_vec<ColorMode> modes;
|
||||
Error err = mHal->getColorModes(display, &modes);
|
||||
hidl_cb(err, modes);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getDisplayAttribute(Display display, Config config,
|
||||
IComposerClient::Attribute attribute,
|
||||
IComposerClient::getDisplayAttribute_cb hidl_cb) override {
|
||||
int32_t value = 0;
|
||||
Error err = mHal->getDisplayAttribute(display, config, attribute, &value);
|
||||
hidl_cb(err, value);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getDisplayConfigs(Display display,
|
||||
IComposerClient::getDisplayConfigs_cb hidl_cb) override {
|
||||
hidl_vec<Config> configs;
|
||||
Error err = mHal->getDisplayConfigs(display, &configs);
|
||||
hidl_cb(err, configs);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getDisplayName(Display display,
|
||||
IComposerClient::getDisplayName_cb hidl_cb) override {
|
||||
hidl_string name;
|
||||
Error err = mHal->getDisplayName(display, &name);
|
||||
hidl_cb(err, name);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getDisplayType(Display display,
|
||||
IComposerClient::getDisplayType_cb hidl_cb) override {
|
||||
IComposerClient::DisplayType type = IComposerClient::DisplayType::INVALID;
|
||||
Error err = mHal->getDisplayType(display, &type);
|
||||
hidl_cb(err, type);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getDozeSupport(Display display,
|
||||
IComposerClient::getDozeSupport_cb hidl_cb) override {
|
||||
bool support = false;
|
||||
Error err = mHal->getDozeSupport(display, &support);
|
||||
hidl_cb(err, support);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> getHdrCapabilities(Display display,
|
||||
IComposerClient::getHdrCapabilities_cb hidl_cb) override {
|
||||
hidl_vec<Hdr> types;
|
||||
float max_lumi = 0.0f;
|
||||
float max_avg_lumi = 0.0f;
|
||||
float min_lumi = 0.0f;
|
||||
Error err = mHal->getHdrCapabilities(display, &types, &max_lumi, &max_avg_lumi, &min_lumi);
|
||||
hidl_cb(err, types, max_lumi, max_avg_lumi, min_lumi);
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<Error> setActiveConfig(Display display, Config config) override {
|
||||
Error err = mHal->setActiveConfig(display, config);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> setColorMode(Display display, ColorMode mode) override {
|
||||
Error err = mHal->setColorMode(display, mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> setPowerMode(Display display, IComposerClient::PowerMode mode) override {
|
||||
Error err = mHal->setPowerMode(display, mode);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> setVsyncEnabled(Display display, IComposerClient::Vsync enabled) override {
|
||||
Error err = mHal->setVsyncEnabled(display, enabled);
|
||||
return err;
|
||||
}
|
||||
|
||||
Return<Error> setClientTargetSlotCount(Display display,
|
||||
uint32_t clientTargetSlotCount) override {
|
||||
return mResources->setDisplayClientTargetCacheSize(display, clientTargetSlotCount);
|
||||
}
|
||||
|
||||
Return<Error> setInputCommandQueue(const MQDescriptorSync<uint32_t>& descriptor) override {
|
||||
std::lock_guard<std::mutex> lock(mCommandEngineMutex);
|
||||
return mCommandEngine->setInputMQDescriptor(descriptor) ? Error::NONE : Error::NO_RESOURCES;
|
||||
}
|
||||
|
||||
Return<void> getOutputCommandQueue(IComposerClient::getOutputCommandQueue_cb hidl_cb) override {
|
||||
// no locking as we require this function to be called inside
|
||||
// executeCommands_cb
|
||||
auto outDescriptor = mCommandEngine->getOutputMQDescriptor();
|
||||
if (outDescriptor) {
|
||||
hidl_cb(Error::NONE, *outDescriptor);
|
||||
} else {
|
||||
hidl_cb(Error::NO_RESOURCES, CommandQueueType::Descriptor());
|
||||
}
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
Return<void> executeCommands(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
|
||||
IComposerClient::executeCommands_cb hidl_cb) override {
|
||||
std::lock_guard<std::mutex> lock(mCommandEngineMutex);
|
||||
bool outChanged = false;
|
||||
uint32_t outLength = 0;
|
||||
hidl_vec<hidl_handle> outHandles;
|
||||
Error error =
|
||||
mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
|
||||
|
||||
hidl_cb(error, outChanged, outLength, outHandles);
|
||||
|
||||
mCommandEngine->reset();
|
||||
|
||||
return Void();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::unique_ptr<ComposerResources> createResources() {
|
||||
return ComposerResources::create();
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<ComposerCommandEngine> createCommandEngine() {
|
||||
return std::make_unique<ComposerCommandEngine>(mHal, mResources.get());
|
||||
}
|
||||
|
||||
void destroyResources() {
|
||||
// We want to call hwc2_close here (and move hwc2_open to the
|
||||
// constructor), with the assumption that hwc2_close would
|
||||
//
|
||||
// - clean up all resources owned by the client
|
||||
// - make sure all displays are blank (since there is no layer)
|
||||
//
|
||||
// But since SF used to crash at this point, different hwcomposer2
|
||||
// implementations behave differently on hwc2_close. Our only portable
|
||||
// choice really is to abort(). But that is not an option anymore
|
||||
// because we might also have VTS or VR as clients that can come and go.
|
||||
//
|
||||
// Below we manually clean all resources (layers and virtual
|
||||
// displays), and perform a presentDisplay afterwards.
|
||||
mResources->clear([this](Display display, bool isVirtual, const std::vector<Layer> layers) {
|
||||
ALOGW("destroying client resources for display %" PRIu64, display);
|
||||
|
||||
for (auto layer : layers) {
|
||||
mHal->destroyLayer(display, layer);
|
||||
}
|
||||
|
||||
if (isVirtual) {
|
||||
mHal->destroyVirtualDisplay(display);
|
||||
} else {
|
||||
ALOGW("performing a final presentDisplay");
|
||||
|
||||
std::vector<Layer> changedLayers;
|
||||
std::vector<IComposerClient::Composition> compositionTypes;
|
||||
uint32_t displayRequestMask = 0;
|
||||
std::vector<Layer> requestedLayers;
|
||||
std::vector<uint32_t> requestMasks;
|
||||
mHal->validateDisplay(display, &changedLayers, &compositionTypes,
|
||||
&displayRequestMask, &requestedLayers, &requestMasks);
|
||||
|
||||
mHal->acceptDisplayChanges(display);
|
||||
|
||||
int32_t presentFence = -1;
|
||||
std::vector<Layer> releasedLayers;
|
||||
std::vector<int32_t> releaseFences;
|
||||
mHal->presentDisplay(display, &presentFence, &releasedLayers, &releaseFences);
|
||||
if (presentFence >= 0) {
|
||||
close(presentFence);
|
||||
}
|
||||
for (auto fence : releaseFences) {
|
||||
if (fence >= 0) {
|
||||
close(fence);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mResources.reset();
|
||||
}
|
||||
|
||||
Hal* const mHal;
|
||||
|
||||
std::unique_ptr<ComposerResources> mResources;
|
||||
|
||||
std::mutex mCommandEngineMutex;
|
||||
std::unique_ptr<ComposerCommandEngine> mCommandEngine;
|
||||
|
||||
sp<IComposerCallback> mCallback;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
using ComposerClient = detail::ComposerClientImpl<IComposerClient, ComposerHal>;
|
||||
|
||||
} // namespace hal
|
||||
} // namespace V2_1
|
||||
} // namespace composer
|
||||
} // namespace graphics
|
||||
} // namespace hardware
|
||||
} // namespace android
|
Loading…
Reference in a new issue