blob: 8e4a6ad9b5635b0906474e6f367b71a8cb3dad34 [file] [log] [blame]
revemanb195f41d2015-11-19 22:16:481// 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.
4
5#ifndef COMPONENTS_EXO_SURFACE_H_
6#define COMPONENTS_EXO_SURFACE_H_
7
8#include <list>
dcheng31759da2016-04-21 01:26:319#include <memory>
reveman70baca12016-05-31 20:35:3010#include <set>
reveman27fe2642015-11-20 06:33:3911#include <utility>
revemanb195f41d2015-11-19 22:16:4812
13#include "base/callback.h"
14#include "base/macros.h"
jbaumanbd9586a92016-05-28 01:09:0315#include "base/memory/ref_counted.h"
revemanb195f41d2015-11-19 22:16:4816#include "base/memory/weak_ptr.h"
reveman27fe2642015-11-20 06:33:3917#include "base/observer_list.h"
eseckler599d86bb2017-03-15 09:02:5518#include "cc/output/begin_frame_args.h"
jbauman2fdc0732016-06-07 00:55:3619#include "cc/resources/transferable_resource.h"
reveman15aee282016-11-04 19:09:2020#include "cc/scheduler/begin_frame_source.h"
xing.xu1a9aa94c2017-02-23 21:04:3221#include "cc/surfaces/local_surface_id_allocator.h"
starazd8f4f642016-12-10 23:49:2022#include "components/exo/compositor_frame_sink.h"
23#include "components/exo/compositor_frame_sink_holder.h"
reedcc9c70f2016-11-22 04:26:0124#include "third_party/skia/include/core/SkBlendMode.h"
revemanb195f41d2015-11-19 22:16:4825#include "third_party/skia/include/core/SkRegion.h"
reveman4c94cf962015-12-03 06:49:4326#include "ui/aura/window.h"
reveman15aee282016-11-04 19:09:2027#include "ui/aura/window_observer.h"
reveman211cf802017-01-10 00:30:5928#include "ui/compositor/compositor_vsync_manager.h"
revemanb195f41d2015-11-19 22:16:4829#include "ui/gfx/geometry/rect.h"
revemane295c662017-01-30 23:01:2130#include "ui/gfx/native_widget_types.h"
revemanb195f41d2015-11-19 22:16:4831
32namespace base {
33namespace trace_event {
34class TracedValue;
35}
36}
37
jbaumanbd9586a92016-05-28 01:09:0338namespace cc {
xing.xu1a9aa94c2017-02-23 21:04:3239class LocalSurfaceIdAllocator;
jbaumanbd9586a92016-05-28 01:09:0340}
41
reveman2966d7702016-02-12 02:09:5442namespace gfx {
43class Path;
44}
45
revemanb195f41d2015-11-19 22:16:4846namespace exo {
47class Buffer;
reveman70baca12016-05-31 20:35:3048class Pointer;
revemanb195f41d2015-11-19 22:16:4849class SurfaceDelegate;
reveman27fe2642015-11-20 06:33:3950class SurfaceObserver;
jbaumanbd9586a92016-05-28 01:09:0351class Surface;
52
jbaumanb362a892016-06-17 03:30:5653namespace subtle {
54class PropertyHelper;
55}
56
reveman70baca12016-05-31 20:35:3057// The pointer class is currently the only cursor provider class but this can
58// change in the future when better hardware cursor support is added.
59using CursorProvider = Pointer;
60
revemanb195f41d2015-11-19 22:16:4861// This class represents a rectangular area that is displayed on the screen.
62// It has a location, size and pixel contents.
reveman211cf802017-01-10 00:30:5963class Surface : public ui::ContextFactoryObserver,
64 public aura::WindowObserver,
kylixrdf81b1e42017-01-31 14:05:4165 public ui::PropertyHandler,
eseckler599d86bb2017-03-15 09:02:5566 public ui::CompositorVSyncManager::Observer,
67 public cc::BeginFrameObserverBase {
revemanb195f41d2015-11-19 22:16:4868 public:
reveman2d3815d2016-06-26 20:13:2569 using PropertyDeallocator = void (*)(int64_t value);
jbaumanb362a892016-06-17 03:30:5670
revemanb195f41d2015-11-19 22:16:4871 Surface();
72 ~Surface() override;
73
reveman39b32c872015-12-08 05:34:0574 // Type-checking downcast routine.
kinabad14ca03e2016-02-23 04:43:3575 static Surface* AsSurface(const aura::Window* window);
reveman39b32c872015-12-08 05:34:0576
jbaumane3526252016-06-09 18:43:0577 aura::Window* window() { return window_.get(); }
78
fsamuel01f36202016-10-06 01:08:2879 cc::SurfaceId GetSurfaceId() const;
jbauman45c06862016-06-23 19:35:0280
starazd8f4f642016-12-10 23:49:2081 CompositorFrameSinkHolder* compositor_frame_sink_holder() {
82 return compositor_frame_sink_holder_.get();
83 }
84
revemanb195f41d2015-11-19 22:16:4885 // Set a buffer as the content of this surface. A buffer can only be attached
86 // to one surface at a time.
87 void Attach(Buffer* buffer);
88
89 // Describe the regions where the pending buffer is different from the
90 // current surface contents, and where the surface therefore needs to be
91 // repainted.
92 void Damage(const gfx::Rect& rect);
93
reveman211cf802017-01-10 00:30:5994 // Request notification when it's a good time to produce a new frame. Useful
95 // for throttling redrawing operations, and driving animations.
revemanb195f41d2015-11-19 22:16:4896 using FrameCallback = base::Callback<void(base::TimeTicks frame_time)>;
97 void RequestFrameCallback(const FrameCallback& callback);
98
reveman211cf802017-01-10 00:30:5999 // Request notification when the next frame is displayed. Useful for
100 // throttling redrawing operations, and driving animations.
101 using PresentationCallback =
102 base::Callback<void(base::TimeTicks presentation_time,
103 base::TimeDelta refresh)>;
104 void RequestPresentationCallback(const PresentationCallback& callback);
105
revemanb195f41d2015-11-19 22:16:48106 // This sets the region of the surface that contains opaque content.
107 void SetOpaqueRegion(const SkRegion& region);
108
reveman2966d7702016-02-12 02:09:54109 // This sets the region of the surface that can receive pointer and touch
110 // events.
111 void SetInputRegion(const SkRegion& region);
112
reveman7efa4b02016-01-06 08:29:54113 // This sets the scaling factor used to interpret the contents of the buffer
114 // attached to the surface. Note that if the scale is larger than 1, then you
115 // have to attach a buffer that is larger (by a factor of scale in each
116 // dimension) than the desired surface size.
117 void SetBufferScale(float scale);
118
reveman27fe2642015-11-20 06:33:39119 // Functions that control sub-surface state. All sub-surface state is
120 // double-buffered and will be applied when Commit() is called.
121 void AddSubSurface(Surface* sub_surface);
122 void RemoveSubSurface(Surface* sub_surface);
123 void SetSubSurfacePosition(Surface* sub_surface, const gfx::Point& position);
124 void PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference);
125 void PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling);
126
reveman642d8c332016-02-19 19:55:44127 // This sets the surface viewport for scaling.
128 void SetViewport(const gfx::Size& viewport);
129
reveman8e323902016-05-23 21:55:36130 // This sets the surface crop rectangle.
131 void SetCrop(const gfx::RectF& crop);
132
reveman85b7a562016-03-17 23:27:32133 // This sets the only visible on secure output flag, preventing it from
134 // appearing in screenshots or from being viewed on non-secure displays.
135 void SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output);
136
revemanfca687e2016-05-10 21:44:48137 // This sets the blend mode that will be used when drawing the surface.
reedcc9c70f2016-11-22 04:26:01138 void SetBlendMode(SkBlendMode blend_mode);
revemanfca687e2016-05-10 21:44:48139
140 // This sets the alpha value that will be applied to the whole surface.
141 void SetAlpha(float alpha);
142
revemanb195f41d2015-11-19 22:16:48143 // Surface state (damage regions, attached buffers, etc.) is double-buffered.
144 // A Commit() call atomically applies all pending state, replacing the
reveman27fe2642015-11-20 06:33:39145 // current state. Commit() is not guaranteed to be synchronous. See
146 // CommitSurfaceHierarchy() below.
revemanb195f41d2015-11-19 22:16:48147 void Commit();
148
reveman27fe2642015-11-20 06:33:39149 // This will synchronously commit all pending state of the surface and its
150 // descendants by recursively calling CommitSurfaceHierarchy() for each
151 // sub-surface with pending state.
152 void CommitSurfaceHierarchy();
153
154 // Returns true if surface is in synchronized mode.
155 bool IsSynchronized() const;
156
revemanb9470762016-04-10 03:49:24157 // Returns the bounds of the current input region of surface.
158 gfx::Rect GetHitTestBounds() const;
reveman2966d7702016-02-12 02:09:54159
160 // Returns true if |rect| intersects this surface's bounds.
161 bool HitTestRect(const gfx::Rect& rect) const;
162
163 // Returns true if the current input region is different than the surface
164 // bounds.
165 bool HasHitTestMask() const;
166
167 // Returns the current input region of surface in the form of a hit-test mask.
168 void GetHitTestMask(gfx::Path* mask) const;
reveman4c94cf962015-12-03 06:49:43169
reveman70baca12016-05-31 20:35:30170 // Surface does not own cursor providers. It is the responsibility of the
171 // caller to remove the cursor provider before it is destroyed.
172 void RegisterCursorProvider(CursorProvider* provider);
173 void UnregisterCursorProvider(CursorProvider* provider);
174
revemane295c662017-01-30 23:01:21175 // Returns the cursor for the surface. If no cursor provider is registered
176 // then kCursorNull is returned.
177 gfx::NativeCursor GetCursor();
reveman70baca12016-05-31 20:35:30178
revemanb195f41d2015-11-19 22:16:48179 // Set the surface delegate.
180 void SetSurfaceDelegate(SurfaceDelegate* delegate);
181
reveman27fe2642015-11-20 06:33:39182 // Returns true if surface has been assigned a surface delegate.
183 bool HasSurfaceDelegate() const;
184
185 // Surface does not own observers. It is the responsibility of the observer
186 // to remove itself when it is done observing.
187 void AddSurfaceObserver(SurfaceObserver* observer);
188 void RemoveSurfaceObserver(SurfaceObserver* observer);
189 bool HasSurfaceObserver(const SurfaceObserver* observer) const;
190
revemanb195f41d2015-11-19 22:16:48191 // Returns a trace value representing the state of the surface.
dcheng31759da2016-04-21 01:26:31192 std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
revemanb195f41d2015-11-19 22:16:48193
reveman211cf802017-01-10 00:30:59194 // Call this to indicate that surface is being scheduled for a draw.
reveman15aee282016-11-04 19:09:20195 void WillDraw();
revemanb195f41d2015-11-19 22:16:48196
eseckler599d86bb2017-03-15 09:02:55197 // Called when the begin frame source has changed.
198 void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
jbaumanbd9586a92016-05-28 01:09:03199
jbaumanf4c3f292016-06-11 00:57:33200 // Check whether this Surface and its children need to create new cc::Surface
201 // IDs for their contents next time they get new buffer contents.
202 void CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
203
reveman15aee282016-11-04 19:09:20204 // Returns the active contents size.
jbaumanb362a892016-06-17 03:30:56205 gfx::Size content_size() const { return content_size_; }
206
reveman15aee282016-11-04 19:09:20207 // Overridden from ui::ContextFactoryObserver:
208 void OnLostResources() override;
209
210 // Overridden from aura::WindowObserver:
211 void OnWindowAddedToRootWindow(aura::Window* window) override;
212 void OnWindowRemovingFromRootWindow(aura::Window* window,
213 aura::Window* new_root) override;
214
reveman211cf802017-01-10 00:30:59215 // Overridden from ui::CompositorVSyncManager::Observer:
216 void OnUpdateVSyncParameters(base::TimeTicks timebase,
217 base::TimeDelta interval) override;
218
reveman15aee282016-11-04 19:09:20219 bool HasPendingDamageForTesting(const gfx::Rect& damage) const {
220 return pending_damage_.contains(gfx::RectToSkIRect(damage));
221 }
222
eseckler599d86bb2017-03-15 09:02:55223 // Overridden from cc::BeginFrameObserverBase:
224 bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
225 void OnBeginFrameSourcePausedChanged(bool paused) override {}
226
revemanb195f41d2015-11-19 22:16:48227 private:
jbaumanf4c3f292016-06-11 00:57:33228 struct State {
229 State();
230 ~State();
231
232 bool operator==(const State& other);
233 bool operator!=(const State& other) { return !(*this == other); }
234
235 SkRegion opaque_region;
236 SkRegion input_region;
reveman2d3815d2016-06-26 20:13:25237 float buffer_scale = 1.0f;
jbaumanf4c3f292016-06-11 00:57:33238 gfx::Size viewport;
239 gfx::RectF crop;
240 bool only_visible_on_secure_output = false;
reedcc9c70f2016-11-22 04:26:01241 SkBlendMode blend_mode = SkBlendMode::kSrcOver;
jbaumanf4c3f292016-06-11 00:57:33242 float alpha = 1.0f;
jbauman45c06862016-06-23 19:35:02243 };
244 class BufferAttachment {
245 public:
246 BufferAttachment();
247 ~BufferAttachment();
248
249 BufferAttachment& operator=(BufferAttachment&& buffer);
250
251 base::WeakPtr<Buffer>& buffer();
252 const base::WeakPtr<Buffer>& buffer() const;
253 void Reset(base::WeakPtr<Buffer> buffer);
254
255 private:
256 base::WeakPtr<Buffer> buffer_;
257
258 DISALLOW_COPY_AND_ASSIGN(BufferAttachment);
jbaumanf4c3f292016-06-11 00:57:33259 };
260
jbaumanb362a892016-06-17 03:30:56261 friend class subtle::PropertyHelper;
262
reveman27fe2642015-11-20 06:33:39263 bool needs_commit_surface_hierarchy() const {
264 return needs_commit_surface_hierarchy_;
265 }
266
jbaumanf4c3f292016-06-11 00:57:33267 // Returns true if this surface or any child surface needs a commit and has
268 // has_pending_layer_changes_ true.
269 bool HasLayerHierarchyChanged() const;
270
271 // Sets that all children must create new cc::SurfaceIds for their contents.
272 void SetSurfaceHierarchyNeedsCommitToNewSurfaces();
273
reveman56f345902016-06-06 03:58:28274 // Set SurfaceLayer contents to the current buffer.
275 void SetSurfaceLayerContents(ui::Layer* layer);
276
jbauman45c06862016-06-23 19:35:02277 // Updates current_resource_ with a new resource id corresponding to the
278 // contents of the attached buffer (or id 0, if no buffer is attached).
279 // UpdateSurface must be called afterwards to ensure the release callback
280 // will be called.
281 void UpdateResource(bool client_usage);
282
283 // Updates the current Surface with a new frame referring to the resource in
284 // current_resource_.
285 void UpdateSurface(bool full_damage);
286
eseckler599d86bb2017-03-15 09:02:55287 // Adds/Removes begin frame observer based on state.
288 void UpdateNeedsBeginFrame();
289
revemanced21f82015-11-24 00:42:49290 // This returns true when the surface has some contents assigned to it.
jbauman45c06862016-06-23 19:35:02291 bool has_contents() const { return !!current_buffer_.buffer(); }
revemanced21f82015-11-24 00:42:49292
jbaumane3526252016-06-09 18:43:05293 // This window has the layer which contains the Surface contents.
294 std::unique_ptr<aura::Window> window_;
295
jbaumanf4c3f292016-06-11 00:57:33296 // This is true if it's possible that the layer properties (size, opacity,
297 // etc.) may have been modified since the last commit. Attaching a new
298 // buffer with the same size as the old shouldn't set this to true.
299 bool has_pending_layer_changes_ = true;
300
301 // This is true if the next commit to this surface should put its contents
302 // into a new cc::SurfaceId. This allows for synchronization between Surface
303 // and layer changes.
304 bool needs_commit_to_new_surface_ = true;
305
jbaumanb362a892016-06-17 03:30:56306 // This is the size of the last committed contents.
307 gfx::Size content_size_;
308
revemanced21f82015-11-24 00:42:49309 // This is true when Attach() has been called and new contents should take
310 // effect next time Commit() is called.
reveman2d3815d2016-06-26 20:13:25311 bool has_pending_contents_ = false;
reveman27fe2642015-11-20 06:33:39312
revemanb195f41d2015-11-19 22:16:48313 // The buffer that will become the content of surface when Commit() is called.
jbauman45c06862016-06-23 19:35:02314 BufferAttachment pending_buffer_;
revemanb195f41d2015-11-19 22:16:48315
starazd8f4f642016-12-10 23:49:20316 const cc::FrameSinkId frame_sink_id_;
samans5258bfb2017-01-27 21:16:26317 cc::LocalSurfaceId local_surface_id_;
jbaumanbd9586a92016-05-28 01:09:03318
starazd8f4f642016-12-10 23:49:20319 scoped_refptr<CompositorFrameSinkHolder> compositor_frame_sink_holder_;
320
xing.xu1a9aa94c2017-02-23 21:04:32321 cc::LocalSurfaceIdAllocator id_allocator_;
starazd8f4f642016-12-10 23:49:20322
jbaumanbd9586a92016-05-28 01:09:03323 // The next resource id the buffer will be attached to.
jbauman2fdc0732016-06-07 00:55:36324 int next_resource_id_ = 1;
jbaumanbd9586a92016-05-28 01:09:03325
revemanb195f41d2015-11-19 22:16:48326 // The damage region to schedule paint for when Commit() is called.
reveman5c353d52016-02-11 21:28:56327 SkRegion pending_damage_;
revemanb195f41d2015-11-19 22:16:48328
329 // These lists contains the callbacks to notify the client when it is a good
330 // time to start producing a new frame. These callbacks move to
331 // |frame_callbacks_| when Commit() is called. Later they are moved to
reveman15aee282016-11-04 19:09:20332 // |active_frame_callbacks_| when the effect of the Commit() is scheduled to
333 // be drawn. They fire at the first begin frame notification after this.
revemanb195f41d2015-11-19 22:16:48334 std::list<FrameCallback> pending_frame_callbacks_;
335 std::list<FrameCallback> frame_callbacks_;
reveman211cf802017-01-10 00:30:59336 std::list<FrameCallback> active_frame_callbacks_;
337
338 // These lists contains the callbacks to notify the client when surface
339 // contents have been presented. These callbacks move to
340 // |presentation_callbacks_| when Commit() is called. Later they are moved to
341 // |swapping_presentation_callbacks_| when the effect of the Commit() is
342 // scheduled to be drawn and then moved to |swapped_presentation_callbacks_|
343 // after receiving VSync parameters update for the previous frame. They fire
344 // at the next VSync parameters update after that.
345 std::list<PresentationCallback> pending_presentation_callbacks_;
346 std::list<PresentationCallback> presentation_callbacks_;
347 std::list<PresentationCallback> swapping_presentation_callbacks_;
348 std::list<PresentationCallback> swapped_presentation_callbacks_;
revemanb195f41d2015-11-19 22:16:48349
jbaumanf4c3f292016-06-11 00:57:33350 // This is the state that has yet to be committed.
351 State pending_state_;
revemanb195f41d2015-11-19 22:16:48352
jbaumanf4c3f292016-06-11 00:57:33353 // This is the state that has been committed.
354 State state_;
reveman7efa4b02016-01-06 08:29:54355
reveman27fe2642015-11-20 06:33:39356 // The stack of sub-surfaces to take effect when Commit() is called.
357 // Bottom-most sub-surface at the front of the list and top-most sub-surface
358 // at the back.
359 using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
360 using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
361 SubSurfaceEntryList pending_sub_surfaces_;
362
revemanced21f82015-11-24 00:42:49363 // The buffer that is currently set as content of surface.
jbauman45c06862016-06-23 19:35:02364 BufferAttachment current_buffer_;
revemanced21f82015-11-24 00:42:49365
jbauman2fdc0732016-06-07 00:55:36366 // The last resource that was sent to a surface.
367 cc::TransferableResource current_resource_;
368
revemanca132dc2017-01-31 22:35:54369 // Whether the last resource that was sent to a surface has an alpha channel.
370 bool current_resource_has_alpha_ = false;
371
reveman27fe2642015-11-20 06:33:39372 // This is true if a call to Commit() as been made but
373 // CommitSurfaceHierarchy() has not yet been called.
reveman2d3815d2016-06-26 20:13:25374 bool needs_commit_surface_hierarchy_ = false;
reveman27fe2642015-11-20 06:33:39375
reveman7cadea42016-02-05 20:14:38376 // This is set when the compositing starts and passed to active frame
377 // callbacks when compositing successfully ends.
378 base::TimeTicks last_compositing_start_time_;
379
reveman70baca12016-05-31 20:35:30380 // Cursor providers. Surface does not own the cursor providers.
381 std::set<CursorProvider*> cursor_providers_;
382
revemanb195f41d2015-11-19 22:16:48383 // This can be set to have some functions delegated. E.g. ShellSurface class
384 // can set this to handle Commit() and apply any double buffered state it
385 // maintains.
reveman2d3815d2016-06-26 20:13:25386 SurfaceDelegate* delegate_ = nullptr;
revemanb195f41d2015-11-19 22:16:48387
reveman27fe2642015-11-20 06:33:39388 // Surface observer list. Surface does not own the observers.
389 base::ObserverList<SurfaceObserver, true> observers_;
390
samans72b2a282016-12-17 02:44:15391 // A reference factory that uses the compositor frame sink holder provided
392 // to this class to construct surface references. This object is passed to
393 // ui::Layer::SetShowSurface because the layer needs to know how to add
394 // references to surfaces.
395 scoped_refptr<cc::SurfaceReferenceFactory> surface_reference_factory_;
396
eseckler599d86bb2017-03-15 09:02:55397 // The begin frame source being observed.
398 cc::BeginFrameSource* begin_frame_source_ = nullptr;
399 bool needs_begin_frame_ = false;
400 cc::BeginFrameAck current_begin_frame_ack_;
401
revemanb195f41d2015-11-19 22:16:48402 DISALLOW_COPY_AND_ASSIGN(Surface);
403};
404
405} // namespace exo
406
407#endif // COMPONENTS_EXO_SURFACE_H_