Enable the Sky compositor again

This CL fixes two bugs:

1) We need to enter the Ganesh context in order to destroy the GrContext.

2) We had a race condition whereby we'd try to upload a frame to a surface that
   didn't yet exist. This CL fixes that race by adding a state to LayerHost to
   wait for the surface to be created before trying to upload to it.

R=esprehn@chromium.org

Review URL: https://codereview.chromium.org/753643002
This commit is contained in:
Adam Barth
2014-11-21 12:15:30 -08:00
parent eda246d9f3
commit f219a84961
4 changed files with 43 additions and 1 deletions

View File

@@ -15,6 +15,7 @@ namespace sky {
LayerHost::LayerHost(LayerHostClient* client)
: client_(client),
state_(kIdle),
surface_holder_(this, client->GetShell()),
gl_context_(mojo::GLContext::Create(client->GetShell())),
ganesh_context_(gl_context_),
@@ -29,6 +30,7 @@ LayerHost::~LayerHost() {
void LayerHost::SetNeedsAnimate() {
scheduler_.SetNeedsFrame();
state_ = kWaitingForBeginFrame;
}
void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) {
@@ -39,6 +41,9 @@ void LayerHost::SetRootLayer(scoped_refptr<Layer> layer) {
void LayerHost::OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) {
client_->OnSurfaceIdAvailable(surface_id.Pass());
if (state_ == kWaitingForSurfaceToUploadFrame)
Upload(root_layer_.get());
}
void LayerHost::ReturnResources(
@@ -48,6 +53,8 @@ void LayerHost::ReturnResources(
void LayerHost::BeginFrame(base::TimeTicks frame_time,
base::TimeTicks deadline) {
DCHECK_EQ(state_, kWaitingForBeginFrame);
state_ = kProducingFrame;
client_->BeginFrame(frame_time);
{
@@ -57,9 +64,30 @@ void LayerHost::BeginFrame(base::TimeTicks frame_time,
}
Upload(root_layer_.get());
if (state_ == kProducingFrame)
state_ = kIdle;
}
void LayerHost::Upload(Layer* layer) {
if (!surface_holder_.IsReadyForFrame()) {
if (state_ == kProducingFrame) {
// Currently we use a timer to drive the BeginFrame cycle, which means we
// can produce frames before the surfaces service is ready to receive
// frames from us. In that situation, we wait for surfaces before
// uploading the frame. The upload will actually happen when the surface
// id is available (i.e., in OnSurfaceIdAvailable). If SetNeedsAnimate is
// called before then, we'll go back into the kWaitingForBeginFrame state
// and defer to the timer again.
//
// We can avoid this complexity if we use feedback from the surfaces
// service to drive the BeginFrame cycle. In that approach, we wouldn't
// get here before we've attached to a surface.
state_ = kWaitingForSurfaceToUploadFrame;
}
return;
}
gfx::Size size = layer->size();
surface_holder_.SetSize(size);

View File

@@ -41,6 +41,13 @@ class LayerHost : public SurfaceHolder::Client, public Scheduler::Client {
void SetRootLayer(scoped_refptr<Layer> layer);
private:
enum State {
kIdle,
kWaitingForBeginFrame,
kProducingFrame,
kWaitingForSurfaceToUploadFrame,
};
// SurfaceHolder::Client
void OnSurfaceIdAvailable(mojo::SurfaceIdPtr surface_id) override;
void ReturnResources(
@@ -53,6 +60,7 @@ class LayerHost : public SurfaceHolder::Client, public Scheduler::Client {
void Upload(Layer* layer);
LayerHostClient* client_;
State state_;
SurfaceHolder surface_holder_;
base::WeakPtr<mojo::GLContext> gl_context_;
mojo::GaneshContext ganesh_context_;

View File

@@ -28,10 +28,14 @@ SurfaceHolder::SurfaceHolder(Client* client, mojo::Shell* shell)
}
SurfaceHolder::~SurfaceHolder() {
if (surface_id_)
if (surface_ && surface_id_)
surface_->DestroySurface(surface_id_.Clone());
}
bool SurfaceHolder::IsReadyForFrame() const {
return surface_;
}
void SurfaceHolder::SubmitFrame(mojo::FramePtr frame) {
surface_->SubmitFrame(surface_id_.Clone(), frame.Pass());
}

View File

@@ -34,6 +34,8 @@ class SurfaceHolder : public mojo::SurfaceClient {
explicit SurfaceHolder(Client* client, mojo::Shell* shell);
~SurfaceHolder() override;
bool IsReadyForFrame() const;
void SetSize(const gfx::Size& size);
void SubmitFrame(mojo::FramePtr frame);