blob: dc2439a45d11f91364fa351dce460682c98ec608 [file] [log] [blame]
/*
* Copyright 2021 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_HWC_DISPLAY_H
#define ANDROID_HWC_DISPLAY_H
#include <android/hardware/graphics/common/1.0/types.h>
#include <utils/Thread.h>
#include <array>
#include <optional>
#include <set>
#include <thread>
#include <unordered_map>
#include <vector>
#include "Common.h"
#include "Composer.h"
#include "FencedBuffer.h"
#include "Layer.h"
namespace android {
class Composer;
class Device;
struct ColorTransformWithMatrix {
android::hardware::graphics::common::V1_0::ColorTransform transformType;
std::optional<std::array<float, 16>> transformMatrixOpt;
};
class Display {
public:
Display(Device& device, Composer* composer, hwc2_display_t id);
~Display();
Display(const Display& display) = delete;
Display& operator=(const Display& display) = delete;
Display(Display&& display) = delete;
Display& operator=(Display&& display) = delete;
HWC2::Error init(
uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
uint32_t refreshRateHz,
const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
HWC2::Error updateParameters(
uint32_t width, uint32_t height, uint32_t dpiX, uint32_t dpiY,
uint32_t refreshRateHz,
const std::optional<std::vector<uint8_t>>& edid = std::nullopt);
hwc2_display_t getId() const { return mId; }
Layer* getLayer(hwc2_layer_t layerHandle);
FencedBuffer& getClientTarget() { return mClientTarget; }
buffer_handle_t waitAndGetClientTargetBuffer();
const std::vector<Layer*>& getOrderedLayers() { return mOrderedLayers; }
HWC2::Error acceptChanges();
HWC2::Error createLayer(hwc2_layer_t* outLayerId);
HWC2::Error destroyLayer(hwc2_layer_t layerId);
HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
HWC2::Error getDisplayAttribute(hwc2_config_t configId, int32_t attribute,
int32_t* outValue);
HWC2::Error getDisplayAttributeEnum(hwc2_config_t configId,
HWC2::Attribute attribute,
int32_t* outValue);
HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
hwc2_layer_t* outLayers,
int32_t* outTypes);
HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
HWC2::Error getConfigs(uint32_t* outNumConfigs, hwc2_config_t* outConfigIds);
HWC2::Error getDozeSupport(int32_t* outSupport);
HWC2::Error getHdrCapabilities(uint32_t* outNumTypes, int32_t* outTypes,
float* outMaxLuminance,
float* outMaxAverageLuminance,
float* outMinLuminance);
HWC2::Error getName(uint32_t* outSize, char* outName);
HWC2::Error addReleaseFenceLocked(int32_t fence);
HWC2::Error addReleaseLayerLocked(hwc2_layer_t layerId);
HWC2::Error getReleaseFences(uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outFences);
HWC2::Error clearReleaseFencesAndIdsLocked();
HWC2::Error getRequests(int32_t* outDisplayRequests, uint32_t* outNumElements,
hwc2_layer_t* outLayers, int32_t* outLayerRequests);
HWC2::Error getType(int32_t* outType);
HWC2::Error present(int32_t* outRetireFence);
HWC2::Error setActiveConfig(hwc2_config_t configId);
HWC2::Error setClientTarget(buffer_handle_t target, int32_t acquireFence,
int32_t dataspace, hwc_region_t damage);
HWC2::Error setColorMode(int32_t mode);
HWC2::Error setColorTransform(const float* matrix, int transform);
HWC2::Error setColorTransformEnum(const float* matrix,
android::hardware::graphics::common::V1_0::ColorTransform transform);
bool hasColorTransform() const { return mColorTransform.has_value(); }
ColorTransformWithMatrix getColorTransform() const { return *mColorTransform; }
HWC2::Error setOutputBuffer(buffer_handle_t buffer, int32_t releaseFence);
HWC2::Error setPowerMode(int32_t mode);
HWC2::Error setVsyncEnabled(int32_t enabled);
HWC2::Error setVsyncPeriod(uint32_t period);
HWC2::Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests);
HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
int32_t format, int32_t dataspace);
HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
uint32_t* outDataSize,
uint8_t* outData);
HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
uint32_t* outCapabilities);
HWC2::Error getDisplayBrightnessSupport(bool* out_support);
HWC2::Error setDisplayBrightness(float brightness);
void lock() { mStateMutex.lock(); }
void unlock() { mStateMutex.unlock(); }
private:
class Config {
public:
Config(hwc2_config_t configId) : mId(configId) {}
Config(const Config& display) = default;
Config& operator=(const Config& display) = default;
Config(Config&& display) = default;
Config& operator=(Config&& display) = default;
hwc2_config_t getId() const { return mId; }
void setId(hwc2_config_t id) { mId = id; }
int32_t getAttribute(HWC2::Attribute attribute) const;
void setAttribute(HWC2::Attribute attribute, int32_t value);
std::string toString() const;
private:
hwc2_config_t mId;
std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
};
// Stores changes requested from the device upon calling prepare().
// Handles change request to:
// - Layer composition type.
// - Layer hints.
class Changes {
public:
uint32_t getNumTypes() const {
return static_cast<uint32_t>(mTypeChanges.size());
}
uint32_t getNumLayerRequests() const {
return static_cast<uint32_t>(mLayerRequests.size());
}
const std::unordered_map<hwc2_layer_t, HWC2::Composition>& getTypeChanges()
const {
return mTypeChanges;
}
const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
getLayerRequests() const {
return mLayerRequests;
}
void addTypeChange(hwc2_layer_t layerId, HWC2::Composition type) {
mTypeChanges.insert({layerId, type});
}
void clearTypeChanges() { mTypeChanges.clear(); }
void addLayerRequest(hwc2_layer_t layerId, HWC2::LayerRequest request) {
mLayerRequests.insert({layerId, request});
}
private:
std::unordered_map<hwc2_layer_t, HWC2::Composition> mTypeChanges;
std::unordered_map<hwc2_layer_t, HWC2::LayerRequest> mLayerRequests;
};
// Generate sw vsync signal
class VsyncThread : public Thread {
public:
VsyncThread(Display& display) : mDisplay(display) {}
virtual ~VsyncThread() {}
VsyncThread(const VsyncThread&) = default;
VsyncThread& operator=(const VsyncThread&) = default;
VsyncThread(VsyncThread&&) = default;
VsyncThread& operator=(VsyncThread&&) = default;
private:
Display& mDisplay;
bool threadLoop() final;
};
private:
// The state of this display should only be modified from
// SurfaceFlinger's main loop, with the exception of when dump is
// called. To prevent a bad state from crashing us during a dump
// call, all public calls into Display must acquire this mutex.
mutable std::recursive_mutex mStateMutex;
Device& mDevice;
Composer* mComposer = nullptr;
const hwc2_display_t mId;
std::string mName;
HWC2::DisplayType mType = HWC2::DisplayType::Physical;
HWC2::PowerMode mPowerMode = HWC2::PowerMode::Off;
HWC2::Vsync mVsyncEnabled = HWC2::Vsync::Invalid;
uint32_t mVsyncPeriod;
sp<VsyncThread> mVsyncThread;
FencedBuffer mClientTarget;
// Will only be non-null after the Display has been validated and
// before it has been presented
std::unique_ptr<Changes> mChanges;
std::unordered_map<hwc2_layer_t, std::unique_ptr<Layer>> mLayers;
// Ordered layers available after validate().
std::vector<Layer*> mOrderedLayers;
std::vector<hwc2_display_t> mReleaseLayerIds;
std::vector<int32_t> mReleaseFences;
std::optional<hwc2_config_t> mActiveConfigId;
std::unordered_map<hwc2_config_t, Config> mConfigs;
std::set<android_color_mode_t> mColorModes;
android_color_mode_t mActiveColorMode;
std::optional<ColorTransformWithMatrix> mColorTransform;
std::optional<std::vector<uint8_t>> mEdid;
};
} // namespace android
#endif