| Index: components/exo/surface.cc
|
| diff --git a/components/exo/surface.cc b/components/exo/surface.cc
|
| index 3f06238588078c265ef61a1321cc270a55285072..83f5972ab85b35994a95482c15308929e82d4378 100644
|
| --- a/components/exo/surface.cc
|
| +++ b/components/exo/surface.cc
|
| @@ -41,8 +41,9 @@ bool ListContainsEntry(T& list, U key) {
|
| // Surface, public:
|
|
|
| Surface::Surface()
|
| - : needs_commit_surface_hierarchy_(false),
|
| - has_contents_(false),
|
| + : has_pending_contents_(false),
|
| + needs_commit_surface_hierarchy_(false),
|
| + update_contents_after_successful_compositing_(false),
|
| compositor_(nullptr),
|
| delegate_(nullptr) {
|
| SetLayer(new ui::Layer(ui::LAYER_SOLID_COLOR));
|
| @@ -71,6 +72,7 @@ Surface::~Surface() {
|
| void Surface::Attach(Buffer* buffer) {
|
| TRACE_EVENT1("exo", "Surface::Attach", "buffer", buffer->AsTracedValue());
|
|
|
| + has_pending_contents_ = true;
|
| pending_buffer_ = buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>();
|
| PreferredSizeChanged();
|
| }
|
| @@ -197,34 +199,41 @@ void Surface::CommitSurfaceHierarchy() {
|
| DCHECK(needs_commit_surface_hierarchy_);
|
| needs_commit_surface_hierarchy_ = false;
|
|
|
| - cc::TextureMailbox texture_mailbox;
|
| - scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
|
| - if (pending_buffer_) {
|
| - texture_mailbox_release_callback =
|
| - pending_buffer_->AcquireTextureMailbox(&texture_mailbox);
|
| + // We update contents if Attach() has been called since last commit.
|
| + if (has_pending_contents_) {
|
| + has_pending_contents_ = false;
|
| +
|
| + current_buffer_ = pending_buffer_;
|
| pending_buffer_.reset();
|
| - has_contents_ = true;
|
| - } else {
|
| - // Show solid color content if there is no pending buffer.
|
| - layer()->SetShowSolidColorContent();
|
| - has_contents_ = false;
|
| - }
|
|
|
| - if (texture_mailbox_release_callback) {
|
| - // Update layer with the new contents.
|
| - layer()->SetTextureMailbox(texture_mailbox,
|
| - texture_mailbox_release_callback.Pass(),
|
| - texture_mailbox.size_in_pixels());
|
| - layer()->SetTextureFlipped(false);
|
| - layer()->SetBounds(gfx::Rect(layer()->bounds().origin(),
|
| - texture_mailbox.size_in_pixels()));
|
| - layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains(
|
| - gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels()))));
|
| - }
|
| + cc::TextureMailbox texture_mailbox;
|
| + scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
|
| + if (current_buffer_) {
|
| + texture_mailbox_release_callback =
|
| + current_buffer_->ProduceTextureMailbox(&texture_mailbox);
|
| + }
|
|
|
| - // Schedule redraw of the damage region.
|
| - layer()->SchedulePaint(pending_damage_);
|
| - pending_damage_ = gfx::Rect();
|
| + if (texture_mailbox_release_callback) {
|
| + // Update layer with the new contents.
|
| + layer()->SetTextureMailbox(texture_mailbox,
|
| + texture_mailbox_release_callback.Pass(),
|
| + texture_mailbox.size_in_pixels());
|
| + layer()->SetTextureFlipped(false);
|
| + layer()->SetBounds(gfx::Rect(layer()->bounds().origin(),
|
| + texture_mailbox.size_in_pixels()));
|
| + layer()->SetFillsBoundsOpaquely(pending_opaque_region_.contains(
|
| + gfx::RectToSkIRect(gfx::Rect(texture_mailbox.size_in_pixels()))));
|
| + } else {
|
| + // Show solid color content if no buffer is attached or we failed
|
| + // to produce a texture mailbox for the currently attached buffer.
|
| + layer()->SetShowSolidColorContent();
|
| + layer()->SetColor(SK_ColorBLACK);
|
| + }
|
| +
|
| + // Schedule redraw of the damage region.
|
| + layer()->SchedulePaint(pending_damage_);
|
| + pending_damage_ = gfx::Rect();
|
| + }
|
|
|
| ui::Compositor* compositor = layer()->GetCompositor();
|
| if (compositor && !pending_frame_callbacks_.empty()) {
|
| @@ -322,6 +331,37 @@ void Surface::OnCompositingStarted(ui::Compositor* compositor,
|
| }
|
| }
|
|
|
| +void Surface::OnCompositingEnded(ui::Compositor* compositor) {
|
| + // Nothing to do in here unless this has been set.
|
| + if (!update_contents_after_successful_compositing_)
|
| + return;
|
| +
|
| + update_contents_after_successful_compositing_ = false;
|
| +
|
| + // Early out if no contents is currently assigned to the surface.
|
| + if (!current_buffer_)
|
| + return;
|
| +
|
| + // Update contents by producing a new texture mailbox for the current buffer.
|
| + cc::TextureMailbox texture_mailbox;
|
| + scoped_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback =
|
| + current_buffer_->ProduceTextureMailbox(&texture_mailbox);
|
| + if (texture_mailbox_release_callback) {
|
| + layer()->SetTextureMailbox(texture_mailbox,
|
| + texture_mailbox_release_callback.Pass(),
|
| + texture_mailbox.size_in_pixels());
|
| + layer()->SetTextureFlipped(false);
|
| + layer()->SchedulePaint(gfx::Rect(texture_mailbox.size_in_pixels()));
|
| + }
|
| +}
|
| +
|
| +void Surface::OnCompositingAborted(ui::Compositor* compositor) {
|
| + // The contents of this surface might be lost if compositing aborted because
|
| + // of a lost graphics context. We recover from this by updating the contents
|
| + // of the surface next time the compositor successfully ends compositing.
|
| + update_contents_after_successful_compositing_ = true;
|
| +}
|
| +
|
| void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) {
|
| compositor->RemoveObserver(this);
|
| compositor_ = nullptr;
|
|
|