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

Side by Side 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: fix browser test 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 unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/exo/surface.h" 5 #include "components/exo/surface.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/callback_helpers.h" 9 #include "base/callback_helpers.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 window_->SetProperty(kSurfaceKey, this); 199 window_->SetProperty(kSurfaceKey, this);
200 window_->Init(ui::LAYER_SOLID_COLOR); 200 window_->Init(ui::LAYER_SOLID_COLOR);
201 window_->set_layer_owner_delegate(this); 201 window_->set_layer_owner_delegate(this);
202 window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter)); 202 window_->SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
203 window_->set_owned_by_parent(false); 203 window_->set_owned_by_parent(false);
204 factory_owner_->surface_ = this; 204 factory_owner_->surface_ = this;
205 factory_owner_->id_allocator_ = 205 factory_owner_->id_allocator_ =
206 aura::Env::GetInstance()->context_factory()->CreateSurfaceIdAllocator(); 206 aura::Env::GetInstance()->context_factory()->CreateSurfaceIdAllocator();
207 factory_owner_->surface_factory_.reset( 207 factory_owner_->surface_factory_.reset(
208 new cc::SurfaceFactory(surface_manager_, factory_owner_.get())); 208 new cc::SurfaceFactory(surface_manager_, factory_owner_.get()));
209 aura::Env::GetInstance()->context_factory()->AddObserver(this);
209 } 210 }
210 211
211 Surface::~Surface() { 212 Surface::~Surface() {
213 aura::Env::GetInstance()->context_factory()->RemoveObserver(this);
212 FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this)); 214 FOR_EACH_OBSERVER(SurfaceObserver, observers_, OnSurfaceDestroying(this));
213 215
214 window_->layer()->SetShowSolidColorContent(); 216 window_->layer()->SetShowSolidColorContent();
215 217
216 factory_owner_->surface_ = nullptr; 218 factory_owner_->surface_ = nullptr;
217 219
218 // Call pending frame callbacks with a null frame time to indicate that they 220 // Call pending frame callbacks with a null frame time to indicate that they
219 // have been cancelled. 221 // have been cancelled.
220 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); 222 frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_);
221 active_frame_callbacks_.splice(active_frame_callbacks_.end(), 223 active_frame_callbacks_.splice(active_frame_callbacks_.end(),
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 } 420 }
419 421
420 if (delegate_) { 422 if (delegate_) {
421 delegate_->OnSurfaceCommit(); 423 delegate_->OnSurfaceCommit();
422 } else { 424 } else {
423 CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces(); 425 CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
424 CommitSurfaceHierarchy(); 426 CommitSurfaceHierarchy();
425 } 427 }
426 } 428 }
427 429
430 void Surface::OnLostResources() {
431 if (surface_id_.is_null())
432 return;
433
434 CreateResource(false);
435 UpdateSurface(false);
436 }
437
428 void Surface::CommitSurfaceHierarchy() { 438 void Surface::CommitSurfaceHierarchy() {
429 DCHECK(needs_commit_surface_hierarchy_); 439 DCHECK(needs_commit_surface_hierarchy_);
430 needs_commit_surface_hierarchy_ = false; 440 needs_commit_surface_hierarchy_ = false;
431 has_pending_layer_changes_ = false; 441 has_pending_layer_changes_ = false;
432 442
433 state_ = pending_state_; 443 state_ = pending_state_;
434 pending_state_.only_visible_on_secure_output = false; 444 pending_state_.only_visible_on_secure_output = false;
435 445
436 // We update contents if Attach() has been called since last commit. 446 // We update contents if Attach() has been called since last commit.
437 // TODO(jbauman): Support producing a new texture mailbox after lost
438 // context.
439 if (has_pending_contents_) { 447 if (has_pending_contents_) {
440 has_pending_contents_ = false; 448 has_pending_contents_ = false;
441 current_buffer_ = pending_buffer_; 449 current_buffer_ = pending_buffer_;
442 pending_buffer_.reset(); 450 pending_buffer_.reset();
443 451
444 if (current_buffer_) { 452 CreateResource(true);
445 std::unique_ptr<cc::SingleReleaseCallback>
446 texture_mailbox_release_callback;
447
448 cc::TextureMailbox texture_mailbox;
449 texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
450 &texture_mailbox, state_.only_visible_on_secure_output,
451 true /* client_usage */);
452 cc::TransferableResource resource;
453 resource.id = next_resource_id_++;
454 resource.format = cc::RGBA_8888;
455 resource.filter =
456 texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
457 resource.size = texture_mailbox.size_in_pixels();
458 resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(),
459 texture_mailbox.sync_token(),
460 texture_mailbox.target());
461 resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate();
462
463 factory_owner_->release_callbacks_[resource.id] = std::make_pair(
464 factory_owner_, std::move(texture_mailbox_release_callback));
465 current_resource_ = resource;
466 } else {
467 current_resource_.id = 0;
468 current_resource_.size = gfx::Size();
469 }
470 } 453 }
471 454
472 cc::SurfaceId old_surface_id = surface_id_; 455 cc::SurfaceId old_surface_id = surface_id_;
473 if (needs_commit_to_new_surface_ || surface_id_.is_null()) { 456 if (needs_commit_to_new_surface_ || surface_id_.is_null()) {
474 needs_commit_to_new_surface_ = false; 457 needs_commit_to_new_surface_ = false;
475 surface_id_ = factory_owner_->id_allocator_->GenerateId(); 458 surface_id_ = factory_owner_->id_allocator_->GenerateId();
476 factory_owner_->surface_factory_->Create(surface_id_); 459 factory_owner_->surface_factory_->Create(surface_id_);
477 } 460 }
478 461
479 gfx::Size buffer_size = current_resource_.size; 462 UpdateSurface(true);
480 gfx::SizeF scaled_buffer_size(
481 gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
482
483 gfx::Size layer_size; // Size of the output layer, in DIP.
484 if (!state_.viewport.IsEmpty()) {
485 layer_size = state_.viewport;
486 } else if (!state_.crop.IsEmpty()) {
487 DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
488 !gfx::IsExpressibleAsInt(state_.crop.height()))
489 << "Crop rectangle size (" << state_.crop.size().ToString()
490 << ") most be expressible using integers when viewport is not set";
491 layer_size = gfx::ToCeiledSize(state_.crop.size());
492 } else {
493 layer_size = gfx::ToCeiledSize(scaled_buffer_size);
494 }
495
496 // TODO(jbauman): Figure out how this interacts with the pixel size of
497 // CopyOutputRequests on the layer.
498 float contents_surface_to_layer_scale = 1.0;
499 gfx::Size contents_surface_size = layer_size;
500
501 gfx::PointF uv_top_left(0.f, 0.f);
502 gfx::PointF uv_bottom_right(1.f, 1.f);
503 if (!state_.crop.IsEmpty()) {
504 uv_top_left = state_.crop.origin();
505
506 uv_top_left.Scale(1.f / scaled_buffer_size.width(),
507 1.f / scaled_buffer_size.height());
508 uv_bottom_right = state_.crop.bottom_right();
509 uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
510 1.f / scaled_buffer_size.height());
511 }
512
513 // pending_damage_ is in Surface coordinates.
514 gfx::Rect damage_rect = gfx::SkIRectToRect(pending_damage_.getBounds());
515
516 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
517 render_pass->SetAll(cc::RenderPassId(1, 1), gfx::Rect(contents_surface_size),
518 damage_rect, gfx::Transform(), true);
519
520 gfx::Rect quad_rect = gfx::Rect(contents_surface_size);
521 cc::SharedQuadState* quad_state =
522 render_pass->CreateAndAppendSharedQuadState();
523 quad_state->quad_layer_bounds = contents_surface_size;
524 quad_state->visible_quad_layer_rect = quad_rect;
525 quad_state->opacity = state_.alpha;
526
527 bool frame_is_opaque = false;
528
529 std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
530 new cc::DelegatedFrameData);
531 if (current_resource_.id) {
532 cc::TextureDrawQuad* texture_quad =
533 render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
534 float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
535 gfx::Rect opaque_rect;
536 frame_is_opaque =
537 state_.blend_mode == SkXfermode::kSrc_Mode ||
538 state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
539 if (frame_is_opaque) {
540 opaque_rect = quad_rect;
541 } else if (state_.opaque_region.isRect()) {
542 opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
543 }
544
545 texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
546 current_resource_.id, true, uv_top_left,
547 uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
548 false, false, state_.only_visible_on_secure_output);
549 delegated_frame->resource_list.push_back(current_resource_);
550 } else {
551 cc::SolidColorDrawQuad* solid_quad =
552 render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
553 solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
554 frame_is_opaque = true;
555 }
556
557 delegated_frame->render_pass_list.push_back(std::move(render_pass));
558 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
559 frame->delegated_frame_data = std::move(delegated_frame);
560
561 factory_owner_->surface_factory_->SubmitCompositorFrame(
562 surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
563 463
564 if (!old_surface_id.is_null() && old_surface_id != surface_id_) { 464 if (!old_surface_id.is_null() && old_surface_id != surface_id_) {
565 factory_owner_->surface_factory_->SetPreviousFrameSurface(surface_id_, 465 factory_owner_->surface_factory_->SetPreviousFrameSurface(surface_id_,
566 old_surface_id); 466 old_surface_id);
567 factory_owner_->surface_factory_->Destroy(old_surface_id); 467 factory_owner_->surface_factory_->Destroy(old_surface_id);
568 } 468 }
569 469
570 content_size_ = layer_size;
571
572 if (old_surface_id != surface_id_) { 470 if (old_surface_id != surface_id_) {
471 float contents_surface_to_layer_scale = 1.0;
573 window_->layer()->SetShowSurface( 472 window_->layer()->SetShowSurface(
574 surface_id_, 473 surface_id_,
575 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)), 474 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)),
576 base::Bind(&RequireCallback, base::Unretained(surface_manager_)), 475 base::Bind(&RequireCallback, base::Unretained(surface_manager_)),
577 contents_surface_size, contents_surface_to_layer_scale, layer_size); 476 content_size_, contents_surface_to_layer_scale, content_size_);
578 window_->layer()->SetBounds( 477 window_->layer()->SetBounds(
579 gfx::Rect(window_->layer()->bounds().origin(), layer_size)); 478 gfx::Rect(window_->layer()->bounds().origin(), content_size_));
580 window_->layer()->SetFillsBoundsOpaquely(state_.alpha == 1.0f && 479 window_->layer()->SetFillsBoundsOpaquely(state_.alpha == 1.0f &&
581 frame_is_opaque); 480 frame_is_opaque_);
582 } 481 }
583 482
584 // Reset damage. 483 // Reset damage.
585 pending_damage_.setEmpty(); 484 pending_damage_.setEmpty();
586 485
587 DCHECK(!current_resource_.id || 486 DCHECK(!current_resource_.id ||
588 factory_owner_->release_callbacks_.count(current_resource_.id)); 487 factory_owner_->release_callbacks_.count(current_resource_.id));
589 488
590 // Move pending frame callbacks to the end of active_frame_callbacks_ 489 // Move pending frame callbacks to the end of active_frame_callbacks_
591 active_frame_callbacks_.splice(active_frame_callbacks_.end(), 490 active_frame_callbacks_.splice(active_frame_callbacks_.end(),
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
750 gfx::Size layer_size = layer->bounds().size(); 649 gfx::Size layer_size = layer->bounds().size();
751 float contents_surface_to_layer_scale = 1.0f; 650 float contents_surface_to_layer_scale = 1.0f;
752 651
753 layer->SetShowSurface( 652 layer->SetShowSurface(
754 surface_id_, 653 surface_id_,
755 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)), 654 base::Bind(&SatisfyCallback, base::Unretained(surface_manager_)),
756 base::Bind(&RequireCallback, base::Unretained(surface_manager_)), 655 base::Bind(&RequireCallback, base::Unretained(surface_manager_)),
757 layer_size, contents_surface_to_layer_scale, layer_size); 656 layer_size, contents_surface_to_layer_scale, layer_size);
758 } 657 }
759 658
659 void Surface::CreateResource(bool for_commit) {
660 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
661
662 cc::TextureMailbox texture_mailbox;
663 if (current_buffer_) {
664 texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
665 &texture_mailbox, state_.only_visible_on_secure_output,
666 for_commit /* client_usage */);
667 }
668
669 // This can fail even if there's a buffer if for_commit is false, zero-copy
reveman 2016/06/21 16:25:46 Can we fix this by not releasing buffers that are
670 // is disabled, and the buffer has already been copied and returned.
671 if (texture_mailbox_release_callback) {
672 cc::TransferableResource resource;
673 resource.id = next_resource_id_++;
674 resource.format = cc::RGBA_8888;
675 resource.filter =
676 texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
677 resource.size = texture_mailbox.size_in_pixels();
678 resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(),
679 texture_mailbox.sync_token(),
680 texture_mailbox.target());
681 resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate();
682
683 factory_owner_->release_callbacks_[resource.id] = std::make_pair(
684 factory_owner_, std::move(texture_mailbox_release_callback));
685 current_resource_ = resource;
686 } else {
687 current_resource_.id = 0;
688 current_resource_.size = gfx::Size();
689 }
690 }
691
692 void Surface::UpdateSurface(bool for_commit) {
693 gfx::Size buffer_size = current_resource_.size;
694 gfx::SizeF scaled_buffer_size(
695 gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
696
697 gfx::Size layer_size; // Size of the output layer, in DIP.
698 if (!state_.viewport.IsEmpty()) {
699 layer_size = state_.viewport;
700 } else if (!state_.crop.IsEmpty()) {
701 DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
702 !gfx::IsExpressibleAsInt(state_.crop.height()))
703 << "Crop rectangle size (" << state_.crop.size().ToString()
704 << ") most be expressible using integers when viewport is not set";
705 layer_size = gfx::ToCeiledSize(state_.crop.size());
706 } else {
707 layer_size = gfx::ToCeiledSize(scaled_buffer_size);
708 }
709
710 content_size_ = layer_size;
711 // TODO(jbauman): Figure out how this interacts with the pixel size of
712 // CopyOutputRequests on the layer.
713 gfx::Size contents_surface_size = layer_size;
714
715 gfx::PointF uv_top_left(0.f, 0.f);
716 gfx::PointF uv_bottom_right(1.f, 1.f);
717 if (!state_.crop.IsEmpty()) {
718 uv_top_left = state_.crop.origin();
719
720 uv_top_left.Scale(1.f / scaled_buffer_size.width(),
721 1.f / scaled_buffer_size.height());
722 uv_bottom_right = state_.crop.bottom_right();
723 uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
724 1.f / scaled_buffer_size.height());
725 }
726
727 // pending_damage_ is in Surface coordinates.
728 gfx::Rect damage_rect = for_commit
reveman 2016/06/21 16:25:46 Can damage_rect be an argument to this function in
729 ? gfx::SkIRectToRect(pending_damage_.getBounds())
730 : gfx::Rect(contents_surface_size);
731
732 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
733 render_pass->SetAll(cc::RenderPassId(1, 1), gfx::Rect(contents_surface_size),
734 damage_rect, gfx::Transform(), true);
735
736 gfx::Rect quad_rect = gfx::Rect(contents_surface_size);
737 cc::SharedQuadState* quad_state =
738 render_pass->CreateAndAppendSharedQuadState();
739 quad_state->quad_layer_bounds = contents_surface_size;
740 quad_state->visible_quad_layer_rect = quad_rect;
741 quad_state->opacity = state_.alpha;
742
743 frame_is_opaque_ = false;
744
745 std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
746 new cc::DelegatedFrameData);
747 if (current_resource_.id) {
748 cc::TextureDrawQuad* texture_quad =
749 render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
750 float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
751 gfx::Rect opaque_rect;
752 frame_is_opaque_ =
753 state_.blend_mode == SkXfermode::kSrc_Mode ||
reveman 2016/06/21 16:25:46 The idea was always to handle this by turning off
754 state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
755 if (frame_is_opaque_) {
756 opaque_rect = quad_rect;
757 } else if (state_.opaque_region.isRect()) {
758 opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
759 }
760
761 texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
762 current_resource_.id, true, uv_top_left,
763 uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
764 false, false, state_.only_visible_on_secure_output);
765 delegated_frame->resource_list.push_back(current_resource_);
766 } else {
767 cc::SolidColorDrawQuad* solid_quad =
768 render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
769 solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
770 frame_is_opaque_ = true;
771 }
772
773 delegated_frame->render_pass_list.push_back(std::move(render_pass));
774 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
775 frame->delegated_frame_data = std::move(delegated_frame);
776
777 factory_owner_->surface_factory_->SubmitCompositorFrame(
778 surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
779 }
780
760 int64_t Surface::SetPropertyInternal(const void* key, 781 int64_t Surface::SetPropertyInternal(const void* key,
761 const char* name, 782 const char* name,
762 PropertyDeallocator deallocator, 783 PropertyDeallocator deallocator,
763 int64_t value, 784 int64_t value,
764 int64_t default_value) { 785 int64_t default_value) {
765 int64_t old = GetPropertyInternal(key, default_value); 786 int64_t old = GetPropertyInternal(key, default_value);
766 if (value == default_value) { 787 if (value == default_value) {
767 prop_map_.erase(key); 788 prop_map_.erase(key);
768 } else { 789 } else {
769 Value prop_value; 790 Value prop_value;
770 prop_value.name = name; 791 prop_value.name = name;
771 prop_value.value = value; 792 prop_value.value = value;
772 prop_value.deallocator = deallocator; 793 prop_value.deallocator = deallocator;
773 prop_map_[key] = prop_value; 794 prop_map_[key] = prop_value;
774 } 795 }
775 return old; 796 return old;
776 } 797 }
777 798
778 int64_t Surface::GetPropertyInternal(const void* key, 799 int64_t Surface::GetPropertyInternal(const void* key,
779 int64_t default_value) const { 800 int64_t default_value) const {
780 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); 801 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
781 if (iter == prop_map_.end()) 802 if (iter == prop_map_.end())
782 return default_value; 803 return default_value;
783 return iter->second.value; 804 return iter->second.value;
784 } 805 }
785 806
786 } // namespace exo 807 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698