// 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 <fbl/algorithm.h>
#include <math.h>
#include <zircon/device/display-controller.h>

#include "utils.h"
#include "virtual-layer.h"

static constexpr uint32_t kSrcFrameBouncePeriod = 90;
static constexpr uint32_t kDestFrameBouncePeriod = 60;
static constexpr uint32_t kRotationPeriod = 24;
static constexpr uint32_t kScalePeriod = 45;

static uint32_t get_fg_color() {
    static uint32_t layer_count = 0;
    static uint32_t colors[] = {
        0xffff0000, 0xff00ff00, 0xff0000ff,
    };
    return colors[layer_count++ % fbl::count_of(colors)];
}

// Checks if two rectangles intersect, and if so, returns their intersection.
static bool compute_intersection(const frame_t& a, const frame_t& b, frame_t* intersection) {
    uint32_t left = fbl::max(a.x_pos, b.x_pos);
    uint32_t right = fbl::min(a.x_pos + a.width, b.x_pos + b.width);
    uint32_t top = fbl::max(a.y_pos, b.y_pos);
    uint32_t bottom = fbl::min(a.y_pos + a.height, b.y_pos + b.height);

    if (left >= right || top >= bottom) {
        return false;
    }

    intersection->x_pos = left;
    intersection->y_pos = top;
    intersection->width = right - left;
    intersection->height = bottom - top;

    return true;
}

static uint32_t interpolate_scaling(uint32_t x, uint32_t frame_num) {
    return x / 2 + interpolate(x / 2, frame_num, kScalePeriod);
}

VirtualLayer::VirtualLayer(Display* display) {
    displays_.push_back(display);
    width_ = display->mode().horizontal_resolution;
    height_ = display->mode().vertical_resolution;
}

VirtualLayer::VirtualLayer(const fbl::Vector<Display>& displays) {
    for (auto& d : displays) {
        displays_.push_back(&d);
    }

    width_ = 0;
    height_ = 0;
    for (auto* d : displays_) {
        width_ += d->mode().horizontal_resolution;
        height_ = fbl::max(height_, d->mode().vertical_resolution);
    }
}

layer_t* VirtualLayer::CreateLayer(zx_handle_t dc_handle) {
    layers_.push_back(layer_t());
    layers_[layers_.size() - 1].active = false;

    fuchsia_hardware_display_ControllerCreateLayerRequest create_layer_msg;
    create_layer_msg.hdr.ordinal = fuchsia_hardware_display_ControllerCreateLayerOrdinal;

    fuchsia_hardware_display_ControllerCreateLayerResponse create_layer_rsp;
    zx_channel_call_args_t call_args = {};
    call_args.wr_bytes = &create_layer_msg;
    call_args.rd_bytes = &create_layer_rsp;
    call_args.wr_num_bytes = sizeof(create_layer_msg);
    call_args.rd_num_bytes = sizeof(create_layer_rsp);
    uint32_t actual_bytes, actual_handles;
    if (zx_channel_call(dc_handle, 0, ZX_TIME_INFINITE, &call_args,
                        &actual_bytes, &actual_handles) != ZX_OK) {
        printf("Creating layer failed\n");
        return nullptr;
    }
    if (create_layer_rsp.res != ZX_OK) {
        printf("Creating layer failed\n");
        return nullptr;
    }
    layers_[layers_.size() - 1].id = create_layer_rsp.layer_id;

    return &layers_[layers_.size() - 1];
}

PrimaryLayer::PrimaryLayer(Display* display) : VirtualLayer(display) {
    image_format_ = display->format();
}

PrimaryLayer::PrimaryLayer(const fbl::Vector<Display>& displays) : VirtualLayer(displays) {
    image_format_ = displays_[0]->format();
    SetImageDimens(width_, height_);
}

bool PrimaryLayer::Init(zx_handle_t dc_handle) {
    if ((displays_.size() > 1 || rotates_) && scaling_) {
        printf("Unsupported config\n");
        return false;
    }
    uint32_t fg_color = get_fg_color();
    uint32_t bg_color = alpha_enable_ ? 0x3fffffff : 0xffffffff;

    images_[0] = Image::Create(
        dc_handle, image_width_, image_height_, image_format_, fg_color, bg_color,
        intel_y_tiling_);
    if (layer_flipping_) {
        images_[1] = Image::Create(
            dc_handle, image_width_, image_height_, image_format_, fg_color, bg_color,
            intel_y_tiling_);
    } else {
        images_[0]->Render(-1, -1);
    }

    if (!images_[0] || (layer_flipping_ && !images_[1])) {
        return false;
    }

    for (unsigned i = 0; i < displays_.size(); i++) {
        layer_t* layer = CreateLayer(dc_handle);
        if (layer == nullptr) {
            return false;
        }

        if (!images_[0]->Import(dc_handle, &layer->import_info[0])) {
            return false;
        }
        if (layer_flipping_) {
            if (!images_[1]->Import(dc_handle, &layer->import_info[1])) {
                return false;
            }
        } else {
            zx_object_signal(layer->import_info[alt_image_].events[WAIT_EVENT],
                             0, ZX_EVENT_SIGNALED);
        }

        fuchsia_hardware_display_ControllerSetLayerPrimaryConfigRequest config;
        config.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerPrimaryConfigOrdinal;
        config.layer_id = layer->id;
        images_[0]->GetConfig(&config.image_config);

        if (zx_channel_write(dc_handle, 0, &config, sizeof(config), nullptr, 0) != ZX_OK) {
            printf("Setting layer config failed\n");
            return false;
        }

        fuchsia_hardware_display_ControllerSetLayerPrimaryAlphaRequest alpha_config;
        alpha_config.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerPrimaryAlphaOrdinal;
        alpha_config.layer_id = layer->id;
        alpha_config.mode = alpha_enable_ ? fuchsia_hardware_display_AlphaMode_HW_MULTIPLY
                                          : fuchsia_hardware_display_AlphaMode_DISABLE;
        alpha_config.val = alpha_val_;

        if (zx_channel_write(dc_handle, 0,
                             &alpha_config, sizeof(alpha_config), nullptr, 0) != ZX_OK) {
            printf("Setting layer alpha config failed\n");
            return false;
        }
    }

    StepLayout(0);
    if (!layer_flipping_) {
        SetLayerImages(dc_handle, false);
    }
    if (!(pan_src_ || pan_dest_)) {
        SetLayerPositions(dc_handle);
    }

    return true;
}

void PrimaryLayer::StepLayout(int32_t frame_num) {
    if (layer_flipping_) {
        alt_image_ = frame_num % 2;
    }
    if (pan_src_) {
        src_frame_.x_pos =
                interpolate(image_width_ - src_frame_.width, frame_num, kSrcFrameBouncePeriod);

    }
    if (pan_dest_) {
        dest_frame_.x_pos =
                interpolate(width_ - dest_frame_.width, frame_num, kDestFrameBouncePeriod);
    }
    if (rotates_) {
        switch ((frame_num / kRotationPeriod) % 4) {
        case 0:
            rotation_ = fuchsia_hardware_display_Transform_IDENTITY;
            break;
        case 1:
            rotation_ = fuchsia_hardware_display_Transform_ROT_90;
            break;
        case 2:
            rotation_ = fuchsia_hardware_display_Transform_ROT_180;
            break;
        case 3:
            rotation_ = fuchsia_hardware_display_Transform_ROT_270;
            break;
        }

        if (frame_num % kRotationPeriod == 0 && frame_num != 0) {
            uint32_t tmp = dest_frame_.width;
            dest_frame_.width = dest_frame_.height;
            dest_frame_.height = tmp;
        }
    }

    frame_t display = {};
    for (unsigned i = 0; i < displays_.size(); i++) {
        display.height = displays_[i]->mode().vertical_resolution;
        display.width = displays_[i]->mode().horizontal_resolution;

        // Calculate the portion of the dest frame which shows up on this display
        if (compute_intersection(display, dest_frame_, &layers_[i].dest)) {
            // Find the subset of the src region which shows up on this display
            if (rotation_ == fuchsia_hardware_display_Transform_IDENTITY ||
                rotation_ == fuchsia_hardware_display_Transform_ROT_180) {
                if (!scaling_) {
                    layers_[i].src.x_pos =
                            src_frame_.x_pos + (layers_[i].dest.x_pos - dest_frame_.x_pos);
                    layers_[i].src.y_pos = src_frame_.y_pos;
                    layers_[i].src.width = layers_[i].dest.width;
                    layers_[i].src.height = layers_[i].dest.height;
                } else {
                    layers_[i].src.x_pos = src_frame_.x_pos + interpolate_scaling(
                            layers_[i].dest.x_pos - dest_frame_.x_pos, frame_num);
                    layers_[i].src.y_pos = src_frame_.y_pos;
                    layers_[i].src.width = interpolate_scaling(layers_[i].dest.width, frame_num);
                    layers_[i].src.height = interpolate_scaling(layers_[i].dest.height, frame_num);
                }
            } else {
                layers_[i].src.x_pos = src_frame_.x_pos;
                layers_[i].src.y_pos =
                        src_frame_.y_pos + (layers_[i].dest.y_pos - dest_frame_.y_pos);
                layers_[i].src.height = layers_[i].dest.width;
                layers_[i].src.width = layers_[i].dest.height;
            }

            // Put the dest frame coordinates in the display's coord space
            layers_[i].dest.x_pos -= display.x_pos;
            layers_[i].active = true;
        } else {
            layers_[i].active = false;
        }

        display.x_pos += display.width;
    }

    if (layer_toggle_) {
        for (auto& layer : layers_) {
            layer.active = !(frame_num % 2);
        }
    }
}

void PrimaryLayer::SendLayout(zx_handle_t channel) {
    if (layer_flipping_) {
        SetLayerImages(channel, alt_image_);
    }
    if (scaling_ || pan_src_ || pan_dest_) {
        SetLayerPositions(channel);
    }
}

bool PrimaryLayer::WaitForReady() {
    return Wait(SIGNAL_EVENT);
}

void PrimaryLayer::Render(int32_t frame_num) {
    if (!layer_flipping_) {
        return;
    }
    images_[alt_image_]->Render(frame_num < 2 ? 0 : frame_num - 2, frame_num);
    for (auto& layer : layers_) {
        zx_object_signal(layer.import_info[alt_image_].events[WAIT_EVENT], 0, ZX_EVENT_SIGNALED);
    }
}

void PrimaryLayer::SetLayerPositions(zx_handle_t dc_handle) {
    fuchsia_hardware_display_ControllerSetLayerPrimaryPositionRequest msg;
    msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerPrimaryPositionOrdinal;

    for (auto& layer : layers_) {
        msg.layer_id = layer.id;
        msg.transform = rotation_;

        msg.src_frame.width = layer.src.width;
        msg.src_frame.height = layer.src.height;
        msg.src_frame.x_pos = layer.src.x_pos;
        msg.src_frame.y_pos = layer.src.y_pos;

        msg.dest_frame.width = layer.dest.width;
        msg.dest_frame.height = layer.dest.height;
        msg.dest_frame.x_pos = layer.dest.x_pos;
        msg.dest_frame.y_pos = layer.dest.y_pos;

        if (zx_channel_write(dc_handle, 0, &msg, sizeof(msg), nullptr, 0) != ZX_OK) {
            ZX_ASSERT(false);
        }
    }
}

void VirtualLayer::SetLayerImages(zx_handle_t dc_handle, bool alt_image) {
    fuchsia_hardware_display_ControllerSetLayerImageRequest msg;
    msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerImageOrdinal;

    for (auto& layer : layers_) {
        msg.layer_id = layer.id;
        msg.image_id = layer.import_info[alt_image].id;
        msg.wait_event_id = layer.import_info[alt_image].event_ids[WAIT_EVENT];
        msg.signal_event_id = layer.import_info[alt_image].event_ids[SIGNAL_EVENT];

        if (zx_channel_write(dc_handle, 0, &msg, sizeof(msg), nullptr, 0) != ZX_OK) {
            ZX_ASSERT(false);
        }
    }
}

bool PrimaryLayer::Wait(uint32_t idx) {
    zx_time_t deadline = zx_deadline_after(ZX_MSEC(100));
    for (auto& layer : layers_) {
        uint32_t observed;
        if (!layer.active) {
            continue;
        }
        zx_handle_t event = layer.import_info[alt_image_].events[idx];
        zx_status_t res;
        if ((res = zx_object_wait_one(event, ZX_EVENT_SIGNALED, deadline, &observed)) == ZX_OK) {
            if (layer_flipping_) {
                zx_object_signal(event, ZX_EVENT_SIGNALED, 0);
            }
        } else {
            return false;
        }
    }
    return true;
}

CursorLayer::CursorLayer(Display* display) : VirtualLayer(display) { }

CursorLayer::CursorLayer(const fbl::Vector<Display>& displays) : VirtualLayer(displays) { }

bool CursorLayer::Init(zx_handle_t dc_handle) {
    fuchsia_hardware_display_CursorInfo info = displays_[0]->cursor();
    uint32_t bg_color = 0xffffffff;
    image_ = Image::Create(
        dc_handle, info.width, info.height, info.pixel_format, get_fg_color(), bg_color, false);
    if (!image_) {
        return false;
    }
    image_->Render(-1, -1);

    for (unsigned i = 0; i < displays_.size(); i++) {
        layer_t* layer = CreateLayer(dc_handle);
        if (layer == nullptr) {
            return false;
        }

        layer->active = true;
        if (!image_->Import(dc_handle, &layer->import_info[0])) {
            return false;
        }
        zx_object_signal(layer->import_info[0].events[WAIT_EVENT], 0, ZX_EVENT_SIGNALED);

        fuchsia_hardware_display_ControllerSetLayerCursorConfigRequest config;
        config.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerCursorConfigOrdinal;
        config.layer_id = layer->id;
        config.image_config.height = info.height;
        config.image_config.width = info.width;
        config.image_config.pixel_format = info.pixel_format;
        config.image_config.type = IMAGE_TYPE_SIMPLE;

        if (zx_channel_write(dc_handle, 0, &config, sizeof(config), nullptr, 0) != ZX_OK) {
            printf("Setting layer config failed\n");
            return false;
        }
    }

    SetLayerImages(dc_handle, false);

    return true;
}

void CursorLayer::StepLayout(int32_t frame_num) {
    fuchsia_hardware_display_CursorInfo info = displays_[0]->cursor();

    x_pos_ = interpolate(width_ + info.width, frame_num, kDestFrameBouncePeriod) - info.width;
    y_pos_ = interpolate(height_ + info.height, frame_num, kDestFrameBouncePeriod) - info.height;
}

void CursorLayer::SendLayout(zx_handle_t dc_handle) {
    fuchsia_hardware_display_ControllerSetLayerCursorPositionRequest msg;
    msg.hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerCursorPositionOrdinal;

    uint32_t display_start = 0;
    for (unsigned i = 0; i < displays_.size(); i++) {
        msg.layer_id = layers_[i].id;
        msg.x = x_pos_ - display_start;
        msg.y = y_pos_;

        if (zx_channel_write(dc_handle, 0, &msg, sizeof(msg), nullptr, 0) != ZX_OK) {
            ZX_ASSERT(false);
        }

        display_start += displays_[i]->mode().horizontal_resolution;
    }
}

ColorLayer::ColorLayer(Display* display) : VirtualLayer(display) { }

ColorLayer::ColorLayer(const fbl::Vector<Display>& displays) : VirtualLayer(displays) { }

bool ColorLayer::Init(zx_handle_t dc_handle) {
    for (unsigned i = 0; i < displays_.size(); i++) {
        layer_t* layer = CreateLayer(dc_handle);
        if (layer == nullptr) {
            return false;
        }

        layer->active = true;

        constexpr uint32_t kColorLayerFormat = ZX_PIXEL_FORMAT_ARGB_8888;
        uint32_t kColorLayerColor = get_fg_color();

        uint32_t size = sizeof(fuchsia_hardware_display_ControllerSetLayerColorConfigRequest) +
                        FIDL_ALIGN(ZX_PIXEL_FORMAT_BYTES(kColorLayerFormat));
        uint8_t data[size];

        auto config =
            reinterpret_cast<fuchsia_hardware_display_ControllerSetLayerColorConfigRequest*>(data);
        config->hdr.ordinal = fuchsia_hardware_display_ControllerSetLayerColorConfigOrdinal;
        config->layer_id = layer->id;
        config->pixel_format = kColorLayerFormat;
        config->color_bytes.count = ZX_PIXEL_FORMAT_BYTES(kColorLayerFormat);
        config->color_bytes.data = reinterpret_cast<void*>(FIDL_ALLOC_PRESENT);

        *reinterpret_cast<uint32_t*>(config + 1) = kColorLayerColor;

        if (zx_channel_write(dc_handle, 0, data, size, nullptr, 0) != ZX_OK) {
            printf("Setting layer config failed\n");
            return false;
        }
    }

    return true;
}
