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

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: 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 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) {
reveman 2016/06/22 17:15:26 nit: s/for_commit/client_usage/
jbauman 2016/06/22 23:45:48 Done.
660 std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
661
662 cc::TextureMailbox texture_mailbox;
663 if (current_buffer_) {
664 base::Closure new_buffer_release_callback;
665 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
666 &texture_mailbox, state_.only_visible_on_secure_output,
667 for_commit /* client_usage */, &new_buffer_release_callback);
668 current_buffer_release_runner_.Reset(new_buffer_release_callback);
669 } else {
670 current_buffer_release_runner_.Reset();
671 }
672
673 if (texture_mailbox_release_callback) {
674 cc::TransferableResource resource;
675 resource.id = next_resource_id_++;
676 resource.format = cc::RGBA_8888;
677 resource.filter =
678 texture_mailbox.nearest_neighbor() ? GL_NEAREST : GL_LINEAR;
679 resource.size = texture_mailbox.size_in_pixels();
680 resource.mailbox_holder = gpu::MailboxHolder(texture_mailbox.mailbox(),
681 texture_mailbox.sync_token(),
682 texture_mailbox.target());
683 resource.is_overlay_candidate = texture_mailbox.is_overlay_candidate();
684
685 factory_owner_->release_callbacks_[resource.id] = std::make_pair(
686 factory_owner_, std::move(texture_mailbox_release_callback));
687 current_resource_ = resource;
688 } else {
689 current_resource_.id = 0;
690 current_resource_.size = gfx::Size();
691 }
692 }
693
694 void Surface::UpdateSurface(bool for_commit) {
695 gfx::Size buffer_size = current_resource_.size;
696 gfx::SizeF scaled_buffer_size(
697 gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / state_.buffer_scale));
698
699 gfx::Size layer_size; // Size of the output layer, in DIP.
700 if (!state_.viewport.IsEmpty()) {
701 layer_size = state_.viewport;
702 } else if (!state_.crop.IsEmpty()) {
703 DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) ||
704 !gfx::IsExpressibleAsInt(state_.crop.height()))
705 << "Crop rectangle size (" << state_.crop.size().ToString()
706 << ") most be expressible using integers when viewport is not set";
707 layer_size = gfx::ToCeiledSize(state_.crop.size());
708 } else {
709 layer_size = gfx::ToCeiledSize(scaled_buffer_size);
710 }
711
712 content_size_ = layer_size;
713 // TODO(jbauman): Figure out how this interacts with the pixel size of
714 // CopyOutputRequests on the layer.
715 gfx::Size contents_surface_size = layer_size;
716
717 gfx::PointF uv_top_left(0.f, 0.f);
718 gfx::PointF uv_bottom_right(1.f, 1.f);
719 if (!state_.crop.IsEmpty()) {
720 uv_top_left = state_.crop.origin();
721
722 uv_top_left.Scale(1.f / scaled_buffer_size.width(),
723 1.f / scaled_buffer_size.height());
724 uv_bottom_right = state_.crop.bottom_right();
725 uv_bottom_right.Scale(1.f / scaled_buffer_size.width(),
726 1.f / scaled_buffer_size.height());
727 }
728
729 // pending_damage_ is in Surface coordinates.
730 gfx::Rect damage_rect = for_commit
731 ? gfx::SkIRectToRect(pending_damage_.getBounds())
732 : gfx::Rect(contents_surface_size);
733
734 std::unique_ptr<cc::RenderPass> render_pass = cc::RenderPass::Create();
735 render_pass->SetAll(cc::RenderPassId(1, 1), gfx::Rect(contents_surface_size),
736 damage_rect, gfx::Transform(), true);
737
738 gfx::Rect quad_rect = gfx::Rect(contents_surface_size);
739 cc::SharedQuadState* quad_state =
740 render_pass->CreateAndAppendSharedQuadState();
741 quad_state->quad_layer_bounds = contents_surface_size;
742 quad_state->visible_quad_layer_rect = quad_rect;
743 quad_state->opacity = state_.alpha;
744
745 frame_is_opaque_ = false;
746
747 std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
748 new cc::DelegatedFrameData);
749 if (current_resource_.id) {
750 cc::TextureDrawQuad* texture_quad =
751 render_pass->CreateAndAppendDrawQuad<cc::TextureDrawQuad>();
752 float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
753 gfx::Rect opaque_rect;
754 frame_is_opaque_ =
755 state_.blend_mode == SkXfermode::kSrc_Mode ||
756 state_.opaque_region.contains(gfx::RectToSkIRect(quad_rect));
757 if (frame_is_opaque_) {
758 opaque_rect = quad_rect;
759 } else if (state_.opaque_region.isRect()) {
760 opaque_rect = gfx::SkIRectToRect(state_.opaque_region.getBounds());
761 }
762
763 texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
764 current_resource_.id, true, uv_top_left,
765 uv_bottom_right, SK_ColorTRANSPARENT, vertex_opacity,
766 false, false, state_.only_visible_on_secure_output);
767 delegated_frame->resource_list.push_back(current_resource_);
768 } else {
769 cc::SolidColorDrawQuad* solid_quad =
770 render_pass->CreateAndAppendDrawQuad<cc::SolidColorDrawQuad>();
771 solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, false);
772 frame_is_opaque_ = true;
773 }
774
775 delegated_frame->render_pass_list.push_back(std::move(render_pass));
776 std::unique_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
777 frame->delegated_frame_data = std::move(delegated_frame);
778
779 factory_owner_->surface_factory_->SubmitCompositorFrame(
780 surface_id_, std::move(frame), cc::SurfaceFactory::DrawCallback());
781 }
782
760 int64_t Surface::SetPropertyInternal(const void* key, 783 int64_t Surface::SetPropertyInternal(const void* key,
761 const char* name, 784 const char* name,
762 PropertyDeallocator deallocator, 785 PropertyDeallocator deallocator,
763 int64_t value, 786 int64_t value,
764 int64_t default_value) { 787 int64_t default_value) {
765 int64_t old = GetPropertyInternal(key, default_value); 788 int64_t old = GetPropertyInternal(key, default_value);
766 if (value == default_value) { 789 if (value == default_value) {
767 prop_map_.erase(key); 790 prop_map_.erase(key);
768 } else { 791 } else {
769 Value prop_value; 792 Value prop_value;
770 prop_value.name = name; 793 prop_value.name = name;
771 prop_value.value = value; 794 prop_value.value = value;
772 prop_value.deallocator = deallocator; 795 prop_value.deallocator = deallocator;
773 prop_map_[key] = prop_value; 796 prop_map_[key] = prop_value;
774 } 797 }
775 return old; 798 return old;
776 } 799 }
777 800
778 int64_t Surface::GetPropertyInternal(const void* key, 801 int64_t Surface::GetPropertyInternal(const void* key,
779 int64_t default_value) const { 802 int64_t default_value) const {
780 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key); 803 std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
781 if (iter == prop_map_.end()) 804 if (iter == prop_map_.end())
782 return default_value; 805 return default_value;
783 return iter->second.value; 806 return iter->second.value;
784 } 807 }
785 808
786 } // namespace exo 809 } // namespace exo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698