Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(220)

Unified Diff: components/exo/surface.cc

Issue 2041193006: exo: Only create new SurfaceLayer if layer properties change. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « components/exo/surface.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: components/exo/surface.cc
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 3d990bbc18a5e29f949a0cf1b308df3e0a248ca0..eebd302c0fc36371c9648af7092edbbf4dd73207 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -189,14 +189,6 @@ void SurfaceFactoryOwner::SetBeginFrameSource(
Surface::Surface()
: window_(new aura::Window(new CustomWindowDelegate(this))),
has_pending_contents_(false),
- pending_input_region_(SkIRect::MakeLargest()),
- pending_buffer_scale_(1.0f),
- pending_only_visible_on_secure_output_(false),
- only_visible_on_secure_output_(false),
- pending_blend_mode_(SkXfermode::kSrcOver_Mode),
- pending_alpha_(1.0f),
- alpha_(1.0f),
- input_region_(SkIRect::MakeLargest()),
needs_commit_surface_hierarchy_(false),
update_contents_after_successful_compositing_(false),
compositor_(nullptr),
@@ -283,20 +275,20 @@ void Surface::SetOpaqueRegion(const SkRegion& region) {
TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region",
gfx::SkIRectToRect(region.getBounds()).ToString());
- pending_opaque_region_ = region;
+ pending_state_.opaque_region = region;
}
void Surface::SetInputRegion(const SkRegion& region) {
TRACE_EVENT1("exo", "Surface::SetInputRegion", "region",
gfx::SkIRectToRect(region.getBounds()).ToString());
- pending_input_region_ = region;
+ pending_state_.input_region = region;
}
void Surface::SetBufferScale(float scale) {
TRACE_EVENT1("exo", "Surface::SetBufferScale", "scale", scale);
- pending_buffer_scale_ = scale;
+ pending_state_.buffer_scale = scale;
}
void Surface::AddSubSurface(Surface* sub_surface) {
@@ -309,6 +301,7 @@ void Surface::AddSubSurface(Surface* sub_surface) {
DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface));
pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
+ has_pending_layer_changes_ = true;
}
void Surface::RemoveSubSurface(Surface* sub_surface) {
@@ -322,6 +315,7 @@ void Surface::RemoveSubSurface(Surface* sub_surface) {
DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
pending_sub_surfaces_.erase(
FindListEntry(pending_sub_surfaces_, sub_surface));
+ has_pending_layer_changes_ = true;
}
void Surface::SetSubSurfacePosition(Surface* sub_surface,
@@ -331,7 +325,10 @@ void Surface::SetSubSurfacePosition(Surface* sub_surface,
auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
DCHECK(it != pending_sub_surfaces_.end());
+ if (it->second == position)
+ return;
it->second = position;
+ has_pending_layer_changes_ = true;
}
void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
@@ -359,9 +356,11 @@ void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
}
DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
- pending_sub_surfaces_.splice(
- position_it, pending_sub_surfaces_,
- FindListEntry(pending_sub_surfaces_, sub_surface));
+ auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
+ if (it == position_it)
+ return;
+ pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it);
+ has_pending_layer_changes_ = true;
}
void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
@@ -382,40 +381,42 @@ void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
}
DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
- pending_sub_surfaces_.splice(
- sibling_it, pending_sub_surfaces_,
- FindListEntry(pending_sub_surfaces_, sub_surface));
+ auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
+ if (it == sibling_it)
+ return;
+ pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it);
+ has_pending_layer_changes_ = true;
}
void Surface::SetViewport(const gfx::Size& viewport) {
TRACE_EVENT1("exo", "Surface::SetViewport", "viewport", viewport.ToString());
- pending_viewport_ = viewport;
+ pending_state_.viewport = viewport;
}
void Surface::SetCrop(const gfx::RectF& crop) {
TRACE_EVENT1("exo", "Surface::SetCrop", "crop", crop.ToString());
- pending_crop_ = crop;
+ pending_state_.crop = crop;
}
void Surface::SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output) {
TRACE_EVENT1("exo", "Surface::SetOnlyVisibleOnSecureOutput",
"only_visible_on_secure_output", only_visible_on_secure_output);
- pending_only_visible_on_secure_output_ = only_visible_on_secure_output;
+ pending_state_.only_visible_on_secure_output = only_visible_on_secure_output;
}
void Surface::SetBlendMode(SkXfermode::Mode blend_mode) {
TRACE_EVENT1("exo", "Surface::SetBlendMode", "blend_mode", blend_mode);
- pending_blend_mode_ = blend_mode;
+ pending_state_.blend_mode = blend_mode;
}
void Surface::SetAlpha(float alpha) {
TRACE_EVENT1("exo", "Surface::SetAlpha", "alpha", alpha);
- pending_alpha_ = alpha;
+ pending_state_.alpha = alpha;
}
void Surface::Commit() {
@@ -423,27 +424,33 @@ void Surface::Commit() {
needs_commit_surface_hierarchy_ = true;
- if (delegate_)
+ if (state_ != pending_state_)
+ has_pending_layer_changes_ = true;
+
+ if (has_pending_contents_) {
+ if (pending_buffer_ &&
+ (current_resource_.size != pending_buffer_->GetSize())) {
+ has_pending_layer_changes_ = true;
+ } else if (!pending_buffer_ && !current_resource_.size.IsEmpty()) {
+ has_pending_layer_changes_ = true;
+ }
+ }
+
+ if (delegate_) {
delegate_->OnSurfaceCommit();
- else
+ } else {
+ CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
CommitSurfaceHierarchy();
+ }
}
void Surface::CommitSurfaceHierarchy() {
DCHECK(needs_commit_surface_hierarchy_);
needs_commit_surface_hierarchy_ = false;
+ has_pending_layer_changes_ = false;
- // TODO(dcastagna): Make secure_output_only a layer property instead of a
- // texture mailbox flag so this can be changed without have to provide
- // new contents.
- only_visible_on_secure_output_ = pending_only_visible_on_secure_output_;
- pending_only_visible_on_secure_output_ = false;
-
- // Update current alpha.
- alpha_ = pending_alpha_;
-
- // Update current crop rectangle.
- crop_ = pending_crop_;
+ state_ = pending_state_;
+ pending_state_.only_visible_on_secure_output = false;
if (factory_owner_) {
CommitSurfaceContents();
@@ -451,9 +458,6 @@ void Surface::CommitSurfaceHierarchy() {
CommitTextureContents();
}
- // Update current input region.
- input_region_ = pending_input_region_;
-
// Synchronize window hierarchy. This will position and update the stacking
// order of all sub-surfaces after committing all pending state of sub-surface
// descendants.
@@ -490,7 +494,7 @@ bool Surface::IsSynchronized() const {
}
gfx::Rect Surface::GetHitTestBounds() const {
- SkIRect bounds = input_region_.getBounds();
+ SkIRect bounds = state_.input_region.getBounds();
if (!bounds.intersect(
gfx::RectToSkIRect(gfx::Rect(window_->layer()->size()))))
return gfx::Rect();
@@ -499,18 +503,18 @@ gfx::Rect Surface::GetHitTestBounds() const {
bool Surface::HitTestRect(const gfx::Rect& rect) const {
if (HasHitTestMask())
- return input_region_.intersects(gfx::RectToSkIRect(rect));
+ return state_.input_region.intersects(gfx::RectToSkIRect(rect));
return rect.Intersects(gfx::Rect(window_->layer()->size()));
}
bool Surface::HasHitTestMask() const {
- return !input_region_.contains(
+ return !state_.input_region.contains(
gfx::RectToSkIRect(gfx::Rect(window_->layer()->size())));
}
void Surface::GetHitTestMask(gfx::Path* mask) const {
- input_region_.getBoundaryPath(mask);
+ state_.input_region.getBoundaryPath(mask);
}
void Surface::RegisterCursorProvider(Pointer* provider) {
@@ -640,6 +644,41 @@ void Surface::WillDraw(cc::SurfaceId id) {
}
}
+void Surface::CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces() {
+ if (HasLayerHierarchyChanged())
+ SetSurfaceHierarchyNeedsCommitToNewSurfaces();
+}
+
+Surface::State::State() : input_region(SkIRect::MakeLargest()) {}
+
+Surface::State::~State() = default;
+
+bool Surface::State::operator==(const State& other) {
+ return (other.crop == crop && alpha == other.alpha &&
+ other.blend_mode == blend_mode && other.viewport == viewport &&
+ other.opaque_region == opaque_region &&
+ other.buffer_scale == buffer_scale &&
+ other.input_region == input_region);
+}
+
+bool Surface::HasLayerHierarchyChanged() const {
+ if (needs_commit_surface_hierarchy_ && has_pending_layer_changes_)
+ return true;
+
+ for (const auto& sub_surface_entry : pending_sub_surfaces_) {
+ if (sub_surface_entry.first->HasLayerHierarchyChanged())
+ return true;
+ }
+ return false;
+}
+
+void Surface::SetSurfaceHierarchyNeedsCommitToNewSurfaces() {
+ needs_commit_to_new_surface_ = true;
+ for (auto& sub_surface_entry : pending_sub_surfaces_) {
+ sub_surface_entry.first->SetSurfaceHierarchyNeedsCommitToNewSurfaces();
+ }
+}
+
void Surface::CommitTextureContents() {
// We update contents if Attach() has been called since last commit.
if (has_pending_contents_) {
@@ -652,14 +691,14 @@ void Surface::CommitTextureContents() {
std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
if (current_buffer_) {
texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
- &texture_mailbox, only_visible_on_secure_output_,
+ &texture_mailbox, state_.only_visible_on_secure_output,
true /* client_usage */);
}
// Update layer with the new contents.
if (texture_mailbox_release_callback) {
texture_size_in_dip_ = gfx::ScaleToFlooredSize(
- texture_mailbox.size_in_pixels(), 1.0f / pending_buffer_scale_);
+ texture_mailbox.size_in_pixels(), 1.0f / state_.buffer_scale);
window_->layer()->SetTextureMailbox(
texture_mailbox, std::move(texture_mailbox_release_callback),
texture_size_in_dip_);
@@ -685,22 +724,22 @@ void Surface::CommitTextureContents() {
// - If a viewport is set then that defines the size, otherwise
// the crop rectangle defines the size if set.
gfx::Size contents_size = texture_size_in_dip_;
- if (!pending_viewport_.IsEmpty()) {
- contents_size = pending_viewport_;
- } else if (!crop_.IsEmpty()) {
- DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(crop_.width()) ||
- !gfx::IsExpressibleAsInt(crop_.height()))
- << "Crop rectangle size (" << crop_.size().ToString()
+ if (!state_.viewport.IsEmpty()) {
+ contents_size = state_.viewport;
+ } else if (!state_.crop.IsEmpty()) {
+ DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
+ !gfx::IsExpressibleAsInt(state_.crop.height()))
+ << "Crop rectangle size (" << state_.crop.size().ToString()
<< ") most be expressible using integers when viewport is not set";
- contents_size = gfx::ToCeiledSize(crop_.size());
+ contents_size = gfx::ToCeiledSize(state_.crop.size());
}
- window_->layer()->SetTextureCrop(crop_);
+ window_->layer()->SetTextureCrop(state_.crop);
window_->layer()->SetTextureScale(
static_cast<float>(texture_size_in_dip_.width()) /
contents_size.width(),
static_cast<float>(texture_size_in_dip_.height()) /
contents_size.height());
- window_->layer()->SetTextureAlpha(alpha_);
+ window_->layer()->SetTextureAlpha(state_.alpha);
window_->layer()->SetBounds(
gfx::Rect(window_->layer()->bounds().origin(), contents_size));
}
@@ -712,8 +751,8 @@ void Surface::CommitTextureContents() {
// TODO(reveman): Use a more reliable way to force blending off than setting
// fills-bounds-opaquely.
window_->layer()->SetFillsBoundsOpaquely(
- pending_blend_mode_ == SkXfermode::kSrc_Mode ||
- pending_opaque_region_.contains(
+ state_.blend_mode == SkXfermode::kSrc_Mode ||
+ state_.opaque_region.contains(
gfx::RectToSkIRect(gfx::Rect(window_->layer()->size()))));
}
@@ -730,7 +769,7 @@ void Surface::CommitSurfaceContents() {
cc::TextureMailbox texture_mailbox;
texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
- &texture_mailbox, only_visible_on_secure_output_,
+ &texture_mailbox, state_.only_visible_on_secure_output,
true /* client_usage */);
cc::TransferableResource resource;
resource.id = next_resource_id_++;
@@ -753,22 +792,25 @@ void Surface::CommitSurfaceContents() {
}
cc::SurfaceId old_surface_id = surface_id_;
- surface_id_ = factory_owner_->id_allocator_->GenerateId();
- factory_owner_->surface_factory_->Create(surface_id_);
+ if (needs_commit_to_new_surface_ || surface_id_.is_null()) {
+ needs_commit_to_new_surface_ = false;
+ surface_id_ = factory_owner_->id_allocator_->GenerateId();
+ factory_owner_->surface_factory_->Create(surface_id_);
+ }
gfx::Size buffer_size = current_resource_.size;
gfx::SizeF scaled_buffer_size(
- gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / pending_buffer_scale_));
+ gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
gfx::Size layer_size; // Size of the output layer, in DIP.
- if (!pending_viewport_.IsEmpty()) {
- layer_size = pending_viewport_;
- } else if (!crop_.IsEmpty()) {
- DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(crop_.width()) ||
- !gfx::IsExpressibleAsInt(crop_.height()))
- << "Crop rectangle size (" << crop_.size().ToString()
+ if (!state_.viewport.IsEmpty()) {
+ layer_size = state_.viewport;
+ } else if (!state_.crop.IsEmpty()) {
+ DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
+ !gfx::IsExpressibleAsInt(state_.crop.height()))
+ << "Crop rectangle size (" << state_.crop.size().ToString()
<< ") most be expressible using integers when viewport is not set";
- layer_size = gfx::ToCeiledSize(crop_.size());
+ layer_size = gfx::ToCeiledSize(state_.crop.size());
} else {
layer_size = gfx::ToCeiledSize(scaled_buffer_size);
}
@@ -780,12 +822,12 @@ void Surface::CommitSurfaceContents() {
gfx::PointF uv_top_left(0.f, 0.f);
gfx::PointF uv_bottom_right(1.f, 1.f);
- if (!crop_.IsEmpty()) {
- uv_top_left = crop_.origin();
+ if (!state_.crop.IsEmpty()) {
+ uv_top_left = state_.crop.origin();
uv_top_left.Scale(1.f / scaled_buffer_size.width(),
1.f / scaled_buffer_size.height());
- uv_bottom_right = crop_.bottom_right();
+ uv_bottom_right = state_.crop.bottom_right();
uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
1.f / scaled_buffer_size.height());
}
@@ -802,7 +844,7 @@ void Surface::CommitSurfaceContents() {
render_pass->CreateAndAppendSharedQuadState();
quad_state->quad_layer_bounds = contents_surface_size;
quad_state->visible_quad_layer_rect = quad_rect;
- quad_state->opacity = alpha_;
+ quad_state->opacity = state_.alpha;
bool frame_is_opaque = false;
@@ -814,18 +856,18 @@ void Surface::CommitSurfaceContents() {
float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
gfx::Rect opaque_rect;
frame_is_opaque =
- pending_blend_mode_ == SkXfermode::kSrc_Mode ||
- pending_opaque_region_.contains(gfx::RectToSkIRect(quad_rect));
+ state_.blend_mode == SkXfermode::kSrc_Mode ||
+ state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
if (frame_is_opaque) {
opaque_rect = quad_rect;
- } else if (pending_opaque_region_.isRect()) {
- opaque_rect = gfx::SkIRectToRect(pending_opaque_region_.getBounds());
+ } else if (state_.opaque_region.isRect()) {
+ opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
}
texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
current_resource_.id, true, uv_top_left,
uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
- false, false, only_visible_on_secure_output_);
+ false, false, state_.only_visible_on_secure_output);
delegated_frame->resource_list.push_back(current_resource_);
} else {
cc::SolidColorDrawQuad* solid_quad =
@@ -841,20 +883,23 @@ void Surface::CommitSurfaceContents() {
factory_owner_->surface_factory_->SubmitCompositorFrame(
surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
- if (!old_surface_id.is_null()) {
+ if (!old_surface_id.is_null() && old_surface_id != surface_id_) {
factory_owner_->surface_factory_->SetPreviousFrameSurface(surface_id_,
old_surface_id);
factory_owner_->surface_factory_->Destroy(old_surface_id);
}
- window_->layer()->SetShowSurface(
- surface_id_,
- base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)),
- base::Bind(&RequireCallback, base::Unretained(surface_manager_)),
- contents_surface_size, contents_surface_to_layer_scale, layer_size);
- window_->layer()->SetBounds(
- gfx::Rect(window_->layer()->bounds().origin(), layer_size));
- window_->layer()->SetFillsBoundsOpaquely(alpha_ == 1.0f && frame_is_opaque);
+ if (old_surface_id != surface_id_) {
+ window_->layer()->SetShowSurface(
+ surface_id_,
+ base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)),
+ base::Bind(&RequireCallback, base::Unretained(surface_manager_)),
+ contents_surface_size, contents_surface_to_layer_scale, layer_size);
+ window_->layer()->SetBounds(
+ gfx::Rect(window_->layer()->bounds().origin(), layer_size));
+ window_->layer()->SetFillsBoundsOpaquely(state_.alpha == 1.0f &&
+ frame_is_opaque);
+ }
// Reset damage.
pending_damage_.setEmpty();
@@ -872,9 +917,9 @@ void Surface::SetTextureLayerContents(ui::Layer* layer) {
cc::TextureMailbox texture_mailbox;
std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback =
- current_buffer_->ProduceTextureMailbox(&texture_mailbox,
- only_visible_on_secure_output_,
- false /* client_usage */);
+ current_buffer_->ProduceTextureMailbox(
+ &texture_mailbox, state_.only_visible_on_secure_output,
+ false /* client_usage */);
if (!texture_mailbox_release_callback)
return;
@@ -882,12 +927,12 @@ void Surface::SetTextureLayerContents(ui::Layer* layer) {
std::move(texture_mailbox_release_callback),
texture_size_in_dip_);
layer->SetTextureFlipped(false);
- layer->SetTextureCrop(crop_);
+ layer->SetTextureCrop(state_.crop);
layer->SetTextureScale(static_cast<float>(texture_size_in_dip_.width()) /
layer->bounds().width(),
static_cast<float>(texture_size_in_dip_.height()) /
layer->bounds().height());
- layer->SetTextureAlpha(alpha_);
+ layer->SetTextureAlpha(state_.alpha);
}
void Surface::SetSurfaceLayerContents(ui::Layer* layer) {
« no previous file with comments | « components/exo/surface.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698