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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
|
// 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.
#ifndef COMPONENTS_EXO_SURFACE_H_
#define COMPONENTS_EXO_SURFACE_H_
#include <list>
#include <set>
#include <utility>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "cc/resources/transferable_resource.h"
#include "cc/scheduler/begin_frame_source.h"
#include "components/exo/compositor_frame_sink_holder.h"
#include "third_party/skia/include/core/SkBlendMode.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
namespace base {
namespace trace_event {
class TracedValue;
}
}
namespace gfx {
class Path;
}
namespace exo {
class Buffer;
class Pointer;
class SurfaceDelegate;
class SurfaceObserver;
class Surface;
namespace subtle {
class PropertyHelper;
}
// The pointer class is currently the only cursor provider class but this can
// change in the future when better hardware cursor support is added.
using CursorProvider = Pointer;
// This class represents a rectangular area that is displayed on the screen.
// It has a location, size and pixel contents.
class Surface : public ui::ContextFactoryObserver,
public aura::WindowObserver,
public ui::PropertyHandler,
public ui::CompositorVSyncManager::Observer,
public cc::BeginFrameObserverBase {
public:
using PropertyDeallocator = void (*)(int64_t value);
Surface();
~Surface() override;
// Type-checking downcast routine.
static Surface* AsSurface(const aura::Window* window);
aura::Window* window() { return window_.get(); }
cc::SurfaceId GetSurfaceId() const;
CompositorFrameSinkHolder* compositor_frame_sink_holder() {
return compositor_frame_sink_holder_.get();
}
// Set a buffer as the content of this surface. A buffer can only be attached
// to one surface at a time.
void Attach(Buffer* buffer);
// Describe the regions where the pending buffer is different from the
// current surface contents, and where the surface therefore needs to be
// repainted.
void Damage(const gfx::Rect& rect);
// Request notification when it's a good time to produce a new frame. Useful
// for throttling redrawing operations, and driving animations.
using FrameCallback = base::Callback<void(base::TimeTicks frame_time)>;
void RequestFrameCallback(const FrameCallback& callback);
// Request notification when the next frame is displayed. Useful for
// throttling redrawing operations, and driving animations.
using PresentationCallback =
base::Callback<void(base::TimeTicks presentation_time,
base::TimeDelta refresh)>;
void RequestPresentationCallback(const PresentationCallback& callback);
// This sets the region of the surface that contains opaque content.
void SetOpaqueRegion(const SkRegion& region);
// This sets the region of the surface that can receive pointer and touch
// events.
void SetInputRegion(const SkRegion& region);
// This sets the scaling factor used to interpret the contents of the buffer
// attached to the surface. Note that if the scale is larger than 1, then you
// have to attach a buffer that is larger (by a factor of scale in each
// dimension) than the desired surface size.
void SetBufferScale(float scale);
// Functions that control sub-surface state. All sub-surface state is
// double-buffered and will be applied when Commit() is called.
void AddSubSurface(Surface* sub_surface);
void RemoveSubSurface(Surface* sub_surface);
void SetSubSurfacePosition(Surface* sub_surface, const gfx::Point& position);
void PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference);
void PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling);
// This sets the surface viewport for scaling.
void SetViewport(const gfx::Size& viewport);
// This sets the surface crop rectangle.
void SetCrop(const gfx::RectF& crop);
// This sets the only visible on secure output flag, preventing it from
// appearing in screenshots or from being viewed on non-secure displays.
void SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output);
// This sets the blend mode that will be used when drawing the surface.
void SetBlendMode(SkBlendMode blend_mode);
// This sets the alpha value that will be applied to the whole surface.
void SetAlpha(float alpha);
// This sets the device scale factor sent in CompositorFrames.
void SetDeviceScaleFactor(float device_scale_factor);
// Surface state (damage regions, attached buffers, etc.) is double-buffered.
// A Commit() call atomically applies all pending state, replacing the
// current state. Commit() is not guaranteed to be synchronous. See
// CommitSurfaceHierarchy() below.
void Commit();
// This will synchronously commit all pending state of the surface and its
// descendants by recursively calling CommitSurfaceHierarchy() for each
// sub-surface with pending state.
void CommitSurfaceHierarchy();
// Returns true if surface is in synchronized mode.
bool IsSynchronized() const;
// Returns the bounds of the current input region of surface.
gfx::Rect GetHitTestBounds() const;
// Returns true if |rect| intersects this surface's bounds.
bool HitTestRect(const gfx::Rect& rect) const;
// Returns true if the current input region is different than the surface
// bounds.
bool HasHitTestMask() const;
// Returns the current input region of surface in the form of a hit-test mask.
void GetHitTestMask(gfx::Path* mask) const;
// Surface does not own cursor providers. It is the responsibility of the
// caller to remove the cursor provider before it is destroyed.
void RegisterCursorProvider(CursorProvider* provider);
void UnregisterCursorProvider(CursorProvider* provider);
// Returns the cursor for the surface. If no cursor provider is registered
// then CursorType::kNull is returned.
gfx::NativeCursor GetCursor();
// Set the surface delegate.
void SetSurfaceDelegate(SurfaceDelegate* delegate);
// Returns true if surface has been assigned a surface delegate.
bool HasSurfaceDelegate() const;
// Surface does not own observers. It is the responsibility of the observer
// to remove itself when it is done observing.
void AddSurfaceObserver(SurfaceObserver* observer);
void RemoveSurfaceObserver(SurfaceObserver* observer);
bool HasSurfaceObserver(const SurfaceObserver* observer) const;
// Returns a trace value representing the state of the surface.
std::unique_ptr<base::trace_event::TracedValue> AsTracedValue() const;
// Call this to indicate that the previous CompositorFrame is processed and
// the surface is being scheduled for a draw.
void DidReceiveCompositorFrameAck();
// Called when the begin frame source has changed.
void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source);
// Check whether this Surface and its children need to create new cc::Surface
// IDs for their contents next time they get new buffer contents.
void CheckIfSurfaceHierarchyNeedsCommitToNewSurfaces();
// Returns the active contents size.
gfx::Size content_size() const { return content_size_; }
// Returns true if the associated window is in 'stylus-only' mode.
bool IsStylusOnly();
// Enables 'stylus-only' mode for the associated window.
void SetStylusOnly();
// Overridden from ui::ContextFactoryObserver:
void OnLostResources() override;
// Overridden from aura::WindowObserver:
void OnWindowAddedToRootWindow(aura::Window* window) override;
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
// Overridden from ui::CompositorVSyncManager::Observer:
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) override;
bool HasPendingDamageForTesting(const gfx::Rect& damage) const {
return pending_damage_.contains(gfx::RectToSkIRect(damage));
}
// Overridden from cc::BeginFrameObserverBase:
bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
void OnBeginFrameSourcePausedChanged(bool paused) override {}
private:
struct State {
State();
~State();
bool operator==(const State& other);
bool operator!=(const State& other) { return !(*this == other); }
SkRegion opaque_region;
SkRegion input_region;
float buffer_scale = 1.0f;
gfx::Size viewport;
gfx::RectF crop;
bool only_visible_on_secure_output = false;
SkBlendMode blend_mode = SkBlendMode::kSrcOver;
float alpha = 1.0f;
};
class BufferAttachment {
public:
BufferAttachment();
~BufferAttachment();
BufferAttachment& operator=(BufferAttachment&& buffer);
base::WeakPtr<Buffer>& buffer();
const base::WeakPtr<Buffer>& buffer() const;
void Reset(base::WeakPtr<Buffer> buffer);
private:
base::WeakPtr<Buffer> buffer_;
DISALLOW_COPY_AND_ASSIGN(BufferAttachment);
};
friend class subtle::PropertyHelper;
bool needs_commit_surface_hierarchy() const {
return needs_commit_surface_hierarchy_;
}
// Returns true if this surface or any child surface needs a commit and has
// has_pending_layer_changes_ true.
bool HasLayerHierarchyChanged() const;
// Sets that all children must create new cc::SurfaceIds for their contents.
void SetSurfaceHierarchyNeedsCommitToNewSurfaces();
// Set SurfaceLayer contents to the current buffer.
void SetSurfaceLayerContents(ui::Layer* layer);
// Updates current_resource_ with a new resource id corresponding to the
// contents of the attached buffer (or id 0, if no buffer is attached).
// UpdateSurface must be called afterwards to ensure the release callback
// will be called.
void UpdateResource(bool client_usage);
// Updates the current Surface with a new frame referring to the resource in
// current_resource_.
void UpdateSurface(bool full_damage);
// Adds/Removes begin frame observer based on state.
void UpdateNeedsBeginFrame();
// This returns true when the surface has some contents assigned to it.
bool has_contents() const { return !!current_buffer_.buffer(); }
// This window has the layer which contains the Surface contents.
std::unique_ptr<aura::Window> window_;
// This is true if it's possible that the layer properties (size, opacity,
// etc.) may have been modified since the last commit. Attaching a new
// buffer with the same size as the old shouldn't set this to true.
bool has_pending_layer_changes_ = true;
// This is true if the next commit to this surface should put its contents
// into a new cc::SurfaceId. This allows for synchronization between Surface
// and layer changes.
bool needs_commit_to_new_surface_ = true;
// This is the size of the last committed contents.
gfx::Size content_size_;
// This is true when Attach() has been called and new contents should take
// effect next time Commit() is called.
bool has_pending_contents_ = false;
// The buffer that will become the content of surface when Commit() is called.
BufferAttachment pending_buffer_;
// The device scale factor sent in CompositorFrames.
float device_scale_factor_ = 1.0f;
std::unique_ptr<CompositorFrameSinkHolder> compositor_frame_sink_holder_;
// The next resource id the buffer will be attached to.
int next_resource_id_ = 1;
// The damage region to schedule paint for when Commit() is called.
SkRegion pending_damage_;
// These lists contains the callbacks to notify the client when it is a good
// time to start producing a new frame. These callbacks move to
// |frame_callbacks_| when Commit() is called. Later they are moved to
// |active_frame_callbacks_| when the effect of the Commit() is scheduled to
// be drawn. They fire at the first begin frame notification after this.
std::list<FrameCallback> pending_frame_callbacks_;
std::list<FrameCallback> frame_callbacks_;
std::list<FrameCallback> active_frame_callbacks_;
// These lists contains the callbacks to notify the client when surface
// contents have been presented. These callbacks move to
// |presentation_callbacks_| when Commit() is called. Later they are moved to
// |swapping_presentation_callbacks_| when the effect of the Commit() is
// scheduled to be drawn and then moved to |swapped_presentation_callbacks_|
// after receiving VSync parameters update for the previous frame. They fire
// at the next VSync parameters update after that.
std::list<PresentationCallback> pending_presentation_callbacks_;
std::list<PresentationCallback> presentation_callbacks_;
std::list<PresentationCallback> swapping_presentation_callbacks_;
std::list<PresentationCallback> swapped_presentation_callbacks_;
// This is the state that has yet to be committed.
State pending_state_;
// This is the state that has been committed.
State state_;
// The stack of sub-surfaces to take effect when Commit() is called.
// Bottom-most sub-surface at the front of the list and top-most sub-surface
// at the back.
using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
SubSurfaceEntryList pending_sub_surfaces_;
// The buffer that is currently set as content of surface.
BufferAttachment current_buffer_;
// The last resource that was sent to a surface.
cc::TransferableResource current_resource_;
// Whether the last resource that was sent to a surface has an alpha channel.
bool current_resource_has_alpha_ = false;
// This is true if a call to Commit() as been made but
// CommitSurfaceHierarchy() has not yet been called.
bool needs_commit_surface_hierarchy_ = false;
// This is set when the compositing starts and passed to active frame
// callbacks when compositing successfully ends.
base::TimeTicks last_compositing_start_time_;
// Cursor providers. Surface does not own the cursor providers.
std::set<CursorProvider*> cursor_providers_;
// This can be set to have some functions delegated. E.g. ShellSurface class
// can set this to handle Commit() and apply any double buffered state it
// maintains.
SurfaceDelegate* delegate_ = nullptr;
// Surface observer list. Surface does not own the observers.
base::ObserverList<SurfaceObserver, true> observers_;
// The begin frame source being observed.
cc::BeginFrameSource* begin_frame_source_ = nullptr;
bool needs_begin_frame_ = false;
cc::BeginFrameAck current_begin_frame_ack_;
DISALLOW_COPY_AND_ASSIGN(Surface);
};
} // namespace exo
#endif // COMPONENTS_EXO_SURFACE_H_
|