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

#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/service/surfaces/surface_manager.h"
#include "components/viz/test/begin_frame_args_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/test/context_factories_for_test.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
#include "ui/compositor/test/in_process_context_factory.h"

using testing::Mock;
using testing::_;

namespace ui {
namespace {

class CompositorTest : public testing::Test {
 public:
  CompositorTest() {}
  ~CompositorTest() override {}

  void SetUp() override {
    ui::ContextFactory* context_factory = nullptr;
    ui::ContextFactoryPrivate* context_factory_private = nullptr;
    ui::InitializeContextFactoryForTests(false, &context_factory,
                                         &context_factory_private);

    compositor_.reset(new ui::Compositor(
        context_factory_private->AllocateFrameSinkId(), context_factory,
        context_factory_private, CreateTaskRunner(),
        false /* enable_surface_synchronization */,
        false /* enable_pixel_canvas */));
    compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
  }

  void TearDown() override {
    compositor_.reset();
    ui::TerminateContextFactoryForTests();
  }

  void DestroyCompositor() { compositor_.reset(); }

 protected:
  virtual scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() = 0;

  ui::Compositor* compositor() { return compositor_.get(); }

 private:
  std::unique_ptr<ui::Compositor> compositor_;

  DISALLOW_COPY_AND_ASSIGN(CompositorTest);
};

// For tests that control time.
class CompositorTestWithMockedTime : public CompositorTest {
 protected:
  scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
    task_runner_ = new base::TestMockTimeTaskRunner;
    return task_runner_;
  }

  base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }

 protected:
  scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
};

// For tests that run on a real MessageLoop with real time.
class CompositorTestWithMessageLoop : public CompositorTest {
 protected:
  scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
    task_runner_ = base::ThreadTaskRunnerHandle::Get();
    return task_runner_;
  }

  base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }

 private:
  scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};

class CompositorObserverForLocks : public CompositorObserver {
 public:
  CompositorObserverForLocks() = default;

  void OnCompositingDidCommit(Compositor* compositor) override {}
  void OnCompositingStarted(Compositor* compositor,
                            base::TimeTicks start_time) override {}
  void OnCompositingEnded(Compositor* compositor) override {}
  void OnCompositingLockStateChanged(Compositor* compositor) override {
    changed_ = true;
    locked_ = compositor->IsLocked();
  }
  void OnCompositingChildResizing(Compositor* compositor) override {}

  void OnCompositingShuttingDown(Compositor* compositor) override {}

  bool changed() const { return changed_; }
  bool locked() const { return locked_; }

  void Reset() { changed_ = false; }

 private:
  bool changed_ = false;
  bool locked_ = false;
};

}  // namespace

TEST_F(CompositorTestWithMessageLoop, OutputColorMatrix) {
  auto root_layer = std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
  root_layer->SetBounds(gfx::Rect(10, 10));
  compositor()->SetRootLayer(root_layer.get());
  compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10), viz::LocalSurfaceId());
  DCHECK(compositor()->IsVisible());

  // Set a non-identity color matrix on the compistor display, and expect it to
  // be set on the context factory.
  SkMatrix44 color_matrix(SkMatrix44::kIdentity_Constructor);
  color_matrix.set(1, 1, 0.7f);
  color_matrix.set(2, 2, 0.4f);
  compositor()->SetDisplayColorMatrix(color_matrix);
  InProcessContextFactory* context_factory_private =
      static_cast<InProcessContextFactory*>(
          compositor()->context_factory_private());
  compositor()->ScheduleDraw();
  DrawWaiterForTest::WaitForCompositingEnded(compositor());
  EXPECT_EQ(color_matrix,
            context_factory_private->GetOutputColorMatrix(compositor()));

  // Simulate a lost context by releasing the output surface and setting it on
  // the compositor again. Expect that the same color matrix will be set again
  // on the context factory.
  context_factory_private->ResetOutputColorMatrixToIdentity(compositor());
  compositor()->SetVisible(false);
  EXPECT_EQ(gfx::kNullAcceleratedWidget,
            compositor()->ReleaseAcceleratedWidget());
  compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
  compositor()->SetVisible(true);
  compositor()->ScheduleDraw();
  DrawWaiterForTest::WaitForCompositingEnded(compositor());
  EXPECT_EQ(color_matrix,
            context_factory_private->GetOutputColorMatrix(compositor()));
  compositor()->SetRootLayer(nullptr);
}

TEST_F(CompositorTestWithMockedTime, LocksAreObserved) {
  std::unique_ptr<CompositorLock> lock;

  CompositorObserverForLocks observer;
  compositor()->AddObserver(&observer);

  EXPECT_FALSE(observer.changed());

  lock = compositor()->GetCompositorLock(nullptr, base::TimeDelta());
  // The observer see that locks changed and that the compositor is locked
  // at the time.
  EXPECT_TRUE(observer.changed());
  EXPECT_TRUE(observer.locked());

  observer.Reset();
  EXPECT_FALSE(observer.changed());

  lock = nullptr;
  // The observer see that locks changed and that the compositor is not locked
  // at the time.
  EXPECT_TRUE(observer.changed());
  EXPECT_FALSE(observer.locked());

  compositor()->RemoveObserver(&observer);
}

TEST_F(CompositorTestWithMockedTime,
       ReleaseWidgetWithOutputSurfaceNeverCreated) {
  compositor()->SetVisible(false);
  EXPECT_EQ(gfx::kNullAcceleratedWidget,
            compositor()->ReleaseAcceleratedWidget());
  compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
  compositor()->SetVisible(true);
}

#if defined(OS_WIN)
// TODO(crbug.com/608436): Flaky on windows trybots
#define MAYBE_CreateAndReleaseOutputSurface \
  DISABLED_CreateAndReleaseOutputSurface
#else
#define MAYBE_CreateAndReleaseOutputSurface CreateAndReleaseOutputSurface
#endif
TEST_F(CompositorTestWithMessageLoop, MAYBE_CreateAndReleaseOutputSurface) {
  std::unique_ptr<Layer> root_layer(new Layer(ui::LAYER_SOLID_COLOR));
  root_layer->SetBounds(gfx::Rect(10, 10));
  compositor()->SetRootLayer(root_layer.get());
  compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10), viz::LocalSurfaceId());
  DCHECK(compositor()->IsVisible());
  compositor()->ScheduleDraw();
  DrawWaiterForTest::WaitForCompositingEnded(compositor());
  compositor()->SetVisible(false);
  EXPECT_EQ(gfx::kNullAcceleratedWidget,
            compositor()->ReleaseAcceleratedWidget());
  compositor()->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
  compositor()->SetVisible(true);
  compositor()->ScheduleDraw();
  DrawWaiterForTest::WaitForCompositingEnded(compositor());
  compositor()->SetRootLayer(nullptr);
}

}  // namespace ui
