blob: a5b59e1cb8f8db1ba71ed65e24a997fbc8746680 [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>
reveman70baca12016-05-31 20:35:309#include <set>
reveman27fe2642015-11-20 06:33:3910#include <utility>
revemanb195f41d2015-11-19 22:16:4811
12#include "base/callback.h"
13#include "base/macros.h"
jbaumanbd9586a92016-05-28 01:09:0314#include "base/memory/ref_counted.h"
revemanb195f41d2015-11-19 22:16:4815#include "base/memory/weak_ptr.h"
reveman27fe2642015-11-20 06:33:3916#include "base/observer_list.h"
Dominik Laskowski0dcf91352017-11-29 19:21:3517#include "cc/base/region.h"
danakjc7afae52017-06-20 21:12:4118#include "components/exo/layer_tree_frame_sink_holder.h"
David Reveman93f67c02017-09-06 03:23:0819#include "components/exo/surface_delegate.h"
Fady Samuelc645ffe2017-07-24 17:28:2020#include "components/viz/common/frame_sinks/begin_frame_source.h"
Fady Samuel4f7f0fb32017-07-28 15:33:3721#include "components/viz/common/resources/transferable_resource.h"
reedcc9c70f2016-11-22 04:26:0122#include "third_party/skia/include/core/SkBlendMode.h"
reveman4c94cf962015-12-03 06:49:4323#include "ui/aura/window.h"
Peng Huangb921f3f2017-09-27 20:01:2324#include "ui/aura/window_targeter.h"
revemanb195f41d2015-11-19 22:16:4825#include "ui/gfx/geometry/rect.h"
revemane295c662017-01-30 23:01:2126#include "ui/gfx/native_widget_types.h"
Lloyd Pique0a3045f2017-09-15 23:34:1227#include "ui/gfx/transform.h"
revemanb195f41d2015-11-19 22:16:4828
29namespace base {
30namespace trace_event {
31class TracedValue;
32}
33}
34
reveman2966d7702016-02-12 02:09:5435namespace gfx {
36class Path;
37}
38
danakj5e0a12b2017-09-25 17:26:4939namespace viz {
40class CompositorFrame;
41}
42
revemanb195f41d2015-11-19 22:16:4843namespace exo {
44class Buffer;
Peng Huang583c9dc62017-07-27 23:38:2845class LayerTreeFrameSinkHolder;
reveman70baca12016-05-31 20:35:3046class Pointer;
reveman27fe2642015-11-20 06:33:3947class SurfaceObserver;
jbaumanbd9586a92016-05-28 01:09:0348class Surface;
49
jbaumanb362a892016-06-17 03:30:5650namespace subtle {
51class PropertyHelper;
52}
53
David Revemanfca309b2017-08-24 18:18:1154// Counter-clockwise rotations.
55enum class Transform { NORMAL, ROTATE_90, ROTATE_180, ROTATE_270 };
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.
Hans Wennborgaf90ff12017-09-04 19:46:0263class Surface final : public ui::PropertyHandler {
revemanb195f41d2015-11-19 22:16:4864 public:
reveman2d3815d2016-06-26 20:13:2565 using PropertyDeallocator = void (*)(int64_t value);
jbaumanb362a892016-06-17 03:30:5666
revemanb195f41d2015-11-19 22:16:4867 Surface();
Peng Huang583c9dc62017-07-27 23:38:2868 ~Surface();
revemanb195f41d2015-11-19 22:16:4869
reveman39b32c872015-12-08 05:34:0570 // Type-checking downcast routine.
kinabad14ca03e2016-02-23 04:43:3571 static Surface* AsSurface(const aura::Window* window);
reveman39b32c872015-12-08 05:34:0572
jbaumane3526252016-06-09 18:43:0573 aura::Window* window() { return window_.get(); }
74
revemanb195f41d2015-11-19 22:16:4875 // Set a buffer as the content of this surface. A buffer can only be attached
76 // to one surface at a time.
77 void Attach(Buffer* buffer);
78
79 // Describe the regions where the pending buffer is different from the
80 // current surface contents, and where the surface therefore needs to be
81 // repainted.
82 void Damage(const gfx::Rect& rect);
83
reveman211cf802017-01-10 00:30:5984 // Request notification when it's a good time to produce a new frame. Useful
85 // for throttling redrawing operations, and driving animations.
revemanb195f41d2015-11-19 22:16:4886 using FrameCallback = base::Callback<void(base::TimeTicks frame_time)>;
87 void RequestFrameCallback(const FrameCallback& callback);
88
reveman211cf802017-01-10 00:30:5989 // Request notification when the next frame is displayed. Useful for
90 // throttling redrawing operations, and driving animations.
91 using PresentationCallback =
92 base::Callback<void(base::TimeTicks presentation_time,
Peng Huang5207a6e2017-10-26 00:39:3093 base::TimeDelta refresh,
94 uint32_t flags)>;
reveman211cf802017-01-10 00:30:5995 void RequestPresentationCallback(const PresentationCallback& callback);
96
revemanb195f41d2015-11-19 22:16:4897 // This sets the region of the surface that contains opaque content.
Dominik Laskowski0dcf91352017-11-29 19:21:3598 void SetOpaqueRegion(const cc::Region& region);
revemanb195f41d2015-11-19 22:16:4899
reveman2966d7702016-02-12 02:09:54100 // This sets the region of the surface that can receive pointer and touch
Dominik Laskowski57064702017-11-30 10:31:41101 // events. The region is clipped to the surface bounds.
Dominik Laskowski0dcf91352017-11-29 19:21:35102 void SetInputRegion(const cc::Region& region);
reveman2966d7702016-02-12 02:09:54103
reveman7efa4b02016-01-06 08:29:54104 // This sets the scaling factor used to interpret the contents of the buffer
105 // attached to the surface. Note that if the scale is larger than 1, then you
106 // have to attach a buffer that is larger (by a factor of scale in each
107 // dimension) than the desired surface size.
108 void SetBufferScale(float scale);
109
David Revemanfca309b2017-08-24 18:18:11110 // This sets the transformation used to interpret the contents of the buffer
111 // attached to the surface.
112 void SetBufferTransform(Transform transform);
113
reveman27fe2642015-11-20 06:33:39114 // Functions that control sub-surface state. All sub-surface state is
115 // double-buffered and will be applied when Commit() is called.
116 void AddSubSurface(Surface* sub_surface);
117 void RemoveSubSurface(Surface* sub_surface);
118 void SetSubSurfacePosition(Surface* sub_surface, const gfx::Point& position);
119 void PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference);
120 void PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling);
David Reveman8b43b352017-11-03 15:24:51121 void OnSubSurfaceCommit();
reveman27fe2642015-11-20 06:33:39122
reveman642d8c332016-02-19 19:55:44123 // This sets the surface viewport for scaling.
124 void SetViewport(const gfx::Size& viewport);
125
reveman8e323902016-05-23 21:55:36126 // This sets the surface crop rectangle.
127 void SetCrop(const gfx::RectF& crop);
128
reveman85b7a562016-03-17 23:27:32129 // This sets the only visible on secure output flag, preventing it from
130 // appearing in screenshots or from being viewed on non-secure displays.
131 void SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output);
132
revemanfca687e2016-05-10 21:44:48133 // This sets the blend mode that will be used when drawing the surface.
reedcc9c70f2016-11-22 04:26:01134 void SetBlendMode(SkBlendMode blend_mode);
revemanfca687e2016-05-10 21:44:48135
136 // This sets the alpha value that will be applied to the whole surface.
137 void SetAlpha(float alpha);
138
David Reveman93f67c02017-09-06 03:23:08139 // Request that surface should have the specified frame type.
140 void SetFrame(SurfaceFrameType type);
141
David Reveman32715092017-12-05 18:24:11142 // Request "parent" for surface.
143 void SetParent(Surface* parent, const gfx::Point& position);
144
revemanb195f41d2015-11-19 22:16:48145 // Surface state (damage regions, attached buffers, etc.) is double-buffered.
146 // A Commit() call atomically applies all pending state, replacing the
reveman27fe2642015-11-20 06:33:39147 // current state. Commit() is not guaranteed to be synchronous. See
148 // CommitSurfaceHierarchy() below.
revemanb195f41d2015-11-19 22:16:48149 void Commit();
150
David Reveman8b43b352017-11-03 15:24:51151 // This will commit all pending state of the surface and its descendants by
David Reveman7a126ba2017-11-09 17:17:41152 // recursively calling CommitSurfaceHierarchy() for each sub-surface.
153 // If |synchronized| is set to false, then synchronized surfaces should not
154 // commit pending state.
David Revemanef1cb082017-11-09 21:14:40155 void CommitSurfaceHierarchy(bool synchronized);
reveman27fe2642015-11-20 06:33:39156
David Revemanef1cb082017-11-09 21:14:40157 // This will append current callbacks for surface and its descendants to
158 // |frame_callbacks| and |presentation_callbacks|.
159 void AppendSurfaceHierarchyCallbacks(
160 std::list<FrameCallback>* frame_callbacks,
161 std::list<PresentationCallback>* presentation_callbacks);
162
163 // This will append contents for surface and its descendants to frame.
Peng Huang76f5fd02017-09-01 00:59:39164 void AppendSurfaceHierarchyContentsToFrame(
165 const gfx::Point& origin,
166 float device_scale_factor,
167 LayerTreeFrameSinkHolder* frame_sink_holder,
danakj5e0a12b2017-09-25 17:26:49168 viz::CompositorFrame* frame);
Peng Huang76f5fd02017-09-01 00:59:39169
reveman27fe2642015-11-20 06:33:39170 // Returns true if surface is in synchronized mode.
171 bool IsSynchronized() const;
172
Dominik Laskowski57064702017-11-30 10:31:41173 // Returns false if the hit test region is empty.
174 bool HasHitTestRegion() const;
reveman2966d7702016-02-12 02:09:54175
Dominik Laskowski57064702017-11-30 10:31:41176 // Returns true if |point| is inside the surface.
177 bool HitTest(const gfx::Point& point) const;
reveman2966d7702016-02-12 02:09:54178
Dominik Laskowski57064702017-11-30 10:31:41179 // Sets |mask| to the path that delineates the hit test region of the surface.
reveman2966d7702016-02-12 02:09:54180 void GetHitTestMask(gfx::Path* mask) const;
reveman4c94cf962015-12-03 06:49:43181
Peng Huangb921f3f2017-09-27 20:01:23182 // Returns the current input region of surface in the form of a set of
183 // hit-test rects.
184 std::unique_ptr<aura::WindowTargeter::HitTestRects> GetHitTestShapeRects()
185 const;
186
reveman70baca12016-05-31 20:35:30187 // Surface does not own cursor providers. It is the responsibility of the
188 // caller to remove the cursor provider before it is destroyed.
189 void RegisterCursorProvider(CursorProvider* provider);
190 void UnregisterCursorProvider(CursorProvider* provider);
191
revemane295c662017-01-30 23:01:21192 // Returns the cursor for the surface. If no cursor provider is registered
ergeeba7c622017-04-25 18:06:16193 // then CursorType::kNull is returned.
revemane295c662017-01-30 23:01:21194 gfx::NativeCursor GetCursor();
reveman70baca12016-05-31 20:35:30195
revemanb195f41d2015-11-19 22:16:48196 // Set the surface delegate.
197 void SetSurfaceDelegate(SurfaceDelegate* delegate);
198
reveman27fe2642015-11-20 06:33:39199 // Returns true if surface has been assigned a surface delegate.
200 bool HasSurfaceDelegate() const;
201
202 // Surface does not own observers. It is the responsibility of the observer
203 // to remove itself when it is done observing.
204 void AddSurfaceObserver(SurfaceObserver* observer);
205 void RemoveSurfaceObserver(SurfaceObserver* observer);
206 bool HasSurfaceObserver(const SurfaceObserver* observer) const;
207
revemanb195f41d2015-11-19 22:16:48208 // Returns a trace value representing the state of the surface.
dcheng31759da2016-04-21 01:26:31209 std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
revemanb195f41d2015-11-19 22:16:48210
eseckler599d86bb2017-03-15 09:02:55211 // Called when the begin frame source has changed.
Fady Samuelc645ffe2017-07-24 17:28:20212 void SetBeginFrameSource(viz::BeginFrameSource* begin_frame_source);
jbaumanbd9586a92016-05-28 01:09:03213
David Reveman7a126ba2017-11-09 17:17:41214 // Returns the active content size.
Peng Huangb07b0652017-06-27 17:25:22215 const gfx::Size& content_size() const { return content_size_; }
jbaumanb362a892016-06-17 03:30:56216
David Reveman7a126ba2017-11-09 17:17:41217 // Returns the active content bounds for surface hierarchy. ie. the bounding
218 // box of the surface and its descendants, in the local coordinate space of
219 // the surface.
220 const gfx::Rect& surface_hierarchy_content_bounds() const {
221 return surface_hierarchy_content_bounds_;
222 }
223
kaznacheev8e270592017-05-25 06:13:26224 // Returns true if the associated window is in 'stylus-only' mode.
225 bool IsStylusOnly();
226
227 // Enables 'stylus-only' mode for the associated window.
228 void SetStylusOnly();
229
Peng Huangc51f7aba2017-09-05 16:00:39230 // Notify surface that resources and subsurfaces' resources have been lost.
231 void SurfaceHierarchyResourcesLost();
reveman15aee282016-11-04 19:09:20232
Peng Huang583c9dc62017-07-27 23:38:28233 // Returns true if the surface's bounds should be filled opaquely.
234 bool FillsBoundsOpaquely() const;
reveman211cf802017-01-10 00:30:59235
reveman15aee282016-11-04 19:09:20236 bool HasPendingDamageForTesting(const gfx::Rect& damage) const {
Dominik Laskowski0dcf91352017-11-29 19:21:35237 return pending_damage_.Contains(damage);
reveman15aee282016-11-04 19:09:20238 }
239
revemanb195f41d2015-11-19 22:16:48240 private:
jbaumanf4c3f292016-06-11 00:57:33241 struct State {
242 State();
243 ~State();
244
245 bool operator==(const State& other);
246 bool operator!=(const State& other) { return !(*this == other); }
247
Dominik Laskowski0dcf91352017-11-29 19:21:35248 cc::Region opaque_region;
249 cc::Region input_region;
reveman2d3815d2016-06-26 20:13:25250 float buffer_scale = 1.0f;
David Revemanfca309b2017-08-24 18:18:11251 Transform buffer_transform = Transform::NORMAL;
jbaumanf4c3f292016-06-11 00:57:33252 gfx::Size viewport;
253 gfx::RectF crop;
254 bool only_visible_on_secure_output = false;
reedcc9c70f2016-11-22 04:26:01255 SkBlendMode blend_mode = SkBlendMode::kSrcOver;
jbaumanf4c3f292016-06-11 00:57:33256 float alpha = 1.0f;
jbauman45c06862016-06-23 19:35:02257 };
258 class BufferAttachment {
259 public:
260 BufferAttachment();
261 ~BufferAttachment();
262
263 BufferAttachment& operator=(BufferAttachment&& buffer);
264
265 base::WeakPtr<Buffer>& buffer();
266 const base::WeakPtr<Buffer>& buffer() const;
David Revemane6e23342017-11-07 06:18:06267 const gfx::Size& size() const;
jbauman45c06862016-06-23 19:35:02268 void Reset(base::WeakPtr<Buffer> buffer);
269
270 private:
271 base::WeakPtr<Buffer> buffer_;
David Revemane6e23342017-11-07 06:18:06272 gfx::Size size_;
jbauman45c06862016-06-23 19:35:02273
274 DISALLOW_COPY_AND_ASSIGN(BufferAttachment);
jbaumanf4c3f292016-06-11 00:57:33275 };
276
jbaumanb362a892016-06-17 03:30:56277 friend class subtle::PropertyHelper;
278
jbauman45c06862016-06-23 19:35:02279 // Updates current_resource_ with a new resource id corresponding to the
280 // contents of the attached buffer (or id 0, if no buffer is attached).
281 // UpdateSurface must be called afterwards to ensure the release callback
282 // will be called.
Peng Huangc51f7aba2017-09-05 16:00:39283 void UpdateResource(LayerTreeFrameSinkHolder* frame_sink_holder);
jbauman45c06862016-06-23 19:35:02284
Lloyd Pique0a3045f2017-09-15 23:34:12285 // Updates buffer_transform_ to match the current buffer parameters.
286 void UpdateBufferTransform();
287
Peng Huang583c9dc62017-07-27 23:38:28288 // Puts the current surface into a draw quad, and appends the draw quads into
289 // the |frame|.
290 void AppendContentsToFrame(const gfx::Point& origin,
Peng Huang76f5fd02017-09-01 00:59:39291 float device_scale_factor,
danakj5e0a12b2017-09-25 17:26:49292 viz::CompositorFrame* frame);
jbauman45c06862016-06-23 19:35:02293
Peng Huangc51f7aba2017-09-05 16:00:39294 // Update surface content size base on current buffer size.
Peng Huang583c9dc62017-07-27 23:38:28295 void UpdateContentSize();
eseckler599d86bb2017-03-15 09:02:55296
revemanced21f82015-11-24 00:42:49297 // This returns true when the surface has some contents assigned to it.
David Revemane6e23342017-11-07 06:18:06298 bool has_contents() const { return !current_buffer_.size().IsEmpty(); }
revemanced21f82015-11-24 00:42:49299
jbaumane3526252016-06-09 18:43:05300 // This window has the layer which contains the Surface contents.
301 std::unique_ptr<aura::Window> window_;
302
Peng Huang583c9dc62017-07-27 23:38:28303 // This true, if sub_surfaces_ has changes (order, position, etc).
304 bool sub_surfaces_changed_ = false;
jbaumanf4c3f292016-06-11 00:57:33305
jbaumanb362a892016-06-17 03:30:56306 // This is the size of the last committed contents.
307 gfx::Size content_size_;
308
David Reveman7a126ba2017-11-09 17:17:41309 // This is the bounds of the last committed surface hierarchy contents.
310 gfx::Rect surface_hierarchy_content_bounds_;
311
revemanced21f82015-11-24 00:42:49312 // This is true when Attach() has been called and new contents should take
313 // effect next time Commit() is called.
reveman2d3815d2016-06-26 20:13:25314 bool has_pending_contents_ = false;
reveman27fe2642015-11-20 06:33:39315
revemanb195f41d2015-11-19 22:16:48316 // The buffer that will become the content of surface when Commit() is called.
jbauman45c06862016-06-23 19:35:02317 BufferAttachment pending_buffer_;
revemanb195f41d2015-11-19 22:16:48318
319 // The damage region to schedule paint for when Commit() is called.
Dominik Laskowski0dcf91352017-11-29 19:21:35320 cc::Region pending_damage_;
revemanb195f41d2015-11-19 22:16:48321
Peng Huang76f5fd02017-09-01 00:59:39322 // The damage region which will be used by
323 // AppendSurfaceHierarchyContentsToFrame() to generate frame.
Dominik Laskowski0dcf91352017-11-29 19:21:35324 cc::Region damage_;
Peng Huang76f5fd02017-09-01 00:59:39325
revemanb195f41d2015-11-19 22:16:48326 // These lists contains the callbacks to notify the client when it is a good
327 // time to start producing a new frame. These callbacks move to
328 // |frame_callbacks_| when Commit() is called. Later they are moved to
reveman15aee282016-11-04 19:09:20329 // |active_frame_callbacks_| when the effect of the Commit() is scheduled to
330 // be drawn. They fire at the first begin frame notification after this.
revemanb195f41d2015-11-19 22:16:48331 std::list<FrameCallback> pending_frame_callbacks_;
David Revemanef1cb082017-11-09 21:14:40332 std::list<FrameCallback> frame_callbacks_;
reveman211cf802017-01-10 00:30:59333
334 // These lists contains the callbacks to notify the client when surface
335 // contents have been presented. These callbacks move to
336 // |presentation_callbacks_| when Commit() is called. Later they are moved to
337 // |swapping_presentation_callbacks_| when the effect of the Commit() is
338 // scheduled to be drawn and then moved to |swapped_presentation_callbacks_|
339 // after receiving VSync parameters update for the previous frame. They fire
340 // at the next VSync parameters update after that.
341 std::list<PresentationCallback> pending_presentation_callbacks_;
David Revemanef1cb082017-11-09 21:14:40342 std::list<PresentationCallback> presentation_callbacks_;
revemanb195f41d2015-11-19 22:16:48343
jbaumanf4c3f292016-06-11 00:57:33344 // This is the state that has yet to be committed.
345 State pending_state_;
revemanb195f41d2015-11-19 22:16:48346
jbaumanf4c3f292016-06-11 00:57:33347 // This is the state that has been committed.
348 State state_;
reveman7efa4b02016-01-06 08:29:54349
Dominik Laskowski57064702017-11-30 10:31:41350 // Cumulative input region of surface and its sub-surfaces.
351 cc::Region hit_test_region_;
352
reveman27fe2642015-11-20 06:33:39353 // The stack of sub-surfaces to take effect when Commit() is called.
354 // Bottom-most sub-surface at the front of the list and top-most sub-surface
355 // at the back.
356 using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
357 using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
358 SubSurfaceEntryList pending_sub_surfaces_;
Peng Huang583c9dc62017-07-27 23:38:28359 SubSurfaceEntryList sub_surfaces_;
reveman27fe2642015-11-20 06:33:39360
revemanced21f82015-11-24 00:42:49361 // The buffer that is currently set as content of surface.
jbauman45c06862016-06-23 19:35:02362 BufferAttachment current_buffer_;
revemanced21f82015-11-24 00:42:49363
jbauman2fdc0732016-06-07 00:55:36364 // The last resource that was sent to a surface.
Fady Samuel4f7f0fb32017-07-28 15:33:37365 viz::TransferableResource current_resource_;
jbauman2fdc0732016-06-07 00:55:36366
revemanca132dc2017-01-31 22:35:54367 // Whether the last resource that was sent to a surface has an alpha channel.
368 bool current_resource_has_alpha_ = false;
369
reveman27fe2642015-11-20 06:33:39370 // This is true if a call to Commit() as been made but
371 // CommitSurfaceHierarchy() has not yet been called.
Peng Huang76f5fd02017-09-01 00:59:39372 bool needs_commit_surface_ = false;
reveman27fe2642015-11-20 06:33:39373
Peng Huangc51f7aba2017-09-05 16:00:39374 // This is true if UpdateResources() should be called.
375 bool needs_update_resource_ = true;
376
Lloyd Pique0a3045f2017-09-15 23:34:12377 // The current buffer transform matrix. It specifies the transformation from
378 // normalized buffer coordinates to post-tranform buffer coordinates.
379 gfx::Transform buffer_transform_;
380
reveman7cadea42016-02-05 20:14:38381 // This is set when the compositing starts and passed to active frame
382 // callbacks when compositing successfully ends.
383 base::TimeTicks last_compositing_start_time_;
384
reveman70baca12016-05-31 20:35:30385 // Cursor providers. Surface does not own the cursor providers.
386 std::set<CursorProvider*> cursor_providers_;
387
revemanb195f41d2015-11-19 22:16:48388 // This can be set to have some functions delegated. E.g. ShellSurface class
389 // can set this to handle Commit() and apply any double buffered state it
390 // maintains.
reveman2d3815d2016-06-26 20:13:25391 SurfaceDelegate* delegate_ = nullptr;
revemanb195f41d2015-11-19 22:16:48392
reveman27fe2642015-11-20 06:33:39393 // Surface observer list. Surface does not own the observers.
394 base::ObserverList<SurfaceObserver, true> observers_;
395
revemanb195f41d2015-11-19 22:16:48396 DISALLOW_COPY_AND_ASSIGN(Surface);
397};
398
399} // namespace exo
400
401#endif // COMPONENTS_EXO_SURFACE_H_