reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 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. |
| 4 | |
| 5 | #include "components/exo/surface.h" |
| 6 | |
dcheng | 27f7483f | 2015-12-29 22:26:56 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Evan Stade | 4bfb334 | 2019-01-30 21:43:59 | [diff] [blame] | 9 | #include "ash/public/cpp/shell_window_ids.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 10 | #include "base/callback_helpers.h" |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 11 | #include "base/containers/adapters.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 12 | #include "base/logging.h" |
avi | bc5337b | 2015-12-25 23:16:33 | [diff] [blame] | 13 | #include "base/macros.h" |
dcheng | 31759da | 2016-04-21 01:26:31 | [diff] [blame] | 14 | #include "base/memory/ptr_util.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 15 | #include "base/trace_event/trace_event.h" |
David 'Digit' Turner | ea07114 | 2018-10-29 15:38:12 | [diff] [blame] | 16 | #include "base/trace_event/traced_value.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 17 | #include "components/exo/buffer.h" |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 18 | #include "components/exo/frame_sink_resource_manager.h" |
[email protected] | 29befae | 2019-01-09 22:55:35 | [diff] [blame] | 19 | #include "components/exo/shell_surface_util.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 20 | #include "components/exo/surface_delegate.h" |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 21 | #include "components/exo/surface_observer.h" |
Shawn Gallea | 6190601 | 2018-11-08 20:44:16 | [diff] [blame] | 22 | #include "components/exo/wm_helper.h" |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 23 | #include "components/viz/common/quads/render_pass.h" |
Alex Zhang | abad229 | 2017-08-23 21:55:19 | [diff] [blame] | 24 | #include "components/viz/common/quads/shared_quad_state.h" |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 25 | #include "components/viz/common/quads/solid_color_draw_quad.h" |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 26 | #include "components/viz/common/quads/surface_draw_quad.h" |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 27 | #include "components/viz/common/quads/texture_draw_quad.h" |
danakj | f20f450 | 2017-09-26 17:13:31 | [diff] [blame] | 28 | #include "components/viz/common/resources/single_release_callback.h" |
Fady Samuel | e478607 | 2017-07-24 20:03:38 | [diff] [blame] | 29 | #include "components/viz/service/surfaces/surface.h" |
| 30 | #include "components/viz/service/surfaces/surface_manager.h" |
jbauman | bd9586a9 | 2016-05-28 01:09:03 | [diff] [blame] | 31 | #include "third_party/khronos/GLES2/gl2.h" |
Raul Tambre | 038e96d | 2019-01-07 21:47:44 | [diff] [blame] | 32 | #include "third_party/skia/include/core/SkPath.h" |
kaznacheev | 8e27059 | 2017-05-25 06:13:26 | [diff] [blame] | 33 | #include "ui/aura/client/aura_constants.h" |
Daichi Hirono | 7a55201 | 2017-08-04 05:29:28 | [diff] [blame] | 34 | #include "ui/aura/client/drag_drop_delegate.h" |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 35 | #include "ui/aura/window_delegate.h" |
Eliot Courtney | bb051d1 | 2018-12-15 02:41:31 | [diff] [blame] | 36 | #include "ui/aura/window_occlusion_tracker.h" |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 37 | #include "ui/aura/window_targeter.h" |
kylixrd | 61e45cf | 2017-01-30 19:52:53 | [diff] [blame] | 38 | #include "ui/base/class_property.h" |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 39 | #include "ui/base/cursor/cursor.h" |
| 40 | #include "ui/base/hit_test.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 41 | #include "ui/compositor/layer.h" |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 42 | #include "ui/events/event.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 43 | #include "ui/gfx/buffer_format_util.h" |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 44 | #include "ui/gfx/geometry/dip_util.h" |
reveman | 8e32390 | 2016-05-23 21:55:36 | [diff] [blame] | 45 | #include "ui/gfx/geometry/safe_integer_conversions.h" |
| 46 | #include "ui/gfx/geometry/size_conversions.h" |
Alexandros Frantzis | 4ee9da5 | 2019-03-11 15:29:23 | [diff] [blame] | 47 | #include "ui/gfx/gpu_fence.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 48 | #include "ui/gfx/gpu_memory_buffer.h" |
Sadrul Habib Chowdhury | b62a9730 | 2018-06-06 03:33:48 | [diff] [blame] | 49 | #include "ui/gfx/presentation_feedback.h" |
reveman | 7efa4b0 | 2016-01-06 08:29:54 | [diff] [blame] | 50 | #include "ui/gfx/transform_util.h" |
kinaba | 70a3044 | 2016-03-31 04:09:57 | [diff] [blame] | 51 | #include "ui/views/widget/widget.h" |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 52 | |
Ahmed Fakhry | f929d5f | 2019-04-11 02:22:48 | [diff] [blame] | 53 | #if defined(OS_CHROMEOS) |
Dominik Laskowski | 638b163 | 2019-06-28 20:59:02 | [diff] [blame] | 54 | #include "ash/display/output_protection_delegate.h" |
Ahmed Fakhry | f929d5f | 2019-04-11 02:22:48 | [diff] [blame] | 55 | #include "ash/wm/desks/desks_util.h" |
| 56 | #endif // defined(OS_CHROMEOS) |
| 57 | |
Nico Weber | 0f1ed9a | 2019-02-20 18:26:30 | [diff] [blame] | 58 | DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Surface*) |
reveman | 39b32c87 | 2015-12-08 05:34:05 | [diff] [blame] | 59 | |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 60 | namespace exo { |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 61 | namespace { |
| 62 | |
reveman | 39b32c87 | 2015-12-08 05:34:05 | [diff] [blame] | 63 | // A property key containing the surface that is associated with |
| 64 | // window. If unset, no surface is associated with window. |
Nico Weber | 0f1ed9a | 2019-02-20 18:26:30 | [diff] [blame] | 65 | DEFINE_UI_CLASS_PROPERTY_KEY(Surface*, kSurfaceKey, nullptr) |
reveman | 39b32c87 | 2015-12-08 05:34:05 | [diff] [blame] | 66 | |
kaznacheev | 8e27059 | 2017-05-25 06:13:26 | [diff] [blame] | 67 | // A property key to store whether the surface should only consume |
| 68 | // stylus input events. |
Nico Weber | 0f1ed9a | 2019-02-20 18:26:30 | [diff] [blame] | 69 | DEFINE_UI_CLASS_PROPERTY_KEY(bool, kStylusOnlyKey, false) |
kaznacheev | 8e27059 | 2017-05-25 06:13:26 | [diff] [blame] | 70 | |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 71 | // Helper function that returns an iterator to the first entry in |list| |
| 72 | // with |key|. |
| 73 | template <typename T, typename U> |
| 74 | typename T::iterator FindListEntry(T& list, U key) { |
| 75 | return std::find_if(list.begin(), list.end(), |
| 76 | [key](const typename T::value_type& entry) { |
| 77 | return entry.first == key; |
| 78 | }); |
| 79 | } |
| 80 | |
| 81 | // Helper function that returns true if |list| contains an entry with |key|. |
| 82 | template <typename T, typename U> |
| 83 | bool ListContainsEntry(T& list, U key) { |
| 84 | return FindListEntry(list, key) != list.end(); |
| 85 | } |
| 86 | |
reveman | ca132dc | 2017-01-31 22:35:54 | [diff] [blame] | 87 | // Helper function that returns true if |format| may have an alpha channel. |
| 88 | // Note: False positives are allowed but false negatives are not. |
| 89 | bool FormatHasAlpha(gfx::BufferFormat format) { |
| 90 | switch (format) { |
| 91 | case gfx::BufferFormat::BGR_565: |
| 92 | case gfx::BufferFormat::RGBX_8888: |
| 93 | case gfx::BufferFormat::BGRX_8888: |
| 94 | case gfx::BufferFormat::YVU_420: |
| 95 | case gfx::BufferFormat::YUV_420_BIPLANAR: |
reveman | ca132dc | 2017-01-31 22:35:54 | [diff] [blame] | 96 | return false; |
| 97 | default: |
| 98 | return true; |
| 99 | } |
| 100 | } |
| 101 | |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 102 | // Helper function that returns |size| after adjusting for |transform|. |
| 103 | gfx::Size ToTransformedSize(const gfx::Size& size, Transform transform) { |
| 104 | switch (transform) { |
| 105 | case Transform::NORMAL: |
| 106 | case Transform::ROTATE_180: |
| 107 | return size; |
| 108 | case Transform::ROTATE_90: |
| 109 | case Transform::ROTATE_270: |
| 110 | return gfx::Size(size.height(), size.width()); |
| 111 | } |
| 112 | |
| 113 | NOTREACHED(); |
| 114 | } |
| 115 | |
Ahmed Fakhry | f929d5f | 2019-04-11 02:22:48 | [diff] [blame] | 116 | bool IsDeskContainer(aura::Window* container) { |
| 117 | #if defined(OS_CHROMEOS) |
| 118 | return ash::desks_util::IsDeskContainer(container); |
| 119 | #else |
| 120 | return container->id() == ash::kShellWindowId_DefaultContainerDeprecated; |
| 121 | #endif // defined(OS_CHROMEOS) |
| 122 | } |
| 123 | |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 124 | class CustomWindowDelegate : public aura::WindowDelegate { |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 125 | public: |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 126 | explicit CustomWindowDelegate(Surface* surface) : surface_(surface) {} |
| 127 | ~CustomWindowDelegate() override {} |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 128 | |
| 129 | // Overridden from aura::WindowDelegate: |
| 130 | gfx::Size GetMinimumSize() const override { return gfx::Size(); } |
| 131 | gfx::Size GetMaximumSize() const override { return gfx::Size(); } |
| 132 | void OnBoundsChanged(const gfx::Rect& old_bounds, |
| 133 | const gfx::Rect& new_bounds) override {} |
| 134 | gfx::NativeCursor GetCursor(const gfx::Point& point) override { |
Mitsuru Oshima | 46d3870 | 2018-03-10 06:21:15 | [diff] [blame] | 135 | views::Widget* widget = |
| 136 | views::Widget::GetTopLevelWidgetForNativeView(surface_->window()); |
| 137 | if (widget) |
| 138 | return widget->GetNativeWindow()->GetCursor(point /* not used */); |
| 139 | return ui::CursorType::kNull; |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 140 | } |
| 141 | int GetNonClientComponent(const gfx::Point& point) const override { |
Evan Stade | 4bfb334 | 2019-01-30 21:43:59 | [diff] [blame] | 142 | views::Widget* widget = |
| 143 | views::Widget::GetTopLevelWidgetForNativeView(surface_->window()); |
Ahmed Fakhry | f929d5f | 2019-04-11 02:22:48 | [diff] [blame] | 144 | if (widget && IsDeskContainer(widget->GetNativeView()->parent()) && |
Evan Stade | 4bfb334 | 2019-01-30 21:43:59 | [diff] [blame] | 145 | surface_->HitTest(point)) { |
| 146 | return HTCLIENT; |
| 147 | } |
| 148 | |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 149 | return HTNOWHERE; |
| 150 | } |
| 151 | bool ShouldDescendIntoChildForEventHandling( |
| 152 | aura::Window* child, |
| 153 | const gfx::Point& location) override { |
reveman | f999944b | 2016-01-28 00:12:06 | [diff] [blame] | 154 | return true; |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 155 | } |
| 156 | bool CanFocus() override { return true; } |
| 157 | void OnCaptureLost() override {} |
| 158 | void OnPaint(const ui::PaintContext& context) override {} |
Scott Violet | 06aff2b4 | 2017-09-08 00:26:32 | [diff] [blame] | 159 | void OnDeviceScaleFactorChanged(float old_device_scale_factor, |
| 160 | float new_device_scale_factor) override {} |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 161 | void OnWindowDestroying(aura::Window* window) override {} |
| 162 | void OnWindowDestroyed(aura::Window* window) override { delete this; } |
| 163 | void OnWindowTargetVisibilityChanged(bool visible) override {} |
Eliot Courtney | bb051d1 | 2018-12-15 02:41:31 | [diff] [blame] | 164 | void OnWindowOcclusionChanged(aura::Window::OcclusionState occlusion_state, |
| 165 | const SkRegion& occluded_region) override { |
| 166 | surface_->OnWindowOcclusionChanged(); |
| 167 | } |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 168 | bool HasHitTestMask() const override { return true; } |
Raul Tambre | 038e96d | 2019-01-07 21:47:44 | [diff] [blame] | 169 | void GetHitTestMask(SkPath* mask) const override { |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 170 | surface_->GetHitTestMask(mask); |
| 171 | } |
kinaba | 70a3044 | 2016-03-31 04:09:57 | [diff] [blame] | 172 | void OnKeyEvent(ui::KeyEvent* event) override { |
| 173 | // Propagates the key event upto the top-level views Widget so that we can |
| 174 | // trigger proper events in the views/ash level there. Event handling for |
| 175 | // Surfaces is done in a post event handler in keyboard.cc. |
| 176 | views::Widget* widget = |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 177 | views::Widget::GetTopLevelWidgetForNativeView(surface_->window()); |
kinaba | 70a3044 | 2016-03-31 04:09:57 | [diff] [blame] | 178 | if (widget) |
| 179 | widget->OnKeyEvent(event); |
| 180 | } |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 181 | |
| 182 | private: |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 183 | Surface* const surface_; |
| 184 | |
| 185 | DISALLOW_COPY_AND_ASSIGN(CustomWindowDelegate); |
| 186 | }; |
| 187 | |
| 188 | class CustomWindowTargeter : public aura::WindowTargeter { |
| 189 | public: |
| 190 | CustomWindowTargeter() {} |
| 191 | ~CustomWindowTargeter() override {} |
| 192 | |
| 193 | // Overridden from aura::WindowTargeter: |
| 194 | bool EventLocationInsideBounds(aura::Window* window, |
| 195 | const ui::LocatedEvent& event) const override { |
| 196 | Surface* surface = Surface::AsSurface(window); |
Dominik Laskowski | 14a16377 | 2018-02-09 19:25:18 | [diff] [blame] | 197 | if (!surface || !surface->IsInputEnabled(surface)) |
Dominik Laskowski | 3e2f9479 | 2017-12-15 00:27:10 | [diff] [blame] | 198 | return false; |
| 199 | |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 200 | gfx::Point local_point = event.location(); |
| 201 | if (window->parent()) |
| 202 | aura::Window::ConvertPointToTarget(window->parent(), window, |
| 203 | &local_point); |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 204 | return surface->HitTest(local_point); |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 205 | } |
| 206 | |
| 207 | private: |
| 208 | DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter); |
reveman | 4c94cf96 | 2015-12-03 06:49:43 | [diff] [blame] | 209 | }; |
| 210 | |
[email protected] | 29befae | 2019-01-09 22:55:35 | [diff] [blame] | 211 | const std::string& GetApplicationId(aura::Window* window) { |
| 212 | static const std::string empty_app_id; |
| 213 | if (!window) |
| 214 | return empty_app_id; |
| 215 | while (window) { |
| 216 | const std::string* app_id = exo::GetShellApplicationId(window); |
| 217 | if (app_id) |
| 218 | return *app_id; |
| 219 | window = window->parent(); |
| 220 | } |
| 221 | return empty_app_id; |
| 222 | } |
| 223 | |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 224 | } // namespace |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 225 | |
Ryo Hashimoto | 4e7c572f | 2019-04-18 05:55:56 | [diff] [blame] | 226 | DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kClientSurfaceIdKey, 0) |
| 227 | |
Fergus Dall | a429385 | 2019-07-26 07:13:47 | [diff] [blame] | 228 | ScopedSurface::ScopedSurface(Surface* surface, SurfaceObserver* observer) |
| 229 | : surface_(surface), observer_(observer) { |
| 230 | surface_->AddSurfaceObserver(observer_); |
| 231 | } |
| 232 | |
| 233 | ScopedSurface::~ScopedSurface() { |
| 234 | surface_->RemoveSurfaceObserver(observer_); |
| 235 | } |
| 236 | |
reveman | 2d3815d | 2016-06-26 20:13:25 | [diff] [blame] | 237 | //////////////////////////////////////////////////////////////////////////////// |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 238 | // Surface, public: |
| 239 | |
Scott Violet | 13de50d | 2018-08-10 20:07:11 | [diff] [blame] | 240 | Surface::Surface() |
Jun Mukai | 1f426ff | 2019-05-16 18:19:24 | [diff] [blame] | 241 | : window_( |
| 242 | std::make_unique<aura::Window>(new CustomWindowDelegate(this), |
| 243 | aura::client::WINDOW_TYPE_CONTROL)) { |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 244 | window_->SetName("ExoSurface"); |
| 245 | window_->SetProperty(kSurfaceKey, this); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 246 | window_->Init(ui::LAYER_NOT_DRAWN); |
Scott Violet | ec3b3b68 | 2018-08-30 20:06:30 | [diff] [blame] | 247 | window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>()); |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 248 | window_->set_owned_by_parent(false); |
Daichi Hirono | 7a55201 | 2017-08-04 05:29:28 | [diff] [blame] | 249 | WMHelper::GetInstance()->SetDragDropDelegate(window_.get()); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 250 | } |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 251 | Surface::~Surface() { |
ericwilligers | a22488d4 | 2016-10-25 01:20:57 | [diff] [blame] | 252 | for (SurfaceObserver& observer : observers_) |
| 253 | observer.OnSurfaceDestroying(this); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 254 | |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 255 | // Call all frame callbacks with a null frame time to indicate that they |
| 256 | // have been cancelled. |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 257 | frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
| 258 | for (const auto& frame_callback : frame_callbacks_) |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 259 | frame_callback.Run(base::TimeTicks()); |
| 260 | |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 261 | // Call all presentation callbacks with a null presentation time to indicate |
| 262 | // that they have been cancelled. |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 263 | presentation_callbacks_.splice(presentation_callbacks_.end(), |
| 264 | pending_presentation_callbacks_); |
| 265 | for (const auto& presentation_callback : presentation_callbacks_) |
Sadrul Habib Chowdhury | b62a9730 | 2018-06-06 03:33:48 | [diff] [blame] | 266 | presentation_callback.Run(gfx::PresentationFeedback()); |
Daichi Hirono | 7a55201 | 2017-08-04 05:29:28 | [diff] [blame] | 267 | |
| 268 | WMHelper::GetInstance()->ResetDragDropDelegate(window_.get()); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 269 | } |
| 270 | |
reveman | 39b32c87 | 2015-12-08 05:34:05 | [diff] [blame] | 271 | // static |
kinaba | d14ca03e | 2016-02-23 04:43:35 | [diff] [blame] | 272 | Surface* Surface::AsSurface(const aura::Window* window) { |
reveman | 39b32c87 | 2015-12-08 05:34:05 | [diff] [blame] | 273 | return window->GetProperty(kSurfaceKey); |
| 274 | } |
| 275 | |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 276 | void Surface::Attach(Buffer* buffer) { |
Fergus Dall | a429385 | 2019-07-26 07:13:47 | [diff] [blame] | 277 | Attach(buffer, gfx::Vector2d()); |
| 278 | } |
| 279 | |
| 280 | void Surface::Attach(Buffer* buffer, gfx::Vector2d offset) { |
[email protected] | 29befae | 2019-01-09 22:55:35 | [diff] [blame] | 281 | TRACE_EVENT2("exo", "Surface::Attach", "buffer_id", |
| 282 | buffer ? buffer->gfx_buffer() : nullptr, "app_id", |
| 283 | GetApplicationId(window_.get())); |
reveman | ced21f8 | 2015-11-24 00:42:49 | [diff] [blame] | 284 | has_pending_contents_ = true; |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 285 | pending_buffer_.Reset(buffer ? buffer->AsWeakPtr() : base::WeakPtr<Buffer>()); |
Fergus Dall | a429385 | 2019-07-26 07:13:47 | [diff] [blame] | 286 | pending_state_.offset = offset; |
| 287 | } |
| 288 | |
| 289 | gfx::Vector2d Surface::GetBufferOffset() { |
| 290 | return state_.offset; |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 291 | } |
| 292 | |
Alexandros Frantzis | 4ee9da5 | 2019-03-11 15:29:23 | [diff] [blame] | 293 | bool Surface::HasPendingAttachedBuffer() const { |
| 294 | return pending_buffer_.buffer() != nullptr; |
| 295 | } |
| 296 | |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 297 | void Surface::Damage(const gfx::Rect& damage) { |
| 298 | TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString()); |
| 299 | |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 300 | pending_damage_.Union(damage); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 301 | } |
| 302 | |
| 303 | void Surface::RequestFrameCallback(const FrameCallback& callback) { |
| 304 | TRACE_EVENT0("exo", "Surface::RequestFrameCallback"); |
| 305 | |
| 306 | pending_frame_callbacks_.push_back(callback); |
| 307 | } |
| 308 | |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 309 | void Surface::RequestPresentationCallback( |
| 310 | const PresentationCallback& callback) { |
| 311 | TRACE_EVENT0("exo", "Surface::RequestPresentationCallback"); |
| 312 | |
| 313 | pending_presentation_callbacks_.push_back(callback); |
| 314 | } |
| 315 | |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 316 | void Surface::SetOpaqueRegion(const cc::Region& region) { |
| 317 | TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", region.ToString()); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 318 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 319 | pending_state_.opaque_region = region; |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 320 | } |
| 321 | |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 322 | void Surface::SetInputRegion(const cc::Region& region) { |
| 323 | TRACE_EVENT1("exo", "Surface::SetInputRegion", "region", region.ToString()); |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 324 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 325 | pending_state_.input_region = region; |
reveman | 2966d770 | 2016-02-12 02:09:54 | [diff] [blame] | 326 | } |
| 327 | |
Mike Reed | 2c570fa | 2018-01-11 21:59:22 | [diff] [blame] | 328 | void Surface::ResetInputRegion() { |
| 329 | TRACE_EVENT0("exo", "Surface::ResetInputRegion"); |
| 330 | |
| 331 | pending_state_.input_region = base::nullopt; |
| 332 | } |
| 333 | |
Dominik Laskowski | 2d431641 | 2017-12-13 19:14:44 | [diff] [blame] | 334 | void Surface::SetInputOutset(int outset) { |
| 335 | TRACE_EVENT1("exo", "Surface::SetInputOutset", "outset", outset); |
| 336 | |
| 337 | pending_state_.input_outset = outset; |
| 338 | } |
| 339 | |
reveman | 7efa4b0 | 2016-01-06 08:29:54 | [diff] [blame] | 340 | void Surface::SetBufferScale(float scale) { |
| 341 | TRACE_EVENT1("exo", "Surface::SetBufferScale", "scale", scale); |
| 342 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 343 | pending_state_.buffer_scale = scale; |
reveman | 7efa4b0 | 2016-01-06 08:29:54 | [diff] [blame] | 344 | } |
| 345 | |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 346 | void Surface::SetBufferTransform(Transform transform) { |
| 347 | TRACE_EVENT1("exo", "Surface::SetBufferTransform", "transform", |
| 348 | static_cast<int>(transform)); |
| 349 | |
| 350 | pending_state_.buffer_transform = transform; |
| 351 | } |
| 352 | |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 353 | void Surface::AddSubSurface(Surface* sub_surface) { |
| 354 | TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface", |
| 355 | sub_surface->AsTracedValue()); |
| 356 | |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 357 | DCHECK(!sub_surface->window()->parent()); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 358 | sub_surface->window()->SetBounds( |
| 359 | gfx::Rect(sub_surface->window()->bounds().size())); |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 360 | window_->AddChild(sub_surface->window()); |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 361 | |
| 362 | DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 363 | pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point())); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 364 | sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point())); |
Peng Huang | f925ebf | 2017-10-31 15:37:50 | [diff] [blame] | 365 | sub_surfaces_changed_ = true; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 366 | } |
| 367 | |
| 368 | void Surface::RemoveSubSurface(Surface* sub_surface) { |
yoshiki | a56c53c | 2016-11-19 07:07:56 | [diff] [blame] | 369 | TRACE_EVENT1("exo", "Surface::RemoveSubSurface", "sub_surface", |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 370 | sub_surface->AsTracedValue()); |
| 371 | |
jbauman | e352625 | 2016-06-09 18:43:05 | [diff] [blame] | 372 | if (sub_surface->window()->IsVisible()) |
| 373 | sub_surface->window()->Hide(); |
Eliot Courtney | b5a8f33 | 2019-09-10 08:25:26 | [diff] [blame] | 374 | window_->RemoveChild(sub_surface->window()); |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 375 | |
| 376 | DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
| 377 | pending_sub_surfaces_.erase( |
| 378 | FindListEntry(pending_sub_surfaces_, sub_surface)); |
Eliot Courtney | 28e7aa5 | 2017-09-27 02:16:21 | [diff] [blame] | 379 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 380 | DCHECK(ListContainsEntry(sub_surfaces_, sub_surface)); |
Eliot Courtney | 28e7aa5 | 2017-09-27 02:16:21 | [diff] [blame] | 381 | auto it = FindListEntry(sub_surfaces_, sub_surface); |
Eliot Courtney | 28e7aa5 | 2017-09-27 02:16:21 | [diff] [blame] | 382 | sub_surfaces_.erase(it); |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 383 | // Force recreating resources when the surface is added to a tree again. |
| 384 | sub_surface->SurfaceHierarchyResourcesLost(); |
Peng Huang | f925ebf | 2017-10-31 15:37:50 | [diff] [blame] | 385 | sub_surfaces_changed_ = true; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 386 | } |
| 387 | |
| 388 | void Surface::SetSubSurfacePosition(Surface* sub_surface, |
| 389 | const gfx::Point& position) { |
| 390 | TRACE_EVENT2("exo", "Surface::SetSubSurfacePosition", "sub_surface", |
| 391 | sub_surface->AsTracedValue(), "position", position.ToString()); |
| 392 | |
| 393 | auto it = FindListEntry(pending_sub_surfaces_, sub_surface); |
| 394 | DCHECK(it != pending_sub_surfaces_.end()); |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 395 | if (it->second == position) |
| 396 | return; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 397 | it->second = position; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 398 | sub_surfaces_changed_ = true; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 399 | } |
| 400 | |
| 401 | void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) { |
| 402 | TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceAbove", "sub_surface", |
| 403 | sub_surface->AsTracedValue(), "reference", |
| 404 | reference->AsTracedValue()); |
| 405 | |
| 406 | if (sub_surface == reference) { |
| 407 | DLOG(WARNING) << "Client tried to place sub-surface above itself"; |
| 408 | return; |
| 409 | } |
| 410 | |
| 411 | auto position_it = pending_sub_surfaces_.begin(); |
| 412 | if (reference != this) { |
| 413 | position_it = FindListEntry(pending_sub_surfaces_, reference); |
| 414 | if (position_it == pending_sub_surfaces_.end()) { |
| 415 | DLOG(WARNING) << "Client tried to place sub-surface above a reference " |
| 416 | "surface that is neither a parent nor a sibling"; |
| 417 | return; |
| 418 | } |
| 419 | |
| 420 | // Advance iterator to have |position_it| point to the sibling surface |
| 421 | // above |reference|. |
| 422 | ++position_it; |
| 423 | } |
| 424 | |
| 425 | DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 426 | auto it = FindListEntry(pending_sub_surfaces_, sub_surface); |
| 427 | if (it == position_it) |
| 428 | return; |
| 429 | pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 430 | sub_surfaces_changed_ = true; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 431 | } |
| 432 | |
| 433 | void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) { |
| 434 | TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceBelow", "sub_surface", |
| 435 | sub_surface->AsTracedValue(), "sibling", |
| 436 | sibling->AsTracedValue()); |
| 437 | |
| 438 | if (sub_surface == sibling) { |
| 439 | DLOG(WARNING) << "Client tried to place sub-surface below itself"; |
| 440 | return; |
| 441 | } |
| 442 | |
| 443 | auto sibling_it = FindListEntry(pending_sub_surfaces_, sibling); |
| 444 | if (sibling_it == pending_sub_surfaces_.end()) { |
| 445 | DLOG(WARNING) << "Client tried to place sub-surface below a surface that " |
| 446 | "is not a sibling"; |
| 447 | return; |
| 448 | } |
| 449 | |
| 450 | DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface)); |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 451 | auto it = FindListEntry(pending_sub_surfaces_, sub_surface); |
| 452 | if (it == sibling_it) |
| 453 | return; |
| 454 | pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 455 | sub_surfaces_changed_ = true; |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 456 | } |
| 457 | |
David Reveman | 8b43b35 | 2017-11-03 15:24:51 | [diff] [blame] | 458 | void Surface::OnSubSurfaceCommit() { |
| 459 | if (delegate_) |
| 460 | delegate_->OnSurfaceCommit(); |
| 461 | } |
| 462 | |
reveman | 642d8c33 | 2016-02-19 19:55:44 | [diff] [blame] | 463 | void Surface::SetViewport(const gfx::Size& viewport) { |
| 464 | TRACE_EVENT1("exo", "Surface::SetViewport", "viewport", viewport.ToString()); |
| 465 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 466 | pending_state_.viewport = viewport; |
reveman | 642d8c33 | 2016-02-19 19:55:44 | [diff] [blame] | 467 | } |
| 468 | |
reveman | 8e32390 | 2016-05-23 21:55:36 | [diff] [blame] | 469 | void Surface::SetCrop(const gfx::RectF& crop) { |
| 470 | TRACE_EVENT1("exo", "Surface::SetCrop", "crop", crop.ToString()); |
| 471 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 472 | pending_state_.crop = crop; |
reveman | 8e32390 | 2016-05-23 21:55:36 | [diff] [blame] | 473 | } |
| 474 | |
reveman | 85b7a56 | 2016-03-17 23:27:32 | [diff] [blame] | 475 | void Surface::SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output) { |
| 476 | TRACE_EVENT1("exo", "Surface::SetOnlyVisibleOnSecureOutput", |
| 477 | "only_visible_on_secure_output", only_visible_on_secure_output); |
| 478 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 479 | pending_state_.only_visible_on_secure_output = only_visible_on_secure_output; |
reveman | 85b7a56 | 2016-03-17 23:27:32 | [diff] [blame] | 480 | } |
| 481 | |
reed | cc9c70f | 2016-11-22 04:26:01 | [diff] [blame] | 482 | void Surface::SetBlendMode(SkBlendMode blend_mode) { |
| 483 | TRACE_EVENT1("exo", "Surface::SetBlendMode", "blend_mode", |
| 484 | static_cast<int>(blend_mode)); |
reveman | fca687e | 2016-05-10 21:44:48 | [diff] [blame] | 485 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 486 | pending_state_.blend_mode = blend_mode; |
reveman | fca687e | 2016-05-10 21:44:48 | [diff] [blame] | 487 | } |
| 488 | |
| 489 | void Surface::SetAlpha(float alpha) { |
| 490 | TRACE_EVENT1("exo", "Surface::SetAlpha", "alpha", alpha); |
| 491 | |
jbauman | f4c3f29 | 2016-06-11 00:57:33 | [diff] [blame] | 492 | pending_state_.alpha = alpha; |
reveman | fca687e | 2016-05-10 21:44:48 | [diff] [blame] | 493 | } |
| 494 | |
David Reveman | 93f67c0 | 2017-09-06 03:23:08 | [diff] [blame] | 495 | void Surface::SetFrame(SurfaceFrameType type) { |
| 496 | TRACE_EVENT1("exo", "Surface::SetFrame", "type", static_cast<uint32_t>(type)); |
| 497 | |
| 498 | if (delegate_) |
| 499 | delegate_->OnSetFrame(type); |
| 500 | } |
| 501 | |
David Reveman | 786d318 | 2017-12-20 22:04:33 | [diff] [blame] | 502 | void Surface::SetFrameColors(SkColor active_color, SkColor inactive_color) { |
| 503 | TRACE_EVENT2("exo", "Surface::SetFrameColors", "active_color", active_color, |
| 504 | "inactive_color", inactive_color); |
| 505 | |
| 506 | if (delegate_) |
| 507 | delegate_->OnSetFrameColors(active_color, inactive_color); |
| 508 | } |
| 509 | |
Tim Zheng | 08df566 | 2018-04-04 05:08:15 | [diff] [blame] | 510 | void Surface::SetStartupId(const char* startup_id) { |
| 511 | TRACE_EVENT1("exo", "Surface::SetStartupId", "startup_id", startup_id); |
| 512 | |
| 513 | if (delegate_) |
| 514 | delegate_->OnSetStartupId(startup_id); |
| 515 | } |
| 516 | |
David Reveman | 21e2236d | 2018-04-12 06:01:10 | [diff] [blame] | 517 | void Surface::SetApplicationId(const char* application_id) { |
| 518 | TRACE_EVENT1("exo", "Surface::SetApplicationId", "application_id", |
| 519 | application_id); |
| 520 | |
| 521 | if (delegate_) |
| 522 | delegate_->OnSetApplicationId(application_id); |
| 523 | } |
| 524 | |
David Reveman | 3271509 | 2017-12-05 18:24:11 | [diff] [blame] | 525 | void Surface::SetParent(Surface* parent, const gfx::Point& position) { |
| 526 | TRACE_EVENT2("exo", "Surface::SetParent", "parent", !!parent, "position", |
| 527 | position.ToString()); |
| 528 | |
| 529 | if (delegate_) |
| 530 | delegate_->OnSetParent(parent, position); |
| 531 | } |
| 532 | |
Ryo Hashimoto | 8f10c88 | 2018-11-28 17:43:52 | [diff] [blame] | 533 | void Surface::SetClientSurfaceId(int32_t client_surface_id) { |
| 534 | if (client_surface_id) |
| 535 | window_->SetProperty(kClientSurfaceIdKey, client_surface_id); |
| 536 | else |
| 537 | window_->ClearProperty(kClientSurfaceIdKey); |
| 538 | } |
| 539 | |
| 540 | int32_t Surface::GetClientSurfaceId() const { |
| 541 | return window_->GetProperty(kClientSurfaceIdKey); |
| 542 | } |
| 543 | |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 544 | void Surface::SetEmbeddedSurfaceId( |
| 545 | base::RepeatingCallback<viz::SurfaceId()> surface_id_callback) { |
| 546 | get_current_surface_id_ = std::move(surface_id_callback); |
| 547 | first_embedded_surface_id_ = viz::SurfaceId(); |
| 548 | } |
| 549 | |
Alexandros Frantzis | 4ee9da5 | 2019-03-11 15:29:23 | [diff] [blame] | 550 | void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) { |
| 551 | TRACE_EVENT1("exo", "Surface::SetAcquireFence", "fence_fd", |
| 552 | gpu_fence ? gpu_fence->GetGpuFenceHandle().native_fd.fd : -1); |
| 553 | |
| 554 | pending_acquire_fence_ = std::move(gpu_fence); |
| 555 | } |
| 556 | |
| 557 | bool Surface::HasPendingAcquireFence() const { |
| 558 | return !!pending_acquire_fence_; |
| 559 | } |
| 560 | |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 561 | void Surface::Commit() { |
[email protected] | 822d6aef | 2019-11-01 22:22:01 | [diff] [blame] | 562 | TRACE_EVENT1("exo", "Surface::Commit", "buffer_id", |
| 563 | pending_buffer_.buffer() ? pending_buffer_.buffer()->gfx_buffer() |
| 564 | : nullptr); |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 565 | |
[email protected] | 1b37dd46 | 2019-07-17 18:20:59 | [diff] [blame] | 566 | for (auto& observer : observers_) |
| 567 | observer.OnCommit(this); |
[email protected] | 009a15e | 2019-03-22 23:43:43 | [diff] [blame] | 568 | |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 569 | needs_commit_surface_ = true; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 570 | if (delegate_) |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 571 | delegate_->OnSurfaceCommit(); |
David Reveman | 7a126ba | 2017-11-09 17:17:41 | [diff] [blame] | 572 | else |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 573 | CommitSurfaceHierarchy(false); |
reveman | 27fe264 | 2015-11-20 06:33:39 | [diff] [blame] | 574 | } |
| 575 | |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 576 | void Surface::CommitSurfaceHierarchy(bool synchronized) { |
[email protected] | 29befae | 2019-01-09 22:55:35 | [diff] [blame] | 577 | TRACE_EVENT0("exo", "Surface::CommitSurfaceHierarchy"); |
David Reveman | 8b43b35 | 2017-11-03 15:24:51 | [diff] [blame] | 578 | if (needs_commit_surface_ && (synchronized || !IsSynchronized())) { |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 579 | needs_commit_surface_ = false; |
David Reveman | 8b43b35 | 2017-11-03 15:24:51 | [diff] [blame] | 580 | synchronized = true; |
Lloyd Pique | d1e23fd | 2017-08-15 23:10:51 | [diff] [blame] | 581 | |
Peng Huang | f925ebf | 2017-10-31 15:37:50 | [diff] [blame] | 582 | // TODO(penghuang): Make the damage more precise for sub surface changes. |
| 583 | // https://crbug.com/779704 |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 584 | bool needs_full_damage = |
Peng Huang | f925ebf | 2017-10-31 15:37:50 | [diff] [blame] | 585 | sub_surfaces_changed_ || |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 586 | pending_state_.opaque_region != state_.opaque_region || |
Lloyd Pique | d1e23fd | 2017-08-15 23:10:51 | [diff] [blame] | 587 | pending_state_.buffer_scale != state_.buffer_scale || |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 588 | pending_state_.buffer_transform != state_.buffer_transform || |
Lloyd Pique | d1e23fd | 2017-08-15 23:10:51 | [diff] [blame] | 589 | pending_state_.viewport != state_.viewport || |
| 590 | pending_state_.crop != state_.crop || |
| 591 | pending_state_.only_visible_on_secure_output != |
| 592 | state_.only_visible_on_secure_output || |
| 593 | pending_state_.blend_mode != state_.blend_mode || |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 594 | pending_state_.alpha != state_.alpha; |
Lloyd Pique | d1e23fd | 2017-08-15 23:10:51 | [diff] [blame] | 595 | |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 596 | bool needs_update_buffer_transform = |
| 597 | pending_state_.buffer_scale != state_.buffer_scale || |
| 598 | pending_state_.buffer_transform != state_.buffer_transform; |
| 599 | |
Dominik Laskowski | 638b163 | 2019-06-28 20:59:02 | [diff] [blame] | 600 | #if defined(OS_CHROMEOS) |
| 601 | bool needs_output_protection = |
| 602 | pending_state_.only_visible_on_secure_output != |
| 603 | state_.only_visible_on_secure_output; |
| 604 | #endif // defined(OS_CHROMEOS) |
| 605 | |
Zach Reizner | 8bcce6e | 2018-10-31 00:04:37 | [diff] [blame] | 606 | bool pending_invert_y = false; |
| 607 | |
Peng Huang | a72f3a9 | 2017-10-05 00:32:27 | [diff] [blame] | 608 | // If the current state is fully transparent, the last submitted frame will |
| 609 | // not include the TextureDrawQuad for the resource, so the resource might |
| 610 | // have been released and needs to be updated again. |
| 611 | if (!state_.alpha && pending_state_.alpha) |
| 612 | needs_update_resource_ = true; |
| 613 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 614 | state_ = pending_state_; |
| 615 | pending_state_.only_visible_on_secure_output = false; |
reveman | bf33b94 | 2016-06-07 00:22:34 | [diff] [blame] | 616 | |
Peng Huang | 45e581ff | 2017-09-14 22:46:42 | [diff] [blame] | 617 | window_->SetEventTargetingPolicy( |
Mike Reed | 2c570fa | 2018-01-11 21:59:22 | [diff] [blame] | 618 | (state_.input_region.has_value() && state_.input_region->IsEmpty()) |
Scott Violet | 827d23b | 2019-05-24 16:12:49 | [diff] [blame] | 619 | ? aura::EventTargetingPolicy::kDescendantsOnly |
| 620 | : aura::EventTargetingPolicy::kTargetAndDescendants); |
Peng Huang | 45e581ff | 2017-09-14 22:46:42 | [diff] [blame] | 621 | |
Dominik Laskowski | 638b163 | 2019-06-28 20:59:02 | [diff] [blame] | 622 | #if defined(OS_CHROMEOS) |
| 623 | if (needs_output_protection) { |
| 624 | if (!output_protection_) { |
| 625 | output_protection_ = |
| 626 | std::make_unique<ash::OutputProtectionDelegate>(window_.get()); |
| 627 | } |
| 628 | |
| 629 | uint32_t protection_mask = state_.only_visible_on_secure_output |
| 630 | ? display::CONTENT_PROTECTION_METHOD_HDCP |
| 631 | : display::CONTENT_PROTECTION_METHOD_NONE; |
| 632 | |
| 633 | output_protection_->SetProtection(protection_mask, base::DoNothing()); |
| 634 | } |
| 635 | #endif // defined(OS_CHROMEOS) |
| 636 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 637 | // We update contents if Attach() has been called since last commit. |
| 638 | if (has_pending_contents_) { |
| 639 | has_pending_contents_ = false; |
Zach Reizner | 8bcce6e | 2018-10-31 00:04:37 | [diff] [blame] | 640 | |
| 641 | bool current_invert_y = |
| 642 | current_buffer_.buffer() && current_buffer_.buffer()->y_invert(); |
| 643 | pending_invert_y = |
| 644 | pending_buffer_.buffer() && pending_buffer_.buffer()->y_invert(); |
| 645 | if (current_invert_y != pending_invert_y) |
| 646 | needs_update_buffer_transform = true; |
| 647 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 648 | current_buffer_ = std::move(pending_buffer_); |
Alexandros Frantzis | 4ee9da5 | 2019-03-11 15:29:23 | [diff] [blame] | 649 | acquire_fence_ = std::move(pending_acquire_fence_); |
Peng Huang | a72f3a9 | 2017-10-05 00:32:27 | [diff] [blame] | 650 | if (state_.alpha) |
| 651 | needs_update_resource_ = true; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 652 | } |
Alexandros Frantzis | 4ee9da5 | 2019-03-11 15:29:23 | [diff] [blame] | 653 | // Either we didn't have a pending acquire fence, or we had one along with |
| 654 | // a new buffer, and it was already moved to acquire_fence_. Note that |
| 655 | // it is a commit-time client error to commit a fence without a buffer. |
| 656 | DCHECK(!pending_acquire_fence_); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 657 | |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 658 | if (needs_update_buffer_transform) |
Zach Reizner | 8bcce6e | 2018-10-31 00:04:37 | [diff] [blame] | 659 | UpdateBufferTransform(pending_invert_y); |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 660 | |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 661 | // Move pending frame callbacks to the end of |frame_callbacks_|. |
| 662 | frame_callbacks_.splice(frame_callbacks_.end(), pending_frame_callbacks_); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 663 | |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 664 | // Move pending presentation callbacks to the end of |
| 665 | // |presentation_callbacks_|. |
| 666 | presentation_callbacks_.splice(presentation_callbacks_.end(), |
| 667 | pending_presentation_callbacks_); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 668 | |
| 669 | UpdateContentSize(); |
| 670 | |
| 671 | // Synchronize window hierarchy. This will position and update the stacking |
| 672 | // order of all sub-surfaces after committing all pending state of |
| 673 | // sub-surface descendants. |
| 674 | if (sub_surfaces_changed_) { |
| 675 | sub_surfaces_.clear(); |
| 676 | aura::Window* stacking_target = nullptr; |
| 677 | for (const auto& sub_surface_entry : pending_sub_surfaces_) { |
| 678 | Surface* sub_surface = sub_surface_entry.first; |
| 679 | sub_surfaces_.push_back(sub_surface_entry); |
| 680 | // Move sub-surface to its new position in the stack. |
| 681 | if (stacking_target) |
| 682 | window_->StackChildAbove(sub_surface->window(), stacking_target); |
| 683 | |
| 684 | // Stack next sub-surface above this sub-surface. |
| 685 | stacking_target = sub_surface->window(); |
| 686 | |
| 687 | // Update sub-surface position relative to surface origin. |
| 688 | sub_surface->window()->SetBounds(gfx::Rect( |
| 689 | sub_surface_entry.second, sub_surface->window()->bounds().size())); |
| 690 | } |
| 691 | sub_surfaces_changed_ = false; |
| 692 | } |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 693 | |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 694 | gfx::Rect output_rect(content_size_); |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 695 | if (needs_full_damage) { |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 696 | damage_ = output_rect; |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 697 | } else { |
| 698 | // pending_damage_ is in Surface coordinates. |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 699 | damage_.Swap(&pending_damage_); |
| 700 | damage_.Intersect(output_rect); |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 701 | } |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 702 | pending_damage_.Clear(); |
reveman | aabfd71 | 2016-05-13 01:40:20 | [diff] [blame] | 703 | } |
jbauman | 2fdc073 | 2016-06-07 00:55:36 | [diff] [blame] | 704 | |
David Reveman | 7a126ba | 2017-11-09 17:17:41 | [diff] [blame] | 705 | surface_hierarchy_content_bounds_ = gfx::Rect(content_size_); |
Mike Reed | 2c570fa | 2018-01-11 21:59:22 | [diff] [blame] | 706 | if (state_.input_region) { |
| 707 | hit_test_region_ = *state_.input_region; |
| 708 | hit_test_region_.Intersect(surface_hierarchy_content_bounds_); |
Lei Zhang | 1c9963ba | 2018-05-15 04:50:21 | [diff] [blame] | 709 | } else { |
Mike Reed | 2c570fa | 2018-01-11 21:59:22 | [diff] [blame] | 710 | hit_test_region_ = surface_hierarchy_content_bounds_; |
Lei Zhang | 1c9963ba | 2018-05-15 04:50:21 | [diff] [blame] | 711 | } |
Dominik Laskowski | 2af53e7 | 2017-10-03 00:16:37 | [diff] [blame] | 712 | |
Dominik Laskowski | 2d431641 | 2017-12-13 19:14:44 | [diff] [blame] | 713 | int outset = state_.input_outset; |
| 714 | if (outset > 0) { |
| 715 | gfx::Rect input_rect = surface_hierarchy_content_bounds_; |
| 716 | input_rect.Inset(-outset, -outset); |
| 717 | hit_test_region_ = input_rect; |
| 718 | } |
| 719 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 720 | for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) { |
| 721 | auto* sub_surface = sub_surface_entry.first; |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 722 | gfx::Vector2d offset = sub_surface_entry.second.OffsetFromOrigin(); |
Dominik Laskowski | 2af53e7 | 2017-10-03 00:16:37 | [diff] [blame] | 723 | // Synchronously commit all pending state of the sub-surface and its |
| 724 | // descendants. |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 725 | sub_surface->CommitSurfaceHierarchy(synchronized); |
David Reveman | 7a126ba | 2017-11-09 17:17:41 | [diff] [blame] | 726 | surface_hierarchy_content_bounds_.Union( |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 727 | sub_surface->surface_hierarchy_content_bounds() + offset); |
| 728 | hit_test_region_.Union(sub_surface->hit_test_region_ + offset); |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 729 | } |
| 730 | } |
| 731 | |
David Reveman | ef1cb08 | 2017-11-09 21:14:40 | [diff] [blame] | 732 | void Surface::AppendSurfaceHierarchyCallbacks( |
| 733 | std::list<FrameCallback>* frame_callbacks, |
| 734 | std::list<PresentationCallback>* presentation_callbacks) { |
| 735 | // Move frame callbacks to the end of |frame_callbacks|. |
| 736 | frame_callbacks->splice(frame_callbacks->end(), frame_callbacks_); |
| 737 | // Move presentation callbacks to the end of |presentation_callbacks|. |
| 738 | presentation_callbacks->splice(presentation_callbacks->end(), |
| 739 | presentation_callbacks_); |
| 740 | |
| 741 | for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) { |
| 742 | auto* sub_surface = sub_surface_entry.first; |
| 743 | sub_surface->AppendSurfaceHierarchyCallbacks(frame_callbacks, |
| 744 | presentation_callbacks); |
| 745 | } |
| 746 | } |
| 747 | |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 748 | void Surface::AppendSurfaceHierarchyContentsToFrame( |
| 749 | const gfx::Point& origin, |
| 750 | float device_scale_factor, |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 751 | FrameSinkResourceManager* resource_manager, |
danakj | 5e0a12b | 2017-09-25 17:26:49 | [diff] [blame] | 752 | viz::CompositorFrame* frame) { |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 753 | // The top most sub-surface is at the front of the RenderPass's quad_list, |
| 754 | // so we need composite sub-surface in reversed order. |
| 755 | for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) { |
| 756 | auto* sub_surface = sub_surface_entry.first; |
| 757 | // Synchronsouly commit all pending state of the sub-surface and its |
| 758 | // decendents. |
| 759 | sub_surface->AppendSurfaceHierarchyContentsToFrame( |
| 760 | origin + sub_surface_entry.second.OffsetFromOrigin(), |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 761 | device_scale_factor, resource_manager, frame); |
Kazuhiro Inaba | 4f19a78 | 2017-07-18 05:28:51 | [diff] [blame] | 762 | } |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 763 | |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 764 | if (needs_update_resource_) |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 765 | UpdateResource(resource_manager); |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 766 | |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 767 | AppendContentsToFrame(origin, device_scale_factor, frame); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 768 | |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 769 | DCHECK(!current_resource_.id || |
| 770 | resource_manager->HasReleaseCallbackForResource(current_resource_.id)); |
jbauman | bd9586a9 | 2016-05-28 01:09:03 | [diff] [blame] | 771 | } |
| 772 | |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 773 | bool Surface::IsSynchronized() const { |
Dominik Laskowski | 3e2f9479 | 2017-12-15 00:27:10 | [diff] [blame] | 774 | return delegate_ && delegate_->IsSurfaceSynchronized(); |
| 775 | } |
| 776 | |
Dominik Laskowski | 14a16377 | 2018-02-09 19:25:18 | [diff] [blame] | 777 | bool Surface::IsInputEnabled(Surface* surface) const { |
| 778 | return !delegate_ || delegate_->IsInputEnabled(surface); |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 779 | } |
reveman | 56f34590 | 2016-06-06 03:58:28 | [diff] [blame] | 780 | |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 781 | bool Surface::HasHitTestRegion() const { |
| 782 | return !hit_test_region_.IsEmpty(); |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 783 | } |
| 784 | |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 785 | bool Surface::HitTest(const gfx::Point& point) const { |
| 786 | return hit_test_region_.Contains(point); |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 787 | } |
| 788 | |
Raul Tambre | 038e96d | 2019-01-07 21:47:44 | [diff] [blame] | 789 | void Surface::GetHitTestMask(SkPath* mask) const { |
Dominik Laskowski | 5706470 | 2017-11-30 10:31:41 | [diff] [blame] | 790 | hit_test_region_.GetBoundaryPath(mask); |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 791 | } |
| 792 | |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 793 | void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) { |
| 794 | DCHECK(!delegate_ || !delegate); |
| 795 | delegate_ = delegate; |
| 796 | } |
| 797 | |
| 798 | bool Surface::HasSurfaceDelegate() const { |
| 799 | return !!delegate_; |
| 800 | } |
| 801 | |
| 802 | void Surface::AddSurfaceObserver(SurfaceObserver* observer) { |
| 803 | observers_.AddObserver(observer); |
| 804 | } |
| 805 | |
| 806 | void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) { |
| 807 | observers_.RemoveObserver(observer); |
| 808 | } |
| 809 | |
| 810 | bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const { |
| 811 | return observers_.HasObserver(observer); |
| 812 | } |
| 813 | |
| 814 | std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const { |
| 815 | std::unique_ptr<base::trace_event::TracedValue> value( |
| 816 | new base::trace_event::TracedValue()); |
| 817 | value->SetString("name", window_->layer()->name()); |
| 818 | return value; |
| 819 | } |
| 820 | |
kaznacheev | 8e27059 | 2017-05-25 06:13:26 | [diff] [blame] | 821 | bool Surface::IsStylusOnly() { |
| 822 | return window_->GetProperty(kStylusOnlyKey); |
| 823 | } |
| 824 | |
| 825 | void Surface::SetStylusOnly() { |
| 826 | window_->SetProperty(kStylusOnlyKey, true); |
| 827 | } |
| 828 | |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 829 | void Surface::SurfaceHierarchyResourcesLost() { |
| 830 | // Update resource and full damage are needed for next frame. |
| 831 | needs_update_resource_ = true; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 832 | for (const auto& sub_surface : sub_surfaces_) |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 833 | sub_surface.first->SurfaceHierarchyResourcesLost(); |
reveman | 15aee28 | 2016-11-04 19:09:20 | [diff] [blame] | 834 | } |
| 835 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 836 | bool Surface::FillsBoundsOpaquely() const { |
| 837 | return !current_resource_has_alpha_ || |
| 838 | state_.blend_mode == SkBlendMode::kSrc || |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 839 | state_.opaque_region.Contains(gfx::Rect(content_size_)); |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 840 | } |
| 841 | |
Eliot Courtney | bb051d1 | 2018-12-15 02:41:31 | [diff] [blame] | 842 | void Surface::SetOcclusionTracking(bool tracking) { |
| 843 | is_tracking_occlusion_ = tracking; |
| 844 | // TODO(edcourtney): Currently, it doesn't seem to be possible to stop |
| 845 | // tracking the occlusion state once started, but it would be nice to stop if |
| 846 | // the tracked occlusion region becomes empty. |
| 847 | if (is_tracking_occlusion_) |
| 848 | window()->TrackOcclusionState(); |
| 849 | } |
| 850 | |
[email protected] | 9385573 | 2019-06-24 19:49:30 | [diff] [blame] | 851 | void Surface::SetSurfaceHierarchyContentBoundsForTest( |
| 852 | const gfx::Rect& content_bounds) { |
| 853 | surface_hierarchy_content_bounds_ = content_bounds; |
| 854 | } |
| 855 | |
reveman | 211cf80 | 2017-01-10 00:30:59 | [diff] [blame] | 856 | //////////////////////////////////////////////////////////////////////////////// |
| 857 | // Buffer, private: |
| 858 | |
Mike Reed | 2c570fa | 2018-01-11 21:59:22 | [diff] [blame] | 859 | Surface::State::State() {} |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 860 | |
| 861 | Surface::State::~State() = default; |
| 862 | |
Lei Zhang | 1c9963ba | 2018-05-15 04:50:21 | [diff] [blame] | 863 | bool Surface::State::operator==(const State& other) const { |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 864 | return other.opaque_region == opaque_region && |
| 865 | other.input_region == input_region && |
| 866 | other.buffer_scale == buffer_scale && |
| 867 | other.buffer_transform == buffer_transform && |
| 868 | other.viewport == viewport && other.crop == crop && |
| 869 | other.only_visible_on_secure_output == only_visible_on_secure_output && |
| 870 | other.blend_mode == blend_mode && other.alpha == alpha; |
jbauman | 9041045 | 2016-06-15 22:40:56 | [diff] [blame] | 871 | } |
| 872 | |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 873 | Surface::BufferAttachment::BufferAttachment() {} |
| 874 | |
| 875 | Surface::BufferAttachment::~BufferAttachment() { |
| 876 | if (buffer_) |
| 877 | buffer_->OnDetach(); |
| 878 | } |
| 879 | |
| 880 | Surface::BufferAttachment& Surface::BufferAttachment::operator=( |
| 881 | BufferAttachment&& other) { |
| 882 | if (buffer_) |
| 883 | buffer_->OnDetach(); |
| 884 | buffer_ = other.buffer_; |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 885 | size_ = other.size_; |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 886 | other.buffer_ = base::WeakPtr<Buffer>(); |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 887 | other.size_ = gfx::Size(); |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 888 | return *this; |
| 889 | } |
| 890 | |
| 891 | base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() { |
| 892 | return buffer_; |
| 893 | } |
| 894 | |
| 895 | const base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() const { |
| 896 | return buffer_; |
| 897 | } |
| 898 | |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 899 | const gfx::Size& Surface::BufferAttachment::size() const { |
| 900 | return size_; |
| 901 | } |
| 902 | |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 903 | void Surface::BufferAttachment::Reset(base::WeakPtr<Buffer> buffer) { |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 904 | size_ = gfx::Size(); |
| 905 | if (buffer) { |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 906 | buffer->OnAttach(); |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 907 | size_ = buffer->GetSize(); |
| 908 | } |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 909 | if (buffer_) |
| 910 | buffer_->OnDetach(); |
| 911 | buffer_ = buffer; |
| 912 | } |
| 913 | |
Albert Chaulk | 56e9658 | 2019-01-30 19:33:18 | [diff] [blame] | 914 | void Surface::UpdateResource(FrameSinkResourceManager* resource_manager) { |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 915 | DCHECK(needs_update_resource_); |
| 916 | needs_update_resource_ = false; |
| 917 | if (current_buffer_.buffer()) { |
| 918 | if (current_buffer_.buffer()->ProduceTransferableResource( |
Daniele Castagna | fade7366 | 2019-06-04 03:30:31 | [diff] [blame] | 919 | resource_manager, std::move(acquire_fence_), |
| 920 | state_.only_visible_on_secure_output, ¤t_resource_)) { |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 921 | current_resource_has_alpha_ = |
| 922 | FormatHasAlpha(current_buffer_.buffer()->GetFormat()); |
| 923 | } else { |
| 924 | current_resource_.id = 0; |
| 925 | // Use the buffer's size, so the AppendContentsToFrame() will append |
| 926 | // a SolidColorDrawQuad with the buffer's size. |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 927 | current_resource_.size = current_buffer_.size(); |
Peng Huang | c51f7aba | 2017-09-05 16:00:39 | [diff] [blame] | 928 | current_resource_has_alpha_ = false; |
| 929 | } |
reveman | ca132dc | 2017-01-31 22:35:54 | [diff] [blame] | 930 | } else { |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 931 | current_resource_.id = 0; |
| 932 | current_resource_.size = gfx::Size(); |
reveman | ca132dc | 2017-01-31 22:35:54 | [diff] [blame] | 933 | current_resource_has_alpha_ = false; |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 934 | } |
| 935 | } |
| 936 | |
Zach Reizner | 8bcce6e | 2018-10-31 00:04:37 | [diff] [blame] | 937 | void Surface::UpdateBufferTransform(bool y_invert) { |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 938 | SkMatrix buffer_matrix; |
| 939 | switch (state_.buffer_transform) { |
| 940 | case Transform::NORMAL: |
| 941 | buffer_matrix.setIdentity(); |
| 942 | break; |
| 943 | case Transform::ROTATE_90: |
| 944 | buffer_matrix.setSinCos(-1, 0, 0.5f, 0.5f); |
| 945 | break; |
| 946 | case Transform::ROTATE_180: |
| 947 | buffer_matrix.setSinCos(0, -1, 0.5f, 0.5f); |
| 948 | break; |
| 949 | case Transform::ROTATE_270: |
| 950 | buffer_matrix.setSinCos(1, 0, 0.5f, 0.5f); |
| 951 | break; |
| 952 | } |
Zach Reizner | 8bcce6e | 2018-10-31 00:04:37 | [diff] [blame] | 953 | if (y_invert) |
| 954 | buffer_matrix.preScale(1, -1, 0.5f, 0.5f); |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 955 | buffer_matrix.postIDiv(state_.buffer_scale, state_.buffer_scale); |
| 956 | buffer_transform_ = gfx::Transform(buffer_matrix); |
| 957 | } |
| 958 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 959 | void Surface::AppendContentsToFrame(const gfx::Point& origin, |
Peng Huang | 76f5fd0 | 2017-09-01 00:59:39 | [diff] [blame] | 960 | float device_scale_factor, |
danakj | 5e0a12b | 2017-09-25 17:26:49 | [diff] [blame] | 961 | viz::CompositorFrame* frame) { |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 962 | const std::unique_ptr<viz::RenderPass>& render_pass = |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 963 | frame->render_pass_list.back(); |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 964 | gfx::Rect output_rect(origin, content_size_); |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 965 | gfx::Rect quad_rect(0, 0, 1, 1); |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 966 | |
Dominik Laskowski | 2af53e7 | 2017-10-03 00:16:37 | [diff] [blame] | 967 | // Surface bounds are in DIPs, but |damage_rect| and |output_rect| are in |
| 968 | // pixels, so we need to scale by the |device_scale_factor|. |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 969 | gfx::Rect damage_rect = damage_.bounds(); |
David Reveman | 472ec321 | 2017-11-11 04:19:03 | [diff] [blame] | 970 | if (!damage_rect.IsEmpty()) { |
| 971 | // Outset damage by 1 DIP to as damage is in surface coordinate space and |
| 972 | // client might not be aware of |device_scale_factor| and the |
| 973 | // scaling/filtering it requires. |
| 974 | damage_rect.Inset(-1, -1); |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 975 | damage_rect += origin.OffsetFromOrigin(); |
David Reveman | 472ec321 | 2017-11-11 04:19:03 | [diff] [blame] | 976 | damage_rect.Intersect(output_rect); |
| 977 | render_pass->damage_rect.Union( |
| 978 | gfx::ConvertRectToPixel(device_scale_factor, damage_rect)); |
| 979 | } |
| 980 | |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 981 | // Compute the total transformation from post-transform buffer coordinates to |
| 982 | // target coordinates. |
| 983 | SkMatrix viewport_to_target_matrix; |
| 984 | // Scale and offset the normalized space to fit the content size rectangle. |
| 985 | viewport_to_target_matrix.setScale( |
| 986 | content_size_.width() * state_.buffer_scale, |
| 987 | content_size_.height() * state_.buffer_scale); |
| 988 | viewport_to_target_matrix.postTranslate(origin.x(), origin.y()); |
| 989 | // Convert from DPs to pixels. |
| 990 | viewport_to_target_matrix.postScale(device_scale_factor, device_scale_factor); |
| 991 | |
| 992 | gfx::Transform quad_to_target_transform(buffer_transform_); |
| 993 | quad_to_target_transform.ConcatTransform( |
| 994 | gfx::Transform(viewport_to_target_matrix)); |
David Reveman | fca309b | 2017-08-24 18:18:11 | [diff] [blame] | 995 | |
Dominik Laskowski | 0dcf9135 | 2017-11-29 19:21:35 | [diff] [blame] | 996 | bool are_contents_opaque = !current_resource_has_alpha_ || |
| 997 | state_.blend_mode == SkBlendMode::kSrc || |
| 998 | state_.opaque_region.Contains(output_rect); |
yiyix | 10141eca | 2017-09-05 20:36:52 | [diff] [blame] | 999 | |
Alex Zhang | abad229 | 2017-08-23 21:55:19 | [diff] [blame] | 1000 | viz::SharedQuadState* quad_state = |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 1001 | render_pass->CreateAndAppendSharedQuadState(); |
Weiliang Chen | 5b0f31f6 | 2017-08-02 17:20:58 | [diff] [blame] | 1002 | quad_state->SetAll( |
Malay Keshav | c91ca41 | 2019-03-13 20:46:45 | [diff] [blame] | 1003 | quad_to_target_transform, quad_rect /*quad_layer_rect=*/, |
| 1004 | quad_rect /*visible_quad_layer_rect=*/, |
| 1005 | gfx::RRectF() /*rounded_corner_bounds=*/, gfx::Rect() /*clip_rect=*/, |
| 1006 | false /*is_clipped=*/, are_contents_opaque, state_.alpha /*opacity=*/, |
| 1007 | SkBlendMode::kSrcOver /*blend_mode=*/, 0 /*sorting_context_id=*/); |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 1008 | |
Kazuhiro Inaba | 4f19a78 | 2017-07-18 05:28:51 | [diff] [blame] | 1009 | if (current_resource_.id) { |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 1010 | gfx::RectF uv_crop(gfx::SizeF(1, 1)); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1011 | if (!state_.crop.IsEmpty()) { |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 1012 | // The crop rectangle is a post-transformation rectangle. To get the UV |
| 1013 | // coordinates, we need to convert it to normalized buffer coordinates and |
| 1014 | // pass them through the inverse of the buffer transformation. |
| 1015 | uv_crop = gfx::RectF(state_.crop); |
| 1016 | gfx::Size transformed_buffer_size( |
| 1017 | ToTransformedSize(current_resource_.size, state_.buffer_transform)); |
| 1018 | if (!transformed_buffer_size.IsEmpty()) |
| 1019 | uv_crop.Scale(1.f / transformed_buffer_size.width(), |
| 1020 | 1.f / transformed_buffer_size.height()); |
| 1021 | |
| 1022 | buffer_transform_.TransformRectReverse(&uv_crop); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1023 | } |
Lloyd Pique | 0a3045f | 2017-09-15 23:34:12 | [diff] [blame] | 1024 | |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 1025 | SkColor background_color = SK_ColorTRANSPARENT; |
| 1026 | if (current_resource_has_alpha_ && are_contents_opaque) |
| 1027 | background_color = SK_ColorBLACK; // Avoid writing alpha < 1 |
| 1028 | |
| 1029 | // If this surface is being replaced by a SurfaceId emit a SurfaceDrawQuad. |
| 1030 | if (get_current_surface_id_) { |
| 1031 | auto current_surface_id = get_current_surface_id_.Run(); |
Albert Chaulk | 0adb8b8d | 2019-11-06 20:06:27 | [diff] [blame] | 1032 | // If the surface ID is valid update it, otherwise keep showing the old |
| 1033 | // one for now. |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 1034 | if (current_surface_id.is_valid()) { |
Albert Chaulk | 0adb8b8d | 2019-11-06 20:06:27 | [diff] [blame] | 1035 | latest_embedded_surface_id_ = current_surface_id; |
| 1036 | if (!current_surface_id.HasSameEmbedTokenAs( |
| 1037 | first_embedded_surface_id_)) { |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 1038 | first_embedded_surface_id_ = current_surface_id; |
Albert Chaulk | 0adb8b8d | 2019-11-06 20:06:27 | [diff] [blame] | 1039 | } |
| 1040 | } |
| 1041 | if (latest_embedded_surface_id_.is_valid()) { |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 1042 | viz::SurfaceDrawQuad* surface_quad = |
| 1043 | render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>(); |
Albert Chaulk | 0adb8b8d | 2019-11-06 20:06:27 | [diff] [blame] | 1044 | surface_quad->SetNew(quad_state, quad_rect, quad_rect, |
| 1045 | viz::SurfaceRange(first_embedded_surface_id_, |
| 1046 | latest_embedded_surface_id_), |
| 1047 | background_color, |
| 1048 | /*stretch_content_to_fill_bounds=*/true, |
| 1049 | /*ignores_input_event=*/false); |
Albert Chaulk | fd08f984 | 2019-10-11 15:26:14 | [diff] [blame] | 1050 | } |
| 1051 | } else if (state_.alpha) { |
| 1052 | // Texture quad is only needed if buffer is not fully transparent. |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 1053 | viz::TextureDrawQuad* texture_quad = |
| 1054 | render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>(); |
reveman | e2d54b8 | 2016-08-25 00:30:38 | [diff] [blame] | 1055 | float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0}; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1056 | texture_quad->SetNew( |
Daniele Castagna | 9f26254 | 2019-02-20 05:50:31 | [diff] [blame] | 1057 | quad_state, quad_rect, quad_rect, |
| 1058 | /* needs_blending=*/!are_contents_opaque, current_resource_.id, |
| 1059 | /* premultiplied_alpha=*/true, uv_crop.origin(), |
| 1060 | uv_crop.bottom_right(), background_color, vertex_opacity, |
| 1061 | /* y_flipped=*/false, /* nearest_neighbor=*/false, |
Maggie Chen | a507bbb1 | 2019-06-04 00:19:51 | [diff] [blame] | 1062 | state_.only_visible_on_secure_output, |
| 1063 | gfx::ProtectedVideoType::kClear); |
reveman | e2d54b8 | 2016-08-25 00:30:38 | [diff] [blame] | 1064 | if (current_resource_.is_overlay_candidate) |
| 1065 | texture_quad->set_resource_size_in_pixels(current_resource_.size); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1066 | frame->resource_list.push_back(current_resource_); |
reveman | e2d54b8 | 2016-08-25 00:30:38 | [diff] [blame] | 1067 | } |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 1068 | } else { |
danakj | e5805be | 2017-09-15 19:24:55 | [diff] [blame] | 1069 | viz::SolidColorDrawQuad* solid_quad = |
| 1070 | render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>(); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1071 | solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK, |
| 1072 | false /* force_anti_aliasing_off */); |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 1073 | } |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1074 | } |
jbauman | 45c0686 | 2016-06-23 19:35:02 | [diff] [blame] | 1075 | |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1076 | void Surface::UpdateContentSize() { |
Peng Huang | 11ddbb4 | 2017-08-15 15:43:18 | [diff] [blame] | 1077 | gfx::Size content_size; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1078 | if (!state_.viewport.IsEmpty()) { |
Peng Huang | 11ddbb4 | 2017-08-15 15:43:18 | [diff] [blame] | 1079 | content_size = state_.viewport; |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1080 | } else if (!state_.crop.IsEmpty()) { |
| 1081 | DLOG_IF(WARNING, !gfx::IsExpressibleAsInt(state_.crop.width()) || |
| 1082 | !gfx::IsExpressibleAsInt(state_.crop.height())) |
| 1083 | << "Crop rectangle size (" << state_.crop.size().ToString() |
| 1084 | << ") most be expressible using integers when viewport is not set"; |
Peng Huang | 11ddbb4 | 2017-08-15 15:43:18 | [diff] [blame] | 1085 | content_size = gfx::ToCeiledSize(state_.crop.size()); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1086 | } else { |
David Reveman | e6e2334 | 2017-11-07 06:18:06 | [diff] [blame] | 1087 | content_size = gfx::ToCeiledSize( |
| 1088 | gfx::ScaleSize(gfx::SizeF(ToTransformedSize(current_buffer_.size(), |
| 1089 | state_.buffer_transform)), |
| 1090 | 1.0f / state_.buffer_scale)); |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1091 | } |
Peng Huang | 583c9dc6 | 2017-07-27 23:38:28 | [diff] [blame] | 1092 | |
| 1093 | // Enable/disable sub-surface based on if it has contents. |
| 1094 | if (has_contents()) |
| 1095 | window_->Show(); |
| 1096 | else |
| 1097 | window_->Hide(); |
Peng Huang | 11ddbb4 | 2017-08-15 15:43:18 | [diff] [blame] | 1098 | |
| 1099 | if (content_size_ != content_size) { |
| 1100 | content_size_ = content_size; |
| 1101 | window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_)); |
Peng Huang | 11ddbb4 | 2017-08-15 15:43:18 | [diff] [blame] | 1102 | } |
reveman | 15aee28 | 2016-11-04 19:09:20 | [diff] [blame] | 1103 | } |
| 1104 | |
Eliot Courtney | bb051d1 | 2018-12-15 02:41:31 | [diff] [blame] | 1105 | void Surface::OnWindowOcclusionChanged() { |
| 1106 | if (!is_tracking_occlusion_) |
| 1107 | return; |
| 1108 | |
| 1109 | for (SurfaceObserver& observer : observers_) |
| 1110 | observer.OnWindowOcclusionChanged(this); |
| 1111 | } |
| 1112 | |
reveman | b195f41d | 2015-11-19 22:16:48 | [diff] [blame] | 1113 | } // namespace exo |