flutter_flutter/compositor/layer_host.cc
James Robinson a88056c0b1 Use local ids for Surfaces APIs that can only apply to local surfaces
Surfaces identifiers have a local and a namespace component. The
namespace is particular to a connection. The local component is up to
the endpoint of the connection to manage. In contexts where a surface
that may be from anywhere is referenced, a fully qualified ID with both
the local and namespace component is needed in order to be unambiguous.
In contexts that can only apply to local surfaces only the local id is
needed.

This updates the mojo.Surface APIs that can only refer to local IDs to
only take the local component. In particular creating, destroying, or
submitting a frame can only refer to surfaces created on that connection.
References to surfaces within a frame may refer to local or foreign
surfaces so they use fully qualified IDs.

This also skips the SurfacesService indirection since many applications
can perform useful operations on a mojo.Surface interface such as create
surfaces and submit frames without knowing their ID namespace. The
namespace component is needed only to pass fully qualified IDs to other
actors that may wish to reference the produced frame.

R=sky@chromium.org

Review URL: https://codereview.chromium.org/826423008
2015-01-14 10:25:31 -08:00

157 lines
4.5 KiB
C++

// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/compositor/layer_host.h"
#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/gpu/gl_context.h"
#include "mojo/services/surfaces/public/cpp/surfaces_utils.h"
#include "mojo/skia/ganesh_context.h"
#include "sky/compositor/layer.h"
namespace sky {
LayerHost::LayerHost(LayerHostClient* client)
: client_(client),
state_(kReadyForFrame),
frame_requested_(false),
surface_holder_(this, client->GetShell()),
gl_context_owner_(client->GetShell()),
ganesh_context_(gl_context()),
resource_manager_(gl_context()),
weak_factory_(this) {
}
LayerHost::~LayerHost() {
}
void LayerHost::SetNeedsAnimate() {
if (frame_requested_)
return;
frame_requested_ = true;
if (state_ == kReadyForFrame)
BeginFrameSoon();
}
void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) {
DCHECK(!root_layer_.get());
root_layer_ = layer;
root_layer_->set_host(this);
}
void LayerHost::GetPixelsForTesting(std::vector<unsigned char>* pixels) {
return root_layer_->GetPixelsForTesting(pixels);
}
void LayerHost::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) {
client_->OnSurfaceIdAvailable(surface_id.Pass());
}
void LayerHost::ReturnResources(
mojo::Array<mojo::ReturnedResourcePtr> resources) {
resource_manager_.ReturnResources(resources.Pass());
}
void LayerHost::BeginFrameSoon() {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&LayerHost::BeginFrame, weak_factory_.GetWeakPtr()));
}
void LayerHost::BeginFrame() {
TRACE_EVENT0("sky", "LayerHost::BeginFrame");
DCHECK(frame_requested_);
frame_requested_ = false;
DCHECK_EQ(state_, kReadyForFrame);
state_ = kWaitingForFrameAcknowldgement;
client_->BeginFrame(base::TimeTicks::Now());
// If the root layer is empty, there's no reason to draw into it. (In fact,
// Ganesh will get upset if we try.) Instead, we just schedule the ack that
// the frame is complete.
if (root_layer_->size().IsEmpty()) {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&LayerHost::DidCompleteFrame, weak_factory_.GetWeakPtr()));
return;
}
{
mojo::GaneshContext::Scope scope(&ganesh_context_);
ganesh_context_.gr()->resetContext();
root_layer_->Display();
}
Upload(root_layer_.get());
}
void LayerHost::Upload(Layer* layer) {
TRACE_EVENT0("sky", "LayerHost::Upload");
gfx::Size size = layer->size();
surface_holder_.SetSize(size);
mojo::FramePtr frame = mojo::Frame::New();
frame->resources.resize(0u);
mojo::Rect bounds;
bounds.width = size.width();
bounds.height = size.height();
mojo::PassPtr pass = mojo::CreateDefaultPass(1, bounds);
pass->quads.resize(0u);
pass->shared_quad_states.push_back(mojo::CreateDefaultSQS(
mojo::TypeConverter<mojo::Size, gfx::Size>::Convert(size)));
mojo::TransferableResourcePtr resource =
resource_manager_.CreateTransferableResource(layer);
mojo::QuadPtr quad = mojo::Quad::New();
quad->material = mojo::MATERIAL_TEXTURE_CONTENT;
mojo::RectPtr rect = mojo::Rect::New();
rect->width = size.width();
rect->height = size.height();
quad->rect = rect.Clone();
quad->opaque_rect = rect.Clone();
quad->visible_rect = rect.Clone();
quad->needs_blending = true;
quad->shared_quad_state_index = 0u;
mojo::TextureQuadStatePtr texture_state = mojo::TextureQuadState::New();
texture_state->resource_id = resource->id;
texture_state->premultiplied_alpha = true;
texture_state->uv_top_left = mojo::PointF::New();
texture_state->uv_bottom_right = mojo::PointF::New();
texture_state->uv_bottom_right->x = 1.f;
texture_state->uv_bottom_right->y = 1.f;
texture_state->background_color = mojo::Color::New();
texture_state->background_color->rgba = 0;
for (int i = 0; i < 4; ++i)
texture_state->vertex_opacity.push_back(1.f);
texture_state->flipped = false;
frame->resources.push_back(resource.Pass());
quad->texture_quad_state = texture_state.Pass();
pass->quads.push_back(quad.Pass());
frame->passes.push_back(pass.Pass());
surface_holder_.SubmitFrame(
frame.Pass(),
base::Bind(&LayerHost::DidCompleteFrame, weak_factory_.GetWeakPtr()));
}
void LayerHost::DidCompleteFrame() {
DCHECK_EQ(state_, kWaitingForFrameAcknowldgement);
state_ = kReadyForFrame;
if (frame_requested_)
BeginFrame();
}
} // namespace sky