1
0
Fork 0

drm_hwcomposer: Return DrmKmsPlan from Backend

DrmKmsPlan lifetime is used to manage ownership of drm planes that have
affinity for multiple crtcs. As such, the DrmKmsPlan lifetime needs to
persist from a Validate call to when the composition is Presented to
ensure that such planes aren't stolen by another display.

Rather than stashing the DrmKmsPlan as part of TestComposition, return
the DrmKmsPlan as part of the Backend's Validate. HwcDisplay::Validate
then becomes responsible for lifetime management of the resulting
DrmKmsPlan as before.

Change-Id: I14ae115b2eed5c9b27e70f0b695fbbc4f3a4faa6
This commit is contained in:
Drew Davenport 2025-08-21 10:40:48 -06:00
parent b288993101
commit c75316c28e
6 changed files with 56 additions and 38 deletions

View file

@ -52,7 +52,7 @@ std::pair<uint32_t, uint32_t> GetDisplaySize(const HwcDisplay *display) {
} // namespace
auto Backend::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
auto Backend::ValidateDisplay(HwcDisplay* display) -> ValidatedComposition {
auto layers = display->GetOrderLayersByZPos();
auto flatcon = display->GetFlatCon();
@ -65,8 +65,7 @@ auto Backend::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
if (should_flatten) {
display->total_stats().frames_flattened++;
return GetCompositionTypes(layers, 0, layers.size(),
/*use_cursor_plane=*/false);
return GetFlattenedComposition(layers);
}
}
@ -78,19 +77,20 @@ auto Backend::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
!IsClientLayer(display, cursor_layer) &&
cursor_plane->Get()->IsValidForLayer(
&cursor_layer->GetLayerData());
CompositionTypeMap composition_types;
ValidatedComposition validated_composition;
// Validates layers and creates a test composition, returning whether it
// succeeded.
auto validate_and_test = [&]() -> bool {
std::tie(client_start, client_size) = GetClientLayers(display, layers,
use_cursor_plane);
composition_types = GetCompositionTypes(layers, client_start, client_size,
use_cursor_plane);
validated_composition
.composition_types = GetCompositionTypes(layers, client_start,
client_size, use_cursor_plane);
bool testing_needed = client_start != 0 || client_size != layers.size();
if (testing_needed) {
return display->TestComposition(composition_types);
return display->TestComposition(validated_composition);
}
return true;
@ -109,10 +109,7 @@ auto Backend::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
// Final fallback: convert all layers to client composition.
if (!success) {
++display->total_stats().failed_kms_validate;
client_start = 0;
client_size = layers.size();
composition_types = GetCompositionTypes(layers, client_start, client_size,
use_cursor_plane);
validated_composition = GetFlattenedComposition(layers);
}
display->total_stats().gpu_pixops += CalcPixOps(layers, client_start,
@ -123,7 +120,14 @@ auto Backend::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
if (use_cursor_plane) {
++display->total_stats().cursor_plane_frames;
}
return composition_types;
return validated_composition;
}
Backend::ValidatedComposition Backend::GetFlattenedComposition(
const std::vector<const HwcLayer*>& layers) {
return ValidatedComposition{
.composition_types = GetCompositionTypes(layers, 0, layers.size(), false),
.composition_plan = std::make_shared<DrmKmsPlan>()};
}
std::tuple<size_t, size_t> Backend::GetClientLayers(

View file

@ -23,6 +23,7 @@
namespace android {
struct DrmKmsPlan;
class HwcDisplay;
class HwcLayer;
@ -31,15 +32,26 @@ class Backend {
// Mapping of the CompositionType that the Backend assigned to each
// HwcLayer.
using CompositionTypeMap = std::map<const HwcLayer*, CompositionType>;
struct ValidatedComposition {
// The resulting composition type for each layer.
CompositionTypeMap composition_types;
// The DrmKms resources required for the composition. The lifetime of
// the DrmKmsPlan ensures that corresponding drm resources are reserved
// for use by this display. As such, the caller must ensure that the
// DrmKmsPlan is not destructed before the composition is committed.
std::shared_ptr<DrmKmsPlan> composition_plan;
};
virtual ~Backend() = default;
virtual CompositionTypeMap ValidateDisplay(HwcDisplay* display);
virtual ValidatedComposition ValidateDisplay(HwcDisplay* display);
virtual std::tuple<size_t, size_t> GetClientLayers(
HwcDisplay* display, const std::vector<const HwcLayer*>& layers,
bool use_cursor_plane);
virtual bool IsClientLayer(HwcDisplay* display, const HwcLayer* layer);
protected:
static ValidatedComposition GetFlattenedComposition(
const std::vector<const HwcLayer*>& layers);
static bool HardwareSupportsLayerType(CompositionType comp_type);
static uint32_t CalcPixOps(const std::vector<const HwcLayer*>& layers,
size_t first_z, size_t size,

View file

@ -21,12 +21,9 @@
namespace android {
auto BackendClient::ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap {
CompositionTypeMap composition_types;
for (const auto& [layer_handle, layer] : display->layers()) {
composition_types.emplace(&layer, CompositionType::kClient);
}
return composition_types;
auto BackendClient::ValidateDisplay(HwcDisplay* display)
-> ValidatedComposition {
return GetFlattenedComposition(display->GetOrderLayersByZPos());
}
// clang-format off

View file

@ -22,6 +22,6 @@ namespace android {
class BackendClient : public Backend {
public:
auto ValidateDisplay(HwcDisplay* display) -> CompositionTypeMap override;
auto ValidateDisplay(HwcDisplay* display) -> ValidatedComposition override;
};
} // namespace android