state_ |= kSourceRectChanged;
display_scaled_ = rhs->display_scaled_;
+ if (display_scaled_ && (source_rect_changed | rect_changed)) {
+ state_ |= kNeedsReValidation;
+ }
+
+ state_ &= ~kLayerAttributesChanged;
// We expect cursor plane to support alpha always.
if (rhs->gpu_rendered_ || (type_ == kLayerCursor)) {
// supporting XRGB format might not necessarily support
// transparent planes. We assume plane supporting
// ARGB will support XRGB.
- if ((rhs->alpha_ == 0xff) && (alpha_ != rhs->alpha_))
+ if ((rhs->alpha_ == 0xff) && (alpha_ != rhs->alpha_)) {
+ state_ |= kNeedsReValidation;
return;
+ }
- if (blending_ != rhs->blending_)
+ if (blending_ != rhs->blending_) {
+ state_ |= kNeedsReValidation;
return;
+ }
if (rect_changed || layer->HasLayerAttributesChanged()) {
if (layer->IsValidated()) {
+ state_ |= kNeedsReValidation;
return;
}
if (rhs->transform_ != transform_) {
+ state_ |= kNeedsReValidation;
return;
}
(rhs->display_frame_.right != display_frame_.right) ||
(rhs->display_frame_.top != display_frame_.top) ||
(rhs->display_frame_.bottom != display_frame_.bottom)) {
+ state_ |= kNeedsReValidation;
return;
}
}
// shouldn't impact the plane composition results.
if ((source_crop_width_ != rhs->source_crop_width_) ||
(source_crop_height_ != rhs->source_crop_height_)) {
+ state_ |= kNeedsReValidation;
return;
}
}
}
- state_ &= ~kLayerAttributesChanged;
gpu_rendered_ = rhs->gpu_rendered_;
if (!rect_changed) {
return state_ & kSourceRectChanged;
}
+ // Returns true if this layer attributes
+ // have changed compared to last frame
+ // and needs to be re-tested to ensure
+ // we are able to show the layer on screen
+ // correctly.
+ bool NeedsRevalidation() const {
+ return state_ & kNeedsReValidation;
+ }
+
/**
* API for querying if Layer source position has
* changed from last Present call to NativeDisplay.
kDimensionsChanged = 1 << 2,
kClearSurface = 1 << 3,
kInvisible = 1 << 4,
- kSourceRectChanged = 1 << 5
+ kSourceRectChanged = 1 << 5,
+ kNeedsReValidation = 1 << 6
};
struct ImportedBuffer {
}
if (render_layers)
- ValidateForDisplayScaling(composition, commit_planes, primary_layer);
+ ValidateForDisplayScaling(composition.back(), commit_planes, primary_layer);
// We are just compositing Primary layer and nothing else.
if (layers.size() == 1) {
if (previous_layer &&
last_plane.GetCompositionState() ==
DisplayPlaneState::State::kRender) {
- ValidateForDisplayScaling(composition, commit_planes, previous_layer);
+ ValidateForDisplayScaling(composition.back(), commit_planes,
+ previous_layer);
render_layers = true;
}
EnsureOffScreenTarget(last_plane);
}
- ValidateForDisplayScaling(composition, commit_planes, previous_layer);
+ ValidateForDisplayScaling(composition.back(), commit_planes,
+ previous_layer);
}
render_layers = true;
return render_layers;
}
+bool DisplayPlaneManager::ReValidateLayers(std::vector<OverlayLayer> &layers,
+ DisplayPlaneStateList &composition,
+ bool *request_full_validation) {
+ CTRACE();
+ // Let's mark all planes as free to be used.
+ for (auto j = overlay_planes_.begin(); j != overlay_planes_.end(); ++j) {
+ j->get()->SetInUse(false);
+ }
+
+ std::vector<OverlayPlane> commit_planes;
+ for (DisplayPlaneState &temp : composition) {
+ commit_planes.emplace_back(
+ OverlayPlane(temp.plane(), temp.GetOverlayLayer()));
+ // Check if we can still need/use scalar for this plane.
+ if (temp.IsUsingPlaneScalar()) {
+ size_t total_layers = temp.source_layers().size();
+ ValidateForDisplayScaling(
+ temp, commit_planes,
+ &(layers.at(temp.source_layers().at(total_layers - 1))));
+ }
+ }
+
+ bool render_layers = false;
+ // If this combination fails just fall back to 3D for all layers.
+ if (plane_handler_->TestCommit(commit_planes)) {
+ *request_full_validation = false;
+ for (DisplayPlaneState &plane : composition) {
+ if (plane.GetCompositionState() == DisplayPlaneState::State::kRender) {
+ render_layers = true;
+ const std::vector<size_t> &source_layers = plane.source_layers();
+ size_t layers_size = source_layers.size();
+ bool useplanescalar = plane.IsUsingPlaneScalar();
+ for (size_t i = 0; i < layers_size; i++) {
+ size_t source_index = source_layers.at(i);
+ OverlayLayer &layer = layers.at(source_index);
+ layer.GPURendered();
+ layer.UsePlaneScalar(useplanescalar);
+ }
+ }
+ }
+ } else {
+ *request_full_validation = true;
+ }
+
+ return render_layers;
+}
+
DisplayPlaneState *DisplayPlaneManager::GetLastUsedOverlay(
DisplayPlaneStateList &composition) {
CTRACE();
}
void DisplayPlaneManager::ValidateForDisplayScaling(
- DisplayPlaneStateList &composition,
- std::vector<OverlayPlane> &commit_planes, OverlayLayer *current_layer) {
- DisplayPlaneState &last_plane = composition.back();
- size_t total_layers = last_plane.source_layers().size() > 1;
- // We may have cases where additional layers got added to this
- // plane for composition. Reset the state in this case.
- if (last_plane.IsUsingPlaneScalar() && total_layers > 1) {
+ DisplayPlaneState &last_plane, std::vector<OverlayPlane> &commit_planes,
+ OverlayLayer *current_layer) {
+ size_t total_layers = last_plane.source_layers().size();
+ if (last_plane.IsUsingPlaneScalar()) {
last_plane.UsePlaneScalar(false);
last_plane.ResetSourceRectToDisplayFrame();
last_plane.GetOffScreenTarget()->ResetSourceCrop(
DisplayPlaneStateList &composition,
bool request_video_effect);
+ // This can be used to quickly check if the new DisplayPlaneStateList
+ // can be succefully commited before doing a full re-validation.
+ bool ReValidateLayers(std::vector<OverlayLayer> &layers,
+ DisplayPlaneStateList &composition,
+ bool *request_full_validation);
+
// This should be called only in case of a new cursor layer
// being added and all other layers are same as previous
// frame.
void PreparePlaneForCursor(DisplayPlaneState *plane);
- void ValidateForDisplayScaling(DisplayPlaneStateList &composition,
+ void ValidateForDisplayScaling(DisplayPlaneState &last_plane,
std::vector<OverlayPlane> &commit_planes,
OverlayLayer *current_layer);
void DisplayQueue::GetCachedLayers(const std::vector<OverlayLayer>& layers,
bool cursor_layer_removed,
DisplayPlaneStateList* composition,
- bool* render_layers,
- bool* can_ignore_commit) {
+ bool* render_layers, bool* can_ignore_commit,
+ bool* re_validate_commit) {
CTRACE();
bool needs_gpu_composition = false;
bool ignore_commit = true;
+ bool needs_revalidation = false;
for (DisplayPlaneState& plane : previous_plane_state_) {
bool plane_state_render =
plane.GetCompositionState() == DisplayPlaneState::State::kRender;
for (size_t i = 0; i < layers_size; i++) {
size_t source_index = source_layers.at(i);
const OverlayLayer& layer = layers.at(source_index);
+ if (!needs_revalidation)
+ needs_revalidation = layer.NeedsRevalidation();
+
if (layer.HasDimensionsChanged()) {
last_plane.UpdateDisplayFrame(layer.GetDisplayFrame());
clear_surface = true;
if (layer->HasLayerContentChanged() || layer->HasDimensionsChanged()) {
ignore_commit = false;
}
+
+ if (!needs_revalidation) {
+ needs_revalidation = layer->NeedsRevalidation();
+ }
}
}
ignore_commit = false;
*can_ignore_commit = ignore_commit;
+ *re_validate_commit = needs_revalidation;
}
bool DisplayQueue::QueueUpdate(std::vector<HwcLayer*>& source_layers,
// Validate Overlays and Layers usage.
if (!validate_layers) {
bool can_ignore_commit = false;
+ bool request_full_validation = false;
+ bool re_validate_commit = false;
// Before forcing layer validation, check if content has changed
// if not continue showing the current buffer.
GetCachedLayers(layers, cursor_state_ & kIgnoredCursorLayer,
¤t_composition_planes, &render_layers,
- &can_ignore_commit);
- if (add_cursor_layer) {
+ &can_ignore_commit, &re_validate_commit);
+
+ // Let's re-validate if their was a request for this.
+ if (re_validate_commit) {
+ display_plane_manager_->ReValidateLayers(
+ layers, current_composition_planes, &request_full_validation);
+ }
+
+ if (request_full_validation) {
+ validate_layers = true;
+ } else if (add_cursor_layer) {
bool render_cursor = display_plane_manager_->ValidateCursorLayer(
cursor_layers, current_composition_planes);
if (!render_layers)
HandleCommitIgnored(current_composition_planes);
return true;
}
- } else {
+ }
+
+ if (validate_layers) {
if (!idle_frame)
tracker.ResetTrackerState();
void GetCachedLayers(const std::vector<OverlayLayer>& layers,
bool cursor_layer_removed,
DisplayPlaneStateList* composition, bool* render_layers,
- bool* can_ignore_commit);
+ bool* can_ignore_commit, bool* re_validate_commit);
void SetReleaseFenceToLayers(int32_t fence,
std::vector<HwcLayer*>& source_layers) const;
void UpdateSurfaceInUse(bool in_use,