Remove the 'gyp_config' concept from MB.
[chromium-blink-merge.git] / ui / ozone / platform / cast / overlay_manager_cast.cc
blobef09b1fc49dc17e914dfb74167aa72360a0ee22c
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
3 // found in the LICENSE file.
5 #include "ui/ozone/platform/cast/overlay_manager_cast.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/single_thread_task_runner.h"
11 #include "chromecast/media/base/media_message_loop.h"
12 #include "chromecast/public/cast_media_shlib.h"
13 #include "chromecast/public/graphics_types.h"
14 #include "chromecast/public/video_plane.h"
15 #include "ui/gfx/geometry/rect_conversions.h"
16 #include "ui/ozone/public/overlay_candidates_ozone.h"
18 namespace ui {
19 namespace {
21 // Helper class for calling VideoPlane::SetGeometry with rate-limiting.
22 // SetGeometry can take on the order of 100ms to run in some implementations
23 // and can be called on the order of 20x / second (as fast as graphics frames
24 // are produced). This creates an ever-growing backlog of tasks on the media
25 // thread.
26 // This class measures the time taken to run SetGeometry to determine a
27 // reasonable frequency at which to call it. Excess calls are coalesced
28 // to just set the most recent geometry.
29 class RateLimitedSetVideoPlaneGeometry
30 : public base::RefCountedThreadSafe<RateLimitedSetVideoPlaneGeometry> {
31 public:
32 RateLimitedSetVideoPlaneGeometry(
33 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
34 : pending_display_rect_(0, 0, 0, 0),
35 pending_set_geometry_(false),
36 min_calling_interval_ms_(0),
37 sample_counter_(0),
38 task_runner_(task_runner) {}
40 void SetGeometry(
41 const chromecast::RectF& display_rect,
42 chromecast::media::VideoPlane::CoordinateType coordinate_type,
43 chromecast::media::VideoPlane::Transform transform) {
44 DCHECK(task_runner_->BelongsToCurrentThread());
46 base::TimeTicks now = base::TimeTicks::Now();
47 base::TimeDelta elapsed = now - last_set_geometry_time_;
49 if (elapsed < base::TimeDelta::FromMilliseconds(min_calling_interval_ms_)) {
50 if (!pending_set_geometry_) {
51 pending_set_geometry_ = true;
53 task_runner_->PostDelayedTask(
54 FROM_HERE,
55 base::Bind(
56 &RateLimitedSetVideoPlaneGeometry::ApplyPendingSetGeometry,
57 this),
58 base::TimeDelta::FromMilliseconds(2 * min_calling_interval_ms_));
61 pending_display_rect_ = display_rect;
62 pending_coordinate_type_ = coordinate_type;
63 pending_transform_ = transform;
64 return;
66 last_set_geometry_time_ = now;
68 chromecast::media::VideoPlane* video_plane =
69 chromecast::media::CastMediaShlib::GetVideoPlane();
70 CHECK(video_plane);
71 base::TimeTicks start = base::TimeTicks::Now();
72 video_plane->SetGeometry(display_rect, coordinate_type, transform);
74 base::TimeDelta set_geometry_time = base::TimeTicks::Now() - start;
75 UpdateAverageTime(set_geometry_time.InMilliseconds());
78 private:
79 friend class base::RefCountedThreadSafe<RateLimitedSetVideoPlaneGeometry>;
80 ~RateLimitedSetVideoPlaneGeometry() {}
82 void UpdateAverageTime(int64 sample) {
83 const size_t kSampleCount = 5;
84 if (samples_.size() < kSampleCount)
85 samples_.push_back(sample);
86 else
87 samples_[sample_counter_++ % kSampleCount] = sample;
88 int64 total = 0;
89 for (int64 s : samples_)
90 total += s;
91 min_calling_interval_ms_ = 2 * total / samples_.size();
94 void ApplyPendingSetGeometry() {
95 if (pending_set_geometry_) {
96 pending_set_geometry_ = false;
97 SetGeometry(pending_display_rect_, pending_coordinate_type_,
98 pending_transform_);
102 chromecast::RectF pending_display_rect_;
103 chromecast::media::VideoPlane::CoordinateType pending_coordinate_type_;
104 chromecast::media::VideoPlane::Transform pending_transform_;
105 bool pending_set_geometry_;
106 base::TimeTicks last_set_geometry_time_;
108 // Don't call SetGeometry faster than this interval.
109 int64 min_calling_interval_ms_;
111 // Min calling interval is computed as double average of last few time samples
112 // (i.e. allow at least as much time between calls as the call itself takes).
113 std::vector<int64> samples_;
114 size_t sample_counter_;
116 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
118 DISALLOW_COPY_AND_ASSIGN(RateLimitedSetVideoPlaneGeometry);
121 // Translates a gfx::OverlayTransform into a VideoPlane::Transform.
122 // Could be just a lookup table once we have unit tests for this code
123 // to ensure it stays in sync with OverlayTransform.
124 chromecast::media::VideoPlane::Transform ConvertTransform(
125 gfx::OverlayTransform transform) {
126 switch (transform) {
127 case gfx::OVERLAY_TRANSFORM_NONE:
128 return chromecast::media::VideoPlane::TRANSFORM_NONE;
129 case gfx::OVERLAY_TRANSFORM_FLIP_HORIZONTAL:
130 return chromecast::media::VideoPlane::FLIP_HORIZONTAL;
131 case gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL:
132 return chromecast::media::VideoPlane::FLIP_VERTICAL;
133 case gfx::OVERLAY_TRANSFORM_ROTATE_90:
134 return chromecast::media::VideoPlane::ROTATE_90;
135 case gfx::OVERLAY_TRANSFORM_ROTATE_180:
136 return chromecast::media::VideoPlane::ROTATE_180;
137 case gfx::OVERLAY_TRANSFORM_ROTATE_270:
138 return chromecast::media::VideoPlane::ROTATE_270;
139 default:
140 NOTREACHED();
141 return chromecast::media::VideoPlane::TRANSFORM_NONE;
145 bool ExactlyEqual(const chromecast::RectF& r1, const chromecast::RectF& r2) {
146 return r1.x == r2.x && r1.y == r2.y && r1.width == r2.width &&
147 r1.height == r2.height;
150 class OverlayCandidatesCast : public OverlayCandidatesOzone {
151 public:
152 OverlayCandidatesCast()
153 : media_task_runner_(
154 chromecast::media::MediaMessageLoop::GetTaskRunner()),
155 transform_(gfx::OVERLAY_TRANSFORM_INVALID),
156 display_rect_(0, 0, 0, 0),
157 video_plane_wrapper_(
158 new RateLimitedSetVideoPlaneGeometry(media_task_runner_)) {}
160 void CheckOverlaySupport(OverlaySurfaceCandidateList* surfaces) override;
162 private:
163 scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
164 gfx::OverlayTransform transform_;
165 chromecast::RectF display_rect_;
166 scoped_refptr<RateLimitedSetVideoPlaneGeometry> video_plane_wrapper_;
169 void OverlayCandidatesCast::CheckOverlaySupport(
170 OverlaySurfaceCandidateList* surfaces) {
171 for (auto& candidate : *surfaces) {
172 if (candidate.plane_z_order != -1)
173 continue;
175 candidate.overlay_handled = true;
177 // Compositor requires all overlay rectangles to have integer coords.
178 candidate.display_rect =
179 gfx::RectF(gfx::ToEnclosedRect(candidate.display_rect));
181 chromecast::RectF display_rect(
182 candidate.display_rect.x(), candidate.display_rect.y(),
183 candidate.display_rect.width(), candidate.display_rect.height());
185 // Update video plane geometry + transform to match compositor quad.
186 // This must be done on media thread - and no point doing if it hasn't
187 // changed.
188 if (candidate.transform != transform_ ||
189 !ExactlyEqual(display_rect, display_rect_)) {
190 transform_ = candidate.transform;
191 display_rect_ = display_rect;
193 media_task_runner_->PostTask(
194 FROM_HERE,
195 base::Bind(
196 &RateLimitedSetVideoPlaneGeometry::SetGeometry,
197 video_plane_wrapper_, display_rect,
198 chromecast::media::VideoPlane::COORDINATE_TYPE_GRAPHICS_PLANE,
199 ConvertTransform(candidate.transform)));
201 return;
205 } // namespace
207 OverlayManagerCast::OverlayManagerCast() {
210 OverlayManagerCast::~OverlayManagerCast() {
213 scoped_ptr<OverlayCandidatesOzone> OverlayManagerCast::CreateOverlayCandidates(
214 gfx::AcceleratedWidget w) {
215 return make_scoped_ptr(new OverlayCandidatesCast());
218 bool OverlayManagerCast::CanShowPrimaryPlaneAsOverlay() {
219 return false;
222 } // namespace ui