// Copyright 2018 The Fuchsia 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 <errno.h>
#include <fcntl.h>
#include <fuchsia/sysinfo/llcpp/fidl.h>
#include <fuchsia/sysmem/llcpp/fidl.h>
#include <lib/fidl/cpp/message.h>
#include <lib/fzl/fdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/pixelformat.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <memory>

#include <fbl/algorithm.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>

#include "display.h"
#include "fuchsia/hardware/display/llcpp/fidl.h"
#include "lib/fdio/directory.h"
#include "lib/fzl/vmo-mapper.h"
#include "virtual-layer.h"

namespace fhd = ::llcpp::fuchsia::hardware::display;
namespace sysmem = ::llcpp::fuchsia::sysmem;
namespace sysinfo = ::llcpp::fuchsia::sysinfo;

static zx_handle_t device_handle;
static std::unique_ptr<fhd::Controller::SyncClient> dc;
static bool has_ownership;

constexpr uint64_t kEventId = 13;
constexpr uint32_t kCollectionId = 12;
uint64_t capture_id = 0;
zx::event client_event_;
std::unique_ptr<sysmem::BufferCollection::SyncClient> collection_;
zx::vmo capture_vmo;

enum TestBundle {
  SIMPLE = 0,  // BUNDLE0
  FLIP,        // BUNDLE1
  INTEL,       // BUNDLE2
  BUNDLE3,
  BUNDLE_COUNT,
};

enum Platforms {
  INTEL_PLATFORM = 0,
  AMLOGIC_PLATFORM,
  MEDIATEK_PLATFORM,
  AEMU_PLATFORM,
  QEMU_PLATFORM,
  UNKNOWN_PLATFORM,
  PLATFORM_COUNT,
};

Platforms platform = UNKNOWN_PLATFORM;

static bool wait_for_driver_event(zx_time_t deadline) {
  zx_handle_t observed;
  uint32_t signals = ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED;
  if (zx_object_wait_one(dc->channel().get(), signals, ZX_TIME_INFINITE, &observed) != ZX_OK) {
    printf("Wait failed\n");
    return false;
  }
  if (observed & ZX_CHANNEL_PEER_CLOSED) {
    printf("Display controller died\n");
    return false;
  }
  return true;
}

static bool bind_display(const char* controller, fbl::Vector<Display>* displays) {
  printf("Opening controller\n");
  fbl::unique_fd fd(open(controller, O_RDWR));
  if (!fd) {
    printf("Failed to open display controller (%d)\n", errno);
    return false;
  }

  zx::channel device_server, device_client;
  zx_status_t status = zx::channel::create(0, &device_server, &device_client);
  if (status != ZX_OK) {
    printf("Failed to create device channel %d (%s)\n", status, zx_status_get_string(status));
    return false;
  }

  zx::channel dc_server, dc_client;
  status = zx::channel::create(0, &dc_server, &dc_client);
  if (status != ZX_OK) {
    printf("Failed to create controller channel %d (%s)\n", status, zx_status_get_string(status));
    return false;
  }

  fzl::FdioCaller caller(std::move(fd));
  auto open_response = fhd::Provider::Call::OpenController(
      caller.channel(), std::move(device_server), std::move(dc_server));
  if (!open_response.ok()) {
    printf("Failed to call service handle %d (%s)\n", open_response.status(),
           open_response.error());
    return false;
  }
  if (open_response->s != ZX_OK) {
    printf("Failed to open controller %d (%s)\n", open_response->s,
           zx_status_get_string(open_response->s));
    return false;
  }

  dc = std::make_unique<fhd::Controller::SyncClient>(std::move(dc_client));
  device_handle = device_client.release();

  uint8_t byte_buffer[ZX_CHANNEL_MAX_MSG_BYTES];
  fidl::Message msg(fidl::BytePart(byte_buffer, ZX_CHANNEL_MAX_MSG_BYTES), fidl::HandlePart());
  while (displays->is_empty()) {
    printf("Waiting for display\n");
    if (ZX_OK !=
        dc->HandleEvents({
            .displays_changed =
                [&displays](::fidl::VectorView<fhd::Info> added,
                            ::fidl::VectorView<uint64_t> removed) {
                  for (size_t i = 0; i < added.count(); i++) {
                    displays->push_back(Display(added[i]));
                  }
                  return ZX_OK;
                },
            .vsync = [](uint64_t display_id, uint64_t timestamp,
                        ::fidl::VectorView<uint64_t> images) { return ZX_ERR_INVALID_ARGS; },
            .client_ownership_change =
                [](bool owns) {
                  has_ownership = owns;
                  return ZX_OK;
                },
            .unknown = []() { return ZX_ERR_STOP; },
        })) {
      printf("Got unexpected message\n");
      return false;
    }
  }

  if (!dc->EnableVsync(true).ok()) {
    printf("Failed to enable vsync\n");
    return false;
  }

  return true;
}

Display* find_display(fbl::Vector<Display>& displays, const char* id_str) {
  uint64_t id = strtoul(id_str, nullptr, 10);
  if (id != 0) {  // 0 is the invalid id, and luckily what strtoul returns on failure
    for (auto& d : displays) {
      if (d.id() == id) {
        return &d;
      }
    }
  }
  return nullptr;
}

bool update_display_layers(const fbl::Vector<std::unique_ptr<VirtualLayer>>& layers,
                           const Display& display, fbl::Vector<uint64_t>* current_layers) {
  fbl::Vector<uint64_t> new_layers;

  for (auto& layer : layers) {
    uint64_t id = layer->id(display.id());
    if (id != fhd::invalidId) {
      new_layers.push_back(id);
    }
  }

  bool layer_change = new_layers.size() != current_layers->size();
  if (!layer_change) {
    for (unsigned i = 0; i < new_layers.size(); i++) {
      if (new_layers[i] != (*current_layers)[i]) {
        layer_change = true;
        break;
      }
    }
  }

  if (layer_change) {
    current_layers->swap(new_layers);
    if (!dc->SetDisplayLayers(display.id(), {current_layers->data(), current_layers->size()})
             .ok()) {
      printf("Failed to set layers\n");
      return false;
    }
  }
  return true;
}

bool apply_config() {
  auto result = dc->CheckConfig(false);
  if (!result.ok()) {
    printf("Failed to make check call: %d (%s)\n", result.status(), result.error());
    return false;
  }

  if (result->res != fhd::ConfigResult::OK) {
    printf("Config not valid (%d)\n", static_cast<uint32_t>(result->res));
    for (const auto& op : result->ops) {
      printf("Client composition op (display %ld, layer %ld): %hhu\n", op.display_id, op.layer_id,
             static_cast<uint8_t>(op.opcode));
    }
    return false;
  }

  if (!dc->ApplyConfig().ok()) {
    printf("Apply failed\n");
    return false;
  }
  return true;
}

zx_status_t wait_for_vsync(const fbl::Vector<std::unique_ptr<VirtualLayer>>& layers) {
  fhd::Controller::EventHandlers handlers = {
      .displays_changed =
          [](::fidl::VectorView<fhd::Info>, ::fidl::VectorView<uint64_t>) {
            printf("Display disconnected\n");
            return ZX_ERR_STOP;
          },
      .vsync =
          [&layers](uint64_t display_id, uint64_t timestamp, ::fidl::VectorView<uint64_t> images) {
            for (auto& layer : layers) {
              uint64_t id = layer->image_id(display_id);
              if (id == 0) {
                continue;
              }
              for (auto image_id : images) {
                if (image_id == id) {
                  layer->set_frame_done(display_id);
                }
              }
            }

            for (auto& layer : layers) {
              if (!layer->is_done()) {
                return ZX_ERR_NEXT;
              }
            }
            return ZX_OK;
          },
      .client_ownership_change =
          [](bool owned) {
            has_ownership = owned;
            return ZX_ERR_NEXT;
          },
      .unknown = []() { return ZX_ERR_STOP; },
  };
  return dc->HandleEvents(std::move(handlers));
}

zx_status_t capture_setup() {
  // TODO(41413): Pull common image setup code into a library

  // First make sure capture is supported on this platform
  auto support_resp = dc->IsCaptureSupported();
  if (!support_resp.value().result.response().supported) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  // Import event used to get notified once capture is completed
  auto status = zx::event::create(0, &client_event_);
  if (status != ZX_OK) {
    printf("Could not create event %d\n", status);
    return status;
  }
  zx::event e2;
  status = client_event_.duplicate(ZX_RIGHT_SAME_RIGHTS, &e2);
  if (status != ZX_OK) {
    printf("Could not dupicate event %d\n", status);
    return status;
  }
  auto event_status = dc->ImportEvent(std::move(e2), kEventId);
  if (event_status.status() != ZX_OK) {
    printf("Could not import event: %s\n", event_status.error());
    return event_status.status();
  }

  // get connection to sysmem
  zx::channel sysmem_server_channel;
  zx::channel sysmem_client_channel;
  status = zx::channel::create(0, &sysmem_server_channel, &sysmem_client_channel);
  if (status != ZX_OK) {
    printf("Could not create sysmem channel %d\n", status);
    return status;
  }
  status = fdio_service_connect("/svc/fuchsia.sysmem.Allocator", sysmem_server_channel.release());
  if (status != ZX_OK) {
    printf("Could not connect to sysmem Allocator %d\n", status);
    return status;
  }
  std::unique_ptr<sysmem::Allocator::SyncClient> sysmem_allocator;
  sysmem_allocator =
      std::make_unique<sysmem::Allocator::SyncClient>(std::move(sysmem_client_channel));

  // Create and import token
  zx::channel token_server;
  zx::channel token_client;
  status = zx::channel::create(0, &token_server, &token_client);
  if (status != ZX_OK) {
    printf("Could not create token channel %d\n", status);
    return status;
  }
  std::unique_ptr<sysmem::BufferCollectionToken::SyncClient> token =
      std::make_unique<sysmem::BufferCollectionToken::SyncClient>(std::move(token_client));

  // pass token server to sysmem allocator
  auto alloc_status = sysmem_allocator->AllocateSharedCollection(std::move(token_server));
  if (alloc_status.status() != ZX_OK) {
    printf("Could not pass token to sysmem allocator: %s\n", alloc_status.error());
    return alloc_status.status();
  }

  // duplicate the token and pass to display driver
  zx::channel token_dup_client;
  zx::channel token_dup_server;
  status = zx::channel::create(0, &token_dup_server, &token_dup_client);
  if (status != ZX_OK) {
    printf("Could not create duplicate token channel %d\n", status);
    return status;
  }
  sysmem::BufferCollectionToken::SyncClient display_token(std::move(token_dup_client));
  auto dup_res = token->Duplicate(ZX_RIGHT_SAME_RIGHTS, std::move(token_dup_server));
  if (dup_res.status() != ZX_OK) {
    printf("Could not duplicate token: %s\n", dup_res.error());
    return dup_res.status();
  }
  token->Sync();
  auto import_resp =
      dc->ImportBufferCollection(kCollectionId, std::move(*display_token.mutable_channel()));
  if (import_resp.status() != ZX_OK) {
    printf("Could not import token: %s\n", import_resp.error());
    return import_resp.status();
  }

  // set buffer constraints
  fhd::ImageConfig image_config = {};
  image_config.type = fhd::typeCapture;
  auto constraints_resp = dc->SetBufferCollectionConstraints(kCollectionId, image_config);
  if (constraints_resp.status() != ZX_OK) {
    printf("Could not set capture constraints %s\n", constraints_resp.error());
    return constraints_resp.status();
  }

  // setup our our constraints for buffer to be allocated
  zx::channel collection_client;
  zx::channel collection_server;
  status = zx::channel::create(0, &collection_server, &collection_client);
  if (status != ZX_OK) {
    printf("Could not create collection channel %d\n", status);
    return status;
  }
  // let's return token
  auto bind_resp = sysmem_allocator->BindSharedCollection(std::move(*token->mutable_channel()),
                                                          std::move(collection_server));
  if (bind_resp.status() != ZX_OK) {
    printf("Could not bind to shared collection: %s\n", bind_resp.error());
    return bind_resp.status();
  }

  // finally setup our constraints
  sysmem::BufferCollectionConstraints constraints = {};
  constraints.usage.cpu = sysmem::cpuUsageReadOften | sysmem::cpuUsageWriteOften;
  constraints.min_buffer_count_for_camping = 1;
  constraints.has_buffer_memory_constraints = false;
  constraints.image_format_constraints_count = 1;
  sysmem::ImageFormatConstraints& image_constraints = constraints.image_format_constraints[0];
  image_constraints.pixel_format.type = sysmem::PixelFormatType::BGRA32;
  image_constraints.color_spaces_count = 1;
  image_constraints.color_space[0] = sysmem::ColorSpace{
      .type = sysmem::ColorSpaceType::SRGB,
  };
  image_constraints.min_coded_width = 0;
  image_constraints.max_coded_width = std::numeric_limits<uint32_t>::max();
  image_constraints.min_coded_height = 0;
  image_constraints.max_coded_height = std::numeric_limits<uint32_t>::max();
  image_constraints.min_bytes_per_row = 0;
  image_constraints.max_bytes_per_row = std::numeric_limits<uint32_t>::max();
  image_constraints.max_coded_width_times_coded_height = std::numeric_limits<uint32_t>::max();
  image_constraints.layers = 1;
  image_constraints.coded_width_divisor = 1;
  image_constraints.coded_height_divisor = 1;
  image_constraints.bytes_per_row_divisor = 1;
  image_constraints.start_offset_divisor = 1;
  image_constraints.display_width_divisor = 1;
  image_constraints.display_height_divisor = 1;

  collection_ =
      std::make_unique<sysmem::BufferCollection::SyncClient>(std::move(collection_client));
  auto collection_resp = collection_->SetConstraints(true, constraints);
  if (collection_resp.status() != ZX_OK) {
    printf("Could not set buffer constraints: %s\n", collection_resp.error());
    return collection_resp.status();
  }

  // wait for allocation
  auto wait_resp = collection_->WaitForBuffersAllocated();
  if (wait_resp.status() != ZX_OK) {
    printf("Wait for buffer allocation failed: %s\n", wait_resp.error());
    return wait_resp.status();
  }

  capture_vmo = std::move(wait_resp.value().buffer_collection_info.buffers[0].vmo);
  // import image for capture
  fhd::ImageConfig capture_cfg = {};  // will contain a handle
  auto importcap_resp = dc->ImportImageForCapture(capture_cfg, kCollectionId, 0);
  if (importcap_resp.status() != ZX_OK) {
    printf("Failed to start capture: %s\n", importcap_resp.error());
    return importcap_resp.status();
  }
  capture_id = importcap_resp.value().result.response().image_id;

  return ZX_OK;
}

zx_status_t capture_start() {
  // start capture
  auto capstart_resp = dc->StartCapture(kEventId, capture_id);
  if (capstart_resp.status() != ZX_OK) {
    printf("Could not start capture: %s\n", capstart_resp.error());
    return capstart_resp.status();
  }
  // wait for capture to complete
  uint32_t observed;
  auto event_res =
      client_event_.wait_one(ZX_EVENT_SIGNALED, zx::deadline_after(zx::sec(1)), &observed);
  if (event_res == ZX_OK) {
    client_event_.signal(ZX_EVENT_SIGNALED, 0);
  } else {
    printf("capture failed %d\n", event_res);
    return event_res;
  }
  return ZX_OK;
}

bool capture_compare(void* image_buf) {
  if (image_buf == nullptr) {
    printf("%s: null buf\n", __func__);
    return false;
  }
  fzl::VmoMapper mapped_capture_vmo;
  size_t capture_vmo_size;
  auto status = capture_vmo.get_size(&capture_vmo_size);
  if (status != ZX_OK) {
    printf("capture vmo get size failed %d\n", status);
    return status;
  }
  status =
      mapped_capture_vmo.Map(capture_vmo, 0, capture_vmo_size, ZX_VM_PERM_READ | ZX_VM_PERM_WRITE);
  if (status != ZX_OK) {
    printf("Could not map capture vmo %d\n", status);
    return status;
  }
  return (!memcmp(image_buf, mapped_capture_vmo.start(), capture_vmo_size));
}

void capture_release() {
  dc->ReleaseCapture(capture_id);
  dc->ReleaseBufferCollection(kCollectionId);
}

void usage(void) {
  printf(
      "Usage: display-test [OPTIONS]\n\n"
      "--controller N   : open controller N [/dev/class/display-controller/N]\n"
      "--dump           : print properties of attached display\n"
      "--mode-set D N   : Set Display D to mode N (use dump option for choices)\n"
      "--format-set D N : Set Display D to format N (use dump option for choices)\n"
      "--grayscale      : Display images in grayscale mode (default off)\n"
      "--num-frames N   : Run test in N number of frames (default 120)\n"
      "--delay N        : Add delay (ms) between Vsync complete and next configuration\n"
      "--capture        : Capture each display frame and verify\n"
      "\nTest Modes:\n\n"
      "--bundle N       : Run test from test bundle N as described below\n\n"
      "                   bundle %d: Display a single pattern using single buffer\n"
      "                   bundle %d: Flip between two buffers to display a pattern\n"
      "                   bundle %d: Run the standard Intel-based display tests. This includes\n"
      "                             hardware composition of 1 color layer and 3 primary layers.\n"
      "                             The tests include alpha blending, translation, scaling\n"
      "                             and rotation\n"
      "                   bundle %d: 4 layer hardware composition with alpha blending\n"
      "                             and image translation\n"
      "                   (default: bundle %d)\n\n"
      "--help           : Show this help message\n",
      SIMPLE, FLIP, INTEL, BUNDLE3, INTEL);
}

Platforms GetPlatform() {
  zx::channel sysinfo_server_channel, sysinfo_client_channel;
  auto status = zx::channel::create(0, &sysinfo_server_channel, &sysinfo_client_channel);
  if (status != ZX_OK) {
    return UNKNOWN_PLATFORM;
  }

  const char* sysinfo_path = "dev/misc/sysinfo";
  fbl::unique_fd sysinfo_fd(open(sysinfo_path, O_RDWR));
  if (!sysinfo_fd) {
    return UNKNOWN_PLATFORM;
  }
  fzl::FdioCaller caller_sysinfo(std::move(sysinfo_fd));
  auto result = sysinfo::Device::Call::GetBoardName(caller_sysinfo.channel());
  if (!result.ok() || result.value().status != ZX_OK) {
    return UNKNOWN_PLATFORM;
  }

  printf("Found board %s\n", result.value().name.data());

  if (!strcmp(result.value().name.data(), "pc") ||
      !strcmp(result.value().name.data(), "chromebook-x64") ||
      !strcmp(result.value().name.data(), "Eve") ||
      strstr(result.value().name.data(), "Nocturne")) {
    return INTEL_PLATFORM;
  }
  if (!strcmp(result.value().name.data(), "astro") ||
      !strcmp(result.value().name.data(), "sherlock") ||
      !strcmp(result.value().name.data(), "vim2")) {
    return AMLOGIC_PLATFORM;
  }
  if (!strcmp(result.value().name.data(), "cleo") ||
      !strcmp(result.value().name.data(), "mt8167s_ref")) {
    return MEDIATEK_PLATFORM;
  }
  if (!strcmp(result.value().name.data(), "qemu") ||
      !strcmp(result.value().name.data(), "Standard PC (Q35 + ICH9, 2009)")) {
    return QEMU_PLATFORM;
  }
  return UNKNOWN_PLATFORM;
}

int main(int argc, const char* argv[]) {
  printf("Running display test\n");

  fbl::Vector<Display> displays;
  fbl::Vector<fbl::Vector<uint64_t>> display_layers;
  fbl::Vector<std::unique_ptr<VirtualLayer>> layers;
  int32_t num_frames = 120;  // default to 120 frames
  int32_t delay = 0;
  bool capture = false;
  bool verify_capture = false;
  const char* controller = "/dev/class/display-controller/000";

  platform = GetPlatform();

  TestBundle testbundle;
  switch (platform) {
    case INTEL_PLATFORM:
      testbundle = INTEL;
      break;
    case AMLOGIC_PLATFORM:
      testbundle = FLIP;
      break;
    case MEDIATEK_PLATFORM:
      testbundle = BUNDLE3;
      break;
    default:
      testbundle = SIMPLE;
  }

  for (int i = 1; i < argc - 1; i++) {
    if (!strcmp(argv[i], "--controller")) {
      controller = argv[i + 1];
      break;
    }
  }

  if (!bind_display(controller, &displays)) {
    return -1;
  }

  if (displays.is_empty()) {
    printf("No displays available\n");
    return 0;
  }

  for (unsigned i = 0; i < displays.size(); i++) {
    display_layers.push_back(fbl::Vector<uint64_t>());
  }

  argc--;
  argv++;

  while (argc) {
    if (strcmp(argv[0], "--dump") == 0) {
      for (auto& display : displays) {
        display.Dump();
      }
      return 0;
    } else if (strcmp(argv[0], "--mode-set") == 0 || strcmp(argv[0], "--format-set") == 0) {
      Display* display = find_display(displays, argv[1]);
      if (!display) {
        printf("Invalid display \"%s\" for %s\n", argv[1], argv[0]);
        return -1;
      }
      if (strcmp(argv[0], "--mode-set") == 0) {
        if (!display->set_mode_idx(atoi(argv[2]))) {
          printf("Invalid mode id\n");
          return -1;
        }
      } else {
        if (!display->set_format_idx(atoi(argv[2]))) {
          printf("Invalid format id\n");
          return -1;
        }
      }
      argv += 3;
      argc -= 3;
    } else if (strcmp(argv[0], "--grayscale") == 0) {
      for (auto& d : displays) {
        d.set_grayscale(true);
      }
      argv++;
      argc--;
    } else if (strcmp(argv[0], "--num-frames") == 0) {
      num_frames = atoi(argv[1]);
      argv += 2;
      argc -= 2;
    } else if (strcmp(argv[0], "--controller") == 0) {
      // We already processed this, skip it.
      argv += 2;
      argc -= 2;
    } else if (strcmp(argv[0], "--delay") == 0) {
      delay = atoi(argv[1]);
      argv += 2;
      argc -= 2;
    } else if (strcmp(argv[0], "--bundle") == 0) {
      testbundle = static_cast<TestBundle>(atoi(argv[1]));
      if (testbundle >= BUNDLE_COUNT || testbundle < 0) {
        printf("Invalid test bundle selected\n");
        usage();
        return -1;
      }
      argv += 2;
      argc -= 2;
    } else if (strcmp(argv[0], "--capture") == 0) {
      capture = true;
      verify_capture = true;
      argv += 1;
      argc -= 1;
    } else if (strcmp(argv[0], "--help") == 0) {
      usage();
      return 0;
    } else {
      printf("Unrecognized argument \"%s\"\n", argv[0]);
      usage();
      return -1;
    }
  }

  if (capture && capture_setup() != ZX_OK) {
    printf("Cound not setup capture\n");
    capture = false;
  }

  fbl::AllocChecker ac;
  if (testbundle == INTEL) {
    // Intel only supports 90/270 rotation for Y-tiled images, so enable it for testing.
    constexpr bool kIntelYTiling = true;

    // Color layer which covers all displays
    std::unique_ptr<ColorLayer> layer0 = fbl::make_unique_checked<ColorLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layers.push_back(std::move(layer0));

    // Layer which covers all displays and uses page flipping.
    std::unique_ptr<PrimaryLayer> layer1 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer1->SetLayerFlipping(true);
    layer1->SetAlpha(true, .75);
    layer1->SetIntelYTiling(kIntelYTiling);
    layers.push_back(std::move(layer1));

    // Layer which covers the left half of the of the first display
    // and toggles on and off every frame.
    std::unique_ptr<PrimaryLayer> layer2 =
        fbl::make_unique_checked<PrimaryLayer>(&ac, &displays[0]);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer2->SetImageDimens(displays[0].mode().horizontal_resolution / 2,
                           displays[0].mode().vertical_resolution);
    layer2->SetLayerToggle(true);
    layer2->SetScaling(true);
    layer2->SetIntelYTiling(kIntelYTiling);
    layers.push_back(std::move(layer2));

    // Intel only supports 3 layers, so add ifdef for quick toggling of the 3rd layer
#if 1
    // Layer which is smaller than the display and bigger than its image
    // and which animates back and forth across all displays and also
    // its src image and also rotates.
    std::unique_ptr<PrimaryLayer> layer3 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    // Width is the larger of disp_width/2, display_height/2, but we also need
    // to make sure that it's less than the smaller display dimension.
    uint32_t width = fbl::min(
        fbl::max(displays[0].mode().vertical_resolution / 2,
                 displays[0].mode().horizontal_resolution / 2),
        fbl::min(displays[0].mode().vertical_resolution, displays[0].mode().horizontal_resolution));
    uint32_t height = fbl::min(displays[0].mode().vertical_resolution / 2,
                               displays[0].mode().horizontal_resolution / 2);
    layer3->SetImageDimens(width * 2, height);
    layer3->SetDestFrame(width, height);
    layer3->SetSrcFrame(width, height);
    layer3->SetPanDest(true);
    layer3->SetPanSrc(true);
    layer3->SetRotates(true);
    layer3->SetIntelYTiling(kIntelYTiling);
    layers.push_back(std::move(layer3));
#else
    CursorLayer* layer4 = new CursorLayer(displays);
    layers.push_back(std::move(layer4));
#endif
  } else if (testbundle == BUNDLE3) {
    // Mediatek display test
    uint32_t width = displays[0].mode().horizontal_resolution;
    uint32_t height = displays[0].mode().vertical_resolution;
    std::unique_ptr<PrimaryLayer> layer1 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer1->SetAlpha(true, (float)0.2);
    layer1->SetImageDimens(width, height);
    layer1->SetSrcFrame(width / 2, height / 2);
    layer1->SetDestFrame(width / 2, height / 2);
    layer1->SetPanSrc(true);
    layer1->SetPanDest(true);
    layers.push_back(std::move(layer1));

    // Layer which covers the left half of the of the first display
    // and toggles on and off every frame.
    float alpha2 = (float)0.5;
    std::unique_ptr<PrimaryLayer> layer2 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer2->SetLayerFlipping(true);
    layer2->SetAlpha(true, alpha2);
    layers.push_back(std::move(layer2));

    float alpha3 = (float)0.2;
    std::unique_ptr<PrimaryLayer> layer3 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer3->SetAlpha(true, alpha3);
    layers.push_back(std::move(layer3));

    std::unique_ptr<PrimaryLayer> layer4 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer4->SetAlpha(true, (float)0.3);
    layers.push_back(std::move(layer4));
  } else if (testbundle == FLIP) {
    // Amlogic display test
    std::unique_ptr<PrimaryLayer> layer1 = fbl::make_unique_checked<PrimaryLayer>(&ac, displays);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }
    layer1->SetLayerFlipping(true);
    layers.push_back(std::move(layer1));
  } else if (testbundle == SIMPLE) {
    // Simple display test
    bool mirrors = true;
    std::unique_ptr<PrimaryLayer> layer1 =
        fbl::make_unique_checked<PrimaryLayer>(&ac, displays, mirrors);
    if (!ac.check()) {
      return ZX_ERR_NO_MEMORY;
    }

    layers.push_back(std::move(layer1));
  }

  printf("Initializing layers\n");
  for (auto& layer : layers) {
    if (!layer->Init(dc.get())) {
      printf("Layer init failed\n");
      return -1;
    }
  }

  for (auto& display : displays) {
    display.Init(dc.get());
  }

  if (capture && layers.size() > 1) {
    printf("Capture verification disabled for multi-layer display tests\n");
    verify_capture = false;
  }

  printf("Starting rendering\n");
  if (capture) {
    printf("Capturing every frame. Verification is %s\n", verify_capture ? "enabled" : "disabled");
  }
  bool capture_result = true;
  for (int i = 0; i < num_frames; i++) {
    for (auto& layer : layers) {
      // Step before waiting, since not every layer is used every frame
      // so we won't necessarily need to wait.
      layer->StepLayout(i);

      if (!layer->WaitForReady()) {
        printf("Buffer failed to become free\n");
        return -1;
      }

      layer->clear_done();
      layer->SendLayout(dc.get());
    }

    for (unsigned i = 0; i < displays.size(); i++) {
      if (!update_display_layers(layers, displays[i], &display_layers[i])) {
        return -1;
      }
    }

    // This delay is used to skew the timing between vsync and ApplyConfiguration
    // in order to observe any tearing effects
    zx_nanosleep(zx_deadline_after(ZX_MSEC(delay)));
    if (!apply_config()) {
      return -1;
    }

    for (auto& layer : layers) {
      layer->Render(i);
    }

    zx_status_t status;
    while ((status = wait_for_vsync(layers)) == ZX_ERR_NEXT) {
    }
    ZX_ASSERT(status == ZX_OK);
    if (capture) {
      // capture has been requested.
      status = capture_start();
      if (status != ZX_OK) {
        printf("Capture start failed %d\n", status);
        capture_release();
        capture = false;
        break;
      }
      if (verify_capture && !capture_compare(layers[0]->GetCurrentImageBuf())) {
        capture_result = false;
      }
    }
  }

  printf("Done rendering\n");

  if (capture) {
    printf("Capture completed\n");
    if (verify_capture) {
      if (capture_result) {
        printf("Capture Verification Passed\n");
      } else {
        printf("Capture Verification Failed!\n");
      }
    }
    capture_release();
  }
  zx_handle_close(device_handle);

  return 0;
}
