summaryrefslogtreecommitdiffstats
path: root/components/mus/surfaces/top_level_display_client.cc
blob: e3218af35b1b8a7aa75f6adc0903c1d16364754b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright 2015 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 "components/mus/surfaces/top_level_display_client.h"

#include "cc/output/compositor_frame.h"
#include "cc/surfaces/display.h"
#include "components/mus/gles2/gpu_state.h"
#include "components/mus/surfaces/surfaces_context_provider.h"
#include "components/mus/surfaces/surfaces_output_surface.h"
#include "components/mus/surfaces/surfaces_scheduler.h"
#include "components/mus/surfaces/surfaces_state.h"

namespace surfaces {
namespace {
void CallCallback(const base::Closure& callback, cc::SurfaceDrawStatus status) {
  callback.Run();
}
}

TopLevelDisplayClient::TopLevelDisplayClient(
    gfx::AcceleratedWidget widget,
    const scoped_refptr<gles2::GpuState>& gpu_state,
    const scoped_refptr<SurfacesState>& surfaces_state)
    : surfaces_state_(surfaces_state),
      factory_(surfaces_state->manager(), this),
      cc_id_(static_cast<uint64_t>(surfaces_state->next_id_namespace()) << 32) {
  factory_.Create(cc_id_);

  display_.reset(new cc::Display(this, surfaces_state_->manager(), nullptr,
                                 nullptr, cc::RendererSettings()));
  surfaces_state_->scheduler()->AddDisplay(display_.get());

  // TODO(brianderson): Reconcile with SurfacesScheduler crbug.com/476676
  cc::DisplayScheduler* null_display_scheduler = nullptr;
  display_->Initialize(
      make_scoped_ptr(new surfaces::DirectOutputSurface(
          new SurfacesContextProvider(this, widget, gpu_state))),
      null_display_scheduler);

  display_->Resize(last_submitted_frame_size_);

  // TODO(fsamuel): Plumb the proper device scale factor.
  display_->SetSurfaceId(cc_id_, 1.f /* device_scale_factor */);
}

TopLevelDisplayClient::~TopLevelDisplayClient() {
  if (display_) {
    factory_.Destroy(cc_id_);
    surfaces_state_->scheduler()->RemoveDisplay(display_.get());
    // By deleting the object after display_ is reset, OutputSurfaceLost can
    // know not to do anything (which would result in double delete).
    delete display_.release();
  }
}

void TopLevelDisplayClient::SubmitCompositorFrame(
    scoped_ptr<cc::CompositorFrame> frame,
    const base::Closure& callback) {
  pending_frame_ = frame.Pass();

  last_submitted_frame_size_ =
      pending_frame_->delegated_frame_data->render_pass_list.back()
          ->output_rect.size();
  display_->Resize(last_submitted_frame_size_);
  factory_.SubmitCompositorFrame(cc_id_, pending_frame_.Pass(),
                                 base::Bind(&CallCallback, callback));
  surfaces_state_->scheduler()->SetNeedsDraw();
}

void TopLevelDisplayClient::CommitVSyncParameters(base::TimeTicks timebase,
                                                  base::TimeDelta interval) {}

void TopLevelDisplayClient::OutputSurfaceLost() {
  if (!display_)  // Shutdown case
    return;

  // If our OutputSurface is lost we can't draw until we get a new one. For now,
  // destroy the display and create a new one when our ContextProvider provides
  // a new one.
  // TODO: This is more violent than necessary - we could simply remove this
  // display from the scheduler's set and pass a new context in to the
  // OutputSurface. It should be able to reinitialize properly.
  surfaces_state_->scheduler()->RemoveDisplay(display_.get());
  display_.reset();
}

void TopLevelDisplayClient::SetMemoryPolicy(
    const cc::ManagedMemoryPolicy& policy) {}

void TopLevelDisplayClient::OnVSyncParametersUpdated(int64_t timebase,
                                                     int64_t interval) {
  surfaces_state_->scheduler()->OnVSyncParametersUpdated(
      base::TimeTicks::FromInternalValue(timebase),
      base::TimeDelta::FromInternalValue(interval));
}

void TopLevelDisplayClient::ReturnResources(
    const cc::ReturnedResourceArray& resources) {
  // TODO(fsamuel): Implement this.
}

}  // namespace surfaces