namespace hwcomposer {
DisplayPlaneState::DisplayPlaneState(DisplayPlane *plane, OverlayLayer *layer,
- uint32_t index)
- : plane_(plane), layer_(layer) {
- source_layers_.emplace_back(index);
- display_frame_ = layer->GetDisplayFrame();
- source_crop_ = layer->GetSourceCrop();
+ uint32_t index) {
+ private_data_ = std::make_shared<DisplayPlanePrivateState>();
+ private_data_->source_layers_.emplace_back(index);
+ private_data_->display_frame_ = layer->GetDisplayFrame();
+ private_data_->source_crop_ = layer->GetSourceCrop();
if (layer->IsCursorLayer()) {
- type_ = PlaneType::kCursor;
- has_cursor_layer_ = true;
+ private_data_->type_ = DisplayPlanePrivateState::PlaneType::kCursor;
+ private_data_->has_cursor_layer_ = true;
}
+
+ plane->SetInUse(true);
+ private_data_->plane_ = plane;
+ private_data_->layer_ = layer;
}
void DisplayPlaneState::CopyState(DisplayPlaneState &state) {
- has_cursor_layer_ = state.has_cursor_layer_;
- type_ = state.type_;
- use_plane_scalar_ = state.use_plane_scalar_;
- plane_ = state.plane_;
- state_ = state.state_;
- source_crop_ = state.source_crop_;
- display_frame_ = state.display_frame_;
- apply_effects_ = state.apply_effects_;
- plane_->SetInUse(true);
+ private_data_ = state.private_data_;
// We don't copy recycled_surface_ state as this
// should be determined in DisplayQueue for every frame.
}
const HwcRect<int> &DisplayPlaneState::GetDisplayFrame() const {
- return display_frame_;
+ return private_data_->display_frame_;
}
const HwcRect<float> &DisplayPlaneState::GetSourceCrop() const {
- return source_crop_;
+ return private_data_->source_crop_;
}
void DisplayPlaneState::SetSourceCrop(const HwcRect<float> &crop) {
- source_crop_ = crop;
+ private_data_->source_crop_ = crop;
}
void DisplayPlaneState::ResetSourceRectToDisplayFrame() {
- source_crop_ = HwcRect<float>(display_frame_);
+ private_data_->source_crop_ = HwcRect<float>(private_data_->display_frame_);
}
void DisplayPlaneState::AddLayer(const OverlayLayer *layer) {
const HwcRect<int> &display_frame = layer->GetDisplayFrame();
- display_frame_.left = std::min(display_frame_.left, display_frame.left);
- display_frame_.top = std::min(display_frame_.top, display_frame.top);
- display_frame_.right = std::max(display_frame_.right, display_frame.right);
- display_frame_.bottom = std::max(display_frame_.bottom, display_frame.bottom);
-
- source_layers_.emplace_back(layer->GetZorder());
-
- state_ = State::kRender;
- has_cursor_layer_ = layer->IsCursorLayer();
-
- if (source_layers_.size() == 1 && has_cursor_layer_) {
- type_ = PlaneType::kCursor;
+ HwcRect<int> &target_display_frame = private_data_->display_frame_;
+ target_display_frame.left =
+ std::min(target_display_frame.left, display_frame.left);
+ target_display_frame.top =
+ std::min(target_display_frame.top, display_frame.top);
+ target_display_frame.right =
+ std::max(target_display_frame.right, display_frame.right);
+ target_display_frame.bottom =
+ std::max(target_display_frame.bottom, display_frame.bottom);
+
+ private_data_->source_layers_.emplace_back(layer->GetZorder());
+
+ private_data_->state_ = DisplayPlanePrivateState::State::kRender;
+ private_data_->has_cursor_layer_ = layer->IsCursorLayer();
+
+ if (private_data_->source_layers_.size() == 1 &&
+ private_data_->has_cursor_layer_) {
+ private_data_->type_ = DisplayPlanePrivateState::PlaneType::kCursor;
} else {
// TODO: Add checks for Video type once our
// Media backend can support compositing more
// than one layer together.
- type_ = PlaneType::kNormal;
- apply_effects_ = false;
+ private_data_->type_ = DisplayPlanePrivateState::PlaneType::kNormal;
+ private_data_->apply_effects_ = false;
}
- if (!use_plane_scalar_)
- source_crop_ = HwcRect<float>(display_frame_);
-}
-
-// This API should be called only when Cursor layer is being
-// added, is part of layers displayed by plane or is being
-// removed in this frame. AddLayers should be used in all
-// other cases.
-void DisplayPlaneState::AddLayers(const std::vector<size_t> &source_layers,
- const std::vector<OverlayLayer> &layers,
- bool ignore_cursor_layer) {
- if (ignore_cursor_layer) {
- size_t lsize = layers.size();
- size_t size = source_layers.size();
- source_layers_.reserve(size);
- has_cursor_layer_ = false;
- bool initialized = false;
- for (const size_t &index : source_layers) {
- if (index >= lsize) {
- continue;
- }
-
- const OverlayLayer &layer = layers.at(index);
- const HwcRect<int> &df = layer.GetDisplayFrame();
- if (!initialized) {
- display_frame_ = df;
- initialized = true;
- } else {
- display_frame_.left = std::min(display_frame_.left, df.left);
- display_frame_.top = std::min(display_frame_.top, df.top);
- display_frame_.right = std::max(display_frame_.right, df.right);
- display_frame_.bottom = std::max(display_frame_.bottom, df.bottom);
- }
-
- source_layers_.emplace_back(index);
+ if (!private_data_->use_plane_scalar_)
+ private_data_->source_crop_ = HwcRect<float>(private_data_->display_frame_);
+}
+
+void DisplayPlaneState::ResetLayers(const std::vector<OverlayLayer> &layers,
+ bool *layers_changed) {
+ const std::vector<size_t> ¤t_layers = private_data_->source_layers_;
+ size_t lsize = layers.size();
+ size_t size = current_layers.size();
+ std::vector<size_t> source_layers;
+ source_layers.reserve(size);
+ private_data_->has_cursor_layer_ = false;
+ bool initialized = false;
+ HwcRect<int> target_display_frame;
+ bool removed = false;
+ for (const size_t &index : current_layers) {
+ if (index >= lsize) {
+ removed = true;
+ continue;
}
- if (!use_plane_scalar_)
- source_crop_ = HwcRect<float>(display_frame_);
- } else {
- for (const int &index : source_layers) {
- source_layers_.emplace_back(index);
+ const OverlayLayer &layer = layers.at(index);
+ if (layer.IsCursorLayer()) {
+ private_data_->has_cursor_layer_ = true;
+ }
+
+ const HwcRect<int> &df = layer.GetDisplayFrame();
+ if (!initialized) {
+ target_display_frame = df;
+ initialized = true;
+ } else {
+ target_display_frame.left = std::min(target_display_frame.left, df.left);
+ target_display_frame.top = std::min(target_display_frame.top, df.top);
+ target_display_frame.right =
+ std::max(target_display_frame.right, df.right);
+ target_display_frame.bottom =
+ std::max(target_display_frame.bottom, df.bottom);
}
+
+ source_layers.emplace_back(index);
}
+
+ private_data_->source_layers_.swap(source_layers);
+ private_data_->display_frame_ = target_display_frame;
+
+ if (!private_data_->use_plane_scalar_)
+ private_data_->source_crop_ = HwcRect<float>(target_display_frame);
+
+ if (private_data_->source_layers_.size() == 1 &&
+ private_data_->has_cursor_layer_) {
+ private_data_->type_ = DisplayPlanePrivateState::PlaneType::kCursor;
+ }
+
+ *layers_changed = removed;
}
void DisplayPlaneState::UpdateDisplayFrame(const HwcRect<int> &display_frame) {
- display_frame_.left = std::min(display_frame_.left, display_frame.left);
- display_frame_.top = std::min(display_frame_.top, display_frame.top);
- display_frame_.right = std::max(display_frame_.right, display_frame.right);
- display_frame_.bottom = std::max(display_frame_.bottom, display_frame.bottom);
+ HwcRect<int> &target_display_frame = private_data_->display_frame_;
+ target_display_frame.left =
+ std::min(target_display_frame.left, display_frame.left);
+ target_display_frame.top =
+ std::min(target_display_frame.top, display_frame.top);
+ target_display_frame.right =
+ std::max(target_display_frame.right, display_frame.right);
+ target_display_frame.bottom =
+ std::max(target_display_frame.bottom, display_frame.bottom);
- if (!use_plane_scalar_)
- source_crop_ = HwcRect<float>(display_frame_);
+ if (!private_data_->use_plane_scalar_)
+ private_data_->source_crop_ = HwcRect<float>(target_display_frame);
}
void DisplayPlaneState::ForceGPURendering() {
- state_ = State::kRender;
+ private_data_->state_ = DisplayPlanePrivateState::State::kRender;
}
void DisplayPlaneState::SetOverlayLayer(const OverlayLayer *layer) {
- layer_ = layer;
+ private_data_->layer_ = layer;
}
void DisplayPlaneState::ReUseOffScreenTarget() {
}
const OverlayLayer *DisplayPlaneState::GetOverlayLayer() const {
- return layer_;
+ return private_data_->layer_;
}
void DisplayPlaneState::SetOffScreenTarget(NativeSurface *target) {
- surfaces_.emplace(surfaces_.begin(), target);
+ private_data_->layer_ = target->GetLayer();
+ target->ResetDisplayFrame(private_data_->display_frame_);
+ target->ResetSourceCrop(private_data_->source_crop_);
+ private_data_->surfaces_.emplace(private_data_->surfaces_.begin(), target);
+ recycled_surface_ = false;
}
NativeSurface *DisplayPlaneState::GetOffScreenTarget() const {
- if (surfaces_.size() == 0) {
+ if (private_data_->surfaces_.size() == 0) {
return NULL;
}
- return surfaces_.at(0);
+ return private_data_->surfaces_.at(0);
}
-void DisplayPlaneState::TransferSurfaces(
- const std::vector<NativeSurface *> &surfaces, bool swap_front_buffer) {
- size_t size = surfaces.size();
- source_layers_.reserve(size);
- if (size < 3 || !swap_front_buffer) {
- for (uint32_t i = 0; i < size; i++) {
- surfaces_.emplace_back(surfaces.at(i));
- }
- } else {
- // Lets make sure front buffer is now back in the list.
- surfaces_.emplace_back(surfaces.at(1));
- surfaces_.emplace_back(surfaces.at(2));
- surfaces_.emplace_back(surfaces.at(0));
- }
-
- NativeSurface *surface = surfaces_.at(0);
- surface->SetInUse(true);
- SetOverlayLayer(surface->GetLayer());
-
- if (surfaces_.size() == 3) {
- surface_swapped_ = swap_front_buffer;
- } else {
- // We will be using an empty buffer, no need to
- // swap buffer in this case.
- surface_swapped_ = true;
- }
+void DisplayPlaneState::SwapSurface() {
+ surface_swapped_ = false;
+ SwapSurfaceIfNeeded();
}
void DisplayPlaneState::SwapSurfaceIfNeeded() {
return;
}
- std::vector<NativeSurface *> temp;
- temp.reserve(surfaces_.size());
- temp.emplace_back(surfaces_.at(1));
- temp.emplace_back(surfaces_.at(2));
- temp.emplace_back(surfaces_.at(0));
- temp.swap(surfaces_);
+ size_t size = private_data_->surfaces_.size();
+
+ if (size == 3) {
+ std::vector<NativeSurface *> temp;
+ temp.reserve(size);
+ // Lets make sure front buffer is now back in the list.
+ temp.emplace_back(private_data_->surfaces_.at(1));
+ temp.emplace_back(private_data_->surfaces_.at(2));
+ temp.emplace_back(private_data_->surfaces_.at(0));
+ private_data_->surfaces_.swap(temp);
+ }
+
surface_swapped_ = true;
- NativeSurface *surface = surfaces_.at(0);
+ recycled_surface_ = false;
+ NativeSurface *surface = private_data_->surfaces_.at(0);
surface->SetInUse(true);
- SetOverlayLayer(surface->GetLayer());
+ private_data_->layer_ = surface->GetLayer();
}
const std::vector<NativeSurface *> &DisplayPlaneState::GetSurfaces() const {
- return surfaces_;
+ return private_data_->surfaces_;
+}
+
+void DisplayPlaneState::ReleaseSurfaces(bool only_release) {
+ if (!only_release) {
+ for (NativeSurface *surface : private_data_->surfaces_) {
+ surface->SetInUse(false);
+ }
+ }
+
+ std::vector<NativeSurface *>().swap(private_data_->surfaces_);
}
-void DisplayPlaneState::ReleaseSurfaces() {
- for (NativeSurface *surface : surfaces_) {
- surface->SetInUse(false);
+void DisplayPlaneState::RefreshSurfaces(bool clear_surface) {
+ const HwcRect<int> &target_display_frame = private_data_->display_frame_;
+ const HwcRect<float> &target_src_rect = private_data_->source_crop_;
+ bool use_scalar = private_data_->use_plane_scalar_;
+ for (NativeSurface *surface : private_data_->surfaces_) {
+ surface->ResetDisplayFrame(target_display_frame);
+ surface->ResetSourceCrop(target_src_rect);
+ surface->UpdateSurfaceDamage(target_src_rect, target_src_rect);
+ if (!surface->ClearSurface())
+ surface->SetClearSurface(clear_surface);
+ surface->GetLayer()->UsePlaneScalar(use_scalar);
}
- std::vector<NativeSurface *>().swap(surfaces_);
+ std::vector<CompositionRegion>().swap(private_data_->composition_region_);
}
DisplayPlane *DisplayPlaneState::GetDisplayPlane() const {
- return plane_;
+ return private_data_->plane_;
}
const std::vector<size_t> &DisplayPlaneState::GetSourceLayers() const {
- return source_layers_;
+ return private_data_->source_layers_;
}
std::vector<CompositionRegion> &DisplayPlaneState::GetCompositionRegion() {
- return composition_region_;
+ return private_data_->composition_region_;
}
-const std::vector<CompositionRegion> &DisplayPlaneState::GetCompositionRegion()
- const {
- return composition_region_;
+void DisplayPlaneState::ResetCompositionRegion() {
+ std::vector<CompositionRegion>().swap(private_data_->composition_region_);
}
bool DisplayPlaneState::IsCursorPlane() const {
- return type_ == PlaneType::kCursor;
+ return private_data_->type_ == DisplayPlanePrivateState::PlaneType::kCursor;
}
bool DisplayPlaneState::HasCursorLayer() const {
- return has_cursor_layer_;
+ return private_data_->has_cursor_layer_;
}
bool DisplayPlaneState::IsVideoPlane() const {
- return type_ == PlaneType::kVideo;
+ return private_data_->type_ == DisplayPlanePrivateState::PlaneType::kVideo;
}
void DisplayPlaneState::SetVideoPlane() {
- type_ = PlaneType::kVideo;
+ private_data_->type_ = DisplayPlanePrivateState::PlaneType::kVideo;
}
void DisplayPlaneState::UsePlaneScalar(bool enable) {
- use_plane_scalar_ = enable;
+ private_data_->use_plane_scalar_ = enable;
}
bool DisplayPlaneState::IsUsingPlaneScalar() const {
- return use_plane_scalar_;
+ return private_data_->use_plane_scalar_;
}
void DisplayPlaneState::SetApplyEffects(bool apply_effects) {
- apply_effects_ = apply_effects;
+ private_data_->apply_effects_ = apply_effects;
// Doesn't have any impact on planes which
// are not meant for video purpose.
- if (type_ != PlaneType::kVideo) {
- apply_effects_ = false;
+ if (private_data_->type_ != DisplayPlanePrivateState::PlaneType::kVideo) {
+ private_data_->apply_effects_ = false;
}
}
bool DisplayPlaneState::ApplyEffects() const {
- return apply_effects_;
+ return private_data_->apply_effects_;
}
bool DisplayPlaneState::Scanout() const {
return true;
}
- if (apply_effects_) {
+ if (private_data_->apply_effects_) {
return false;
}
- return state_ == State::kScanout;
+ return private_data_->state_ == DisplayPlanePrivateState::State::kScanout;
}
bool DisplayPlaneState::NeedsOffScreenComposition() {
- if (state_ == State::kRender)
+ if (private_data_->state_ == DisplayPlanePrivateState::State::kRender)
return true;
if (recycled_surface_) {
return true;
}
- if (apply_effects_) {
+ if (private_data_->apply_effects_) {
return true;
}
void AddLayer(const OverlayLayer *layer);
- // This API should be called only when Cursor layer is being
- // added, is part of layers displayed by plane or is being
- // removed in this frame. AddLayers should be used in all
- // other cases.
- void AddLayers(const std::vector<size_t> &source_layers,
- const std::vector<OverlayLayer> &layers,
- bool ignore_cursor_layer);
+ // This API should be called only when source_layers being
+ // shown by this plane might be removed in this frame.
+ // layer_removed will be set to true in case layers
+ // associated with this plane are changed.
+ void ResetLayers(const std::vector<OverlayLayer> &layers,
+ bool *layers_changed);
// Updates Display frame rect of this plane to include
// display_frame.
// SetOffcreen Surface for this plane.
void SetOffScreenTarget(NativeSurface *target);
- // Moves surfaces to this plane. If swap_front_buffer
- // is true we would swap the buffer first in surfaces to
- // last.
- void TransferSurfaces(const std::vector<NativeSurface *> &surfaces,
- bool swap_front_buffer);
+ // Put's current OffscreenSurface to back in the
+ // list.
+ void SwapSurface();
const HwcRect<int> &GetDisplayFrame() const;
// Marks all surfaces used by this plane as not in use
// and removes surfaces from this plane. After this call
// this plane will not have have any associated offscreen
- // surfaces.
- void ReleaseSurfaces();
+ // surfaces. If only_release is set to true than we dont
+ // change the use flag.
+ void ReleaseSurfaces(bool only_release);
+
+ // Updates all offscreen surfaces to have same display frame
+ // and source rect as displayplanestate. Also, resets
+ // composition region to null. Also updates if layer
+ // needs to use scalar or not depending on what
+ // IsUsingPlaneScalar returns.
+ void RefreshSurfaces(bool clear_surface);
DisplayPlane *GetDisplayPlane() const;
// Returns source layers for this plane.
const std::vector<size_t> &GetSourceLayers() const;
+ // Returns composition region used by this plane.
std::vector<CompositionRegion> &GetCompositionRegion();
- const std::vector<CompositionRegion> &GetCompositionRegion() const;
+ // Resets composition region to null.
+ void ResetCompositionRegion();
bool IsCursorPlane() const;
bool NeedsOffScreenComposition();
private:
- enum class PlaneType : int32_t {
- kCursor, // Plane is compositing only Cursor.
- kVideo, // Plane is compositing only Media content.
- kNormal // Plane is compositing different types of content.
- };
-
- enum class State : int32_t {
- kScanout, // Scanout the layer directly.
- kRender, // Needs to render the contents to
- // layer before scanning out.
+ class DisplayPlanePrivateState {
+ public:
+ enum class PlaneType : int32_t {
+ kCursor, // Plane is compositing only Cursor.
+ kVideo, // Plane is compositing only Media content.
+ kNormal // Plane is compositing different types of content.
+ };
+
+ enum class State : int32_t {
+ kScanout, // Scanout the layer directly.
+ kRender, // Needs to render the contents to
+ // layer before scanning out.
+ };
+
+ State state_ = State::kScanout;
+ DisplayPlane *plane_ = NULL;
+ const OverlayLayer *layer_ = NULL;
+ HwcRect<int> display_frame_;
+ HwcRect<float> source_crop_;
+ std::vector<size_t> source_layers_;
+ std::vector<CompositionRegion> composition_region_;
+
+ bool use_plane_scalar_ = false;
+ // Even if layer can be scanned out
+ // directly, post processing for
+ // applying video effects is needed.
+ bool apply_effects_ = false;
+ // This plane shows cursor.
+ bool has_cursor_layer_ = false;
+ // Any offscreen surfaces used by this
+ // plane.
+ std::vector<NativeSurface *> surfaces_;
+ PlaneType type_ = PlaneType::kNormal;
};
- State state_ = State::kScanout;
- DisplayPlane *plane_ = NULL;
- const OverlayLayer *layer_ = NULL;
- HwcRect<int> display_frame_;
- HwcRect<float> source_crop_;
- std::vector<size_t> source_layers_;
- std::vector<CompositionRegion> composition_region_;
bool recycled_surface_ = false;
- bool has_cursor_layer_ = false;
bool surface_swapped_ = true;
- bool use_plane_scalar_ = false;
- bool apply_effects_ = false; // Even if layer can be scanned out
- // directly, post processing for
- // applying video effects is needed.
- std::vector<NativeSurface *> surfaces_;
- PlaneType type_ = PlaneType::kNormal;
+ std::shared_ptr<DisplayPlanePrivateState> private_data_;
};
} // namespace hwcomposer
continue;
}
- // We consider last_commit_failed_update_ state here. Displayplanemanager
- // Tries to recycle free surfaces and it could have changed the rect of
- // these surfaces during test commit. Let's make sure the rect is correct
- // even in this case.
- bool clear_surface = last_commit_failed_update_;
- if (cursor_layer_removed && plane.HasCursorLayer()) {
- clear_surface = true;
- }
-
+ bool clear_surface = false;
composition->emplace_back();
DisplayPlaneState& last_plane = composition->back();
last_plane.CopyState(plane);
- last_plane.AddLayers(plane.GetSourceLayers(), layers, cursor_layer_removed);
+ if (cursor_layer_removed && plane.HasCursorLayer()) {
+ last_plane.ResetLayers(layers, &clear_surface);
+ }
if (plane.NeedsOffScreenComposition()) {
bool content_changed = false;
}
}
- if (update_rect) {
+ // If surfaces need to be cleared or rect is updated,
+ // let's make sure all surfaces are refreshed.
+ if (clear_surface || update_rect) {
content_changed = true;
+ last_plane.RefreshSurfaces(clear_surface);
}
- // Let's make sure we swap the surface if content has changed or
- // we need to clear the surface.
- last_plane.TransferSurfaces(plane.GetSurfaces(),
- content_changed || clear_surface);
- const std::vector<NativeSurface*>& surfaces = last_plane.GetSurfaces();
- size_t size = surfaces.size();
- if (clear_surface || update_rect) {
- content_changed = true;
- const HwcRect<int>& current_rect = last_plane.GetDisplayFrame();
- const HwcRect<float>& source_crop = last_plane.GetSourceCrop();
- for (size_t i = 0; i < size; i++) {
- surfaces.at(i)->ResetDisplayFrame(current_rect);
- surfaces.at(i)->ResetSourceCrop(source_crop);
- }
- } else {
- clear_surface = true;
+ // Let's make sure we swap the surface in case content has changed.
+ if (content_changed) {
+ last_plane.SwapSurface();
+ }
+
+ // Let's get the state from surface if it needs to be cleared.
+ if (!clear_surface) {
NativeSurface* surface = last_plane.GetOffScreenTarget();
if (surface) {
clear_surface = surface->ClearSurface();
}
-
- if (!clear_surface) {
- const std::vector<CompositionRegion>& comp_regions =
- plane.GetCompositionRegion();
- last_plane.GetCompositionRegion().assign(comp_regions.begin(),
- comp_regions.end());
- } else {
- content_changed = true;
- }
}
if (content_changed) {
}
if (!composition_passed) {
- IgnoreCompositionResults(current_composition_planes);
last_commit_failed_update_ = true;
return false;
}
disable_ovelays, &fence);
if (!composition_passed) {
- IgnoreCompositionResults(current_composition_planes);
last_commit_failed_update_ = true;
return false;
}
void DisplayQueue::SetMediaEffectsState(
bool apply_effects, const std::vector<OverlayLayer>& layers,
- DisplayPlaneStateList& current_composition_planes) const {
+ DisplayPlaneStateList& current_composition_planes) {
for (DisplayPlaneState& plane : current_composition_planes) {
if (!plane.IsVideoPlane()) {
continue;
// scanned out directly. In this case we will need to delete all
// offscreen surfaces and set the right overlayer layer to the
// plane.
- plane.ReleaseSurfaces();
+ RecyclePreviousPlaneSurfaces();
+ plane.ReleaseSurfaces(true);
const std::vector<size_t>& source = plane.GetSourceLayers();
plane.SetOverlayLayer(&(layers.at(source.at(0))));
}
}
}
-void DisplayQueue::IgnoreCompositionResults(
- DisplayPlaneStateList& current_composition_planes) {
- UpdateSurfaceInUse(false, current_composition_planes);
- UpdateSurfaceInUse(true, previous_plane_state_);
- ReleaseSurfaces();
-}
-
void DisplayQueue::SetReleaseFenceToLayers(
int32_t fence, std::vector<HwcLayer*>& source_layers) const {
for (const DisplayPlaneState& plane : previous_plane_state_) {