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

Unified Diff: components/exo/surface.cc

Issue 2083853002: exo: Recreate Surface resources on context lost. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Make ContextFactory pure; hold on to buffer reference 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
Index: components/exo/surface.cc
diff --git a/components/exo/surface.cc b/components/exo/surface.cc
index 2c2edd9124da2357f6f60c5ee8a306628f7ea24e..8f74693c09101646ab0792a43d7bcc3a01cfa341 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -206,9 +206,11 @@ Surface::Surface()
aura::Env::GetInstance()->context_factory()->CreateSurfaceIdAllocator();
factory_owner_->surface_factory_.reset(
new cc::SurfaceFactory(surface_manager_, factory_owner_.get()));
+ aura::Env::GetInstance()->context_factory()->AddObserver(this);
}
Surface::~Surface() {
+ aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this));
window_->layer()->SetShowSolidColorContent();
@@ -425,6 +427,14 @@ void Surface::Commit() {
}
}
+void Surface::OnLostResources() {
+ if (surface_id_.is_null())
+ return;
+
+ CreateResource(false);
+ UpdateSurface(false);
+}
+
void Surface::CommitSurfaceHierarchy() {
DCHECK(needs_commit_surface_hierarchy_);
needs_commit_surface_hierarchy_ = false;
@@ -434,39 +444,12 @@ void Surface::CommitSurfaceHierarchy() {
pending_state_.only_visible_on_secure_output = false;
// We update contents if Attach() has been called since last commit.
- // TODO(jbauman): Support producing a new texture mailbox after lost
- // context.
if (has_pending_contents_) {
has_pending_contents_ = false;
current_buffer_ = pending_buffer_;
pending_buffer_.reset();
- if (current_buffer_) {
- std::unique_ptr<cc::SingleReleaseCallback>
- texture_mailbox_release_callback;
-
- cc::TextureMailbox texture_mailbox;
- texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
- &texture_mailbox, state_.only_visible_on_secure_output,
- true /* client_usage */);
- cc::TransferableResource resource;
- resource.id = next_resource_id_++;
- resource.format = cc::RGBA_8888;
- resource.filter =
- texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
- resource.size = texture_mailbox.size_in_pixels();
- resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(),
- texture_mailbox.sync_token(),
- texture_mailbox.target());
- resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate();
-
- factory_owner_->release_callbacks_[resource.id] = std::make_pair(
- factory_owner_, std::move(texture_mailbox_release_callback));
- current_resource_ = resource;
- } else {
- current_resource_.id = 0;
- current_resource_.size = gfx::Size();
- }
+ CreateResource(true);
}
cc::SurfaceId old_surface_id = surface_id_;
@@ -476,90 +459,7 @@ void Surface::CommitSurfaceHierarchy() {
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 / state_.buffer_scale));
-
- gfx::Size layer_size; // Size of the output layer, in DIP.
- 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(state_.crop.size());
- } else {
- layer_size = gfx::ToCeiledSize(scaled_buffer_size);
- }
-
- // TODO(jbauman): Figure out how this interacts with the pixel size of
- // CopyOutputRequests on the layer.
- float contents_surface_to_layer_scale = 1.0;
- gfx::Size contents_surface_size = layer_size;
-
- gfx::PointF uv_top_left(0.f, 0.f);
- gfx::PointF uv_bottom_right(1.f, 1.f);
- 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 = state_.crop.bottom_right();
- uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
- 1.f / scaled_buffer_size.height());
- }
-
- // pending_damage_ is in Surface coordinates.
- gfx::Rect damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
-
- std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
- render_pass->SetAll(cc::RenderPassId(1, 1), gfx::Rect(contents_surface_size),
- damage_rect, gfx::Transform(), true);
-
- gfx::Rect quad_rect = gfx::Rect(contents_surface_size);
- cc::SharedQuadState* quad_state =
- render_pass->CreateAndAppendSharedQuadState();
- quad_state->quad_layer_bounds = contents_surface_size;
- quad_state->visible_quad_layer_rect = quad_rect;
- quad_state->opacity = state_.alpha;
-
- bool frame_is_opaque = false;
-
- std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
- new cc::DelegatedFrameData);
- if (current_resource_.id) {
- cc::TextureDrawQuad* texture_quad =
- render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
- float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
- gfx::Rect opaque_rect;
- frame_is_opaque =
- state_.blend_mode == SkXfermode::kSrc_Mode ||
- state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
- if (frame_is_opaque) {
- opaque_rect = quad_rect;
- } 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, state_.only_visible_on_secure_output);
- delegated_frame->resource_list.push_back(current_resource_);
- } else {
- cc::SolidColorDrawQuad* solid_quad =
- render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
- solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
- frame_is_opaque = true;
- }
-
- delegated_frame->render_pass_list.push_back(std::move(render_pass));
- std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- frame->delegated_frame_data = std::move(delegated_frame);
-
- factory_owner_->surface_factory_->SubmitCompositorFrame(
- surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
+ UpdateSurface(true);
if (!old_surface_id.is_null() && old_surface_id != surface_id_) {
factory_owner_->surface_factory_->SetPreviousFrameSurface(surface_id_,
@@ -567,18 +467,17 @@ void Surface::CommitSurfaceHierarchy() {
factory_owner_->surface_factory_->Destroy(old_surface_id);
}
- content_size_ = layer_size;
-
if (old_surface_id != surface_id_) {
+ float contents_surface_to_layer_scale = 1.0;
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);
+ content_size_, contents_surface_to_layer_scale, content_size_);
window_->layer()->SetBounds(
- gfx::Rect(window_->layer()->bounds().origin(), layer_size));
+ gfx::Rect(window_->layer()->bounds().origin(), content_size_));
window_->layer()->SetFillsBoundsOpaquely(state_.alpha == 1.0f &&
- frame_is_opaque);
+ frame_is_opaque_);
}
// Reset damage.
@@ -757,6 +656,130 @@ void Surface::SetSurfaceLayerContents(ui::Layer* layer) {
layer_size, contents_surface_to_layer_scale, layer_size);
}
+void Surface::CreateResource(bool for_commit) {
reveman 2016/06/22 17:15:26 nit: s/for_commit/client_usage/
jbauman 2016/06/22 23:45:48 Done.
+ std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
+
+ cc::TextureMailbox texture_mailbox;
+ if (current_buffer_) {
+ base::Closure new_buffer_release_callback;
+ texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
reveman 2016/06/22 17:15:26 What would it look like if we moved this ProduceTe
jbauman 2016/06/22 23:45:48 There's still some duplication of checking only_vi
+ &texture_mailbox, state_.only_visible_on_secure_output,
+ for_commit /* client_usage */, &new_buffer_release_callback);
+ current_buffer_release_runner_.Reset(new_buffer_release_callback);
+ } else {
+ current_buffer_release_runner_.Reset();
+ }
+
+ if (texture_mailbox_release_callback) {
+ cc::TransferableResource resource;
+ resource.id = next_resource_id_++;
+ resource.format = cc::RGBA_8888;
+ resource.filter =
+ texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
+ resource.size = texture_mailbox.size_in_pixels();
+ resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(),
+ texture_mailbox.sync_token(),
+ texture_mailbox.target());
+ resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate();
+
+ factory_owner_->release_callbacks_[resource.id] = std::make_pair(
+ factory_owner_, std::move(texture_mailbox_release_callback));
+ current_resource_ = resource;
+ } else {
+ current_resource_.id = 0;
+ current_resource_.size = gfx::Size();
+ }
+}
+
+void Surface::UpdateSurface(bool for_commit) {
+ gfx::Size buffer_size = current_resource_.size;
+ gfx::SizeF scaled_buffer_size(
+ gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
+
+ gfx::Size layer_size; // Size of the output layer, in DIP.
+ 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(state_.crop.size());
+ } else {
+ layer_size = gfx::ToCeiledSize(scaled_buffer_size);
+ }
+
+ content_size_ = layer_size;
+ // TODO(jbauman): Figure out how this interacts with the pixel size of
+ // CopyOutputRequests on the layer.
+ gfx::Size contents_surface_size = layer_size;
+
+ gfx::PointF uv_top_left(0.f, 0.f);
+ gfx::PointF uv_bottom_right(1.f, 1.f);
+ 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 = state_.crop.bottom_right();
+ uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
+ 1.f / scaled_buffer_size.height());
+ }
+
+ // pending_damage_ is in Surface coordinates.
+ gfx::Rect damage_rect = for_commit
+ ? gfx::SkIRectToRect(pending_damage_.getBounds())
+ : gfx::Rect(contents_surface_size);
+
+ std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
+ render_pass->SetAll(cc::RenderPassId(1, 1), gfx::Rect(contents_surface_size),
+ damage_rect, gfx::Transform(), true);
+
+ gfx::Rect quad_rect = gfx::Rect(contents_surface_size);
+ cc::SharedQuadState* quad_state =
+ render_pass->CreateAndAppendSharedQuadState();
+ quad_state->quad_layer_bounds = contents_surface_size;
+ quad_state->visible_quad_layer_rect = quad_rect;
+ quad_state->opacity = state_.alpha;
+
+ frame_is_opaque_ = false;
+
+ std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
+ new cc::DelegatedFrameData);
+ if (current_resource_.id) {
+ cc::TextureDrawQuad* texture_quad =
+ render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
+ float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
+ gfx::Rect opaque_rect;
+ frame_is_opaque_ =
+ state_.blend_mode == SkXfermode::kSrc_Mode ||
+ state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
+ if (frame_is_opaque_) {
+ opaque_rect = quad_rect;
+ } 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, state_.only_visible_on_secure_output);
+ delegated_frame->resource_list.push_back(current_resource_);
+ } else {
+ cc::SolidColorDrawQuad* solid_quad =
+ render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
+ solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
+ frame_is_opaque_ = true;
+ }
+
+ delegated_frame->render_pass_list.push_back(std::move(render_pass));
+ std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ frame->delegated_frame_data = std::move(delegated_frame);
+
+ factory_owner_->surface_factory_->SubmitCompositorFrame(
+ surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
+}
+
int64_t Surface::SetPropertyInternal(const void* key,
const char* name,
PropertyDeallocator deallocator,

Powered by Google App Engine
This is Rietveld 408576698