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

Unified Diff: components/exo/surface.cc

Issue 2008153002: Add initial implementation of cc::Surfaces backend for exo. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 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') | components/exo/surface_unittest.cc » ('j') | 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 8a86434211e5cb68e06bdde071602263b1d0c537..b8080fe1c40fa4a086a7516f55bea19e027afe90 100644
--- a/components/exo/surface.cc
+++ b/components/exo/surface.cc
@@ -12,10 +12,20 @@
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
+#include "cc/quads/render_pass.h"
+#include "cc/quads/shared_quad_state.h"
+#include "cc/quads/solid_color_draw_quad.h"
+#include "cc/quads/texture_draw_quad.h"
#include "cc/resources/single_release_callback.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_id_allocator.h"
+#include "cc/surfaces/surface_manager.h"
#include "components/exo/buffer.h"
#include "components/exo/surface_delegate.h"
#include "components/exo/surface_observer.h"
+#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/aura/env.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_property.h"
#include "ui/aura/window_targeter.h"
@@ -28,6 +38,7 @@
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/path.h"
+#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/widget/widget.h"
@@ -127,8 +138,48 @@ class CustomWindowTargeter : public aura::WindowTargeter {
DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};
+void SatisfyCallback(cc::SurfaceManager* manager,
+ cc::SurfaceSequence sequence) {
+ std::vector<uint32_t> sequences;
+ sequences.push_back(sequence.sequence);
+ manager->DidSatisfySequences(sequence.id_namespace, &sequences);
+}
+
+void RequireCallback(cc::SurfaceManager* manager,
+ cc::SurfaceId id,
+ cc::SurfaceSequence sequence) {
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ if (!surface) {
+ LOG(ERROR) << "Attempting to require callback on nonexistent surface";
+ return;
+ }
+ surface->AddDestructionDependency(sequence);
+}
+
} // namespace
+SurfaceFactoryOwner::SurfaceFactoryOwner() {}
+SurfaceFactoryOwner::~SurfaceFactoryOwner() {}
+
+void SurfaceFactoryOwner::ReturnResources(
+ const cc::ReturnedResourceArray& resources) {
+ scoped_refptr<SurfaceFactoryOwner> holder(this);
+ for (auto& resource : resources) {
+ auto it = release_callbacks_.find(resource.id);
+ DCHECK(it != release_callbacks_.end());
+ it->second.second->Run(resource.sync_token, resource.lost);
+ release_callbacks_.erase(it);
+ }
+}
+void SurfaceFactoryOwner::WillDrawSurface(cc::SurfaceId id,
+ const gfx::Rect& damage_rect) {
+ if (surface_)
+ surface_->WillDraw(id);
+}
+
+void SurfaceFactoryOwner::SetBeginFrameSource(
+ cc::BeginFrameSource* begin_frame_source) {}
+
////////////////////////////////////////////////////////////////////////////////
// Surface, public:
@@ -152,7 +203,20 @@ Surface::Surface()
Init(ui::LAYER_SOLID_COLOR);
SetEventTargeter(base::WrapUnique(new CustomWindowTargeter));
set_owned_by_parent(false);
- AddObserver(this);
+ surface_manager_ =
+ aura::Env::GetInstance()->context_factory()->GetSurfaceManager();
+ if (use_surface_layer_) {
+ factory_owner_ = make_scoped_refptr(new SurfaceFactoryOwner);
+ factory_owner_->surface_ = this;
+ factory_owner_->id_allocator_ =
+ aura::Env::GetInstance()->context_factory()->CreateSurfaceIdAllocator();
+ factory_owner_->surface_factory_.reset(
+ new cc::SurfaceFactory(surface_manager_, factory_owner_.get()));
+ }
+
+ if (!factory_owner_) {
+ AddObserver(this);
+ }
}
Surface::~Surface() {
@@ -160,7 +224,11 @@ Surface::~Surface() {
layer()->SetShowSolidColorContent();
- RemoveObserver(this);
+ if (factory_owner_) {
+ factory_owner_->surface_ = nullptr;
+ } else {
+ RemoveObserver(this);
+ }
if (compositor_)
compositor_->RemoveObserver(this);
@@ -171,6 +239,9 @@ Surface::~Surface() {
frame_callbacks_);
for (const auto& frame_callback : active_frame_callbacks_)
frame_callback.Run(base::TimeTicks());
+
+ if (!surface_id_.is_null())
+ factory_owner_->surface_factory_->Destroy(surface_id_);
}
// static
@@ -178,6 +249,11 @@ Surface* Surface::AsSurface(const aura::Window* window) {
return window->GetProperty(kSurfaceKey);
}
+// static
+void Surface::SetUseSurfaceLayer(bool use_surface_layer) {
+ use_surface_layer_ = use_surface_layer;
+}
+
void Surface::Attach(Buffer* buffer) {
TRACE_EVENT1("exo", "Surface::Attach", "buffer",
buffer ? buffer->GetSize().ToString() : "null");
@@ -348,10 +424,7 @@ void Surface::Commit() {
CommitSurfaceHierarchy();
}
-void Surface::CommitSurfaceHierarchy() {
- DCHECK(needs_commit_surface_hierarchy_);
- needs_commit_surface_hierarchy_ = false;
-
+void Surface::CommitLayerContents() {
// We update contents if Attach() has been called since last commit.
if (has_pending_contents_) {
has_pending_contents_ = false;
@@ -417,8 +490,10 @@ void Surface::CommitSurfaceHierarchy() {
pending_damage_.setEmpty();
}
- // Update current input region.
- input_region_ = pending_input_region_;
+ if (layer()->has_external_content()) {
+ layer()->SetTextureAlpha(pending_alpha_);
+ alpha_ = pending_alpha_;
+ }
// Move pending frame callbacks to the end of |frame_callbacks_|.
frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_);
@@ -430,11 +505,167 @@ void Surface::CommitSurfaceHierarchy() {
pending_blend_mode_ == SkXfermode::kSrc_Mode ||
pending_opaque_region_.contains(
gfx::RectToSkIRect(gfx::Rect(layer()->size()))));
- if (layer()->has_external_content()) {
- layer()->SetTextureAlpha(pending_alpha_);
+}
+
+void Surface::CommitSurfaceContents() {
+ // 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();
+
+ bool secure_output_only = pending_only_visible_on_secure_output_;
+ pending_only_visible_on_secure_output_ = false;
+
+ cc::TextureMailbox texture_mailbox;
+ std::unique_ptr<cc::SingleReleaseCallback> texture_mailbox_release_callback;
+ if (current_buffer_) {
+ texture_mailbox_release_callback = current_buffer_->ProduceTextureMailbox(
+ &texture_mailbox, secure_output_only, false);
+ }
+
+ cc::SurfaceId old_surface_id = surface_id_;
+ surface_id_ = factory_owner_->id_allocator_->GenerateId();
+ factory_owner_->surface_factory_->Create(surface_id_);
+
+ gfx::Size buffer_size = texture_mailbox.size_in_pixels();
+ gfx::SizeF scaled_buffer_size(
+ gfx::ScaleSize(gfx::SizeF(buffer_size), 1.0f / pending_buffer_scale_));
+
+ gfx::Size layer_size; // Size of the output layer, in DIP.
+ if (!pending_viewport_.IsEmpty()) {
+ layer_size = pending_viewport_;
+ } else if (!pending_crop_.IsEmpty()) {
+ DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(pending_crop_.width()) ||
+ !gfx::IsExpressibleAsInt(pending_crop_.height()))
+ << "Crop rectangle size (" << pending_crop_.size().ToString()
+ << ") most be expressible using integers when viewport is not set";
+ layer_size = gfx::ToCeiledSize(pending_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 (!pending_crop_.IsEmpty()) {
+ uv_top_left = pending_crop_.origin();
+
+ uv_top_left.Scale(1.f / scaled_buffer_size.width(),
+ 1.f / scaled_buffer_size.height());
+ uv_bottom_right = pending_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(), false);
+
+ 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 = alpha_;
alpha_ = pending_alpha_;
+
+ bool frame_is_opaque = false;
+
+ std::unique_ptr<cc::DelegatedFrameData> delegated_frame(
+ new cc::DelegatedFrameData);
+ 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();
+
+ 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 =
+ pending_blend_mode_ == SkXfermode::kSrc_Mode ||
+ pending_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());
+ }
+
+ texture_quad->SetNew(quad_state, quad_rect, opaque_rect, quad_rect,
+ resource.id, true, uv_top_left, uv_bottom_right,
+ SK_ColorTRANSPARENT, vertex_opacity, false, false,
+ secure_output_only);
+
+ factory_owner_->release_callbacks_[resource.id] = std::make_pair(
+ factory_owner_, std::move(texture_mailbox_release_callback));
+ delegated_frame->resource_list.push_back(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());
+
+ if (!old_surface_id.is_null()) {
+ factory_owner_->surface_factory_->SetPreviousFrameSurface(surface_id_,
+ old_surface_id);
+ factory_owner_->surface_factory_->Destroy(old_surface_id);
+ }
+
+ 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);
+ layer()->SetBounds(gfx::Rect(layer()->bounds().origin(), layer_size));
+ layer()->SetFillsBoundsOpaquely(alpha_ == 1.0f && frame_is_opaque);
+
+ // Reset damage.
+ pending_damage_.setEmpty();
+ }
+ // Move pending frame callbacks to the end of active_frame_callbacks_
+ active_frame_callbacks_.splice(active_frame_callbacks_.end(),
+ pending_frame_callbacks_);
+}
+
+void Surface::CommitSurfaceHierarchy() {
+ DCHECK(needs_commit_surface_hierarchy_);
+ needs_commit_surface_hierarchy_ = false;
+
+ if (factory_owner_) {
+ CommitSurfaceContents();
+ } else {
+ CommitLayerContents();
}
+ // 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.
@@ -542,6 +773,7 @@ std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const {
void Surface::OnWindowAddedToRootWindow(aura::Window* window) {
DCHECK(!compositor_);
+ DCHECK(!factory_owner_);
compositor_ = layer()->GetCompositor();
compositor_->AddObserver(this);
}
@@ -557,6 +789,7 @@ void Surface::OnWindowRemovingFromRootWindow(aura::Window* window,
// ui::CompositorObserver overrides:
void Surface::OnCompositingDidCommit(ui::Compositor* compositor) {
+ DCHECK(!factory_owner_);
// Move frame callbacks to the end of |active_frame_callbacks_|.
active_frame_callbacks_.splice(active_frame_callbacks_.end(),
frame_callbacks_);
@@ -614,4 +847,13 @@ void Surface::OnCompositingShuttingDown(ui::Compositor* compositor) {
compositor_ = nullptr;
}
+void Surface::WillDraw(cc::SurfaceId id) {
+ while (!active_frame_callbacks_.empty()) {
+ active_frame_callbacks_.front().Run(base::TimeTicks::Now());
+ active_frame_callbacks_.pop_front();
+ }
+}
+
+bool Surface::use_surface_layer_ = false;
+
} // namespace exo
« no previous file with comments | « components/exo/surface.h ('k') | components/exo/surface_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698