summaryrefslogtreecommitdiff
path: root/drmdisplaycomposition.cpp
diff options
context:
space:
mode:
authorZach Reizner <zachr@google.com>2015-10-16 19:06:31 -0700
committerZach Reizner <zachr@google.com>2015-10-23 15:51:01 -0700
commit5757e82631820372382d3369c54cc3a1ffef812f (patch)
tree99c1a4f970a1011cf572808249c7a86ad240af8c /drmdisplaycomposition.cpp
parent203f954f267d9027260b0d60c9cc842840fdf229 (diff)
downloaddrm_hwcomposer-5757e82631820372382d3369c54cc3a1ffef812f.tar.gz
drm_hwcomposer-5757e82631820372382d3369c54cc3a1ffef812f.tar.xz
drm_hwcomposer: implement squashing
Change-Id: Ifd4feaa0de303ddfd519d4415ab31d2a72f26022
Diffstat (limited to 'drmdisplaycomposition.cpp')
-rw-r--r--drmdisplaycomposition.cpp201
1 files changed, 122 insertions, 79 deletions
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index 49bacad..34d879e 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -85,11 +85,13 @@ int DrmDisplayComposition::IncreaseTimelineToPoint(int point) {
return ret;
}
-int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers) {
- int ret = 0;
+int DrmDisplayComposition::SetLayers(DrmHwcLayer *layers, size_t num_layers,
+ bool geometry_changed) {
if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
return -EINVAL;
+ geometry_changed_ = geometry_changed;
+
for (size_t layer_index = 0; layer_index < num_layers; layer_index++) {
layers_.emplace_back(std::move(layers[layer_index]));
}
@@ -162,7 +164,7 @@ static std::vector<size_t> SetBitsToVector(uint64_t in, size_t *index_map) {
return out;
}
-static void SeperateLayers(DrmHwcLayer *layers, size_t *used_layers,
+static void SeparateLayers(DrmHwcLayer *layers, size_t *used_layers,
size_t num_used_layers,
DrmHwcRect<int> *exclude_rects,
size_t num_exclude_rects,
@@ -203,82 +205,7 @@ static void SeperateLayers(DrmHwcLayer *layers, size_t *used_layers,
}
}
-int DrmDisplayComposition::Plan(SquashState *squash,
- std::vector<DrmPlane *> *primary_planes,
- std::vector<DrmPlane *> *overlay_planes) {
- size_t planes_can_use =
- CountUsablePlanes(crtc_, primary_planes, overlay_planes);
- if (planes_can_use == 0) {
- ALOGE("Display %d has no usable planes", crtc_->display());
- return -ENODEV;
- }
-
- std::vector<int> layer_squash_area(layers_.size());
- if (squash != NULL && planes_can_use >= 3) {
- std::vector<bool> changed_regions;
- squash->GenerateHistory(layers_.data(), changed_regions);
-
- std::vector<bool> stable_regions;
- squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions);
-
- squash->RecordHistory(layers_.data(), changed_regions);
-
- squash->RecordSquashed(stable_regions);
-
- for (size_t region_index = 0; region_index < stable_regions.size();
- region_index++) {
- const SquashState::Region &region = squash->regions()[region_index];
- if (stable_regions[region_index]) {
- squash_regions_.emplace_back();
- DrmCompositionRegion &squash_region = squash_regions_.back();
- squash_region.frame = region.rect;
- for (size_t layer_index = 0; layer_index < SquashState::kMaxLayers;
- layer_index++) {
- if (region.layer_refs[layer_index]) {
- squash_region.source_layers.push_back(layer_index);
- layer_squash_area[layer_index] += squash_region.frame.area();
- }
- }
- }
- }
- }
-
- std::vector<size_t> layers_remaining;
- for (size_t layer_index = 0; layer_index < layers_.size(); layer_index++) {
- // Skip layers that were completely squashed
- if (layer_squash_area[layer_index] >=
- layers_[layer_index].display_frame.area()) {
- continue;
- }
-
- layers_remaining.push_back(layer_index);
- }
-
- size_t layer_to_composite = layers_remaining.size();
- size_t num_layers_to_pre_composite = 0;
- if (squash_regions_.size() > 0) {
- layers_remaining.push_back(DrmCompositionPlane::kSourceSquash);
- }
-
- if (layers_remaining.size() > planes_can_use) {
- layers_remaining.insert(layers_remaining.begin() + layer_to_composite,
- DrmCompositionPlane::kSourcePreComp);
- size_t num_layers_to_pre_composite =
- layer_to_composite - planes_can_use + 1;
- size_t first_layer_to_pre_composite = planes_can_use - 1;
- SeperateLayers(layers_.data(),
- &layers_remaining[first_layer_to_pre_composite],
- num_layers_to_pre_composite, NULL, 0, pre_comp_regions_);
- layers_remaining.erase(
- layers_remaining.begin() + first_layer_to_pre_composite,
- layers_remaining.begin() + layer_to_composite);
- }
-
- for (size_t i : layers_remaining) {
- composition_planes_.emplace_back(DrmCompositionPlane{
- TakePlane(crtc_, primary_planes, overlay_planes), crtc_, i});
- }
-
+int DrmDisplayComposition::CreateAndAssignReleaseFences() {
std::unordered_set<DrmHwcLayer *> squash_layers;
std::unordered_set<DrmHwcLayer *> pre_comp_layers;
std::unordered_set<DrmHwcLayer *> comp_layers;
@@ -329,6 +256,122 @@ int DrmDisplayComposition::Plan(SquashState *squash,
return 0;
}
+int DrmDisplayComposition::Plan(SquashState *squash,
+ std::vector<DrmPlane *> *primary_planes,
+ std::vector<DrmPlane *> *overlay_planes) {
+ if (type_ != DRM_COMPOSITION_TYPE_FRAME)
+ return 0;
+
+ size_t planes_can_use =
+ CountUsablePlanes(crtc_, primary_planes, overlay_planes);
+ if (planes_can_use == 0) {
+ ALOGE("Display %d has no usable planes", crtc_->display());
+ return -ENODEV;
+ }
+
+ bool use_squash_framebuffer = false;
+ // Used to determine which layers were entirely squashed
+ std::vector<int> layer_squash_area(layers_.size(), 0);
+ // Used to avoid rerendering regions that were squashed
+ std::vector<DrmHwcRect<int>> exclude_rects;
+ if (squash != NULL && planes_can_use >= 3) {
+ if (geometry_changed_) {
+ squash->Init(layers_.data(), layers_.size());
+ } else {
+ std::vector<bool> changed_regions;
+ squash->GenerateHistory(layers_.data(), layers_.size(), changed_regions);
+
+ std::vector<bool> stable_regions;
+ squash->StableRegionsWithMarginalHistory(changed_regions, stable_regions);
+
+ // Only if SOME region is stable
+ use_squash_framebuffer =
+ std::find(stable_regions.begin(), stable_regions.end(), true) !=
+ stable_regions.end();
+
+ squash->RecordHistory(layers_.data(), layers_.size(), changed_regions);
+
+ // Changes in which regions are squashed triggers a rerender via
+ // squash_regions.
+ bool render_squash = squash->RecordAndCompareSquashed(stable_regions);
+
+ for (size_t region_index = 0; region_index < stable_regions.size();
+ region_index++) {
+ const SquashState::Region &region = squash->regions()[region_index];
+ if (!stable_regions[region_index])
+ continue;
+
+ exclude_rects.emplace_back(region.rect);
+
+ if (render_squash) {
+ squash_regions_.emplace_back();
+ squash_regions_.back().frame = region.rect;
+ }
+
+ int frame_area = region.rect.area();
+ // Source layers are sorted front to back i.e. top layer has lowest
+ // index.
+ for (size_t layer_index = layers_.size();
+ layer_index-- > 0; // Yes, I double checked this
+ /* See condition */) {
+ if (!region.layer_refs[layer_index])
+ continue;
+ layer_squash_area[layer_index] += frame_area;
+ if (render_squash)
+ squash_regions_.back().source_layers.push_back(layer_index);
+ }
+ }
+ }
+ }
+
+ std::vector<size_t> layers_remaining;
+ for (size_t layer_index = 0; layer_index < layers_.size(); layer_index++) {
+ // Skip layers that were completely squashed
+ if (layer_squash_area[layer_index] >=
+ layers_[layer_index].display_frame.area()) {
+ continue;
+ }
+
+ layers_remaining.push_back(layer_index);
+ }
+
+ if (use_squash_framebuffer)
+ planes_can_use--;
+
+ if (layers_remaining.size() > planes_can_use)
+ planes_can_use--;
+
+ size_t last_composition_layer = 0;
+ for (last_composition_layer = 0;
+ last_composition_layer < layers_remaining.size() && planes_can_use > 0;
+ last_composition_layer++, planes_can_use--) {
+ composition_planes_.emplace_back(
+ DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
+ crtc_, layers_remaining[last_composition_layer]});
+ }
+
+ layers_remaining.erase(layers_remaining.begin(),
+ layers_remaining.begin() + last_composition_layer);
+
+ if (layers_remaining.size() > 0) {
+ composition_planes_.emplace_back(
+ DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
+ crtc_, DrmCompositionPlane::kSourcePreComp});
+
+ SeparateLayers(layers_.data(), layers_remaining.data(),
+ layers_remaining.size(), exclude_rects.data(),
+ exclude_rects.size(), pre_comp_regions_);
+ }
+
+ if (use_squash_framebuffer) {
+ composition_planes_.emplace_back(
+ DrmCompositionPlane{TakePlane(crtc_, primary_planes, overlay_planes),
+ crtc_, DrmCompositionPlane::kSourceSquash});
+ }
+
+ return CreateAndAssignReleaseFences();
+}
+
static const char *DrmCompositionTypeToString(DrmCompositionType type) {
switch (type) {
case DRM_COMPOSITION_TYPE_EMPTY: