// 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.

#include "components/exo/surface.h"

#include <utility>

#include "ash/public/cpp/shell_window_ids.h"
#include "base/callback_helpers.h"
#include "base/containers/adapters.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/exo/buffer.h"
#include "components/exo/frame_sink_resource_manager.h"
#include "components/exo/shell_surface_util.h"
#include "components/exo/surface_delegate.h"
#include "components/exo/surface_observer.h"
#include "components/exo/wm_helper.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/shared_quad_state.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"
#include "components/viz/common/quads/texture_draw_quad.h"
#include "components/viz/common/resources/single_release_callback.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_targeter.h"
#include "ui/base/class_property.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/hit_test.h"
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/transform_util.h"
#include "ui/views/widget/widget.h"

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/display/output_protection_delegate.h"
#include "ash/wm/desks/desks_util.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Surface*)

namespace exo {
namespace {

// A property key containing the surface that is associated with
// window. If unset, no surface is associated with window.
DEFINE_UI_CLASS_PROPERTY_KEY(Surface*, kSurfaceKey, nullptr)

// A property key to store whether the surface should only consume
// stylus input events.
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kStylusOnlyKey, false)

// Helper function that returns an iterator to the first entry in |list|
// with |key|.
template <typename T, typename U>
typename T::iterator FindListEntry(T& list, U key) {
  return std::find_if(list.begin(), list.end(),
                      [key](const typename T::value_type& entry) {
                        return entry.first == key;
                      });
}

// Helper function that returns true if |list| contains an entry with |key|.
template <typename T, typename U>
bool ListContainsEntry(T& list, U key) {
  return FindListEntry(list, key) != list.end();
}

// Helper function that returns true if |format| may have an alpha channel.
// Note: False positives are allowed but false negatives are not.
bool FormatHasAlpha(gfx::BufferFormat format) {
  switch (format) {
    case gfx::BufferFormat::BGR_565:
    case gfx::BufferFormat::RGBX_8888:
    case gfx::BufferFormat::BGRX_8888:
    case gfx::BufferFormat::YVU_420:
    case gfx::BufferFormat::YUV_420_BIPLANAR:
      return false;
    default:
      return true;
  }
}

// Helper function that returns |size| after adjusting for |transform|.
gfx::Size ToTransformedSize(const gfx::Size& size, Transform transform) {
  switch (transform) {
    case Transform::NORMAL:
    case Transform::ROTATE_180:
      return size;
    case Transform::ROTATE_90:
    case Transform::ROTATE_270:
      return gfx::Size(size.height(), size.width());
  }

  NOTREACHED();
}

bool IsDeskContainer(aura::Window* container) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
  return ash::desks_util::IsDeskContainer(container);
#else
  return container->id() == ash::kShellWindowId_DefaultContainerDeprecated;
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
}

class CustomWindowDelegate : public aura::WindowDelegate {
 public:
  explicit CustomWindowDelegate(Surface* surface) : surface_(surface) {}
  ~CustomWindowDelegate() override {}

  // Overridden from aura::WindowDelegate:
  gfx::Size GetMinimumSize() const override { return gfx::Size(); }
  gfx::Size GetMaximumSize() const override { return gfx::Size(); }
  void OnBoundsChanged(const gfx::Rect& old_bounds,
                       const gfx::Rect& new_bounds) override {}
  gfx::NativeCursor GetCursor(const gfx::Point& point) override {
    views::Widget* widget =
        views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
    if (widget)
      return widget->GetNativeWindow()->GetCursor(point /* not used */);
    return ui::mojom::CursorType::kNull;
  }
  int GetNonClientComponent(const gfx::Point& point) const override {
    views::Widget* widget =
        views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
    if (widget && IsDeskContainer(widget->GetNativeView()->parent()) &&
        surface_->HitTest(point)) {
      return HTCLIENT;
    }

    return HTNOWHERE;
  }
  bool ShouldDescendIntoChildForEventHandling(
      aura::Window* child,
      const gfx::Point& location) override {
    return true;
  }
  bool CanFocus() override { return true; }
  void OnCaptureLost() override {}
  void OnPaint(const ui::PaintContext& context) override {}
  void OnDeviceScaleFactorChanged(float old_device_scale_factor,
                                  float new_device_scale_factor) override {}
  void OnWindowDestroying(aura::Window* window) override {}
  void OnWindowDestroyed(aura::Window* window) override { delete this; }
  void OnWindowTargetVisibilityChanged(bool visible) override {}
  void OnWindowOcclusionChanged(
      aura::Window::OcclusionState occlusion_state) override {
    surface_->OnWindowOcclusionChanged();
  }
  bool HasHitTestMask() const override { return true; }
  void GetHitTestMask(SkPath* mask) const override {
    surface_->GetHitTestMask(mask);
  }
  void OnKeyEvent(ui::KeyEvent* event) override {
    // Propagates the key event upto the top-level views Widget so that we can
    // trigger proper events in the views/ash level there. Event handling for
    // Surfaces is done in a post event handler in keyboard.cc.
    views::Widget* widget =
        views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
    if (widget)
      widget->OnKeyEvent(event);
  }

 private:
  Surface* const surface_;

  DISALLOW_COPY_AND_ASSIGN(CustomWindowDelegate);
};

class CustomWindowTargeter : public aura::WindowTargeter {
 public:
  CustomWindowTargeter() {}
  ~CustomWindowTargeter() override {}

  // Overridden from aura::WindowTargeter:
  bool EventLocationInsideBounds(aura::Window* window,
                                 const ui::LocatedEvent& event) const override {
    Surface* surface = Surface::AsSurface(window);
    if (!surface || !surface->IsInputEnabled(surface))
      return false;

    gfx::Point local_point = event.location();
    if (window->parent())
      aura::Window::ConvertPointToTarget(window->parent(), window,
                                         &local_point);
    return surface->HitTest(local_point);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(CustomWindowTargeter);
};

const std::string& GetApplicationId(aura::Window* window) {
  static const std::string empty_app_id;
  if (!window)
    return empty_app_id;
  while (window) {
    const std::string* app_id = exo::GetShellApplicationId(window);
    if (app_id)
      return *app_id;
    window = window->parent();
  }
  return empty_app_id;
}

int surface_id = 0;

}  // namespace

DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kClientSurfaceIdKey, nullptr)

ScopedSurface::ScopedSurface(Surface* surface, SurfaceObserver* observer)
    : surface_(surface), observer_(observer) {
  surface_->AddSurfaceObserver(observer_);
}

ScopedSurface::~ScopedSurface() {
  surface_->RemoveSurfaceObserver(observer_);
}

////////////////////////////////////////////////////////////////////////////////
// Surface, public:

Surface::Surface()
    : window_(
          std::make_unique<aura::Window>(new CustomWindowDelegate(this),
                                         aura::client::WINDOW_TYPE_CONTROL)) {
  window_->SetName(base::StringPrintf("ExoSurface-%d", surface_id++));
  window_->SetProperty(kSurfaceKey, this);
  window_->Init(ui::LAYER_NOT_DRAWN);
  window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>());
  window_->set_owned_by_parent(false);
  WMHelper::GetInstance()->SetDragDropDelegate(window_.get());
}
Surface::~Surface() {
  for (SurfaceObserver& observer : observers_)
    observer.OnSurfaceDestroying(this);

  // Call all frame callbacks with a null frame time to indicate that they
  // have been cancelled.
  state_.frame_callbacks.splice(state_.frame_callbacks.end(),
                                cached_state_.frame_callbacks);
  state_.frame_callbacks.splice(state_.frame_callbacks.end(),
                                pending_state_.frame_callbacks);
  for (const auto& frame_callback : state_.frame_callbacks)
    frame_callback.Run(base::TimeTicks());

  // Call all presentation callbacks with a null presentation time to indicate
  // that they have been cancelled.
  state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
                                       cached_state_.presentation_callbacks);
  state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
                                       pending_state_.presentation_callbacks);
  for (const auto& presentation_callback : state_.presentation_callbacks)
    presentation_callback.Run(gfx::PresentationFeedback());

  WMHelper::GetInstance()->ResetDragDropDelegate(window_.get());
}

// static
Surface* Surface::AsSurface(const aura::Window* window) {
  return window->GetProperty(kSurfaceKey);
}

void Surface::Attach(Buffer* buffer) {
  Attach(buffer, gfx::Vector2d());
}

void Surface::Attach(Buffer* buffer, gfx::Vector2d offset) {
  TRACE_EVENT2("exo", "Surface::Attach", "buffer_id",
               buffer ? buffer->gfx_buffer() : nullptr, "app_id",
               GetApplicationId(window_.get()));
  has_pending_contents_ = true;
  pending_state_.buffer.Reset(buffer ? buffer->AsWeakPtr()
                                     : base::WeakPtr<Buffer>());
  pending_state_.basic_state.offset = offset;
}

gfx::Vector2d Surface::GetBufferOffset() {
  return state_.basic_state.offset;
}

bool Surface::HasPendingAttachedBuffer() const {
  return pending_state_.buffer.buffer() != nullptr;
}

void Surface::Damage(const gfx::Rect& damage) {
  TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString());

  pending_state_.damage.Union(damage);
}

void Surface::RequestFrameCallback(const FrameCallback& callback) {
  TRACE_EVENT0("exo", "Surface::RequestFrameCallback");

  pending_state_.frame_callbacks.push_back(callback);
}

void Surface::RequestPresentationCallback(
    const PresentationCallback& callback) {
  TRACE_EVENT0("exo", "Surface::RequestPresentationCallback");

  pending_state_.presentation_callbacks.push_back(callback);
}

void Surface::SetOpaqueRegion(const cc::Region& region) {
  TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", region.ToString());

  pending_state_.basic_state.opaque_region = region;
}

void Surface::SetInputRegion(const cc::Region& region) {
  TRACE_EVENT1("exo", "Surface::SetInputRegion", "region", region.ToString());

  pending_state_.basic_state.input_region = region;
}

void Surface::ResetInputRegion() {
  TRACE_EVENT0("exo", "Surface::ResetInputRegion");

  pending_state_.basic_state.input_region = base::nullopt;
}

void Surface::SetInputOutset(int outset) {
  TRACE_EVENT1("exo", "Surface::SetInputOutset", "outset", outset);

  pending_state_.basic_state.input_outset = outset;
}

void Surface::SetBufferScale(float scale) {
  TRACE_EVENT1("exo", "Surface::SetBufferScale", "scale", scale);

  pending_state_.basic_state.buffer_scale = scale;
}

void Surface::SetBufferTransform(Transform transform) {
  TRACE_EVENT1("exo", "Surface::SetBufferTransform", "transform",
               static_cast<int>(transform));

  pending_state_.basic_state.buffer_transform = transform;
}

void Surface::AddSubSurface(Surface* sub_surface) {
  TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface",
               sub_surface->AsTracedValue());

  DCHECK(!sub_surface->window()->parent());
  sub_surface->window()->SetBounds(
      gfx::Rect(sub_surface->window()->bounds().size()));
  window_->AddChild(sub_surface->window());

  DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface));
  pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
  sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::Point()));
  sub_surfaces_changed_ = true;

  // The shell might have not be added to the root yet.
  if (window_->GetRootWindow()) {
    auto display =
        display::Screen::GetScreen()->GetDisplayNearestWindow(window_.get());
    sub_surface->UpdateDisplay(display::kInvalidDisplayId, display.id());
  }
}

void Surface::OnNewOutputAdded() {
  if (delegate_)
    delegate_->OnNewOutputAdded();
}

void Surface::RemoveSubSurface(Surface* sub_surface) {
  TRACE_EVENT1("exo", "Surface::RemoveSubSurface", "sub_surface",
               sub_surface->AsTracedValue());

  if (sub_surface->window()->IsVisible())
    sub_surface->window()->Hide();
  window_->RemoveChild(sub_surface->window());

  DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  pending_sub_surfaces_.erase(
      FindListEntry(pending_sub_surfaces_, sub_surface));

  DCHECK(ListContainsEntry(sub_surfaces_, sub_surface));
  auto it = FindListEntry(sub_surfaces_, sub_surface);
  sub_surfaces_.erase(it);
  // Force recreating resources when the surface is added to a tree again.
  sub_surface->SurfaceHierarchyResourcesLost();
  sub_surfaces_changed_ = true;
}

void Surface::SetSubSurfacePosition(Surface* sub_surface,
                                    const gfx::Point& position) {
  TRACE_EVENT2("exo", "Surface::SetSubSurfacePosition", "sub_surface",
               sub_surface->AsTracedValue(), "position", position.ToString());

  auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  DCHECK(it != pending_sub_surfaces_.end());
  if (it->second == position)
    return;
  it->second = position;
  sub_surfaces_changed_ = true;
}

void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
  TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceAbove", "sub_surface",
               sub_surface->AsTracedValue(), "reference",
               reference->AsTracedValue());

  if (sub_surface == reference) {
    DLOG(WARNING) << "Client tried to place sub-surface above itself";
    return;
  }

  auto position_it = pending_sub_surfaces_.begin();
  if (reference != this) {
    position_it = FindListEntry(pending_sub_surfaces_, reference);
    if (position_it == pending_sub_surfaces_.end()) {
      DLOG(WARNING) << "Client tried to place sub-surface above a reference "
                       "surface that is neither a parent nor a sibling";
      return;
    }

    // Advance iterator to have |position_it| point to the sibling surface
    // above |reference|.
    ++position_it;
  }

  DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  if (it == position_it)
    return;
  pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it);
  sub_surfaces_changed_ = true;
}

void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
  TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceBelow", "sub_surface",
               sub_surface->AsTracedValue(), "sibling",
               sibling->AsTracedValue());

  if (sub_surface == sibling) {
    DLOG(WARNING) << "Client tried to place sub-surface below itself";
    return;
  }

  auto sibling_it = FindListEntry(pending_sub_surfaces_, sibling);
  if (sibling_it == pending_sub_surfaces_.end()) {
    DLOG(WARNING) << "Client tried to place sub-surface below a surface that "
                     "is not a sibling";
    return;
  }

  DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  if (it == sibling_it)
    return;
  pending_sub_surfaces_.splice(sibling_it, pending_sub_surfaces_, it);
  sub_surfaces_changed_ = true;
}

void Surface::OnSubSurfaceCommit() {
  if (delegate_)
    delegate_->OnSurfaceCommit();
}

void Surface::SetViewport(const gfx::Size& viewport) {
  TRACE_EVENT1("exo", "Surface::SetViewport", "viewport", viewport.ToString());

  pending_state_.basic_state.viewport = viewport;
}

void Surface::SetCrop(const gfx::RectF& crop) {
  TRACE_EVENT1("exo", "Surface::SetCrop", "crop", crop.ToString());

  pending_state_.basic_state.crop = crop;
}

void Surface::SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output) {
  TRACE_EVENT1("exo", "Surface::SetOnlyVisibleOnSecureOutput",
               "only_visible_on_secure_output", only_visible_on_secure_output);

  pending_state_.basic_state.only_visible_on_secure_output =
      only_visible_on_secure_output;
}

void Surface::SetBlendMode(SkBlendMode blend_mode) {
  TRACE_EVENT1("exo", "Surface::SetBlendMode", "blend_mode",
               static_cast<int>(blend_mode));

  pending_state_.basic_state.blend_mode = blend_mode;
}

void Surface::SetAlpha(float alpha) {
  TRACE_EVENT1("exo", "Surface::SetAlpha", "alpha", alpha);

  pending_state_.basic_state.alpha = alpha;
}

void Surface::SetFrame(SurfaceFrameType type) {
  TRACE_EVENT1("exo", "Surface::SetFrame", "type", static_cast<uint32_t>(type));

  if (delegate_)
    delegate_->OnSetFrame(type);
}

void Surface::SetFrameColors(SkColor active_color, SkColor inactive_color) {
  TRACE_EVENT2("exo", "Surface::SetFrameColors", "active_color", active_color,
               "inactive_color", inactive_color);

  if (delegate_)
    delegate_->OnSetFrameColors(active_color, inactive_color);
}

void Surface::SetStartupId(const char* startup_id) {
  TRACE_EVENT1("exo", "Surface::SetStartupId", "startup_id", startup_id);

  if (delegate_)
    delegate_->OnSetStartupId(startup_id);
}

void Surface::SetApplicationId(const char* application_id) {
  TRACE_EVENT1("exo", "Surface::SetApplicationId", "application_id",
               application_id);

  if (delegate_)
    delegate_->OnSetApplicationId(application_id);
}

void Surface::SetUseImmersiveForFullscreen(bool value) {
  TRACE_EVENT1("exo", "Surface::SetUseImmersiveForFullscreen", "value", value);

  if (delegate_)
    delegate_->SetUseImmersiveForFullscreen(value);
}

void Surface::SetColorSpace(gfx::ColorSpace color_space) {
  TRACE_EVENT1("exo", "Surface::SetColorSpace", "color_space",
               color_space.ToString());

  pending_state_.basic_state.color_space = color_space;
}

void Surface::SetParent(Surface* parent, const gfx::Point& position) {
  TRACE_EVENT2("exo", "Surface::SetParent", "parent", !!parent, "position",
               position.ToString());

  if (delegate_)
    delegate_->OnSetParent(parent, position);
}

void Surface::RequestActivation() {
  TRACE_EVENT0("exo", "Surface::RequestActivation");

  if (delegate_)
    delegate_->OnActivationRequested();
}

void Surface::SetClientSurfaceId(const char* client_surface_id) {
  if (client_surface_id && strlen(client_surface_id) > 0)
    window_->SetProperty(kClientSurfaceIdKey,
                         new std::string(client_surface_id));
  else
    window_->ClearProperty(kClientSurfaceIdKey);
}

std::string Surface::GetClientSurfaceId() const {
  std::string* value = window_->GetProperty(kClientSurfaceIdKey);
  return value ? *value : std::string();
}

void Surface::SetEmbeddedSurfaceId(
    base::RepeatingCallback<viz::SurfaceId()> surface_id_callback) {
  get_current_surface_id_ = std::move(surface_id_callback);
  first_embedded_surface_id_ = viz::SurfaceId();
}

void Surface::SetEmbeddedSurfaceSize(const gfx::Size& size) {
  embedded_surface_size_ = size;
}

void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) {
#if defined(OS_POSIX)
  TRACE_EVENT1("exo", "Surface::SetAcquireFence", "fence_fd",
               gpu_fence ? gpu_fence->GetGpuFenceHandle().owned_fd.get() : -1);
#endif  // defined(OS_POSIX)

  pending_state_.acquire_fence = std::move(gpu_fence);
}

bool Surface::HasPendingAcquireFence() const {
  return !!pending_state_.acquire_fence;
}

void Surface::Commit() {
  TRACE_EVENT1("exo", "Surface::Commit", "buffer_id",
               pending_state_.buffer.buffer()
                   ? pending_state_.buffer.buffer()->gfx_buffer()
                   : nullptr);

  for (auto& observer : observers_)
    observer.OnCommit(this);

  needs_commit_surface_ = true;

  // Transfer pending state to cached state.
  cached_state_.basic_state = pending_state_.basic_state;
  pending_state_.basic_state.only_visible_on_secure_output = false;
  has_cached_contents_ |= has_pending_contents_;
  has_pending_contents_ = false;
  cached_state_.buffer = std::move(pending_state_.buffer);
  cached_state_.acquire_fence = std::move(pending_state_.acquire_fence);
  cached_state_.frame_callbacks.splice(cached_state_.frame_callbacks.end(),
                                       pending_state_.frame_callbacks);
  cached_state_.damage.Union(pending_state_.damage);
  pending_state_.damage.Clear();

  // Existing presentation callbacks in the cached state when a new pending
  // state is merged in should end up delivered as "discarded".
  for (const auto& presentation_callback : cached_state_.presentation_callbacks)
    presentation_callback.Run(gfx::PresentationFeedback());
  cached_state_.presentation_callbacks.clear();
  cached_state_.presentation_callbacks.splice(
      cached_state_.presentation_callbacks.end(),
      pending_state_.presentation_callbacks);

  if (delegate_)
    delegate_->OnSurfaceCommit();
  else
    CommitSurfaceHierarchy(false);
}

void Surface::UpdateDisplay(int64_t old_display, int64_t new_display) {
  if (!leave_enter_callback_.is_null())
    leave_enter_callback_.Run(old_display, new_display);
  for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
    auto* sub_surface = sub_surface_entry.first;
    sub_surface->UpdateDisplay(old_display, new_display);
  }
}

void Surface::CommitSurfaceHierarchy(bool synchronized) {
  TRACE_EVENT0("exo", "Surface::CommitSurfaceHierarchy");
  if (needs_commit_surface_ && (synchronized || !IsSynchronized())) {
    needs_commit_surface_ = false;
    synchronized = true;

    // TODO(penghuang): Make the damage more precise for sub surface changes.
    // https://crbug.com/779704
    bool needs_full_damage =
        sub_surfaces_changed_ ||
        cached_state_.basic_state.opaque_region !=
            state_.basic_state.opaque_region ||
        cached_state_.basic_state.buffer_scale !=
            state_.basic_state.buffer_scale ||
        cached_state_.basic_state.buffer_transform !=
            state_.basic_state.buffer_transform ||
        cached_state_.basic_state.viewport != state_.basic_state.viewport ||
        cached_state_.basic_state.crop != state_.basic_state.crop ||
        cached_state_.basic_state.only_visible_on_secure_output !=
            state_.basic_state.only_visible_on_secure_output ||
        cached_state_.basic_state.blend_mode != state_.basic_state.blend_mode ||
        cached_state_.basic_state.alpha != state_.basic_state.alpha ||
        cached_state_.basic_state.color_space !=
            state_.basic_state.color_space ||
        cached_state_.basic_state.is_tracking_occlusion !=
            state_.basic_state.is_tracking_occlusion;

    bool needs_update_buffer_transform =
        cached_state_.basic_state.buffer_scale !=
            state_.basic_state.buffer_scale ||
        cached_state_.basic_state.buffer_transform !=
            state_.basic_state.buffer_transform;

#if BUILDFLAG(IS_CHROMEOS_ASH)
    bool needs_output_protection =
        cached_state_.basic_state.only_visible_on_secure_output !=
        state_.basic_state.only_visible_on_secure_output;
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

    bool cached_invert_y = false;

    // If the current state is fully transparent, the last submitted frame will
    // not include the TextureDrawQuad for the resource, so the resource might
    // have been released and needs to be updated again.
    if (!state_.basic_state.alpha && cached_state_.basic_state.alpha)
      needs_update_resource_ = true;

    state_.basic_state = cached_state_.basic_state;
    cached_state_.basic_state.only_visible_on_secure_output = false;

    window_->SetEventTargetingPolicy(
        (state_.basic_state.input_region.has_value() &&
         state_.basic_state.input_region->IsEmpty())
            ? aura::EventTargetingPolicy::kDescendantsOnly
            : aura::EventTargetingPolicy::kTargetAndDescendants);

    if (state_.basic_state.is_tracking_occlusion) {
      // TODO(edcourtney): Currently, it doesn't seem to be possible to stop
      // tracking the occlusion state once started, but it would be nice to stop
      // if the tracked occlusion region becomes empty.
      window_->TrackOcclusionState();
    }

#if BUILDFLAG(IS_CHROMEOS_ASH)
    if (needs_output_protection) {
      if (!output_protection_) {
        output_protection_ =
            std::make_unique<ash::OutputProtectionDelegate>(window_.get());
      }

      uint32_t protection_mask =
          state_.basic_state.only_visible_on_secure_output
              ? display::CONTENT_PROTECTION_METHOD_HDCP
              : display::CONTENT_PROTECTION_METHOD_NONE;

      output_protection_->SetProtection(protection_mask, base::DoNothing());
    }
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

    // We update contents if Attach() has been called since last commit.
    if (has_cached_contents_) {
      has_cached_contents_ = false;

      bool current_invert_y =
          state_.buffer.buffer() && state_.buffer.buffer()->y_invert();
      cached_invert_y = cached_state_.buffer.buffer() &&
                        cached_state_.buffer.buffer()->y_invert();
      if (current_invert_y != cached_invert_y)
        needs_update_buffer_transform = true;

      state_.buffer = std::move(cached_state_.buffer);
      state_.acquire_fence = std::move(cached_state_.acquire_fence);
      if (state_.basic_state.alpha)
        needs_update_resource_ = true;
    }
    // Either we didn't have a pending acquire fence, or we had one along with
    // a new buffer, and it was already moved to state_.acquire_fence. Note that
    // it is a commit-time client error to commit a fence without a buffer.
    DCHECK(!cached_state_.acquire_fence);

    if (needs_update_buffer_transform)
      UpdateBufferTransform(cached_invert_y);

    // Move pending frame callbacks to the end of |state_.frame_callbacks|.
    state_.frame_callbacks.splice(state_.frame_callbacks.end(),
                                  cached_state_.frame_callbacks);

    // Move pending presentation callbacks to the end of
    // |state_.presentation_callbacks|.
    state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
                                         cached_state_.presentation_callbacks);

    UpdateContentSize();

    // Synchronize window hierarchy. This will position and update the stacking
    // order of all sub-surfaces after committing all pending state of
    // sub-surface descendants.
    // Changes to sub_surface stack is immediately applied to pending, which
    // will be copied to active directly when parent surface is committed,
    // skipping the cached state.
    if (sub_surfaces_changed_) {
      sub_surfaces_.clear();
      aura::Window* stacking_target = nullptr;
      for (const auto& sub_surface_entry : pending_sub_surfaces_) {
        Surface* sub_surface = sub_surface_entry.first;
        sub_surfaces_.push_back(sub_surface_entry);
        // Move sub-surface to its new position in the stack.
        if (stacking_target)
          window_->StackChildAbove(sub_surface->window(), stacking_target);

        // Stack next sub-surface above this sub-surface.
        stacking_target = sub_surface->window();

        // Update sub-surface position relative to surface origin.
        sub_surface->window()->SetBounds(gfx::Rect(
            sub_surface_entry.second, sub_surface->window()->bounds().size()));
      }
      sub_surfaces_changed_ = false;
    }

    gfx::Rect output_rect(content_size_);
    if (needs_full_damage) {
      state_.damage = output_rect;
    } else {
      // cached_state_.damage is in Surface coordinates.
      state_.damage.Swap(&cached_state_.damage);
      state_.damage.Intersect(output_rect);
    }
    cached_state_.damage.Clear();
  }

  surface_hierarchy_content_bounds_ = gfx::Rect(content_size_);
  if (state_.basic_state.input_region) {
    hit_test_region_ = *state_.basic_state.input_region;
    hit_test_region_.Intersect(surface_hierarchy_content_bounds_);
  } else {
    hit_test_region_ = surface_hierarchy_content_bounds_;
  }

  int outset = state_.basic_state.input_outset;
  if (outset > 0) {
    gfx::Rect input_rect = surface_hierarchy_content_bounds_;
    input_rect.Inset(-outset, -outset);
    hit_test_region_ = input_rect;
  }

  for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
    auto* sub_surface = sub_surface_entry.first;
    gfx::Vector2d offset = sub_surface_entry.second.OffsetFromOrigin();
    // Synchronously commit all pending state of the sub-surface and its
    // descendants.
    sub_surface->CommitSurfaceHierarchy(synchronized);
    surface_hierarchy_content_bounds_.Union(
        sub_surface->surface_hierarchy_content_bounds() + offset);
    hit_test_region_.Union(sub_surface->hit_test_region_ + offset);
  }
}

void Surface::AppendSurfaceHierarchyCallbacks(
    std::list<FrameCallback>* frame_callbacks,
    std::list<PresentationCallback>* presentation_callbacks) {
  // Move frame callbacks to the end of |frame_callbacks|.
  frame_callbacks->splice(frame_callbacks->end(), state_.frame_callbacks);
  // Move presentation callbacks to the end of |presentation_callbacks|.
  presentation_callbacks->splice(presentation_callbacks->end(),
                                 state_.presentation_callbacks);

  for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
    auto* sub_surface = sub_surface_entry.first;
    sub_surface->AppendSurfaceHierarchyCallbacks(frame_callbacks,
                                                 presentation_callbacks);
  }
}

void Surface::AppendSurfaceHierarchyContentsToFrame(
    const gfx::Point& origin,
    float device_scale_factor,
    FrameSinkResourceManager* resource_manager,
    viz::CompositorFrame* frame) {
  // The top most sub-surface is at the front of the RenderPass's quad_list,
  // so we need composite sub-surface in reversed order.
  for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
    auto* sub_surface = sub_surface_entry.first;
    // Synchronsouly commit all pending state of the sub-surface and its
    // decendents.
    sub_surface->AppendSurfaceHierarchyContentsToFrame(
        origin + sub_surface_entry.second.OffsetFromOrigin(),
        device_scale_factor, resource_manager, frame);
  }

  if (needs_update_resource_)
    UpdateResource(resource_manager);

  AppendContentsToFrame(origin, device_scale_factor, frame);

  DCHECK(!current_resource_.id ||
         resource_manager->HasReleaseCallbackForResource(current_resource_.id));
}

bool Surface::IsSynchronized() const {
  return delegate_ && delegate_->IsSurfaceSynchronized();
}

bool Surface::IsInputEnabled(Surface* surface) const {
  return !delegate_ || delegate_->IsInputEnabled(surface);
}

bool Surface::HasHitTestRegion() const {
  return !hit_test_region_.IsEmpty();
}

bool Surface::HitTest(const gfx::Point& point) const {
  return hit_test_region_.Contains(point);
}

void Surface::GetHitTestMask(SkPath* mask) const {
  hit_test_region_.GetBoundaryPath(mask);
}

void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) {
  DCHECK(!delegate_ || !delegate);
  delegate_ = delegate;
}

bool Surface::HasSurfaceDelegate() const {
  return !!delegate_;
}

void Surface::AddSurfaceObserver(SurfaceObserver* observer) {
  observers_.AddObserver(observer);
}

void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) {
  observers_.RemoveObserver(observer);
}

bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const {
  return observers_.HasObserver(observer);
}

std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const {
  std::unique_ptr<base::trace_event::TracedValue> value(
      new base::trace_event::TracedValue());
  value->SetString("name", window_->layer()->name());
  return value;
}

bool Surface::IsStylusOnly() {
  return window_->GetProperty(kStylusOnlyKey);
}

void Surface::SetStylusOnly() {
  window_->SetProperty(kStylusOnlyKey, true);
}

void Surface::SurfaceHierarchyResourcesLost() {
  // Update resource and full damage are needed for next frame.
  needs_update_resource_ = true;
  for (const auto& sub_surface : sub_surfaces_)
    sub_surface.first->SurfaceHierarchyResourcesLost();
}

bool Surface::FillsBoundsOpaquely() const {
  return !current_resource_has_alpha_ ||
         state_.basic_state.blend_mode == SkBlendMode::kSrc ||
         state_.basic_state.opaque_region.Contains(gfx::Rect(content_size_));
}

void Surface::SetOcclusionTracking(bool tracking) {
  pending_state_.basic_state.is_tracking_occlusion = tracking;
}

bool Surface::IsTrackingOcclusion() {
  return state_.basic_state.is_tracking_occlusion;
}

void Surface::SetSurfaceHierarchyContentBoundsForTest(
    const gfx::Rect& content_bounds) {
  surface_hierarchy_content_bounds_ = content_bounds;
}

////////////////////////////////////////////////////////////////////////////////
// Buffer, private:

Surface::State::State() {}

Surface::State::~State() = default;

bool Surface::State::operator==(const State& other) const {
  return other.opaque_region == opaque_region &&
         other.input_region == input_region &&
         other.buffer_scale == buffer_scale &&
         other.buffer_transform == buffer_transform &&
         other.viewport == viewport && other.crop == crop &&
         other.only_visible_on_secure_output == only_visible_on_secure_output &&
         other.blend_mode == blend_mode && other.alpha == alpha;
}

Surface::BufferAttachment::BufferAttachment() {}

Surface::BufferAttachment::~BufferAttachment() {
  if (buffer_)
    buffer_->OnDetach();
}

Surface::ExtendedState::ExtendedState() = default;

Surface::ExtendedState::~ExtendedState() = default;

Surface::BufferAttachment& Surface::BufferAttachment::operator=(
    BufferAttachment&& other) {
  if (buffer_)
    buffer_->OnDetach();
  buffer_ = other.buffer_;
  size_ = other.size_;
  other.buffer_ = base::WeakPtr<Buffer>();
  other.size_ = gfx::Size();
  return *this;
}

base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() {
  return buffer_;
}

const base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() const {
  return buffer_;
}

const gfx::Size& Surface::BufferAttachment::size() const {
  return size_;
}

void Surface::BufferAttachment::Reset(base::WeakPtr<Buffer> buffer) {
  size_ = gfx::Size();
  if (buffer) {
    buffer->OnAttach();
    size_ = buffer->GetSize();
  }
  if (buffer_)
    buffer_->OnDetach();
  buffer_ = buffer;
}

void Surface::UpdateResource(FrameSinkResourceManager* resource_manager) {
  DCHECK(needs_update_resource_);
  needs_update_resource_ = false;
  if (state_.buffer.buffer()) {
    if (state_.buffer.buffer()->ProduceTransferableResource(
            resource_manager, std::move(state_.acquire_fence),
            state_.basic_state.only_visible_on_secure_output,
            &current_resource_)) {
      current_resource_has_alpha_ =
          FormatHasAlpha(state_.buffer.buffer()->GetFormat());
      // Planar buffers are sampled as RGB. Technically, the driver is supposed
      // to preserve the colorspace, so we could still pass the primaries and
      // transfer function.  However, we don't actually pass the colorspace
      // to the driver, and it's unclear what drivers would actually do if we
      // did. So in effect, the colorspace is undefined.
      if (NumberOfPlanesForLinearBufferFormat(
              state_.buffer.buffer()->GetFormat()) > 1) {
        current_resource_.color_space = state_.basic_state.color_space;
      }
    } else {
      current_resource_.id = 0;
      // Use the buffer's size, so the AppendContentsToFrame() will append
      // a SolidColorDrawQuad with the buffer's size.
      current_resource_.size = state_.buffer.size();
      current_resource_has_alpha_ = false;
    }
  } else {
    current_resource_.id = 0;
    current_resource_.size = gfx::Size();
    current_resource_has_alpha_ = false;
  }
}

void Surface::UpdateBufferTransform(bool y_invert) {
  SkMatrix buffer_matrix;
  switch (state_.basic_state.buffer_transform) {
    case Transform::NORMAL:
      buffer_matrix.setIdentity();
      break;
    case Transform::ROTATE_90:
      buffer_matrix.setSinCos(-1, 0, 0.5f, 0.5f);
      break;
    case Transform::ROTATE_180:
      buffer_matrix.setSinCos(0, -1, 0.5f, 0.5f);
      break;
    case Transform::ROTATE_270:
      buffer_matrix.setSinCos(1, 0, 0.5f, 0.5f);
      break;
  }
  if (y_invert)
    buffer_matrix.preScale(1, -1, 0.5f, 0.5f);
  if (state_.basic_state.buffer_scale != 0)
    buffer_matrix.postScale(1.0f / state_.basic_state.buffer_scale,
                            1.0f / state_.basic_state.buffer_scale);
  buffer_transform_ = gfx::Transform(buffer_matrix);
}

void Surface::AppendContentsToFrame(const gfx::Point& origin,
                                    float device_scale_factor,
                                    viz::CompositorFrame* frame) {
  const std::unique_ptr<viz::CompositorRenderPass>& render_pass =
      frame->render_pass_list.back();
  gfx::Rect output_rect(origin, content_size_);
  gfx::Rect quad_rect(0, 0, 1, 1);

  // Surface bounds are in DIPs, but |damage_rect| and |output_rect| are in
  // pixels, so we need to scale by the |device_scale_factor|.
  gfx::Rect damage_rect = state_.damage.bounds();
  if (!damage_rect.IsEmpty()) {
    // Outset damage by 1 DIP to as damage is in surface coordinate space and
    // client might not be aware of |device_scale_factor| and the
    // scaling/filtering it requires.
    damage_rect.Inset(-1, -1);
    damage_rect += origin.OffsetFromOrigin();
    damage_rect.Intersect(output_rect);
    if (device_scale_factor <= 1) {
      render_pass->damage_rect.Union(gfx::ToEnclosingRect(
          gfx::ConvertRectToPixels(damage_rect, device_scale_factor)));
    } else {
      // The damage will eventually be rescaled by 1/device_scale_factor. Since
      // that scale factor is <1, taking the enclosed rect here means that that
      // rescaled RectF is <1px smaller than |damage_rect| in each dimension,
      // which makes the enclosing rect equal to |damage_rect|.
      gfx::RectF scaled_damage(damage_rect);
      scaled_damage.Scale(device_scale_factor);
      render_pass->damage_rect.Union(gfx::ToEnclosedRect(scaled_damage));
    }
  }
  state_.damage.Clear();

  gfx::PointF scale(content_size_.width(), content_size_.height());

  gfx::Vector2dF translate(0.0f, 0.0f);

  // Surface quads require the quad rect to be appropriately sized and need to
  // use the shared quad clip rect.
  if (get_current_surface_id_) {
    quad_rect = gfx::Rect(embedded_surface_size_);
    scale = gfx::PointF(1.0f, 1.0f);

    if (!state_.basic_state.crop.IsEmpty()) {
      // In order to crop an AxB rect to CxD we need to scale by A/C, B/D.
      // We achieve clipping by scaling it up and then drawing only in the
      // output rectangle.
      scale.Scale(content_size_.width() / state_.basic_state.crop.width(),
                  content_size_.height() / state_.basic_state.crop.height());

      auto offset = state_.basic_state.crop.origin().OffsetFromOrigin();
      translate =
          gfx::Vector2dF(-offset.x() * scale.x(), -offset.y() * scale.y());
    }
  } else {
    scale.Scale(state_.basic_state.buffer_scale);
  }

  // Compute the total transformation from post-transform buffer coordinates to
  // target coordinates.
  SkMatrix viewport_to_target_matrix;
  // Scale and offset the normalized space to fit the content size rectangle.
  viewport_to_target_matrix.setScale(scale.x(), scale.y());

  gfx::PointF target = gfx::PointF(origin) + translate;
  viewport_to_target_matrix.postTranslate(target.x(), target.y());
  // Convert from DPs to pixels.
  viewport_to_target_matrix.postScale(device_scale_factor, device_scale_factor);

  gfx::Transform quad_to_target_transform(buffer_transform_);
  quad_to_target_transform.ConcatTransform(
      gfx::Transform(viewport_to_target_matrix));

  bool are_contents_opaque =
      !current_resource_has_alpha_ ||
      state_.basic_state.blend_mode == SkBlendMode::kSrc ||
      state_.basic_state.opaque_region.Contains(output_rect);

  viz::SharedQuadState* quad_state =
      render_pass->CreateAndAppendSharedQuadState();

  quad_state->SetAll(quad_to_target_transform, quad_rect /*quad_layer_rect=*/,
                     quad_rect /*visible_quad_layer_rect=*/,
                     gfx::MaskFilterInfo() /*mask_filter_info=*/,
                     gfx::Rect() /*clip_rect=*/, false /*is_clipped=*/,
                     are_contents_opaque, state_.basic_state.alpha /*opacity=*/,
                     SkBlendMode::kSrcOver /*blend_mode=*/,
                     0 /*sorting_context_id=*/);
  quad_state->no_damage = damage_rect.IsEmpty();

  if (current_resource_.id) {
    gfx::RectF uv_crop(gfx::SizeF(1, 1));
    if (!state_.basic_state.crop.IsEmpty()) {
      // The crop rectangle is a post-transformation rectangle. To get the UV
      // coordinates, we need to convert it to normalized buffer coordinates and
      // pass them through the inverse of the buffer transformation.
      uv_crop = gfx::RectF(state_.basic_state.crop);
      gfx::Size transformed_buffer_size(ToTransformedSize(
          current_resource_.size, state_.basic_state.buffer_transform));
      if (!transformed_buffer_size.IsEmpty())
        uv_crop.Scale(1.f / transformed_buffer_size.width(),
                      1.f / transformed_buffer_size.height());

      buffer_transform_.TransformRectReverse(&uv_crop);
    }

    SkColor background_color = SK_ColorTRANSPARENT;
    if (current_resource_has_alpha_ && are_contents_opaque)
      background_color = SK_ColorBLACK;  // Avoid writing alpha < 1

    // If this surface is being replaced by a SurfaceId emit a SurfaceDrawQuad.
    if (get_current_surface_id_) {
      auto current_surface_id = get_current_surface_id_.Run();
      // If the surface ID is valid update it, otherwise keep showing the old
      // one for now.
      if (current_surface_id.is_valid()) {
        latest_embedded_surface_id_ = current_surface_id;
        if (!current_surface_id.HasSameEmbedTokenAs(
                first_embedded_surface_id_)) {
          first_embedded_surface_id_ = current_surface_id;
        }
      }
      if (latest_embedded_surface_id_.is_valid() &&
          !embedded_surface_size_.IsEmpty()) {
        if (!state_.basic_state.crop.IsEmpty()) {
          quad_state->is_clipped = true;
          quad_state->clip_rect = output_rect;
        }
        viz::SurfaceDrawQuad* surface_quad =
            render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
        surface_quad->SetNew(quad_state, quad_rect, quad_rect,
                             viz::SurfaceRange(first_embedded_surface_id_,
                                               latest_embedded_surface_id_),
                             background_color,
                             /*stretch_content_to_fill_bounds=*/false);
      }
      // A resource was still produced for this so we still need to release it
      // later.
      frame->resource_list.push_back(current_resource_);
    } else if (state_.basic_state.alpha) {
      // Texture quad is only needed if buffer is not fully transparent.
      viz::TextureDrawQuad* texture_quad =
          render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
      float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
      texture_quad->SetNew(
          quad_state, quad_rect, quad_rect,
          /* needs_blending=*/!are_contents_opaque, current_resource_.id,
          /* premultiplied_alpha=*/true, uv_crop.origin(),
          uv_crop.bottom_right(), background_color, vertex_opacity,
          /* y_flipped=*/false, /* nearest_neighbor=*/false,
          state_.basic_state.only_visible_on_secure_output,
          gfx::ProtectedVideoType::kClear);
      if (current_resource_.is_overlay_candidate)
        texture_quad->set_resource_size_in_pixels(current_resource_.size);
      frame->resource_list.push_back(current_resource_);
    }
  } else {
    viz::SolidColorDrawQuad* solid_quad =
        render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
    solid_quad->SetNew(quad_state, quad_rect, quad_rect, SK_ColorBLACK,
                       false /* force_anti_aliasing_off */);
  }
}

void Surface::UpdateContentSize() {
  gfx::Size content_size;
  if (!state_.basic_state.viewport.IsEmpty()) {
    content_size = state_.basic_state.viewport;
  } else if (!state_.basic_state.crop.IsEmpty()) {
    DLOG_IF(WARNING, !base::IsValueInRangeForNumericType<int>(
                         state_.basic_state.crop.width()) ||
                         !base::IsValueInRangeForNumericType<int>(
                             state_.basic_state.crop.height()))
        << "Crop rectangle size (" << state_.basic_state.crop.size().ToString()
        << ") most be expressible using integers when viewport is not set";
    content_size = gfx::ToCeiledSize(state_.basic_state.crop.size());
  } else {
    content_size = gfx::ToCeiledSize(gfx::ScaleSize(
        gfx::SizeF(ToTransformedSize(state_.buffer.size(),
                                     state_.basic_state.buffer_transform)),
        1.0f / state_.basic_state.buffer_scale));
  }

  // Enable/disable sub-surface based on if it has contents.
  if (has_contents())
    window_->Show();
  else
    window_->Hide();

  if (content_size_ != content_size) {
    content_size_ = content_size;
    window_->SetBounds(gfx::Rect(window_->bounds().origin(), content_size_));

    for (SurfaceObserver& observer : observers_)
      observer.OnContentSizeChanged(this);
  }
}

void Surface::OnWindowOcclusionChanged() {
  if (!state_.basic_state.is_tracking_occlusion)
    return;

  for (SurfaceObserver& observer : observers_)
    observer.OnWindowOcclusionChanged(this);
}

}  // namespace exo
